Author: hbelusca
Date: Sun May 18 22:10:45 2014
New Revision: 63361
URL:
http://svn.reactos.org/svn/reactos?rev=63361&view=rev
Log:
[KERNEL32]
Usually the command line is made of the application name and its parameters. When
launching a DOS program, BaseCheckVDM builds suitable ApplicationName and CommandLine
strings "DOS-compatible". ApplicationName is left-trimmed for whitespace and
then converted to short-path format, and CommandLine sees the application name part (its
first token) removed. We didn't do it before, we do it now. Care is taken when quotes
are present in ApplicationName. Finally DOS command lines usually receive a newline
character, so we also add it there. This is how behave Windows: just put our ntvdm in
Windows, and observe what it receives...
Modified:
trunk/reactos/dll/win32/kernel32/client/vdm.c
Modified: trunk/reactos/dll/win32/kernel32/client/vdm.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/vdm.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/vdm.c [iso-8859-1] Sun May 18 22:10:45 2014
@@ -93,6 +93,122 @@
STARTUPINFOA AnsiStartupInfo;
ULONG NumStrings = 5;
+ /* Parameters validation */
+ if (ApplicationName == NULL || CommandLine == NULL)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ DPRINT1("Before: ApplicationName = '%S' ; CommandLine =
'%S'\n", ApplicationName, CommandLine);
+
+ /* Trim leading whitespace from ApplicationName */
+ while (*ApplicationName == L' ' || *ApplicationName == L'\t')
+ ++ApplicationName;
+
+ /* Calculate the size of the short application name */
+ Length = GetShortPathNameW(ApplicationName, NULL, 0);
+ if (Length == 0)
+ {
+ Status = STATUS_OBJECT_PATH_INVALID;
+ goto Cleanup;
+ }
+
+ /* Allocate memory for the short application name */
+ ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ Length * sizeof(WCHAR));
+ if (!ShortAppName)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ /* Get the short application name */
+ if (GetShortPathNameW(ApplicationName, ShortAppName, Length) == 0)
+ {
+ /* Try to determine which error occurred */
+ switch (GetLastError())
+ {
+ case ERROR_NOT_ENOUGH_MEMORY:
+ {
+ Status = STATUS_NO_MEMORY;
+ break;
+ }
+
+ case ERROR_INVALID_PARAMETER:
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ default:
+ {
+ Status = STATUS_OBJECT_PATH_INVALID;
+ }
+ }
+
+ goto Cleanup;
+ }
+
+ /* Trim leading whitespace from CommandLine */
+ while (*CommandLine == L' ' || *CommandLine == L'\t')
+ ++CommandLine;
+
+ /*
+ * CommandLine is usually formatted as: 'ApplicationName param0 ...'.
+ * So we want to strip the first token (ApplicationName) from it.
+ * Two cases are in fact possible:
+ * - either the first token is indeed ApplicationName, so we just skip it;
+ * - or the first token is not exactly ApplicationName, because it happened
+ * that somebody else already preprocessed CommandLine. Therefore we
+ * suppose that the first token corresponds to an application name and
+ * we skip it. Care should be taken when quotes are present in this token.
+ */
+
+ if (*CommandLine)
+ {
+ /* The first part of CommandLine should be the ApplicationName... */
+ Length = wcslen(ApplicationName);
+ if (Length <= wcslen(CommandLine) &&
+ _wcsnicmp(ApplicationName, CommandLine, Length) == 0)
+ {
+ /* Skip it */
+ CommandLine += Length;
+ }
+ /*
+ * ... but it is not, however we still have a token. We suppose that
+ * it corresponds to some sort of application name, so we skip it too.
+ */
+ else
+ {
+ /* Get rid of the first token. We stop when we see whitespace. */
+ while (*CommandLine && !(*CommandLine == L' ' || *CommandLine
== L'\t'))
+ {
+ if (*CommandLine == L'\"')
+ {
+ /* We enter a quoted part, skip it */
+ ++CommandLine;
+ while (*CommandLine && *CommandLine++ != L'\"')
;
+ }
+ else
+ {
+ /* Go to the next character */
+ ++CommandLine;
+ }
+ }
+ }
+ }
+
+ /*
+ * Trim remaining whitespace from CommandLine that may be
+ * present between the application name and the parameters.
+ */
+ while (*CommandLine == L' ' || *CommandLine == L'\t')
+ ++CommandLine;
+
+ DPRINT1("After: ApplicationName = '%S' ; CommandLine =
'%S'\n", ApplicationName, CommandLine);
+
+ /* Get the current directory */
if (CurrentDirectory == NULL)
{
/* Allocate memory for the current directory path */
@@ -109,46 +225,6 @@
/* Get the current directory */
GetCurrentDirectoryW(Length, CurrentDir);
CurrentDirectory = CurrentDir;
- }
-
- /* Calculate the size of the short application name */
- Length = GetShortPathNameW(ApplicationName, NULL, 0);
-
- /* Allocate memory for the short application name */
- ShortAppName = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
- HEAP_ZERO_MEMORY,
- Length * sizeof(WCHAR));
- if (!ShortAppName)
- {
- Status = STATUS_NO_MEMORY;
- goto Cleanup;
- }
-
- /* Get the short application name */
- if (!GetShortPathNameW(ApplicationName, ShortAppName, Length))
- {
- /* Try to determine which error occurred */
- switch (GetLastError())
- {
- case ERROR_NOT_ENOUGH_MEMORY:
- {
- Status = STATUS_NO_MEMORY;
- break;
- }
-
- case ERROR_INVALID_PARAMETER:
- {
- Status = STATUS_INVALID_PARAMETER;
- break;
- }
-
- default:
- {
- Status = STATUS_OBJECT_PATH_INVALID;
- }
- }
-
- goto Cleanup;
}
/* Calculate the size of the short current directory path */
@@ -214,7 +290,9 @@
}
/* Allocate memory for the ANSI strings */
- AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
CheckVdm->CmdLen);
+
+ /* For the command line we need to add two characters needed for newline
'\r\n' */
+ AnsiCmdLine = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
CheckVdm->CmdLen + 2);
AnsiAppName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
CheckVdm->AppLen);
AnsiCurDirectory = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
CheckVdm->CurDirectoryLen);
if (StartupInfo->lpDesktop) AnsiDesktop =
(PCHAR)RtlAllocateHeap(RtlGetProcessHeap(),
@@ -247,6 +325,11 @@
CheckVdm->CmdLen,
NULL,
NULL);
+ /* Add a needed newline '\r\n' */
+ CheckVdm->CmdLen--; // FIXME....
+ AnsiCmdLine[CheckVdm->CmdLen ] = '\r';
+ AnsiCmdLine[CheckVdm->CmdLen + 1] = '\n';
+ CheckVdm->CmdLen += 2;
/* Convert the short application name into an ANSI string */
WideCharToMultiByte(CP_ACP,
@@ -417,12 +500,12 @@
/* Free the capture buffer */
CsrFreeCaptureBuffer(CaptureBuffer);
- /* Free the short paths */
+ /* Free the current directory, if it was allocated here, and its short path */
+ if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
+ if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
+
+ /* Free the short app name */
if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName);
- if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir);
-
- /* Free the current directory, if it was allocated here */
- if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir);
return Status;
}