#include "dos.h"
#include "bios.h"
+#include "bop.h"
#include "int32.h"
#include "registers.h"
static BOOLEAN DosUmbLinked = FALSE;
static WORD DosErrorLevel = 0x0000;
+/* BOP Identifiers */
+#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
+#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
+
/* PRIVATE FUNCTIONS **********************************************************/
/* Taken from base/shell/cmd/console.c */
}
}
+VOID WINAPI DosSystemBop(LPWORD Stack)
+{
+ /* Get the Function Number and skip it */
+ BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
+ setIP(getIP() + 1);
+
+ DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
+}
+
+VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
+{
+ /* Get the Function Number and skip it */
+ BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
+ setIP(getIP() + 1);
+
+ 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)
{
/* This is the exit interrupt */
{
UNREFERENCED_PARAMETER(Stack);
+ /* Stop the VDM */
VdmRunning = FALSE;
}
+VOID WINAPI DosFastConOut(LPWORD Stack)
+{
+ /*
+ * This is the DOS 2+ Fast Console Output Interrupt.
+ * See Ralf Brown: http://www.ctyme.com/intr/rb-4124.htm
+ * for more information.
+ */
+ UNREFERENCED_PARAMETER(Stack);
+
+ /*
+ * The default handler under DOS 2.x and 3.x simply calls INT 10/AH=0Eh.
+ * Do better and call directly BiosPrintCharacter: it's what INT 10/AH=0Eh
+ * does. Otherwise we would have to set BL to DOS_CHAR_ATTRIBUTE and
+ * BH to Bda->VideoPage.
+ */
+ BiosPrintCharacter(getAL(), DOS_CHAR_ATTRIBUTE, Bda->VideoPage);
+}
+
VOID WINAPI DosInt2Fh(LPWORD Stack)
{
DPRINT1("DOS System Function INT 0x2F, AH = %xh, AL = %xh NOT IMPLEMENTED!\n",
DosSystemFileTable[1] = GetStdHandle(STD_OUTPUT_HANDLE);
DosSystemFileTable[2] = GetStdHandle(STD_ERROR_HANDLE);
+ /* Register the DOS BOPs */
+ RegisterBop(BOP_DOS, DosSystemBop );
+ RegisterBop(BOP_CMD, DosCmdInterpreterBop);
+
/* Register the DOS 32-bit Interrupts */
RegisterInt32(0x20, DosInt20h );
RegisterInt32(0x21, DosInt21h );
// RegisterInt32(0x22, DosInt22h ); // Termination
RegisterInt32(0x23, DosBreakInterrupt); // Ctrl-C / Ctrl-Break
// RegisterInt32(0x24, DosInt24h ); // Critical Error
+ RegisterInt32(0x29, DosFastConOut ); // DOS 2+ Fast Console Output
RegisterInt32(0x2F, DosInt2Fh );
return TRUE;