Changing directories in a DOS program, running in a console window of Windows NT and above, is reflected in the console, too. This is made possible by interaction between NTVDM and CMD via two undocumented functions in kernel32.dll:
BOOL SetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs): Sets NTVDM current directory list. Called by NTVDM upon exit, to return its current directories to its parent CMD process.
cchCurDirs: Length of current directory list, in bytes.
lpszzCurDirs: Current directory list. Similarly to environment variable blocks, it consists of zero-terminated ASCII strings in the form of
X: is the drive letter and
\PATH its current directory) concatenated after each other, with an extra zero byte (an empty string) terminating the list. Usually, only those drives are listed which were actually used in NTVDM, in alphabetical order, but the first element in the list must belong to the current drive: CMD changes to that drive and directory.
TRUE, if the current directory list was successfully updated;
FALSE, if an error occurred.
DWORD GetVDMCurrentDirectories(DWORD cchCurDirs, PCHAR lpszzCurDirs): Gets current directory list. Called by CMD upon exit of of its child NTVDM process, to fetch its final state of current directories.
cchCurDirs: (Maximum) length of buffer, in bytes.
lpszzCurDirs: Buffer to receive current directory list.
Output: Actual length of current directory list, in bytes;
0, if the list is empty or an error occurred.
Notes about non-trivial behavior:
These functions are each called only once, when NTVDM exits. NTVDM and CMD don't interact with each other upon every change of the current directory.
Not only NTVDM but its direct child processes, native Windows console programs launched from it, can also fetch and change current directories via these functions.
When NTVDM starts, the current directories list doesn't exist so
GetVDMCurrentDirectories will return an empty list to it and its child processes. NTVDM actually fetches the current directories from the dynamically generated environment variables
X is the drive letter; the equation mark and the colon are part of the name!). If no such variable exists for a given drive then that drive hasn't been accessed in NTVDM yet or it doesn't exist at all.
What will not work:
SetVDMCurrentDirectories are not reflected in NTVDM because it maintains its own list and never calls
Changes by setting the
=X: variables are not possible because these variables don't actually exist.
SetCurrentDirectory in a child process are not reflected in its parent NTVDM because they are separate processes.
SetVDMCurrentDirectories are not reflected in CMD because they are undone when NTVDM sets its own current directories upon exit. If you remove the call to
ntvdm.exe then, upon its exit, changes by its child processes and only those will become visible to CMD.
It is possible to inject code to the NTVDM process and thus call system functions in its name but that's beyond the scope of this document.
Copyright and license |
Blog page | Recent updates |
(This page best viewed with any browser)