diff --git a/reactos/dll/win32/kernel32/client/vdm.c b/reactos/dll/win32/kernel32/client/vdm.c index e6fa9c3a04b..ca683838b76 100644 --- a/reactos/dll/win32/kernel32/client/vdm.c +++ b/reactos/dll/win32/kernel32/client/vdm.c @@ -93,26 +93,25 @@ BaseCheckVDM(IN ULONG BinaryType, STARTUPINFOA AnsiStartupInfo; ULONG NumStrings = 5; - if (CurrentDirectory == NULL) + /* Parameters validation */ + if (ApplicationName == NULL || CommandLine == NULL) { - /* Allocate memory for the current directory path */ - Length = GetCurrentDirectoryW(0, NULL); - CurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - Length * sizeof(WCHAR)); - if (CurrentDir == NULL) - { - Status = STATUS_NO_MEMORY; - goto Cleanup; - } - - /* Get the current directory */ - GetCurrentDirectoryW(Length, CurrentDir); - CurrentDirectory = CurrentDir; + 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(), @@ -125,7 +124,7 @@ BaseCheckVDM(IN ULONG BinaryType, } /* Get the short application name */ - if (!GetShortPathNameW(ApplicationName, ShortAppName, Length)) + if (GetShortPathNameW(ApplicationName, ShortAppName, Length) == 0) { /* Try to determine which error occurred */ switch (GetLastError()) @@ -151,6 +150,83 @@ BaseCheckVDM(IN ULONG BinaryType, 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 */ + Length = GetCurrentDirectoryW(0, NULL); + CurrentDir = (PWCHAR)RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + Length * sizeof(WCHAR)); + if (CurrentDir == NULL) + { + Status = STATUS_NO_MEMORY; + goto Cleanup; + } + + /* Get the current directory */ + GetCurrentDirectoryW(Length, CurrentDir); + CurrentDirectory = CurrentDir; + } + /* Calculate the size of the short current directory path */ Length = GetShortPathNameW(CurrentDirectory, NULL, 0); @@ -214,7 +290,9 @@ BaseCheckVDM(IN ULONG BinaryType, } /* 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 @@ BaseCheckVDM(IN ULONG BinaryType, 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,13 +500,13 @@ Cleanup: /* Free the capture buffer */ CsrFreeCaptureBuffer(CaptureBuffer); - /* Free the short paths */ - if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName); + /* Free the current directory, if it was allocated here, and its short path */ if (ShortCurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortCurrentDir); - - /* Free the current directory, if it was allocated here */ if (CurrentDir) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDir); + /* Free the short app name */ + if (ShortAppName) RtlFreeHeap(RtlGetProcessHeap(), 0, ShortAppName); + return Status; }