--- 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]