Author: ion Date: Sun Dec 4 16:34:58 2011 New Revision: 54587
URL: http://svn.reactos.org/svn/reactos?rev=54587&view=rev Log: [KERNEL32]: Fix many bugs in BasepInitailizeEnvironment (and rename to BasePushProcessParameters): - Depending on how big the full path is, either the application path or the full path should be used. Size the buffers correctly, too. - If the caller did not specify a window title, should use the app path as title. - Clear the current directory handle if InheritHandles is false. - Correctly handle CREATE_NEW_PROCESS_GROUP and CREATE_NEW_CONSOLE. - Check the failure codes of many APIs that we just assumed returned success. - STARTF_USEHOTKEY | STARTF_SHELLPRIVATE should be checked when inheriting console handles. - Handle 1MB and 16MB reservation requests. - Bugs remain: ImageSubsystem not written, and failure will leak. To be fixed later.
Modified: trunk/reactos/dll/win32/kernel32/client/proc.c
Modified: trunk/reactos/dll/win32/kernel32/client/proc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/p... ============================================================================== --- trunk/reactos/dll/win32/kernel32/client/proc.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/kernel32/client/proc.c [iso-8859-1] Sun Dec 4 16:34:58 2011 @@ -16,13 +16,13 @@ #define NDEBUG #include <debug.h>
- typedef INT (WINAPI *MessageBoxW_Proc) (HWND, LPCWSTR, LPCWSTR, UINT);
/* GLOBALS *******************************************************************/
static UNICODE_STRING CommandLineStringW; static ANSI_STRING CommandLineStringA; +UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH");
static BOOL bCommandLineInitialized = FALSE;
@@ -33,7 +33,6 @@ VOID WINAPI RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
-UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH"); PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry;
#define CMD_STRING L"cmd /c " @@ -219,13 +218,13 @@ { return NULL; } - + Status = BasepNotifyCsrOfThread(hThread, ClientId); if (!NT_SUCCESS(Status)) { ASSERT(FALSE); } - + /* Success */ return hThread; } @@ -580,15 +579,17 @@ DPRINT("BasepCopyHandles %p %p, %d\n", Params, PebParams, InheritHandles);
/* Copy the handle if we are inheriting or if it's a console handle */ - if (InheritHandles || IsConsoleHandle(PebParams->StandardInput)) + if ((InheritHandles) || (IsConsoleHandle(PebParams->StandardInput))) { Params->StandardInput = PebParams->StandardInput; } - if (InheritHandles || IsConsoleHandle(PebParams->StandardOutput)) + + if ((InheritHandles) || (IsConsoleHandle(PebParams->StandardOutput))) { Params->StandardOutput = PebParams->StandardOutput; } - if (InheritHandles || IsConsoleHandle(PebParams->StandardError)) + + if ((InheritHandles) || (IsConsoleHandle(PebParams->StandardError))) { Params->StandardError = PebParams->StandardError; } @@ -596,18 +597,18 @@
NTSTATUS WINAPI -BasepInitializeEnvironment(HANDLE ProcessHandle, - PPEB Peb, - LPWSTR ApplicationPathName, - LPWSTR lpCurrentDirectory, - LPWSTR lpCommandLine, - LPVOID lpEnvironment, - SIZE_T EnvSize, - LPSTARTUPINFOW StartupInfo, - DWORD CreationFlags, - BOOL InheritHandles) -{ - WCHAR FullPath[MAX_PATH]; +BasePushProcessParameters(IN HANDLE ProcessHandle, + IN PPEB Peb, + IN LPWSTR ApplicationPathName, + IN LPWSTR lpCurrentDirectory, + IN LPWSTR lpCommandLine, + IN LPVOID lpEnvironment, + IN SIZE_T EnvSize, + IN LPSTARTUPINFOW StartupInfo, + IN DWORD CreationFlags, + IN BOOL InheritHandles) +{ + WCHAR FullPath[MAX_PATH + 5]; LPWSTR Remaining; LPWSTR DllPathString; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; @@ -620,23 +621,34 @@ UNICODE_STRING Desktop, Shell, Runtime, Title; PPEB OurPeb = NtCurrentPeb(); LPVOID Environment = lpEnvironment; - - DPRINT("BasepInitializeEnvironment\n"); + DPRINT("BasePushProcessParameters\n");
/* Get the full path name */ - GetFullPathNameW(ApplicationPathName, - MAX_PATH, - FullPath, - &Remaining); - DPRINT("ApplicationPathName: %S, FullPath: %S\n", ApplicationPathName, - FullPath); - - /* Get the DLL Path */ - DllPathString = BasepGetDllPath(FullPath, Environment); + Size = GetFullPathNameW(ApplicationPathName, + MAX_PATH + 4, + FullPath, + &Remaining); + if ((Size) && (Size <= (MAX_PATH + 4))) + { + /* Get the DLL Path */ + DllPathString = BasepGetDllPath(ApplicationPathName, Environment); + + /* Initialize Strings */ + RtlInitUnicodeString(&DllPath, DllPathString); + RtlInitUnicodeString(&ImageName, ApplicationPathName); + } + else + { + /* Get the DLL Path */ + DllPathString = BasepGetDllPath(FullPath, Environment); + + /* Initialize Strings */ + RtlInitUnicodeString(&DllPath, DllPathString); + RtlInitUnicodeString(&ImageName, FullPath); + } + DPRINT("DllPath: %wZ, ImageName: %wZ\n", DllPath, ImageName);
/* Initialize Strings */ - RtlInitUnicodeString(&DllPath, DllPathString); - RtlInitUnicodeString(&ImageName, FullPath); RtlInitUnicodeString(&CommandLine, lpCommandLine); RtlInitUnicodeString(&CurrentDirectory, lpCurrentDirectory);
@@ -663,7 +675,7 @@ } else { - RtlInitUnicodeString(&Title, L""); + RtlInitUnicodeString(&Title, ApplicationPathName); }
/* This one is special because the length can differ */ @@ -685,50 +697,22 @@ &Desktop, &Shell, &Runtime); - if (!NT_SUCCESS(Status)) { DPRINT1("Failed to create process parameters!\n"); return Status; }
- /* Check if we got an environment. If not, use ours */ + /* Clear the current directory handle if not inheriting */ + if (!InheritHandles) ProcessParameters->CurrentDirectory.Handle = NULL; + + /* Save pointer and start lookup */ + Environment = ScanChar = ProcessParameters->Environment; if (Environment) { - /* Save pointer and start lookup */ - Environment = ScanChar = ProcessParameters->Environment; - } - else - { - /* Save pointer and start lookup */ - Environment = ScanChar = OurPeb->ProcessParameters->Environment; - } - - /* Find the environment size */ - if (ScanChar) - { - if (EnvSize && Environment == lpEnvironment) - { - /* its a converted ansi environment, bypass the length calculation */ - EnviroSize = EnvSize; - } - else - { - while (*ScanChar) - { - ScanChar += wcslen(ScanChar) + 1; - } - - /* Calculate the size of the block */ - if (ScanChar == Environment) - { - EnviroSize = 2 * sizeof(WCHAR); - } - else - { - EnviroSize = (ULONG)((ULONG_PTR)ScanChar - (ULONG_PTR)Environment + sizeof(WCHAR)); - } - } + /* Find the environment size */ + while (*ScanChar) ScanChar += wcslen(ScanChar) + 1; + EnviroSize = (ULONG_PTR)ScanChar - (ULONG_PTR)Environment; DPRINT("EnvironmentSize %ld\n", EnviroSize);
/* Allocate and Initialize new Environment Block */ @@ -743,15 +727,20 @@ if (!NT_SUCCESS(Status)) { DPRINT1("Failed to allocate Environment Block\n"); - return(Status); + return Status; }
/* Write the Environment Block */ - ZwWriteVirtualMemory(ProcessHandle, - ProcessParameters->Environment, - Environment, - EnviroSize, - NULL); + Status = ZwWriteVirtualMemory(ProcessHandle, + ProcessParameters->Environment, + Environment, + EnviroSize, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to write Environment Block\n"); + return Status; + } }
/* Write new parameters */ @@ -766,7 +755,8 @@ ProcessParameters->ShowWindowFlags = StartupInfo->wShowWindow;
/* Write the handles only if we have to */ - if (StartupInfo->dwFlags & STARTF_USESTDHANDLES) + if (StartupInfo->dwFlags & + (STARTF_USESTDHANDLES | STARTF_USEHOTKEY | STARTF_SHELLPRIVATE)) { DPRINT("Using Standard Handles\n"); ProcessParameters->StandardInput = StartupInfo->hStdInput; @@ -794,7 +784,7 @@
/* Is the shell trampling on our Handles? */ if (!(StartupInfo->dwFlags & - (STARTF_USESTDHANDLES | STARTF_USEHOTKEY | STARTF_SHELLPRIVATE))) + (STARTF_USESTDHANDLES | STARTF_USEHOTKEY | STARTF_SHELLPRIVATE))) { /* Use handles from PEB, if inheriting or they are console */ DPRINT("Copying handles from parent\n"); @@ -805,9 +795,22 @@ }
/* Also set the Console Flag */ - if (CreationFlags & CREATE_NEW_PROCESS_GROUP) + if ((CreationFlags & CREATE_NEW_PROCESS_GROUP) && + (!(CreationFlags & CREATE_NEW_CONSOLE))) { ProcessParameters->ConsoleFlags = 1; + } + + /* See if the first 1MB should be reserved */ + if ((ULONG_PTR)ApplicationPathName & 1) + { + ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB; + } + + /* See if the first 16MB should be reserved */ + if ((ULONG_PTR)ApplicationPathName & 2) + { + ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_16MB; }
/* Allocate memory for the parameter block */ @@ -821,14 +824,13 @@ if (!NT_SUCCESS(Status)) { DPRINT1("Failed to allocate Parameters Block\n"); - return(Status); + return Status; }
/* Set the allocated size */ ProcessParameters->MaximumLength = Size;
/* Handle some Parameter Flags */ - ProcessParameters->ConsoleFlags = (CreationFlags & CREATE_NEW_PROCESS_GROUP); ProcessParameters->Flags |= (CreationFlags & PROFILE_USER) ? RTL_USER_PROCESS_PARAMETERS_PROFILE_USER : 0; ProcessParameters->Flags |= (CreationFlags & PROFILE_KERNEL) ? @@ -844,6 +846,11 @@ ProcessParameters, ProcessParameters->Length, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to write Parameters Block\n"); + return Status; + }
/* Write the PEB Pointer */ Status = NtWriteVirtualMemory(ProcessHandle, @@ -851,6 +858,14 @@ &RemoteParameters, sizeof(PVOID), NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to write Parameters Block\n"); + return Status; + } + + /* FIXME: Write Peb->ImageSubSystem */ +
/* Cleanup */ RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath.Buffer); @@ -2836,17 +2851,17 @@
/* Create Process Environment */ RemotePeb = ProcessBasicInfo.PebBaseAddress; - Status = BasepInitializeEnvironment(hProcess, - RemotePeb, - (LPWSTR)lpApplicationName, - CurrentDirectory, - (QuotesNeeded || CmdLineIsAppName || Escape) ? - QuotedCmdLine : lpCommandLine, - lpEnvironment, - EnvSize, - &StartupInfo, - dwCreationFlags, - bInheritHandles); + Status = BasePushProcessParameters(hProcess, + RemotePeb, + (LPWSTR)lpApplicationName, + CurrentDirectory, + (QuotesNeeded || CmdLineIsAppName || Escape) ? + QuotedCmdLine : lpCommandLine, + lpEnvironment, + EnvSize, + &StartupInfo, + dwCreationFlags, + bInheritHandles);
/* Cleanup Environment */ if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) @@ -2906,7 +2921,7 @@ BaseSetLastNTError(Status); goto Cleanup; } - + /* Create the first thread */ DPRINT("Creating thread for process (EntryPoint = 0x%p)\n", SectionImageInfo.TransferAddress);