[NTVDM]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 18 Dec 2013 01:16:54 +0000 (01:16 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 18 Dec 2013 01:16:54 +0000 (01:16 +0000)
Hackplement BOP_CMD function 0x08: "Launch external command". Still WIP.
Explanation: Launching a command from command.com starts (under certain conditions not implemented there) "cmd.exe /c <the_command>"

See https://groups.google.com/forum/#!topic/microsoft.public.win2000.cmdprompt.admin/n5KbegKJuE0
and http://technet.microsoft.com/en-us/library/cc723564.aspx#XSLTsection123121120120
subsection "CMD.EXE and COMMAND.COM":
"Be aware that a command shell is not an MS-DOS command prompt, even though it shares the same icon.
The Windows NT command shell is a full 32-bit Windows NT console application that resides in the CMD.EXE executable file.
The MS-DOS command prompt is a 16-bit DOS application that resides in the COMMAND.COM executable file.
Because COMMAND.COM is a 16-bit DOS executable, Windows NT executes this shell within a Windows NT virtual DOS machine (VDM).
COMMAND.COM is supplied primarily for compatibility with MS-DOS.
[...]
This behavior reveals a quite subtle feature of Windows NT that is very important. The 16-bit MS-DOS shell (COMMAND.COM)
that ships with Windows NT is specially designed for Windows NT. When a command is entered for execution by this shell,
it does not actually execute it. Instead, it packages the command text and sends it to a 32-bit CMD.EXE command shell for
execution. Because all commands are actually executed by CMD.EXE (the Windows NT command shell), the 16-bit shell inherits
all the features and facilities of the full Windows NT shell."

svn path=/branches/ntvdm/; revision=61290

subsystems/ntvdm/dos.c

index 96d726a..46b330e 100644 (file)
@@ -1422,7 +1422,77 @@ VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
     BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
     setIP(getIP() + 1);
 
     BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
     setIP(getIP() + 1);
 
-    DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum);
+    switch (FuncNum)
+    {
+        case 0x08: // Launch external command
+        {
+#define CMDLINE_LENGTH  1024
+
+            BOOL Result;
+            DWORD dwExitCode;
+
+            LPSTR Command = (LPSTR)SEG_OFF_TO_PTR(getDS(), getSI());
+            CHAR CommandLine[CMDLINE_LENGTH] = "";
+            STARTUPINFOA StartupInfo;
+            PROCESS_INFORMATION ProcessInformation;
+            DPRINT1("CMD Run Command '%s'\n", Command);
+
+            Command[strlen(Command)-1] = 0;
+            
+            strcpy(CommandLine, "cmd.exe /c ");
+            strcat(CommandLine, Command);
+
+            ZeroMemory(&StartupInfo, sizeof(StartupInfo));
+            ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
+
+            StartupInfo.cb = sizeof(StartupInfo);
+
+            DosPrintCharacter('\n');
+
+            Result = CreateProcessA(NULL,
+                                    CommandLine,
+                                    NULL,
+                                    NULL,
+                                    TRUE,
+                                    0,
+                                    NULL,
+                                    NULL,
+                                    &StartupInfo,
+                                    &ProcessInformation);
+            if (Result)
+            {
+                DPRINT1("Command '%s' launched successfully\n");
+
+                /* Wait for process termination */
+                WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
+
+                /* Get the exit code */
+                GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode);
+
+                /* Close handles */
+                CloseHandle(ProcessInformation.hThread);
+                CloseHandle(ProcessInformation.hProcess);
+            }
+            else
+            {
+                DPRINT1("Failed when launched command '%s'\n");
+                dwExitCode = GetLastError();
+            }
+            
+            DosPrintCharacter('\n');
+
+            setAL((UCHAR)dwExitCode);
+
+            break;
+        }
+
+        default:
+        {
+            DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum);
+            // setCF(1); // Disable, otherwise we enter an infinite loop
+            break;
+        }
+    }
 }
 
 VOID WINAPI DosInt20h(LPWORD Stack)
 }
 
 VOID WINAPI DosInt20h(LPWORD Stack)