Author: hbelusca
Date: Sat May 2 01:23:27 2015
New Revision: 67505
URL:
http://svn.reactos.org/svn/reactos?rev=67505&view=rev
Log:
[NTVDM]
- Fix command-line handling.
- Disable a hack introduced in r65012 for testing purposes.
Modified:
trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c
trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dem.c [iso-8859-1] Sat May 2 01:23:27 2015
@@ -116,29 +116,33 @@
{
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] = "";
+ CHAR CmdLine[sizeof("cmd.exe /c ") + DOS_CMDLINE_LENGTH + 1] =
"";
+ LPSTR CmdLinePtr;
+ ULONG CmdLineLen;
STARTUPINFOA StartupInfo;
PROCESS_INFORMATION ProcessInformation;
- /* NULL-terminate the command line by removing the return carriage character
*/
- while (*CmdPtr && *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);
+ CmdLinePtr = CmdLine;
+ strcpy(CmdLinePtr, "cmd.exe /c ");
+ CmdLinePtr += strlen(CmdLinePtr);
+
+ /* Build a Win32-compatible command-line */
+ CmdLineLen = min(strlen(Command), sizeof(CmdLine) - strlen(CmdLinePtr) - 1);
+ RtlCopyMemory(CmdLinePtr, Command, CmdLineLen);
+ CmdLinePtr[CmdLineLen] = '\0';
+
+ /* Remove any trailing return carriage character and NULL-terminate the
command line */
+ while (*CmdLinePtr && *CmdLinePtr != '\r' &&
*CmdLinePtr != '\n') CmdLinePtr++;
+ *CmdLinePtr = '\0';
+
+ DPRINT1("CMD Run Command '%s' ('%s')\n", Command,
CmdLine);
RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
RtlZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
@@ -148,7 +152,7 @@
VidBiosDetachFromConsole();
Result = CreateProcessA(NULL,
- CommandLine,
+ CmdLine,
NULL,
NULL,
TRUE,
@@ -159,7 +163,7 @@
&ProcessInformation);
if (Result)
{
- DPRINT1("Command '%s' launched successfully\n",
Command);
+ DPRINT1("Command '%s' ('%s') launched
successfully\n", Command, CmdLine);
/* Wait for process termination */
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
@@ -173,7 +177,7 @@
}
else
{
- DPRINT1("Failed when launched command '%s'\n");
+ DPRINT1("Failed when launched command '%s'
('%s')\n", Command, CmdLine);
dwExitCode = GetLastError();
}
@@ -210,7 +214,7 @@
PVOID Env = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
UNREFERENCED_PARAMETER(Parameter);
- ASSERT(Env != NULL);
+ ASSERT(Env);
do
{
@@ -253,7 +257,11 @@
}
/* Start the process from the command line */
- DPRINT1("Starting '%s' ('%s')...\n", AppName,
CmdLine);
+ DPRINT1("Starting '%s' ('%.*s')...\n",
+ AppName,
+ CommandInfo.CmdLen >= 2 ? CommandInfo.CmdLen - 2 /* Display the
command line without the terminating 0d 0a */
+ : CommandInfo.CmdLen
+ CmdLine);
Result = DosStartProcess(AppName, CmdLine, Env);
if (Result != ERROR_SUCCESS)
{
@@ -467,8 +475,7 @@
/* Start the process from the command line */
DPRINT1("Starting '%s' ('%s')...\n", ApplicationName,
CommandLine);
- Result = DosStartProcess(ApplicationName,
- CommandLine,
+ Result = DosStartProcess(ApplicationName, CommandLine,
SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0));
if (Result != ERROR_SUCCESS)
{
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c [iso-8859-1] Sat May 2
01:23:27 2015
@@ -160,59 +160,6 @@
}
/* PUBLIC FUNCTIONS ***********************************************************/
-
-VOID DosInitializePsp(WORD PspSegment,
- LPCSTR CommandLine,
- WORD ProgramSize,
- WORD Environment,
- DWORD ReturnAddress)
-{
- PDOS_PSP PspBlock = SEGMENT_TO_PSP(PspSegment);
- LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
-
- RtlZeroMemory(PspBlock, sizeof(*PspBlock));
-
- /* Set the exit interrupt */
- PspBlock->Exit[0] = 0xCD; // int 0x20
- PspBlock->Exit[1] = 0x20;
-
- /* Set the number of the last paragraph */
- PspBlock->LastParagraph = PspSegment + ProgramSize - 1;
-
- /* Save the interrupt vectors */
- PspBlock->TerminateAddress = ReturnAddress;
- PspBlock->BreakAddress = IntVecTable[0x23];
- PspBlock->CriticalAddress = IntVecTable[0x24];
-
- /* Set the parent PSP */
- PspBlock->ParentPsp = CurrentPsp;
-
- /* Copy the parent handle table */
- DosCopyHandleTable(PspBlock->HandleTable);
-
- /* Set the environment block */
- PspBlock->EnvBlock = Environment;
-
- /* Set the handle table pointers to the internal handle table */
- PspBlock->HandleTableSize = 20;
- PspBlock->HandleTablePtr = MAKELONG(0x18, PspSegment);
-
- /* Set the DOS version */
- PspBlock->DosVersion = DOS_VERSION;
-
- /* Set the far call opcodes */
- PspBlock->FarCall[0] = 0xCD; // int 0x21
- PspBlock->FarCall[1] = 0x21;
- PspBlock->FarCall[2] = 0xCB; // retf
-
- if (CommandLine)
- {
- /* Set the command line */
- PspBlock->CommandLineSize = (BYTE)min(strlen(CommandLine), DOS_CMDLINE_LENGTH
- 1);
- RtlCopyMemory(PspBlock->CommandLine, CommandLine,
PspBlock->CommandLineSize);
- PspBlock->CommandLine[PspBlock->CommandLineSize] = '\r';
- }
-}
VOID WINAPI DosInt20h(LPWORD Stack)
{
@@ -1388,30 +1335,45 @@
/* Execute */
case 0x4B:
{
- DOS_EXEC_TYPE LoadType = (DOS_EXEC_TYPE)getAL();
+ BYTE OrgAL = getAL();
LPSTR ProgramName = SEG_OFF_TO_PTR(getDS(), getDX());
PDOS_EXEC_PARAM_BLOCK ParamBlock = SEG_OFF_TO_PTR(getES(), getBX());
DWORD ReturnAddress = MAKELONG(Stack[STACK_IP], Stack[STACK_CS]);
WORD ErrorCode;
-
+
+ if (OrgAL <= DOS_LOAD_OVERLAY)
+ {
+ DOS_EXEC_TYPE LoadType = (DOS_EXEC_TYPE)OrgAL;
+
#ifndef STANDALONE
- if (LoadType == DOS_LOAD_AND_EXECUTE)
- {
- /* Create a new process */
- ErrorCode = DosCreateProcess(ProgramName, ParamBlock, ReturnAddress);
- }
- else
- {
-#else
- {
+ if (LoadType == DOS_LOAD_AND_EXECUTE)
+ {
+ /* Create a new process */
+ ErrorCode = DosCreateProcess(ProgramName,
+ ParamBlock,
+ ReturnAddress);
+ }
+ else
#endif
- /* Just load an executable */
- ErrorCode = DosLoadExecutable(LoadType,
- ProgramName,
- ParamBlock,
- NULL,
- NULL,
- ReturnAddress);
+ {
+ /* Just load an executable */
+ ErrorCode = DosLoadExecutable(LoadType,
+ ProgramName,
+ ParamBlock,
+ NULL,
+ NULL,
+ ReturnAddress);
+ }
+ }
+ else if (OrgAL == 0x05)
+ {
+ //
http://www.ctyme.com/intr/rb-2942.htm
+ DPRINT1("Set execution state is UNIMPLEMENTED\n");
+ ErrorCode = ERROR_CALL_NOT_IMPLEMENTED;
+ }
+ else
+ {
+ ErrorCode = ERROR_INVALID_FUNCTION;
}
if (ErrorCode == ERROR_SUCCESS)
Modified: trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/dos/…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/process.c [iso-8859-1] Sat May 2
01:23:27 2015
@@ -37,10 +37,13 @@
{
PDOS_PSP PspBlock = SEGMENT_TO_PSP(Segment);
- /* Set the command line */
- PspBlock->CommandLineSize = (BYTE)min(strlen(CommandLine), DOS_CMDLINE_LENGTH -
1);
- RtlCopyMemory(PspBlock->CommandLine, CommandLine, PspBlock->CommandLineSize);
- PspBlock->CommandLine[PspBlock->CommandLineSize] = '\r';
+ /*
+ * Copy the command line block.
+ * Format of the CommandLine parameter: 1 byte for size; 127 bytes for contents.
+ */
+ PspBlock->CommandLineSize = min(*(PBYTE)CommandLine, DOS_CMDLINE_LENGTH);
+ CommandLine++;
+ RtlCopyMemory(PspBlock->CommandLine, CommandLine, DOS_CMDLINE_LENGTH);
}
static WORD DosCopyEnvironmentBlock(LPCSTR Environment OPTIONAL,
@@ -115,8 +118,8 @@
VOID DosClonePsp(WORD DestSegment, WORD SourceSegment)
{
- PDOS_PSP DestPsp = SEGMENT_TO_PSP(DestSegment);
- PDOS_PSP SourcePsp = SEGMENT_TO_PSP(SourceSegment);
+ PDOS_PSP DestPsp = SEGMENT_TO_PSP(DestSegment);
+ PDOS_PSP SourcePsp = SEGMENT_TO_PSP(SourceSegment);
LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
/* Literally copy the PSP first */
@@ -132,7 +135,7 @@
/* Set the handle table pointers to the internal handle table */
DestPsp->HandleTableSize = DEFAULT_JFT_SIZE;
- DestPsp->HandleTablePtr = MAKELONG(0x18, DestSegment);
+ DestPsp->HandleTablePtr = MAKELONG(0x18, DestSegment);
/* Copy the parent handle table without referencing the SFT */
RtlCopyMemory(FAR_POINTER(DestPsp->HandleTablePtr),
@@ -142,7 +145,7 @@
VOID DosCreatePsp(WORD Segment, WORD ProgramSize)
{
- PDOS_PSP PspBlock = SEGMENT_TO_PSP(Segment);
+ PDOS_PSP PspBlock = SEGMENT_TO_PSP(Segment);
LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress);
RtlZeroMemory(PspBlock, sizeof(*PspBlock));
@@ -170,7 +173,7 @@
/* Set the handle table pointers to the internal handle table */
PspBlock->HandleTableSize = DEFAULT_JFT_SIZE;
- PspBlock->HandleTablePtr = MAKELONG(0x18, Segment);
+ PspBlock->HandleTablePtr = MAKELONG(0x18, Segment);
/* Set the DOS version */
PspBlock->DosVersion = DOS_VERSION;
@@ -203,6 +206,9 @@
WORD MaxAllocSize;
DWORD i, FileSize;
+ /* Buffer for command line conversion: 1 byte for size; 127 bytes for contents */
+ CHAR CmdLineBuffer[1 + DOS_CMDLINE_LENGTH];
+
DPRINT1("DosLoadExecutable(%d, %s, 0x%08X, 0x%08X)\n",
LoadType,
ExecutablePath,
@@ -249,24 +255,72 @@
if (LoadType != DOS_LOAD_OVERLAY)
{
- LPSTR CmdLinePtr;
-
- if (CommandLine == NULL)
- {
- /* Get the command line from the parameter block */
+ /* If an optional Win32 command line is given... */
+ if (CommandLine)
+ {
+ /* ... convert it into DOS format */
+ BYTE CmdLineLen;
+
+ PBYTE CmdLineSize = (PBYTE)CmdLineBuffer;
+ LPSTR CmdLineStart = CmdLineBuffer + 1;
+ LPSTR CmdLinePtr = CmdLineStart;
+
+ // For debugging purposes
+ RtlFillMemory(CmdLineBuffer, sizeof(CmdLineBuffer), 0xFF);
+
+ /*
+ * Set the command line: it is either an empty command line or has
+ * the format: " foo bar ..." (with at least one leading
whitespace),
+ * and is then always followed by '\r' (and optionally by
'\n').
+ */
+ CmdLineLen = (BYTE)strlen(CommandLine);
+ *CmdLineSize = 0;
+
+ /*
+ * Add the leading space if the command line is not empty
+ * and doesn't already start with some whitespace...
+ */
+ if (*CommandLine && *CommandLine != '\r' &&
*CommandLine != '\n' &&
+ *CommandLine != ' ' && *CommandLine != '\t')
+ {
+ (*CmdLineSize)++;
+ *CmdLinePtr++ = ' ';
+ }
+
+ /* Compute the number of characters we need to copy from the original command
line */
+ CmdLineLen = min(CmdLineLen, DOS_CMDLINE_LENGTH - *CmdLineSize);
+
+ /* The trailing '\r' or '\n' do not count in the PSP command
line size parameter */
+ while (CmdLineLen && (CommandLine[CmdLineLen - 1] == '\r' ||
CommandLine[CmdLineLen - 1] == '\n'))
+ {
+ CmdLineLen--;
+ }
+
+ /* Finally, set everything up */
+ *CmdLineSize += CmdLineLen;
+ RtlCopyMemory(CmdLinePtr, CommandLine, CmdLineLen);
+ CmdLineStart[*CmdLineSize] = '\r';
+
+ /* Finally make the pointer point to the static buffer */
+ CommandLine = CmdLineBuffer;
+ }
+ else
+ {
+ /*
+ * ... otherwise, get the one from the parameter block.
+ * Format of the command line: 1 byte for size; 127 bytes for contents.
+ */
+ ASSERT(Parameters);
CommandLine = (LPCSTR)FAR_POINTER(Parameters->CommandLine);
}
+ /* If no optional environment is given... */
if (Environment == NULL)
{
- /* Get the environment from the parameter block */
+ /* ... get the one from the parameter block */
+ ASSERT(Parameters);
Environment = (LPCSTR)SEG_OFF_TO_PTR(Parameters->Environment, 0);
}
-
- /* NULL-terminate the command line by removing the return carriage character */
- CmdLinePtr = (LPSTR)CommandLine;
- while (*CmdLinePtr && *CmdLinePtr != '\r') CmdLinePtr++;
- *CmdLinePtr = '\0';
/* Copy the environment block to DOS memory */
EnvBlock = DosCopyEnvironmentBlock(Environment, ExecutablePath);
@@ -352,6 +406,7 @@
}
else
{
+ ASSERT(Parameters);
LoadSegment = Parameters->Overlay.Segment;
RelocFactor = Parameters->Overlay.RelocationFactor;
}
@@ -391,8 +446,9 @@
}
else if (LoadType == DOS_LOAD_ONLY)
{
+ ASSERT(Parameters);
Parameters->StackLocation = MAKELONG(Header->e_sp, LoadSegment +
Header->e_ss);
- Parameters->EntryPoint = MAKELONG(Header->e_ip, LoadSegment +
Header->e_cs);
+ Parameters->EntryPoint = MAKELONG(Header->e_ip, LoadSegment +
Header->e_cs);
}
}
else
@@ -436,9 +492,11 @@
}
else
{
+ ASSERT(Parameters);
LoadSegment = Parameters->Overlay.Segment;
}
+ /* Copy the program to the code segment */
RtlCopyMemory(SEG_OFF_TO_PTR(LoadSegment, 0),
Address,
FileSize);
@@ -465,8 +523,9 @@
}
else if (LoadType == DOS_LOAD_ONLY)
{
+ ASSERT(Parameters);
Parameters->StackLocation = MAKELONG(0xFFFE, Segment);
- Parameters->EntryPoint = MAKELONG(0x0100, Segment);
+ Parameters->EntryPoint = MAKELONG(0x0100, Segment);
}
}
@@ -513,8 +572,9 @@
// HACK: Simulate a ENTER key release scancode on the PS/2 port because
// some apps expect to read a key release scancode (> 0x80) when they
// are started.
- IOWriteB(PS2_CONTROL_PORT, 0xD2); // Next write is for the first PS/2 port
- IOWriteB(PS2_DATA_PORT, 0x80 | 0x1C); // ENTER key release
+ // (hbelusca 2 May 2015: I'm not sure it's really useful. See r65012)
+ // IOWriteB(PS2_CONTROL_PORT, 0xD2); // Next write is for the first PS/2 port
+ // IOWriteB(PS2_DATA_PORT, 0x80 | 0x1C); // ENTER key release
/* Start simulation */
SetEvent(VdmTaskEvent);
@@ -537,18 +597,24 @@
DWORD BinaryType;
LPVOID Environment = NULL;
VDM_COMMAND_INFO CommandInfo;
- CHAR CmdLine[MAX_PATH];
+ CHAR CmdLine[MAX_PATH]; // DOS_CMDLINE_LENGTH + 1
CHAR AppName[MAX_PATH];
CHAR PifFile[MAX_PATH];
CHAR Desktop[MAX_PATH];
CHAR Title[MAX_PATH];
+ LPSTR CmdLinePtr;
+ ULONG CmdLineSize;
ULONG EnvSize = 256;
- PVOID Env = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
+ PVOID Env;
STARTUPINFOA StartupInfo;
PROCESS_INFORMATION ProcessInfo;
/* Get the binary type */
if (!GetBinaryTypeA(ProgramName, &BinaryType)) return GetLastError();
+
+ /* Initialize Win32-VDM environment */
+ Env = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, EnvSize);
+ if (Env == NULL) return GetLastError();
/* Did the caller specify an environment segment? */
if (Parameters->Environment)
@@ -561,9 +627,25 @@
RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
+ /*
+ * Convert the DOS command line to Win32-compatible format.
+ * Format of the DOS command line: 1 byte for size; 127 bytes for contents.
+ */
+ CmdLineSize = min(*(PBYTE)FAR_POINTER(Parameters->CommandLine),
DOS_CMDLINE_LENGTH);
+ RtlCopyMemory(CmdLine,
+ FAR_POINTER(Parameters->CommandLine) + 1,
+ CmdLineSize);
+ /* NULL-terminate it */
+ CmdLine[CmdLineSize] = '\0';
+
+ /* Remove any trailing return carriage character and NULL-terminate the command line
*/
+ CmdLinePtr = CmdLine;
+ while (*CmdLinePtr && *CmdLinePtr != '\r' && *CmdLinePtr !=
'\n') CmdLinePtr++;
+ *CmdLinePtr = '\0';
+
/* Create the process */
if (!CreateProcessA(ProgramName,
- FAR_POINTER(Parameters->CommandLine),
+ CmdLine,
NULL,
NULL,
FALSE,
@@ -573,6 +655,7 @@
&StartupInfo,
&ProcessInfo))
{
+ RtlFreeHeap(RtlGetProcessHeap(), 0, Env);
return GetLastError();
}