From 2a6c5d51be5476013ce26d0c1211732b9fe7df02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Wed, 18 Dec 2013 01:16:54 +0000 Subject: [PATCH] [NTVDM] 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 " 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 | 72 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/subsystems/ntvdm/dos.c b/subsystems/ntvdm/dos.c index 96d726a7391..46b330e6ccb 100644 --- a/subsystems/ntvdm/dos.c +++ b/subsystems/ntvdm/dos.c @@ -1422,7 +1422,77 @@ VOID WINAPI DosCmdInterpreterBop(LPWORD Stack) 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)