/* * COPYRIGHT: GPL - See COPYING in the top level directory * PROJECT: ReactOS Virtual DOS Machine * FILE: dem.c * PURPOSE: DOS 32-bit Emulation Support Library - * This library is used by the built-in NTVDM DOS32 and by * the NT 16-bit DOS in Windows (via BOPs). It also exposes * exported functions that can be used by VDDs. * PROGRAMMERS: Aleksandar Andrejevic * Hermes Belusca-Maito (hermes.belusca@sfr.fr) */ /* INCLUDES *******************************************************************/ #define NDEBUG #include "emulator.h" #include "dem.h" #include "bop.h" /* Extra PSDK/NDK Headers */ #include /* PRIVATE VARIABLES **********************************************************/ /**/extern BYTE CurrentDrive;/**/ /* DEFINES ********************************************************************/ /* 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 **********************************************************/ static 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); } static 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()); LPSTR CmdPtr = Command; CHAR CommandLine[CMDLINE_LENGTH] = ""; STARTUPINFOA StartupInfo; PROCESS_INFORMATION ProcessInformation; /* Remove return carriage character */ while (*CmdPtr != '\r') CmdPtr++; *CmdPtr = '\0'; DPRINT1("CMD Run Command '%s'\n", Command); /* Spawn a user-defined 32-bit command preprocessor */ /* Build the command line */ // FIXME: Use COMSPEC env var!! 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", Command); /* 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; } } } /* PUBLIC FUNCTIONS ***********************************************************/ BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames) { /* Register the DOS BOPs */ RegisterBop(BOP_DOS, DosSystemBop ); RegisterBop(BOP_CMD, DosCmdInterpreterBop); if (DosKernelFileNames) { DisplayMessage(L"NTVDM: Loading DOS kernel from external files is currently unsupported"); return FALSE; } else { BOOLEAN Result; Result = DosBIOSInitialize(); // Result &= DosKRNLInitialize(); return Result; } } /* PUBLIC EXPORTED APIS *******************************************************/ // demLFNCleanup // demLFNGetCurrentDirectory // demGetFileTimeByHandle_WOW // demWOWLFNAllocateSearchHandle // demWOWLFNCloseSearchHandle // demWOWLFNEntry // demWOWLFNGetSearchHandle // demWOWLFNInit DWORD WINAPI demClientErrorEx(IN HANDLE FileHandle, IN CHAR Unknown, IN BOOL Flag) { UNIMPLEMENTED; return GetLastError(); } DWORD WINAPI demFileDelete(IN LPCSTR FileName) { if (DeleteFileA(FileName)) SetLastError(ERROR_SUCCESS); return GetLastError(); } DWORD WINAPI demFileFindFirst(OUT PVOID lpFindFileData, IN LPCSTR FileName, IN WORD AttribMask) { BOOLEAN Success = TRUE; WIN32_FIND_DATAA FindData; PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData; /* Fill the block */ FindFileBlock->DriveLetter = CurrentDrive + 'A'; FindFileBlock->AttribMask = AttribMask; FindFileBlock->SearchHandle = FindFirstFileA(FileName, &FindData); if (FindFileBlock->SearchHandle == INVALID_HANDLE_VALUE) return GetLastError(); do { /* Check the attributes */ if (!((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) & ~AttribMask)) { break; } } while ((Success = FindNextFileA(FindFileBlock->SearchHandle, &FindData))); if (!Success) return GetLastError(); FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes); FileTimeToDosDateTime(&FindData.ftLastWriteTime, &FindFileBlock->FileDate, &FindFileBlock->FileTime); FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF : FindData.nFileSizeLow; strcpy(FindFileBlock->FileName, FindData.cAlternateFileName); return ERROR_SUCCESS; } DWORD WINAPI demFileFindNext(OUT PVOID lpFindFileData) { WIN32_FIND_DATAA FindData; PDOS_FIND_FILE_BLOCK FindFileBlock = (PDOS_FIND_FILE_BLOCK)lpFindFileData; do { if (!FindNextFileA(FindFileBlock->SearchHandle, &FindData)) return GetLastError(); /* Update the block */ FindFileBlock->Attributes = LOBYTE(FindData.dwFileAttributes); FileTimeToDosDateTime(&FindData.ftLastWriteTime, &FindFileBlock->FileDate, &FindFileBlock->FileTime); FindFileBlock->FileSize = FindData.nFileSizeHigh ? 0xFFFFFFFF : FindData.nFileSizeLow; strcpy(FindFileBlock->FileName, FindData.cAlternateFileName); } while((FindData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) & ~FindFileBlock->AttribMask); return ERROR_SUCCESS; } UCHAR WINAPI demGetPhysicalDriveType(IN UCHAR DriveNumber) { UNIMPLEMENTED; return DOSDEVICE_DRIVE_UNKNOWN; } BOOL WINAPI demIsShortPathName(IN LPCSTR Path, IN BOOL Unknown) { UNIMPLEMENTED; return FALSE; } DWORD WINAPI demSetCurrentDirectoryGetDrive(IN LPCSTR CurrentDirectory, OUT PUCHAR DriveNumber) { UNIMPLEMENTED; return ERROR_SUCCESS; } /* EOF */