- Final ROSRTL removal patch. The next patch will remove the actual library and code. - Changes: - CreateProcess * Cleanup creation of the initial thread using new utility functions and remove rosrtl * Almost entirely rewrote the function to support features such as: - SxS (locally only, patch will follow), - SFP (SAFER) (locally only, patch will follow), - DllPaths (locally only, patch will follow), - Proper process environment/paramter block creation - Proper console handle management (needs more work in kernel32/csr), - Tokens/CreateProcessAsUser (locally only, patch will follow), - Simpler code for path lookup, and more robust. - Support for "auto-correction" (see Raymond Chen's blog) - 16-bit/NE detection - A variety of creation flags are now properly supported - Added support for an undocumented-yet-known (see comment) shell flag - Alert for flags we don't support yet - Catch invalid flag combinations and other caller errors - Improve and correct path searcing to use documented behaviours - Created a multitude of helper functions to make the code easier to read and allow them to be used for other apis as time goes on.
- BaseProcessStartup * Call NtSetThreadInformation to let the Kernel know of the Thread's Start Address. * Correct prototype of Thread Startup function for this case.
This fixes MANY things, some of which may not be evident, and possibly creates regressions which I have not yet seen but will try to correct. Some of these may be caused by the fact that I've seen code send CreateProcessW incorrect flags. Some things of note: DO NOT send partial names as "lpApplicationName". It's not supposed to work unless you're in the same current directory. Also, do NOT send CREATE_UNICODE_ENVIRONMENT if you don't have a unicode environement, and vice-versa. I've seen lots of code doing mistakes related to this. I hope you appreciate this patch and won't all jump on me for possbile regressions :(. Modified: trunk/reactos/lib/kernel32/process/create.c Modified: trunk/reactos/lib/kernel32/thread/i386/thread.S Modified: trunk/reactos/lib/kernel32/thread/thread.c Modified: trunk/reactos/ntoskrnl/mm/process.c _____
Modified: trunk/reactos/lib/kernel32/process/create.c --- trunk/reactos/lib/kernel32/process/create.c 2005-07-26 00:50:17 UTC (rev 16729) +++ trunk/reactos/lib/kernel32/process/create.c 2005-07-26 04:14:10 UTC (rev 16730) @@ -1,1399 +1,1455 @@
-/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: lib/kernel32/process/create.c * PURPOSE: Process functions - * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) - * UPDATE HISTORY: - * Created 01/11/98 + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * Ariadne ( ariadne@xs4all.nl) */
/* INCLUDES ****************************************************************/
#include <k32.h>
-/* FIXME */ -#include <rosrtl/thread.h> - #define NDEBUG -#include "../include/debug.h" +#include <debug.h>
-/* FUNCTIONS ****************************************************************/ +#define CMD_STRING L"cmd /c "
extern __declspec(noreturn) -VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag); +VOID +CALLBACK +ConsoleControlDispatcher(DWORD CodeAndFlag);
-__declspec(dllimport) -PRTL_BASE_PROCESS_START_ROUTINE RtlBaseProcessStartRoutine; +/* INTERNAL FUNCTIONS *******************************************************/
-typedef NTSTATUS STDCALL (K32_MBSTR_TO_WCSTR) -( - UNICODE_STRING *, - ANSI_STRING *, - BOOLEAN -); - -NTSTATUS STDCALL K32MbStrToWcStr(IN K32_MBSTR_TO_WCSTR * True, - UNICODE_STRING * DestStr, - ANSI_STRING * SourceStr, - BOOLEAN Allocate) +_SEH_FILTER(BaseExceptionFilter) { - if(SourceStr->Buffer == NULL) - { - DestStr->Length = DestStr->MaximumLength = 0; - DestStr->Buffer = NULL; - return STATUS_SUCCESS; - } + EXCEPTION_POINTERS *ExceptionInfo = _SEH_GetExceptionPointers(); + LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
- return True(DestStr, SourceStr, Allocate); + if (GlobalTopLevelExceptionFilter != NULL) + { + _SEH_TRY + { + ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo); + } + _SEH_HANDLE + { + ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo); + } + _SEH_END; + } + + return ExceptionDisposition; }
-VOID STDCALL RtlRosR32AttribsToNativeAttribs(OUT OBJECT_ATTRIBUTES * NativeAttribs, - IN SECURITY_ATTRIBUTES * Ros32Attribs OPTIONAL) +VOID +STDCALL +BaseProcessStartup(PPROCESS_START_ROUTINE lpStartAddress) { - NativeAttribs->Length = sizeof(*NativeAttribs); - NativeAttribs->ObjectName = NULL; - NativeAttribs->RootDirectory = NULL; - NativeAttribs->Attributes = 0; - NativeAttribs->SecurityQualityOfService = NULL; + UINT uExitCode = 0;
+ DPRINT("BaseProcessStartup(..) - setting up exception frame.\n");
- if(Ros32Attribs != NULL && Ros32Attribs->nLength >= sizeof(*Ros32Attribs)) - { - NativeAttribs->SecurityDescriptor = Ros32Attribs->lpSecurityDescriptor; + _SEH_TRY + { + /* Set our Start Address */ + NtSetInformationThread(NtCurrentThread(), + ThreadQuerySetWin32StartAddress, + &lpStartAddress, + sizeof(PPROCESS_START_ROUTINE)); + + /* Call the Start Routine */ + uExitCode = (lpStartAddress)(); + } + _SEH_EXCEPT(BaseExceptionFilter) + { + /* Get the SEH Error */ + uExitCode = _SEH_GetExceptionCode(); + } + _SEH_END;
- if(Ros32Attribs->bInheritHandle) - { - NativeAttribs->Attributes |= OBJ_INHERIT; - } - } - else - { - NativeAttribs->SecurityDescriptor = NULL; - } + /* Exit the Process with our error */ + ExitProcess(uExitCode); }
-VOID STDCALL RtlRosR32AttribsToNativeAttribsNamed(OUT OBJECT_ATTRIBUTES * NativeAttribs, - IN SECURITY_ATTRIBUTES * Ros32Attribs OPTIONAL, - OUT UNICODE_STRING * NativeName OPTIONAL, - IN WCHAR * Ros32Name OPTIONAL, - IN HANDLE Ros32NameRoot OPTIONAL) +/* + * Tells CSR that a new process was created + */ +NTSTATUS +STDCALL +BasepNotifyCsrOfCreation(ULONG dwCreationFlags, + IN HANDLE ProcessId, + IN ULONG SubsystemType, + OUT PHANDLE ConsoleHandle, + OUT PHANDLE InputHandle, + OUT PHANDLE OutputHandle) { - if(!NativeAttribs) return; + ULONG Request = CREATE_PROCESS; + CSR_API_MESSAGE CsrRequest; + NTSTATUS Status; + + DPRINT("BasepNotifyCsrOfCreation\n"); + + /* Some hacks (heck, this whole API is a hack) */ + if (SubsystemType == IMAGE_SUBSYSTEM_WINDOWS_GUI) + { + dwCreationFlags = (dwCreationFlags &~ CREATE_NEW_CONSOLE) | + DETACHED_PROCESS; + } + else if (SubsystemType == IMAGE_SUBSYSTEM_WINDOWS_CUI) + { + dwCreationFlags |= CREATE_NEW_CONSOLE; + } + + /* Fill out the request */ + CsrRequest.Data.CreateProcessRequest.NewProcessId = ProcessId; + CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags; + CsrRequest.Data.CreateProcessRequest.CtrlDispatcher = ConsoleControlDispatcher; + CsrRequest.Data.CreateProcessRequest.InputHandle = 0; + CsrRequest.Data.CreateProcessRequest.OutputHandle = 0; + CsrRequest.Data.CreateProcessRequest.Console = 0; + + /* Call CSR */ + Status = CsrClientCallServer(&CsrRequest, + NULL, + MAKE_CSR_API(Request, CSR_NATIVE), + sizeof(CSR_API_MESSAGE)); + if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status)) + { + DPRINT1("Failed to tell csrss about new process\n"); + return CsrRequest.Status; + } + /* Return Handles */ + *ConsoleHandle = CsrRequest.Data.CreateProcessRequest.Console; + *InputHandle = CsrRequest.Data.CreateProcessRequest.InputHandle; + *OutputHandle = CsrRequest.Data.CreateProcessRequest.OutputHandle; + DPRINT("CSR Created: %lx %lx\n", *InputHandle, *OutputHandle); + + /* REturn Success */ + return STATUS_SUCCESS; +}
- RtlRosR32AttribsToNativeAttribs(NativeAttribs, Ros32Attribs); +/* + * Creates the first Thread in a Proces + */ +HANDLE +STDCALL +BasepCreateFirstThread(HANDLE ProcessHandle, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + PSECTION_IMAGE_INFORMATION SectionImageInfo, + PCLIENT_ID ClientId) +{ + OBJECT_ATTRIBUTES LocalObjectAttributes; + POBJECT_ATTRIBUTES ObjectAttributes; + CONTEXT Context; + INITIAL_TEB InitialTeb; + NTSTATUS Status; + HANDLE hThread; + + DPRINT("BasepCreateFirstThread. hProcess: %lx\n", ProcessHandle);
- if(Ros32Name != NULL && NativeName != NULL) - { - RtlInitUnicodeString(NativeName, Ros32Name); - - NativeAttribs->ObjectName = NativeName; - NativeAttribs->RootDirectory = Ros32NameRoot; - NativeAttribs->Attributes |= OBJ_CASE_INSENSITIVE; - } + /* Create the Thread's Stack */ + BasepCreateStack(ProcessHandle, + SectionImageInfo->MaximumStackSize, + SectionImageInfo->CommittedStackSize, + &InitialTeb); + + /* Create the Thread's Context */ + BasepInitializeContext(&Context, + NtCurrentPeb(), + SectionImageInfo->TransferAddress, + InitialTeb.StackBase, + 0); + + /* Convert the thread attributes */ + ObjectAttributes = BasepConvertObjectAttributes(&LocalObjectAttributes, + lpThreadAttributes, + NULL); + + /* Create the Kernel Thread Object */ + Status = NtCreateThread(&hThread, + THREAD_ALL_ACCESS, + ObjectAttributes, + ProcessHandle, + ClientId, + &Context, + &InitialTeb, + TRUE); + + /* Success */ + return hThread; }
- /* - * @implemented + * Converts ANSI to Unicode Environment */ -BOOL STDCALL CreateProcessA(LPCSTR lpApplicationName, - LPSTR lpCommandLine, - LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - BOOL bInheritHandles, - DWORD dwCreationFlags, - LPVOID lpEnvironment, - LPCSTR lpCurrentDirectory, - LPSTARTUPINFOA lpStartupInfo, - LPPROCESS_INFORMATION lpProcessInformation) -/* - * FUNCTION: The CreateProcess function creates a new process and its - * primary thread. The new process executes the specified executable file - * ARGUMENTS: - * - * lpApplicationName = Pointer to name of executable module - * lpCommandLine = Pointer to command line string - * lpProcessAttributes = Process security attributes - * lpThreadAttributes = Thread security attributes - * bInheritHandles = Handle inheritance flag - * dwCreationFlags = Creation flags - * lpEnvironment = Pointer to new environment block - * lpCurrentDirectory = Pointer to current directory name - * lpStartupInfo = Pointer to startup info - * lpProcessInformation = Pointer to process information - */ +PVOID +STDCALL +BasepConvertUnicodeEnvironment(IN PVOID lpEnvironment) { - UNICODE_STRING wstrApplicationName; - UNICODE_STRING wstrCurrentDirectory; - UNICODE_STRING wstrCommandLine; - UNICODE_STRING wstrReserved; - UNICODE_STRING wstrDesktop; - UNICODE_STRING wstrTitle; - UNICODE_STRING wstrEnvVar; - ANSI_STRING strApplicationName; - ANSI_STRING strCurrentDirectory; - ANSI_STRING strCommandLine; - ANSI_STRING strReserved; - ANSI_STRING strDesktop; - ANSI_STRING strTitle; - BOOL bRetVal; - STARTUPINFOW wsiStartupInfo; + PCHAR pcScan; + SIZE_T EnvSize = 0; + ANSI_STRING AnsiEnv; + UNICODE_STRING UnicodeEnv; + NTSTATUS Status; + + DPRINT("BasepConvertUnicodeEnvironment\n");
- NTSTATUS (STDCALL *pTrue)(UNICODE_STRING *, - ANSI_STRING *, - BOOLEAN); + /* Scan the environment to calculate its Unicode size */ + AnsiEnv.Buffer = pcScan = lpEnvironment; + while (*pcScan) while (*pcScan++);
- ULONG (STDCALL *pRtlMbStringToUnicodeSize)(ANSI_STRING *); - - DPRINT("dwCreationFlags %x, lpEnvironment %x, lpCurrentDirectory %x, " - "lpStartupInfo %x, lpProcessInformation %x\n", - dwCreationFlags, lpEnvironment, lpCurrentDirectory, - lpStartupInfo, lpProcessInformation); - - /* multibyte strings are ANSI */ - if(bIsFileApiAnsi) - { - pTrue = RtlAnsiStringToUnicodeString; - pRtlMbStringToUnicodeSize = RtlAnsiStringToUnicodeSize; - } - /* multibyte strings are OEM */ - else - { - pTrue = RtlOemStringToUnicodeString; - pRtlMbStringToUnicodeSize = RtlOemStringToUnicodeSize; - } - - /* invalid parameter */ - if(lpStartupInfo == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* convert the environment */ - if(lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) - { - PCHAR pcScan; - SIZE_T nEnvLen = 0; - ANSI_STRING strEnvVar; - NTSTATUS Status; - - /* scan the environment to calculate its Unicode size */ - pcScan = lpEnvironment; - do - { - pcScan += strlen(pcScan) + 1; - } - while (*pcScan); - - nEnvLen = (ULONG_PTR)pcScan - (ULONG_PTR)lpEnvironment + 1; - - /* environment too large */ - if(nEnvLen > (SIZE_T)((USHORT)~0)) - { - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - - strEnvVar.Buffer = lpEnvironment; - strEnvVar.MaximumLength = strEnvVar.Length = nEnvLen; - - Status = K32MbStrToWcStr(pTrue, &wstrEnvVar, &strEnvVar, TRUE); - - /* failure */ - if (!NT_SUCCESS(Status)) - { - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - } - - - /* convert the strings */ - RtlInitAnsiString(&strCommandLine, lpCommandLine); - RtlInitAnsiString(&strApplicationName, (LPSTR)lpApplicationName); - RtlInitAnsiString(&strCurrentDirectory, (LPSTR)lpCurrentDirectory); - RtlInitAnsiString(&strReserved, (LPSTR)lpStartupInfo->lpReserved); - RtlInitAnsiString(&strDesktop, (LPSTR)lpStartupInfo->lpDesktop); - RtlInitAnsiString(&strTitle, (LPSTR)lpStartupInfo->lpTitle); - - K32MbStrToWcStr(pTrue, &wstrCommandLine, &strCommandLine, TRUE); - K32MbStrToWcStr(pTrue, &wstrApplicationName, &strApplicationName, TRUE); - K32MbStrToWcStr(pTrue, &wstrCurrentDirectory, &strCurrentDirectory, TRUE); - K32MbStrToWcStr(pTrue, &wstrReserved, &strReserved, TRUE); - K32MbStrToWcStr(pTrue, &wstrDesktop, &strDesktop, TRUE); - K32MbStrToWcStr(pTrue, &wstrTitle, &strTitle, TRUE); - - /* convert the startup information */ - memcpy(&wsiStartupInfo, lpStartupInfo, sizeof(wsiStartupInfo)); - - wsiStartupInfo.lpReserved = wstrReserved.Buffer; - wsiStartupInfo.lpDesktop = wstrDesktop.Buffer; - wsiStartupInfo.lpTitle = wstrTitle.Buffer; - - DPRINT("wstrApplicationName %wZ\n", &wstrApplicationName); - DPRINT("wstrCommandLine %wZ\n", &wstrCommandLine); - DPRINT("wstrCurrentDirectory %wZ\n", &wstrCurrentDirectory); - DPRINT("wstrReserved %wZ\n", &wstrReserved); - DPRINT("wstrDesktop %wZ\n", &wstrDesktop); - DPRINT("wstrTitle %wZ\n", &wstrTitle); - - DPRINT("wstrApplicationName.Buffer %p\n", wstrApplicationName.Buffer); - DPRINT("wstrCommandLine.Buffer %p\n", wstrCommandLine.Buffer); - DPRINT("wstrCurrentDirectory.Buffer %p\n", wstrCurrentDirectory.Buffer); - DPRINT("wstrReserved.Buffer %p\n", wstrReserved.Buffer); - DPRINT("wstrDesktop.Buffer %p\n", wstrDesktop.Buffer); - DPRINT("wstrTitle.Buffer %p\n", wstrTitle.Buffer); - - DPRINT("sizeof(STARTUPINFOA) %lu\n", sizeof(STARTUPINFOA)); - DPRINT("sizeof(STARTUPINFOW) %lu\n", sizeof(STARTUPINFOW)); - - /* call the Unicode function */ - bRetVal = CreateProcessW(wstrApplicationName.Buffer, - wstrCommandLine.Buffer, - lpProcessAttributes, - lpThreadAttributes, - bInheritHandles, - dwCreationFlags, - !lpEnvironment || (dwCreationFlags & CREATE_UNICODE_ENVIRONMENT) ? lpEnvironment : wstrEnvVar.Buffer, - wstrCurrentDirectory.Buffer, - &wsiStartupInfo, - lpProcessInformation); - - RtlFreeUnicodeString(&wstrApplicationName); - RtlFreeUnicodeString(&wstrCommandLine); - RtlFreeUnicodeString(&wstrCurrentDirectory); - RtlFreeUnicodeString(&wstrReserved); - RtlFreeUnicodeString(&wstrDesktop); - RtlFreeUnicodeString(&wstrTitle); - - if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) - { - RtlFreeUnicodeString(&wstrEnvVar); - } - - return bRetVal; + /* Create our ANSI String */ + AnsiEnv.Length = (ULONG_PTR)pcScan - (ULONG_PTR)lpEnvironment + 1; + AnsiEnv.MaximumLength = AnsiEnv.Length + 1; + + /* Allocate memory for the Unicode Environment */ + UnicodeEnv.Buffer = NULL; + EnvSize = AnsiEnv.MaximumLength * sizeof(WCHAR); + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + (PVOID)&UnicodeEnv.Buffer, + 0, + &EnvSize, + MEM_COMMIT, + PAGE_READWRITE); + /* Failure */ + if (!NT_SUCCESS(Status)) + { + SetLastError(Status); + return NULL; + } + + /* Use the allocated size */ + UnicodeEnv.MaximumLength = EnvSize; + + /* Convert */ + RtlAnsiStringToUnicodeString(&UnicodeEnv, &AnsiEnv, FALSE); + return UnicodeEnv.Buffer; }
- -_SEH_FILTER(BaseExceptionFilter) +/* + * Converts a Win32 Priority Class to NT + */ +ULONG +STDCALL +BasepConvertPriorityClass(IN ULONG dwCreationFlags) { - EXCEPTION_POINTERS * ExceptionInfo = _SEH_GetExceptionPointers(); - LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER; - - if (GlobalTopLevelExceptionFilter != NULL) - { - _SEH_TRY - { - ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo); - } - _SEH_HANDLE - { - ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo); - } - _SEH_END; - } - - return ExceptionDisposition; + ULONG ReturnClass; + + if(dwCreationFlags & IDLE_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_IDLE; + } + else if(dwCreationFlags & BELOW_NORMAL_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL; + } + else if(dwCreationFlags & NORMAL_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_NORMAL; + } + else if(dwCreationFlags & ABOVE_NORMAL_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; + } + else if(dwCreationFlags & HIGH_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_HIGH; + } + else if(dwCreationFlags & REALTIME_PRIORITY_CLASS) + { + /* Check for Privilege First */ + if (BasepCheckRealTimePrivilege()) + { + ReturnClass = PROCESS_PRIORITY_CLASS_REALTIME; + } + else + { + ReturnClass = PROCESS_PRIORITY_CLASS_HIGH; + } + } + else + { + ReturnClass = 0 /* FIXME */; + } + + return ReturnClass; }
- -VOID STDCALL -BaseProcessStart(LPTHREAD_START_ROUTINE lpStartAddress, - DWORD lpParameter) +/* + * Duplicates a standard handle and writes it where requested. + */ +VOID +STDCALL +BasepDuplicateAndWriteHandle(IN HANDLE ProcessHandle, + IN HANDLE StandardHandle, + IN PHANDLE Address) { - UINT uExitCode = 0; - - DPRINT("BaseProcessStart(..) - setting up exception frame.\n"); - - _SEH_TRY - { - uExitCode = (lpStartAddress)((PVOID)lpParameter); - } - _SEH_EXCEPT(BaseExceptionFilter) - { - uExitCode = _SEH_GetExceptionCode(); - } - _SEH_END; - - ExitProcess(uExitCode); + NTSTATUS Status; + HANDLE DuplicatedHandle; + ULONG Dummy; + + DPRINT("BasepDuplicateAndWriteHandle. hProcess: %lx, Handle: %lx," + "Address: %p\n", ProcessHandle, StandardHandle, Address); + + /* Don't touch Console Handles */ + if (IsConsoleHandle(StandardHandle)) return; + + /* Duplicate the handle */ + Status = NtDuplicateObject(NtCurrentProcess(), + StandardHandle, + ProcessHandle, + &DuplicatedHandle, + DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES, + 0, + 0); + if (NT_SUCCESS(Status)) + { + /* Write it */ + NtWriteVirtualMemory(ProcessHandle, + Address, + &DuplicatedHandle, + sizeof(HANDLE), + &Dummy); + } }
- -HANDLE STDCALL KlCreateFirstThread(HANDLE ProcessHandle, - LPSECURITY_ATTRIBUTES lpThreadAttributes, - PSECTION_IMAGE_INFORMATION Sii, - LPTHREAD_START_ROUTINE lpStartAddress, - DWORD dwCreationFlags, - LPDWORD lpThreadId) +LPWSTR +STDCALL +BasepGetDllPath(LPWSTR FullPath, + PVOID Environment) { - OBJECT_ATTRIBUTES oaThreadAttribs; - CLIENT_ID cidClientId; - PVOID pTrueStartAddress; - NTSTATUS nErrCode; - HANDLE hThread; - - /* convert the thread attributes */ - RtlRosR32AttribsToNativeAttribs(&oaThreadAttribs, lpThreadAttributes); - - /* native image */ - if(Sii->SubsystemType != IMAGE_SUBSYSTEM_NATIVE) - { - pTrueStartAddress = (PVOID)BaseProcessStart; - } - /* Win32 image */ - else - { - pTrueStartAddress = (PVOID)RtlBaseProcessStartRoutine; - } - - DPRINT("RtlRosCreateUserThreadVa\n" - "(\n" - " ProcessHandle %p,\n" - " ObjectAttributes %p,\n" - " CreateSuspended %d,\n" - " StackZeroBits %d,\n" - " StackReserve %lu,\n" - " StackCommit %lu,\n" - " StartAddress %p,\n" - " ThreadHandle %p,\n" - " ClientId %p,\n" - " ParameterCount %u,\n" - " Parameters[0] %p,\n" - " Parameters[1] %p\n" - ")\n", - ProcessHandle, - &oaThreadAttribs, - dwCreationFlags & CREATE_SUSPENDED, - 0, - Sii->MaximumStackSize, - Sii->CommittedStackSize, - pTrueStartAddress, - &hThread, - &cidClientId, - 2, - lpStartAddress, - PEB_BASE); - - /* create the first thread */ - nErrCode = RtlRosCreateUserThreadVa(ProcessHandle, - &oaThreadAttribs, - dwCreationFlags & CREATE_SUSPENDED, - 0, - &(Sii->MaximumStackSize), - &(Sii->CommittedStackSize), - pTrueStartAddress, - &hThread, - &cidClientId, - 2, - (ULONG_PTR)lpStartAddress, - (ULONG_PTR)PEB_BASE); - /* failure */ - if(!NT_SUCCESS(nErrCode)) - { - SetLastErrorByStatus(nErrCode); - return NULL; - } - - DPRINT("StackReserve %p\n" - "StackCommit %p\n" - "ThreadHandle %p\n" - "ClientId.UniqueThread %p\n", - Sii->MaximumStackSize, - Sii->CommittedStackSize, - hThread, - cidClientId.UniqueThread); - - /* success */ - if(lpThreadId) *lpThreadId = (DWORD)cidClientId.UniqueThread; - return hThread; + /* FIXME: Not yet implemented */ + return NULL; }
-HANDLE KlMapFile(LPCWSTR lpApplicationName) +VOID +STDCALL +BasepCopyHandles(IN PRTL_USER_PROCESS_PARAMETERS Params, + IN PRTL_USER_PROCESS_PARAMETERS PebParams, + IN BOOL InheritHandles) { - HANDLE hFile; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING ApplicationNameString; - OBJECT_ATTRIBUTES ObjectAttributes; - PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; - NTSTATUS Status; - HANDLE hSection; - - hFile = NULL; - - /* - * Find the application name - */ - - if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpApplicationName, - &ApplicationNameString, - NULL, - NULL)) - return NULL; - - DPRINT("ApplicationName %S\n",ApplicationNameString.Buffer); - - InitializeObjectAttributes(&ObjectAttributes, - &ApplicationNameString, - OBJ_CASE_INSENSITIVE, - NULL, - SecurityDescriptor); - - /* - * Try to open the executable - */ - - Status = NtOpenFile(&hFile, - SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA, - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_DELETE|FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE); - - RtlFreeUnicodeString (&ApplicationNameString); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Failed to open file\n"); - SetLastErrorByStatus (Status); - return(NULL); - } - - Status = NtCreateSection(&hSection, - SECTION_ALL_ACCESS, - NULL, - NULL, - PAGE_EXECUTE, - SEC_IMAGE, - hFile); - NtClose(hFile); - - if (!NT_SUCCESS(Status)) - { - DPRINT("Failed to create section\n"); - SetLastErrorByStatus (Status); - return(NULL); - } - - return(hSection); + /* Copy the handle if we are inheriting or if it's a console handle */ + if (InheritHandles || IsConsoleHandle(PebParams->StandardInput)) + { + Params->StandardInput = PebParams->StandardInput; + } + if (InheritHandles || IsConsoleHandle(PebParams->StandardOutput)) + { + Params->StandardOutput = PebParams->StandardOutput; + } + if (InheritHandles || IsConsoleHandle(PebParams->StandardError)) + { + Params->StandardError = PebParams->StandardError; + } }
-static NTSTATUS KlInitPeb(HANDLE ProcessHandle, - PRTL_USER_PROCESS_PARAMETERS Ppb, - PVOID * ImageBaseAddress, - ULONG ImageSubSystem) +NTSTATUS +STDCALL +BasepInitializeEnvironment(HANDLE ProcessHandle, + PPEB Peb, + LPWSTR ApplicationPathName, + LPWSTR lpCurrentDirectory, + LPWSTR lpCommandLine, + LPVOID Environment, + LPSTARTUPINFOW StartupInfo, + DWORD CreationFlags, + BOOL InheritHandles, + HANDLE hInput, + HANDLE hOutput) { - NTSTATUS Status; - PVOID PpbBase; - ULONG PpbSize; - ULONG BytesWritten; - ULONG Offset; - PVOID ParentEnv = NULL; - PVOID EnvPtr = NULL; - PWCHAR ptr; - ULONG EnvSize = 0, EnvSize1 = 0; + WCHAR FullPath[MAX_PATH]; + LPWSTR Remaining; + LPWSTR DllPathString; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + PRTL_USER_PROCESS_PARAMETERS RemoteParameters = NULL; + UNICODE_STRING DllPath, ImageName, CommandLine, CurrentDirectory; + UINT RetVal; + NTSTATUS Status; + PWCHAR ScanChar; + ULONG EnviroSize; + ULONG Size; + UNICODE_STRING Desktop, Shell, Runtime, Title; + PPEB OurPeb = NtCurrentPeb(); + + DPRINT("BasepInitializeEnvironment\n"); + + /* Get the full path name */ + RetVal = GetFullPathNameW(ApplicationPathName, + MAX_PATH, + FullPath, + &Remaining); + DPRINT("ApplicationPathName: %S, FullPath: %S\n", ApplicationPathName, + FullPath); + + /* Get the DLL Path */ + DllPathString = BasepGetDllPath(FullPath, Environment); + + /* Initialize Strings */ + RtlInitUnicodeString(&DllPath, DllPathString); + RtlInitUnicodeString(&ImageName, FullPath); + RtlInitUnicodeString(&CommandLine, lpCommandLine); + RtlInitUnicodeString(&CurrentDirectory, lpCurrentDirectory); + + /* Initialize more Strings from the Startup Info */ + if (StartupInfo->lpDesktop) + { + RtlInitUnicodeString(&Desktop, StartupInfo->lpDesktop); + } + else + { + RtlInitUnicodeString(&Desktop, L""); + } + if (StartupInfo->lpReserved) + { + RtlInitUnicodeString(&Shell, StartupInfo->lpReserved); + } + else + { + RtlInitUnicodeString(&Shell, L""); + } + if (StartupInfo->lpTitle) + { + RtlInitUnicodeString(&Title, StartupInfo->lpTitle); + } + else + { + RtlInitUnicodeString(&Title, L""); + } + + /* This one is special because the length can differ */ + Runtime.Buffer = (LPWSTR)StartupInfo->lpReserved2; + Runtime.MaximumLength = Runtime.Length = StartupInfo->cbReserved2; + + /* Create the Parameter Block */ + DPRINT("Creating Process Parameters: %wZ %wZ %wZ %wZ %wZ %wZ %wZ\n", + &ImageName, &DllPath, &CommandLine, &Desktop, &Title, &Shell, + &Runtime); + Status = RtlCreateProcessParameters(&ProcessParameters, + &ImageName, + &DllPath, + lpCurrentDirectory ? + &CurrentDirectory : NULL, + &CommandLine, + Environment, + &Title, + &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 */ + 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) + { + while (*ScanChar) while (*ScanChar++); + + /* Calculate the size of the block */ + EnviroSize = (ULONG)((ULONG_PTR)ScanChar - (ULONG_PTR)Environment); + DPRINT("EnvironmentSize %ld\n", EnviroSize);
- /* create the Environment */ - if (Ppb->Environment != NULL) - { - ParentEnv = Ppb->Environment; - ptr = ParentEnv; - while (*ptr) - { - while(*ptr++); - } - ptr++; - EnvSize = (ULONG)((ULONG_PTR)ptr - (ULONG_PTR)ParentEnv); - } - else if (NtCurrentPeb()->ProcessParameters->Environment != NULL) - { - MEMORY_BASIC_INFORMATION MemInfo; - ParentEnv = NtCurrentPeb()->ProcessParameters->Environment; + /* Allocate and Initialize new Environment Block */ + Size = EnviroSize; + ProcessParameters->Environment = NULL; + Status = ZwAllocateVirtualMemory(ProcessHandle, + (PVOID*)&ProcessParameters->Environment, + 0, + &Size, + MEM_COMMIT, + PAGE_READWRITE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to allocate Environment Block\n"); + return(Status); + } + + /* Write the Environment Block */ + ZwWriteVirtualMemory(ProcessHandle, + ProcessParameters->Environment, + Environment, + EnviroSize, + NULL); + } + + /* Write new parameters */ + ProcessParameters->StartingX = StartupInfo->dwX; + ProcessParameters->StartingY = StartupInfo->dwY; + ProcessParameters->CountX = StartupInfo->dwXSize; + ProcessParameters->CountY = StartupInfo->dwYSize; + ProcessParameters->CountCharsX = StartupInfo->dwXCountChars; + ProcessParameters->CountCharsY = StartupInfo->dwYCountChars; + ProcessParameters->FillAttribute = StartupInfo->dwFillAttribute; + ProcessParameters->WindowFlags = StartupInfo->dwFlags; + ProcessParameters->ShowWindowFlags = StartupInfo->wShowWindow; + + /* Write the handles only if we have to */ + if (StartupInfo->dwFlags & STARTF_USESTDHANDLES) + { + ProcessParameters->StandardInput = StartupInfo->hStdInput; + ProcessParameters->StandardOutput = StartupInfo->hStdOutput; + ProcessParameters->StandardError = StartupInfo->hStdError; + } + + /* Use Special Flags for ConDllInitialize in Kernel32 */ + if (CreationFlags & DETACHED_PROCESS) + { + ProcessParameters->ConsoleHandle = HANDLE_DETACHED_PROCESS; + } + else if (CreationFlags & CREATE_NO_WINDOW) + { + ProcessParameters->ConsoleHandle = HANDLE_CREATE_NO_WINDOW; + } + else if (CreationFlags & CREATE_NEW_CONSOLE) + { + ProcessParameters->ConsoleHandle = HANDLE_CREATE_NEW_CONSOLE; + } + else + { + /* Inherit our Console Handle */ + ProcessParameters->ConsoleHandle = OurPeb->ProcessParameters->ConsoleHandle; + + /* Is the shell trampling on our Handles? */ + if (!(StartupInfo->dwFlags & + (STARTF_USESTDHANDLES | STARTF_USEHOTKEY | STARTF_SHELLPRIVATE))) + { + /* Use handles from PEB, if inheriting or they are console */ + BasepCopyHandles(ProcessParameters, [truncated at 1000 lines; 3251 more skipped]