reactos/subsystems/ntvdm/dos/dem.c

286 lines
8.1 KiB
C
Raw Normal View History

/*
* 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 <theflash AT sdf DOT lonestar DOT org>
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#define NDEBUG
#include "emulator.h"
#include "dem.h"
#include "bop.h"
/* Extra PSDK/NDK Headers */
#include <ndk/obtypes.h>
/* 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 */