mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 01:15:09 +00:00
[NTVDM]
Rewrite DosCreateProcess, separating the loading code into DosLoadExecutable. Implement INT 21h function AH = 0x4B (Create Process). svn path=/branches/ntvdm/; revision=62972
This commit is contained in:
parent
a8caf51cd0
commit
e5df0c4dfe
3 changed files with 282 additions and 93 deletions
|
@ -383,15 +383,13 @@ static VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner)
|
||||||
Mcb->OwnerPsp = NewOwner;
|
Mcb->OwnerPsp = NewOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WORD DosCopyEnvironmentBlock(LPCVOID Environment, LPCSTR ProgramName)
|
||||||
|
|
||||||
static WORD DosCopyEnvironmentBlock(WORD SourceSegment, LPCSTR ProgramName)
|
|
||||||
{
|
{
|
||||||
PCHAR Ptr, SourceBuffer, DestBuffer = NULL;
|
PCHAR Ptr, DestBuffer = NULL;
|
||||||
ULONG TotalSize = 0;
|
ULONG TotalSize = 0;
|
||||||
WORD DestSegment;
|
WORD DestSegment;
|
||||||
|
|
||||||
Ptr = SourceBuffer = (PCHAR)SEG_OFF_TO_PTR(SourceSegment, 0);
|
Ptr = (PCHAR)Environment;
|
||||||
|
|
||||||
/* Calculate the size of the environment block */
|
/* Calculate the size of the environment block */
|
||||||
while (*Ptr)
|
while (*Ptr)
|
||||||
|
@ -408,7 +406,7 @@ static WORD DosCopyEnvironmentBlock(WORD SourceSegment, LPCSTR ProgramName)
|
||||||
DestSegment = DosAllocateMemory((WORD)((TotalSize + 0x0F) >> 4), NULL);
|
DestSegment = DosAllocateMemory((WORD)((TotalSize + 0x0F) >> 4), NULL);
|
||||||
if (!DestSegment) return 0;
|
if (!DestSegment) return 0;
|
||||||
|
|
||||||
Ptr = SourceBuffer;
|
Ptr = (PCHAR)Environment;
|
||||||
|
|
||||||
DestBuffer = (PCHAR)SEG_OFF_TO_PTR(DestSegment, 0);
|
DestBuffer = (PCHAR)SEG_OFF_TO_PTR(DestSegment, 0);
|
||||||
while (*Ptr)
|
while (*Ptr)
|
||||||
|
@ -1042,57 +1040,51 @@ VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WOR
|
||||||
PspBlock->CommandLine[PspBlock->CommandLineSize] = '\r';
|
PspBlock->CommandLine[PspBlock->CommandLineSize] = '\r';
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
|
DWORD DosLoadExecutable(IN DOS_EXEC_TYPE LoadType,
|
||||||
|
IN LPCSTR ExecutablePath,
|
||||||
|
IN LPCSTR CommandLine,
|
||||||
|
IN PVOID Environment,
|
||||||
|
OUT PDWORD StackLocation OPTIONAL,
|
||||||
|
OUT PDWORD EntryPoint OPTIONAL)
|
||||||
{
|
{
|
||||||
BOOLEAN Success = FALSE, AllocatedEnvBlock = FALSE;
|
DWORD Result = ERROR_SUCCESS;
|
||||||
HANDLE FileHandle = INVALID_HANDLE_VALUE, FileMapping = NULL;
|
HANDLE FileHandle = INVALID_HANDLE_VALUE, FileMapping = NULL;
|
||||||
LPBYTE Address = NULL;
|
LPBYTE Address = NULL;
|
||||||
LPSTR ProgramFilePath, Parameters[256];
|
|
||||||
CHAR CommandLineCopy[DOS_CMDLINE_LENGTH];
|
|
||||||
CHAR ParamString[DOS_CMDLINE_LENGTH];
|
|
||||||
DWORD ParamCount = 0;
|
|
||||||
WORD Segment = 0;
|
WORD Segment = 0;
|
||||||
|
WORD EnvBlock = 0;
|
||||||
WORD MaxAllocSize;
|
WORD MaxAllocSize;
|
||||||
DWORD i, FileSize, ExeSize;
|
DWORD i, FileSize, ExeSize;
|
||||||
PIMAGE_DOS_HEADER Header;
|
PIMAGE_DOS_HEADER Header;
|
||||||
PDWORD RelocationTable;
|
PDWORD RelocationTable;
|
||||||
PWORD RelocWord;
|
PWORD RelocWord;
|
||||||
|
|
||||||
DPRINT("DosCreateProcess: CommandLine \"%s\", EnvBlock 0x%04X\n",
|
DPRINT1("DosLoadExecutable(%d, %s, %s, %s, 0x%08X, 0x%08X)\n",
|
||||||
CommandLine,
|
LoadType,
|
||||||
EnvBlock);
|
ExecutablePath,
|
||||||
|
CommandLine,
|
||||||
|
Environment,
|
||||||
|
StackLocation,
|
||||||
|
EntryPoint);
|
||||||
|
|
||||||
/* Save a copy of the command line */
|
if (LoadType == DOS_LOAD_OVERLAY)
|
||||||
strcpy(CommandLineCopy, CommandLine);
|
|
||||||
|
|
||||||
/* Get the file name of the executable */
|
|
||||||
ProgramFilePath = strtok(CommandLineCopy, " \t");
|
|
||||||
|
|
||||||
/* Load the parameters in the local array */
|
|
||||||
while ((ParamCount < sizeof(Parameters)/sizeof(Parameters[0]))
|
|
||||||
&& ((Parameters[ParamCount] = strtok(NULL, " \t")) != NULL))
|
|
||||||
{
|
{
|
||||||
ParamCount++;
|
DPRINT1("Overlay loading is not supported yet.\n");
|
||||||
}
|
return ERROR_NOT_SUPPORTED;
|
||||||
|
|
||||||
ZeroMemory(ParamString, sizeof(ParamString));
|
|
||||||
|
|
||||||
/* Store the parameters in a string */
|
|
||||||
for (i = 0; i < ParamCount; i++)
|
|
||||||
{
|
|
||||||
strncat(ParamString, Parameters[i], DOS_CMDLINE_LENGTH - strlen(ParamString) - 1);
|
|
||||||
strncat(ParamString, " ", DOS_CMDLINE_LENGTH - strlen(ParamString) - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a handle to the executable */
|
/* Open a handle to the executable */
|
||||||
FileHandle = CreateFileA(ProgramFilePath,
|
FileHandle = CreateFileA(ExecutablePath,
|
||||||
GENERIC_READ,
|
GENERIC_READ,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
NULL);
|
NULL);
|
||||||
if (FileHandle == INVALID_HANDLE_VALUE) goto Cleanup;
|
if (FileHandle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the file size */
|
/* Get the file size */
|
||||||
FileSize = GetFileSize(FileHandle, NULL);
|
FileSize = GetFileSize(FileHandle, NULL);
|
||||||
|
@ -1104,23 +1096,26 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
if (FileMapping == NULL) goto Cleanup;
|
if (FileMapping == NULL)
|
||||||
|
{
|
||||||
|
Result = GetLastError();
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Map the file into memory */
|
/* Map the file into memory */
|
||||||
Address = (LPBYTE)MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0);
|
Address = (LPBYTE)MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0);
|
||||||
if (Address == NULL) goto Cleanup;
|
if (Address == NULL)
|
||||||
|
|
||||||
/* Did we get an environment segment? */
|
|
||||||
if (!EnvBlock)
|
|
||||||
{
|
{
|
||||||
/* Set a flag to know if the environment block was allocated here */
|
Result = GetLastError();
|
||||||
AllocatedEnvBlock = TRUE;
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* No, copy the one from the parent */
|
/* Copy the environment block to DOS memory */
|
||||||
EnvBlock = DosCopyEnvironmentBlock((CurrentPsp != SYSTEM_PSP)
|
EnvBlock = DosCopyEnvironmentBlock(Environment, ExecutablePath);
|
||||||
? SEGMENT_TO_PSP(CurrentPsp)->EnvBlock
|
if (EnvBlock == 0)
|
||||||
: SYSTEM_ENV_BLOCK,
|
{
|
||||||
ProgramFilePath);
|
Result = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this is an EXE file or a COM file */
|
/* Check if this is an EXE file or a COM file */
|
||||||
|
@ -1152,11 +1147,15 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if at least the lowest allocation was successful */
|
/* Check if at least the lowest allocation was successful */
|
||||||
if (Segment == 0) goto Cleanup;
|
if (Segment == 0)
|
||||||
|
{
|
||||||
|
Result = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize the PSP */
|
/* Initialize the PSP */
|
||||||
DosInitializePsp(Segment,
|
DosInitializePsp(Segment,
|
||||||
ParamString,
|
CommandLine,
|
||||||
(WORD)ExeSize,
|
(WORD)ExeSize,
|
||||||
EnvBlock);
|
EnvBlock);
|
||||||
|
|
||||||
|
@ -1184,21 +1183,22 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
|
||||||
*RelocWord += Segment + (sizeof(DOS_PSP) >> 4);
|
*RelocWord += Segment + (sizeof(DOS_PSP) >> 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the initial segment registers */
|
if (LoadType == DOS_LOAD_AND_EXECUTE)
|
||||||
setDS(Segment);
|
{
|
||||||
setES(Segment);
|
/* Set the initial segment registers */
|
||||||
|
setDS(Segment);
|
||||||
|
setES(Segment);
|
||||||
|
|
||||||
/* Set the stack to the location from the header */
|
/* Set the stack to the location from the header */
|
||||||
EmulatorSetStack(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss,
|
EmulatorSetStack(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss,
|
||||||
Header->e_sp);
|
Header->e_sp);
|
||||||
|
|
||||||
/* Execute */
|
/* Execute */
|
||||||
CurrentPsp = Segment;
|
CurrentPsp = Segment;
|
||||||
DiskTransferArea = MAKELONG(0x80, Segment);
|
DiskTransferArea = MAKELONG(0x80, Segment);
|
||||||
EmulatorExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4),
|
EmulatorExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4),
|
||||||
Header->e_ip);
|
Header->e_ip);
|
||||||
|
}
|
||||||
Success = TRUE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1208,11 +1208,19 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
|
||||||
DosAllocateMemory(0xFFFF, &MaxAllocSize);
|
DosAllocateMemory(0xFFFF, &MaxAllocSize);
|
||||||
|
|
||||||
/* Make sure it's enough for the whole program and the PSP */
|
/* Make sure it's enough for the whole program and the PSP */
|
||||||
if (((DWORD)MaxAllocSize << 4) < (FileSize + sizeof(DOS_PSP))) goto Cleanup;
|
if (((DWORD)MaxAllocSize << 4) < (FileSize + sizeof(DOS_PSP)))
|
||||||
|
{
|
||||||
|
Result = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate all of it */
|
/* Allocate all of it */
|
||||||
Segment = DosAllocateMemory(MaxAllocSize, NULL);
|
Segment = DosAllocateMemory(MaxAllocSize, NULL);
|
||||||
if (Segment == 0) goto Cleanup;
|
if (Segment == 0)
|
||||||
|
{
|
||||||
|
Result = ERROR_ARENA_TRASHED;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* The process owns its own memory */
|
/* The process owns its own memory */
|
||||||
DosChangeMemoryOwner(Segment, Segment);
|
DosChangeMemoryOwner(Segment, Segment);
|
||||||
|
@ -1225,36 +1233,37 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
|
||||||
|
|
||||||
/* Initialize the PSP */
|
/* Initialize the PSP */
|
||||||
DosInitializePsp(Segment,
|
DosInitializePsp(Segment,
|
||||||
ParamString,
|
CommandLine,
|
||||||
MaxAllocSize,
|
MaxAllocSize,
|
||||||
EnvBlock);
|
EnvBlock);
|
||||||
|
|
||||||
/* Set the initial segment registers */
|
if (LoadType == DOS_LOAD_AND_EXECUTE)
|
||||||
setDS(Segment);
|
{
|
||||||
setES(Segment);
|
/* Set the initial segment registers */
|
||||||
|
setDS(Segment);
|
||||||
|
setES(Segment);
|
||||||
|
|
||||||
/* Set the stack to the last word of the segment */
|
/* Set the stack to the last word of the segment */
|
||||||
EmulatorSetStack(Segment, 0xFFFE);
|
EmulatorSetStack(Segment, 0xFFFE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the value on the stack to 0, so that a near return
|
* Set the value on the stack to 0, so that a near return
|
||||||
* jumps to PSP:0000 which has the exit code.
|
* jumps to PSP:0000 which has the exit code.
|
||||||
*/
|
*/
|
||||||
*((LPWORD)SEG_OFF_TO_PTR(Segment, 0xFFFE)) = 0;
|
*((LPWORD)SEG_OFF_TO_PTR(Segment, 0xFFFE)) = 0;
|
||||||
|
|
||||||
/* Execute */
|
/* Execute */
|
||||||
CurrentPsp = Segment;
|
CurrentPsp = Segment;
|
||||||
DiskTransferArea = MAKELONG(0x80, Segment);
|
DiskTransferArea = MAKELONG(0x80, Segment);
|
||||||
EmulatorExecute(Segment, 0x100);
|
EmulatorExecute(Segment, 0x100);
|
||||||
|
}
|
||||||
Success = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (!Success)
|
if (Result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
/* It was not successful, cleanup the DOS memory */
|
/* It was not successful, cleanup the DOS memory */
|
||||||
if (AllocatedEnvBlock) DosFreeMemory(EnvBlock);
|
if (EnvBlock) DosFreeMemory(EnvBlock);
|
||||||
if (Segment) DosFreeMemory(Segment);
|
if (Segment) DosFreeMemory(Segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,7 +1276,118 @@ Cleanup:
|
||||||
/* Close the file handle */
|
/* Close the file handle */
|
||||||
if (FileHandle != INVALID_HANDLE_VALUE) CloseHandle(FileHandle);
|
if (FileHandle != INVALID_HANDLE_VALUE) CloseHandle(FileHandle);
|
||||||
|
|
||||||
return Success;
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
WORD DosCreateProcess(DOS_EXEC_TYPE LoadType,
|
||||||
|
LPCSTR ProgramName,
|
||||||
|
PDOS_EXEC_PARAM_BLOCK Parameters)
|
||||||
|
{
|
||||||
|
DWORD BinaryType;
|
||||||
|
LPVOID Environment = NULL;
|
||||||
|
VDM_COMMAND_INFO CommandInfo;
|
||||||
|
CHAR CmdLine[MAX_PATH];
|
||||||
|
CHAR AppName[MAX_PATH];
|
||||||
|
CHAR PifFile[MAX_PATH];
|
||||||
|
CHAR Desktop[MAX_PATH];
|
||||||
|
CHAR Title[MAX_PATH];
|
||||||
|
CHAR Env[MAX_PATH];
|
||||||
|
STARTUPINFOA StartupInfo;
|
||||||
|
PROCESS_INFORMATION ProcessInfo;
|
||||||
|
|
||||||
|
/* Get the binary type */
|
||||||
|
if (!GetBinaryTypeA(ProgramName, &BinaryType)) return GetLastError();
|
||||||
|
|
||||||
|
/* Did the caller specify an environment segment? */
|
||||||
|
if (Parameters->Environment)
|
||||||
|
{
|
||||||
|
/* Yes, use it instead of the parent one */
|
||||||
|
Environment = SEG_OFF_TO_PTR(Parameters->Environment, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the startup info structure */
|
||||||
|
ZeroMemory(&StartupInfo, sizeof(STARTUPINFOA));
|
||||||
|
StartupInfo.cb = sizeof(STARTUPINFOA);
|
||||||
|
|
||||||
|
/* Create the process */
|
||||||
|
if (!CreateProcessA(ProgramName,
|
||||||
|
FAR_POINTER(Parameters->CommandLine),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
0,
|
||||||
|
Environment,
|
||||||
|
NULL,
|
||||||
|
&StartupInfo,
|
||||||
|
&ProcessInfo))
|
||||||
|
{
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the type of the program */
|
||||||
|
switch (BinaryType)
|
||||||
|
{
|
||||||
|
/* These are handled by NTVDM */
|
||||||
|
case SCS_DOS_BINARY:
|
||||||
|
case SCS_WOW_BINARY:
|
||||||
|
{
|
||||||
|
/* Clear the structure */
|
||||||
|
ZeroMemory(&CommandInfo, sizeof(CommandInfo));
|
||||||
|
|
||||||
|
/* Initialize the structure members */
|
||||||
|
CommandInfo.VDMState = VDM_NOT_READY;
|
||||||
|
CommandInfo.CmdLine = CmdLine;
|
||||||
|
CommandInfo.CmdLen = sizeof(CmdLine);
|
||||||
|
CommandInfo.AppName = AppName;
|
||||||
|
CommandInfo.AppLen = sizeof(AppName);
|
||||||
|
CommandInfo.PifFile = PifFile;
|
||||||
|
CommandInfo.PifLen = sizeof(PifFile);
|
||||||
|
CommandInfo.Desktop = Desktop;
|
||||||
|
CommandInfo.DesktopLen = sizeof(Desktop);
|
||||||
|
CommandInfo.Title = Title;
|
||||||
|
CommandInfo.TitleLen = sizeof(Title);
|
||||||
|
CommandInfo.Env = Env;
|
||||||
|
CommandInfo.EnvLen = sizeof(Env);
|
||||||
|
|
||||||
|
/* Get the VDM command information */
|
||||||
|
if (!GetNextVDMCommand(&CommandInfo))
|
||||||
|
{
|
||||||
|
/* Shouldn't happen */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increment the re-entry count */
|
||||||
|
CommandInfo.VDMState = VDM_INC_REENTER_COUNT;
|
||||||
|
GetNextVDMCommand(&CommandInfo);
|
||||||
|
|
||||||
|
/* Load the executable */
|
||||||
|
if (DosLoadExecutable(LoadType,
|
||||||
|
AppName,
|
||||||
|
CmdLine,
|
||||||
|
Env,
|
||||||
|
&Parameters->StackLocation,
|
||||||
|
&Parameters->EntryPoint) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DisplayMessage(L"Could not load '%S'", AppName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not handled by NTVDM */
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
/* Wait for the process to finish executing */
|
||||||
|
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the handles */
|
||||||
|
CloseHandle(ProcessInfo.hProcess);
|
||||||
|
CloseHandle(ProcessInfo.hThread);
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode)
|
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode)
|
||||||
|
@ -2345,6 +2465,27 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Execute */
|
||||||
|
case 0x4B:
|
||||||
|
{
|
||||||
|
DOS_EXEC_TYPE LoadType = (DOS_EXEC_TYPE)getAL();
|
||||||
|
LPSTR ProgramName = SEG_OFF_TO_PTR(getDS(), getDX());
|
||||||
|
PDOS_EXEC_PARAM_BLOCK ParamBlock = SEG_OFF_TO_PTR(getES(), getBX());
|
||||||
|
WORD ErrorCode = DosCreateProcess(LoadType, ProgramName, ParamBlock);
|
||||||
|
|
||||||
|
if (ErrorCode == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
|
||||||
|
setAX(ErrorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Terminate With Return Code */
|
/* Terminate With Return Code */
|
||||||
case 0x4C:
|
case 0x4C:
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,6 +53,13 @@ enum DOS_ALLOC_STRATEGY
|
||||||
DOS_ALLOC_LAST_FIT
|
DOS_ALLOC_LAST_FIT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DOS_LOAD_AND_EXECUTE = 0x00,
|
||||||
|
DOS_LOAD_ONLY = 0x01,
|
||||||
|
DOS_LOAD_OVERLAY = 0x03
|
||||||
|
} DOS_EXEC_TYPE;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
typedef struct _DOS_MCB
|
typedef struct _DOS_MCB
|
||||||
|
@ -136,6 +143,19 @@ typedef struct _DOS_FIND_FILE_BLOCK
|
||||||
CHAR FileName[13];
|
CHAR FileName[13];
|
||||||
} DOS_FIND_FILE_BLOCK, *PDOS_FIND_FILE_BLOCK;
|
} DOS_FIND_FILE_BLOCK, *PDOS_FIND_FILE_BLOCK;
|
||||||
|
|
||||||
|
typedef struct _DOS_EXEC_PARAM_BLOCK
|
||||||
|
{
|
||||||
|
/* Input variables */
|
||||||
|
WORD Environment;
|
||||||
|
DWORD CommandLine;
|
||||||
|
DWORD FirstFcb;
|
||||||
|
DWORD SecondFcb;
|
||||||
|
|
||||||
|
/* Output variables */
|
||||||
|
DWORD StackLocation;
|
||||||
|
DWORD EntryPoint;
|
||||||
|
} DOS_EXEC_PARAM_BLOCK, *PDOS_EXEC_PARAM_BLOCK;
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
/* FUNCTIONS ******************************************************************/
|
/* FUNCTIONS ******************************************************************/
|
||||||
|
@ -169,7 +189,19 @@ WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead);
|
||||||
WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten);
|
WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten);
|
||||||
|
|
||||||
VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment);
|
VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment);
|
||||||
BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock);
|
DWORD DosLoadExecutable(
|
||||||
|
IN DOS_EXEC_TYPE LoadType,
|
||||||
|
IN LPCSTR ExecutablePath,
|
||||||
|
IN LPCSTR CommandLine,
|
||||||
|
IN PVOID Environment,
|
||||||
|
OUT PDWORD StackLocation OPTIONAL,
|
||||||
|
OUT PDWORD EntryPoint OPTIONAL
|
||||||
|
);
|
||||||
|
WORD DosCreateProcess(
|
||||||
|
DOS_EXEC_TYPE LoadType,
|
||||||
|
LPCSTR ProgramName,
|
||||||
|
PDOS_EXEC_PARAM_BLOCK Parameters
|
||||||
|
);
|
||||||
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode);
|
VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode);
|
||||||
BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle);
|
BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle);
|
||||||
|
|
||||||
|
|
|
@ -385,6 +385,7 @@ DWORD WINAPI CommandThreadProc(LPVOID Parameter)
|
||||||
CHAR PifFile[MAX_PATH];
|
CHAR PifFile[MAX_PATH];
|
||||||
CHAR Desktop[MAX_PATH];
|
CHAR Desktop[MAX_PATH];
|
||||||
CHAR Title[MAX_PATH];
|
CHAR Title[MAX_PATH];
|
||||||
|
CHAR Env[MAX_PATH];
|
||||||
|
|
||||||
UNREFERENCED_PARAMETER(Parameter);
|
UNREFERENCED_PARAMETER(Parameter);
|
||||||
|
|
||||||
|
@ -405,13 +406,20 @@ DWORD WINAPI CommandThreadProc(LPVOID Parameter)
|
||||||
CommandInfo.DesktopLen = sizeof(Desktop);
|
CommandInfo.DesktopLen = sizeof(Desktop);
|
||||||
CommandInfo.Title = Title;
|
CommandInfo.Title = Title;
|
||||||
CommandInfo.TitleLen = sizeof(Title);
|
CommandInfo.TitleLen = sizeof(Title);
|
||||||
|
CommandInfo.Env = Env;
|
||||||
|
CommandInfo.EnvLen = sizeof(Env);
|
||||||
|
|
||||||
/* Wait for the next available VDM */
|
/* Wait for the next available VDM */
|
||||||
if (!GetNextVDMCommand(&CommandInfo)) break;
|
if (!GetNextVDMCommand(&CommandInfo)) break;
|
||||||
|
|
||||||
/* Start the process from the command line */
|
/* Start the process from the command line */
|
||||||
DPRINT1("Starting '%s'...\n", AppName);
|
DPRINT1("Starting '%s'...\n", AppName);
|
||||||
if (!DosCreateProcess(AppName, 0))
|
if (DosLoadExecutable(DOS_LOAD_AND_EXECUTE,
|
||||||
|
AppName,
|
||||||
|
CmdLine,
|
||||||
|
Env,
|
||||||
|
NULL,
|
||||||
|
NULL) != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
DisplayMessage(L"Could not start '%S'", AppName);
|
DisplayMessage(L"Could not start '%S'", AppName);
|
||||||
break;
|
break;
|
||||||
|
@ -430,17 +438,20 @@ DWORD WINAPI CommandThreadProc(LPVOID Parameter)
|
||||||
INT wmain(INT argc, WCHAR *argv[])
|
INT wmain(INT argc, WCHAR *argv[])
|
||||||
{
|
{
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
|
CHAR ApplicationName[MAX_PATH];
|
||||||
CHAR CommandLine[DOS_CMDLINE_LENGTH];
|
CHAR CommandLine[DOS_CMDLINE_LENGTH];
|
||||||
|
|
||||||
if (argc == 2 && argv[1] != NULL)
|
if (argc >= 2)
|
||||||
{
|
{
|
||||||
WideCharToMultiByte(CP_ACP, 0, argv[1], -1, CommandLine, sizeof(CommandLine), NULL, NULL);
|
WideCharToMultiByte(CP_ACP, 0, argv[1], -1, ApplicationName, sizeof(ApplicationName), NULL, NULL);
|
||||||
|
|
||||||
|
if (argc >= 3) WideCharToMultiByte(CP_ACP, 0, argv[2], -1, CommandLine, sizeof(CommandLine), NULL, NULL);
|
||||||
|
else strcpy(CommandLine, "");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wprintf(L"\nReactOS Virtual DOS Machine\n\n"
|
wprintf(L"\nReactOS Virtual DOS Machine\n\n"
|
||||||
L"Usage: NTVDM <executable>\n");
|
L"Usage: NTVDM <executable> [<parameters>]\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,9 +507,14 @@ INT wmain(INT argc, WCHAR *argv[])
|
||||||
|
|
||||||
/* Start the process from the command line */
|
/* Start the process from the command line */
|
||||||
DPRINT1("Starting '%s'...\n", CommandLine);
|
DPRINT1("Starting '%s'...\n", CommandLine);
|
||||||
if (!DosCreateProcess(CommandLine, 0))
|
if (DosLoadExecutable(DOS_LOAD_AND_EXECUTE,
|
||||||
|
ApplicationName,
|
||||||
|
CommandLine,
|
||||||
|
GetEnvironmentStrings(),
|
||||||
|
NULL,
|
||||||
|
NULL) != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
DisplayMessage(L"Could not start '%S'", CommandLine);
|
DisplayMessage(L"Could not start '%S'", ApplicationName);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue