--- trunk/reactos/lib/rtl/process.c 2005-07-12 02:45:33 UTC (rev 16541)
+++ trunk/reactos/lib/rtl/process.c 2005-07-12 04:41:41 UTC (rev 16542)
@@ -16,176 +16,161 @@
#define NDEBUG
#include <debug.h>
-/* FUNCTIONS ****************************************************************/
+/* INTERNAL FUNCTIONS *******************************************************/
-
-static NTSTATUS
+NTSTATUS
+STDCALL
RtlpMapFile(PUNICODE_STRING ImageFileName,
- PRTL_USER_PROCESS_PARAMETERS Ppb,
- ULONG Attributes,
- PHANDLE Section)
+ ULONG Attributes,
+ PHANDLE Section)
{
- HANDLE hFile;
- IO_STATUS_BLOCK IoStatusBlock;
- OBJECT_ATTRIBUTES ObjectAttributes;
- PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
- NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE hFile = NULL;
+ IO_STATUS_BLOCK IoStatusBlock;
- hFile = NULL;
+ /* Open the Image File */
+ InitializeObjectAttributes(&ObjectAttributes,
+ ImageFileName,
+ Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
+ NULL,
+ NULL);
+ Status = ZwOpenFile(&hFile,
+ SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_DELETE | FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to read image file from disk\n");
+ return(Status);
+ }
+
+ /* Now create a section for this image */
+ Status = ZwCreateSection(Section,
+ SECTION_ALL_ACCESS,
+ NULL,
+ NULL,
+ PAGE_EXECUTE,
+ SEC_IMAGE,
+ hFile);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create section for image file\n");
+ }
- RtlDeNormalizeProcessParams (Ppb);
+ ZwClose(hFile);
+ return Status;
+}
-/* DbgPrint("ImagePathName 0x%p\n", Ppb->ImagePathName.Buffer); */
+/* FUNCTIONS ****************************************************************/
- InitializeObjectAttributes(&ObjectAttributes,
- ImageFileName,
- Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
- NULL,
- SecurityDescriptor);
-
- RtlNormalizeProcessParams (Ppb);
-
- /*
- * Try to open the executable
- */
-
- Status = ZwOpenFile(&hFile,
- SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_DELETE|FILE_SHARE_READ,
- FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
-
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- Status = ZwCreateSection(Section,
- SECTION_ALL_ACCESS,
- NULL,
- NULL,
- PAGE_EXECUTE,
- SEC_IMAGE,
- hFile);
- ZwClose(hFile);
-
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- return(STATUS_SUCCESS);
-}
-
-static NTSTATUS KlInitPeb (HANDLE ProcessHandle,
- PRTL_USER_PROCESS_PARAMETERS Ppb,
- PVOID* ImageBaseAddress)
+NTSTATUS
+STDCALL
+RtlpInitEnvironment(HANDLE ProcessHandle,
+ PPEB Peb,
+ PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
{
- NTSTATUS Status;
- PVOID PpbBase;
- ULONG PpbSize;
- ULONG BytesWritten;
- ULONG Offset;
- PVOID EnvPtr = NULL;
- ULONG EnvSize = 0;
+ NTSTATUS Status;
+ PVOID BaseAddress = NULL;
+ ULONG EnviroSize;
+ ULONG Size;
+ PWCHAR Environment = 0;
+
+ DPRINT("RtlpInitEnvironment (hProcess: %lx, Peb: %p Params: %p)\n",
+ ProcessHandle, Peb, ProcessParameters);
+
+ /* Give the caller 1MB if he requested it */
+ if (ProcessParameters->Flags & PPF_RESERVE_1MB)
+ {
+ /* Give 1MB starting at 0x4 */
+ BaseAddress = (PVOID)4;
+ EnviroSize = 1024 * 1024;
+ Status = ZwAllocateVirtualMemory(ProcessHandle,
+ &BaseAddress,
+ 0,
+ &EnviroSize,
+ MEM_RESERVE,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to reserve 1MB of space \n");
+ return(Status);
+ }
+ }
+
+ /* Find the end of the Enviroment Block */
+ if ((Environment = (PWCHAR)ProcessParameters->Environment))
+ {
+ while (*Environment++) while (*Environment++);
- /* create the Environment */
- if (Ppb->Environment != NULL)
- {
- MEMORY_BASIC_INFORMATION MemInfo;
+ /* Calculate the size of the block */
+ EnviroSize = (ULONG)((ULONG_PTR)Environment -
+ (ULONG_PTR)ProcessParameters->Environment);
+ DPRINT("EnvironmentSize %ld\n", EnviroSize);
- Status = ZwQueryVirtualMemory (NtCurrentProcess (),
- Ppb->Environment,
- MemoryBasicInformation,
- &MemInfo,
- sizeof(MEMORY_BASIC_INFORMATION),
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- EnvSize = MemInfo.RegionSize;
- }
- DPRINT("EnvironmentSize %ld\n", EnvSize);
+ /* Allocate and Initialize new Environment Block */
+ Size = EnviroSize;
+ Status = ZwAllocateVirtualMemory(ProcessHandle,
+ &BaseAddress,
+ 0,
+ &Size,
+ MEM_RESERVE | MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to allocate Environment Block\n");
+ return(Status);
+ }
+
+ /* Write the Environment Block */
+ ZwWriteVirtualMemory(ProcessHandle,
+ BaseAddress,
+ ProcessParameters->Environment,
+ EnviroSize,
+ NULL);
+
+ /* Save pointer */
+ ProcessParameters->Environment = BaseAddress;
+ }
+
+ DPRINT("EnvironmentPointer %p\n", BaseAddress);
+ DPRINT("Ppb->MaximumLength %x\n", ProcessParameters->MaximumLength);
- /* allocate and initialize new environment block */
- if (EnvSize != 0)
- {
- Status = ZwAllocateVirtualMemory(ProcessHandle,
- &EnvPtr,
- 0,
- &EnvSize,
- MEM_RESERVE | MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
+ /* Now allocate space for the Parameter Block */
+ BaseAddress = NULL;
+ Size = ProcessParameters->MaximumLength;
+ Status = ZwAllocateVirtualMemory(ProcessHandle,
+ &BaseAddress,
+ 0,
+ &Size,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to allocate Parameter Block\n");
+ return(Status);
+ }
+
+ /* Write the Parameter Block */
+ ZwWriteVirtualMemory(ProcessHandle,
+ BaseAddress,
+ ProcessParameters,
+ ProcessParameters->Length,
+ NULL);
+
+ /* Write pointer to Parameter Block */
+ ZwWriteVirtualMemory(ProcessHandle,
+ &Peb->ProcessParameters,
+ &BaseAddress,
+ sizeof(BaseAddress),
+ NULL);
- ZwWriteVirtualMemory(ProcessHandle,
- EnvPtr,
- Ppb->Environment,
- EnvSize,
- &BytesWritten);
- }
- DPRINT("EnvironmentPointer %p\n", EnvPtr);
-
- /* create the PPB */
- PpbBase = NULL;
- PpbSize = Ppb->MaximumLength;
-
- Status = ZwAllocateVirtualMemory(ProcessHandle,
- &PpbBase,
- 0,
- &PpbSize,
- MEM_RESERVE | MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength);
-
- /* write process parameters block*/
- RtlDeNormalizeProcessParams (Ppb);
- ZwWriteVirtualMemory(ProcessHandle,
- PpbBase,
- Ppb,
- Ppb->MaximumLength,
-
- &BytesWritten);
- RtlNormalizeProcessParams (Ppb);
-
- /* write pointer to environment */
- Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
- ZwWriteVirtualMemory(ProcessHandle,
- (PVOID)((ULONG_PTR)PpbBase + Offset),
- &EnvPtr,
- sizeof(EnvPtr),
- &BytesWritten);
-
- /* write pointer to process parameter block */
- Offset = FIELD_OFFSET(PEB, ProcessParameters);
- ZwWriteVirtualMemory(ProcessHandle,
- (PVOID)(PEB_BASE + Offset),
- &PpbBase,
- sizeof(PpbBase),
- &BytesWritten);
-
- /* Read image base address. */
- Offset = FIELD_OFFSET(PEB, ImageBaseAddress);
- ZwReadVirtualMemory(ProcessHandle,
- (PVOID)(PEB_BASE + Offset),
- ImageBaseAddress,
- sizeof(PVOID),
- &BytesWritten);
-
- return(STATUS_SUCCESS);
+ /* Return */
+ return STATUS_SUCCESS;
}
-
/*
* @implemented
*
@@ -200,114 +185,136 @@
*
* -Gunnar
*/
-NTSTATUS STDCALL
-RtlCreateUserProcess(
- IN PUNICODE_STRING ImageFileName,
- IN ULONG Attributes,
- IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
- IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
- IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
- IN HANDLE ParentProcess OPTIONAL,
- IN BOOLEAN InheritHandles,
- IN HANDLE DebugPort OPTIONAL,
- IN HANDLE ExceptionPort OPTIONAL,
- OUT PRTL_USER_PROCESS_INFORMATION ProcessInfo
- )
+NTSTATUS
+STDCALL
+RtlCreateUserProcess(IN PUNICODE_STRING ImageFileName,
+ IN ULONG Attributes,
+ IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
+ IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
+ IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
+ IN HANDLE ParentProcess OPTIONAL,
+ IN BOOLEAN InheritHandles,
+ IN HANDLE DebugPort OPTIONAL,
+ IN HANDLE ExceptionPort OPTIONAL,
+ OUT PRTL_USER_PROCESS_INFORMATION ProcessInfo)
{
- HANDLE hSection;
- NTSTATUS Status;
- PROCESS_BASIC_INFORMATION ProcessBasicInfo;
- ULONG retlen;
- SECTION_IMAGE_INFORMATION Sii;
- ULONG ResultLength;
- PVOID ImageBaseAddress;
+ NTSTATUS Status;
+ HANDLE hSection;
+ PROCESS_BASIC_INFORMATION ProcessBasicInfo;
+ OBJECT_ATTRIBUTES ObjectAttributes;
- DPRINT("RtlCreateUserProcess\n");
+ DPRINT("RtlCreateUserProcess: %wZ\n", ImageFileName);
- Status = RtlpMapFile(ImageFileName,
- ProcessParameters,
- Attributes,
- &hSection);
- if( !NT_SUCCESS( Status ) )
- return Status;
+ /* Map and Load the File */
+ Status = RtlpMapFile(ImageFileName,
+ Attributes,
+ &hSection);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not map process image\n");
+ return Status;
+ }
+
+ /* Clean out the CurDir Handle if we won't use it */
+ if (!InheritHandles) ProcessParameters->CurrentDirectory.Handle = NULL;
+
+ /* Use us as parent if none other specified */
+ if (!ParentProcess) ParentProcess = NtCurrentProcess();
+
+ /* Initialize the Object Attributes */
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ ProcessSecurityDescriptor);
- /*
- * Create a new process
- */
- if (ParentProcess == NULL)
- ParentProcess = NtCurrentProcess();
+ /*
+ * If FLG_ENABLE_CSRDEBUG is used, then CSRSS is created under the
+ * watch of WindowsSS
+ */
+ if ((RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG) &&
+ (wcsstr(ImageFileName->Buffer, L"csrss")))
+ {
+ UNICODE_STRING DebugString = RTL_CONSTANT_STRING(L"\\WindowsSS");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &DebugString,
+ 0,
+ NULL,
+ ProcessSecurityDescriptor);
+ }
+
+
+ /* Create Kernel Process Object */
+ Status = ZwCreateProcess(&ProcessInfo->ProcessHandle,
+ PROCESS_ALL_ACCESS,
+ &ObjectAttributes,
+ ParentProcess,
+ InheritHandles,
+ hSection,
+ DebugPort,
+ ExceptionPort);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not create Kernel Process Object\n");
+ ZwClose(hSection);
+ return(Status);
+ }
+
+ /* Get some information on the image */
+ Status = ZwQuerySection(hSection,
+ SectionImageInformation,
+ &ProcessInfo->ImageInformation,
+ sizeof(SECTION_IMAGE_INFORMATION),
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not query Section Info\n");
+ ZwClose(ProcessInfo->ProcessHandle);
+ ZwClose(hSection);
+ return(Status);
+ }
- Status = ZwCreateProcess(&(ProcessInfo->ProcessHandle),
- PROCESS_ALL_ACCESS,
- NULL,
- ParentProcess,
- InheritHandles,
- hSection,
- DebugPort,
- ExceptionPort);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(hSection);
- return(Status);
- }
+ /* Get some information about the process */
+ ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
+ ProcessBasicInformation,
+ &ProcessBasicInfo,
+ sizeof(ProcessBasicInfo),
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not query Process Info\n");
+ ZwClose(ProcessInfo->ProcessHandle);
+ ZwClose(hSection);
+ return(Status);
+ }
- /*
- * Get some information about the process
- */
- ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
- ProcessBasicInformation,
- &ProcessBasicInfo,
- sizeof(ProcessBasicInfo),
- &retlen);
- DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
- ProcessBasicInfo.UniqueProcessId);
- ProcessInfo->ClientId.UniqueProcess = (HANDLE)ProcessBasicInfo.UniqueProcessId;
+ /* Create Process Environment */
+ RtlpInitEnvironment(ProcessInfo->ProcessHandle,
+ ProcessBasicInfo.PebBaseAddress,
+ ProcessParameters);
- /*
- * Create Process Environment Block
- */
- DPRINT("Creating peb\n");
- KlInitPeb(ProcessInfo->ProcessHandle,
- ProcessParameters,
- &ImageBaseAddress);
-
- Status = ZwQuerySection(hSection,
- SectionImageInformation,
- &Sii,
- sizeof(Sii),
- &ResultLength);
- if (!NT_SUCCESS(Status) || ResultLength != sizeof(Sii))
- {
- DPRINT("Failed to get section image information.\n");
- ZwClose(hSection);
- return(Status);
- }
-
- DPRINT("Creating thread for process\n");
- Status = RtlCreateUserThread(
- ProcessInfo->ProcessHandle,
- NULL,
- TRUE, /* CreateSuspended? */
- 0,
- Sii.MaximumStackSize,
- Sii.CommittedStackSize,
- (PVOID)((ULONG_PTR)ImageBaseAddress + (ULONG_PTR)Sii.TransferAddress),
- (PVOID)PEB_BASE,
- &ProcessInfo->ThreadHandle,
- &ProcessInfo->ClientId
- );
-
- ZwClose(hSection);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Failed to create thread\n");
- return(Status);
- }
-
- return(STATUS_SUCCESS);
+ /* Create the first Thread */
+ Status = RtlCreateUserThread(ProcessInfo->ProcessHandle,
+ ThreadSecurityDescriptor,
+ TRUE,
+ ProcessInfo->ImageInformation.ZeroBits,
+ ProcessInfo->ImageInformation.MaximumStackSize,
+ ProcessInfo->ImageInformation.CommittedStackSize,
+ ProcessInfo->ImageInformation.TransferAddress,
+ ProcessBasicInfo.PebBaseAddress,
+ &ProcessInfo->ThreadHandle,
+ &ProcessInfo->ClientId);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Could not Create Thread\n");
+ ZwClose(ProcessInfo->ProcessHandle);
+ ZwClose(hSection); /* Don't try to optimize this on top! */
+ return Status;
+ }
+
+ /* Close the Section Handle and return */
+ ZwClose(hSection);
+ return STATUS_SUCCESS;
}
-
-
/* EOF */
--- trunk/reactos/lib/rtl/thread.c 2005-07-12 02:45:33 UTC (rev 16541)
+++ trunk/reactos/lib/rtl/thread.c 2005-07-12 04:41:41 UTC (rev 16542)
@@ -3,113 +3,349 @@
* PROJECT: ReactOS kernel
* PURPOSE: Rtl user thread functions
* FILE: lib/ntdll/rtl/thread.c
- * PROGRAMER: Eric Kohl
- * REVISION HISTORY:
- * 09/07/99: Created
- * 09/10/99: Cleanup and full stack support.
- * 25/04/03: Near rewrite. Made code more readable, replaced
- * INITIAL_TEB with USER_STACK, added support for
- * fixed-size stacks
- * 28/04/03: Moved all code to a new statically linked
- * library (ROSRTL) so it can be shared with
- * kernel32.dll without exporting non-standard
- * functions from ntdll.dll
+ * PROGRAMERS:
+ * Alex Ionescu (alex@relsoft.net)
+ * Eric Kohl
+ * KJK::Hyperion
*/
/* INCLUDES *****************************************************************/
#include "rtl.h"
-#include <rosrtl/thread.h>
#define NDEBUG
#include <debug.h>
-/* FUNCTIONS ***************************************************************/
+/* PRIVATE FUNCTIONS *******************************************************/
-/*
- @implemented
-*/
-NTSTATUS STDCALL RtlCreateUserThread
-(
- HANDLE ProcessHandle,
- PSECURITY_DESCRIPTOR SecurityDescriptor,
- BOOLEAN CreateSuspended,
- LONG StackZeroBits,
- ULONG StackReserve,
- ULONG StackCommit,
- PTHREAD_START_ROUTINE StartAddress,
- PVOID Parameter,
- PHANDLE ThreadHandle,
- PCLIENT_ID ClientId
-)
+NTSTATUS
+STDCALL
+RtlpCreateUserStack(HANDLE hProcess,
+ ULONG StackReserve,
+ ULONG StackCommit,
+ ULONG StackZeroBits,
+ PINITIAL_TEB InitialTeb)
{
- OBJECT_ATTRIBUTES oaThreadAttribs;
+ NTSTATUS Status;
+ SYSTEM_BASIC_INFORMATION SystemBasicInfo;
+ PIMAGE_NT_HEADERS Headers;
+ ULONG_PTR Stack = 0;
+ BOOLEAN UseGuard = FALSE;
+
+ DPRINT("RtlpCreateUserStack\n");
+
+ /* Get some memory information */
+ Status = NtQuerySystemInformation(SystemBasicInformation,
+ &SystemBasicInfo,
+ sizeof(SYSTEM_BASIC_INFORMATION),
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failure to query system info\n");
+ return Status;
+ }
+
+ /* Use the Image Settings if we are dealing with the current Process */
+ if (hProcess == NtCurrentProcess())
+ {
+ /* Get the Image Headers */
+ Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
+ DPRINT("Headers: %p\n", Headers);
+
+ /* If we didn't get the parameters, find them ourselves */
+ StackReserve = (StackReserve) ?
+ StackReserve : Headers->OptionalHeader.SizeOfStackReserve;
+ StackCommit = (StackCommit) ?
+ StackCommit : Headers->OptionalHeader.SizeOfStackCommit;
+ }
+ else
+ {
+ /* Use the System Settings if needed */
+ StackReserve = (StackReserve) ? StackReserve :
+ SystemBasicInfo.AllocationGranularity;
+ StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize;
+ }
+
+ /* Align everything to Page Size */
+ StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity);
+ StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize);
+ #if 1 // FIXME: Remove once Guard Page support is here
+ StackCommit = StackReserve;
+ #endif
+ DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit);
+
+ /* Reserve memory for the stack */
+ Status = ZwAllocateVirtualMemory(hProcess,
+ (PVOID*)&Stack,
+ StackZeroBits,
+ &StackReserve,
+ MEM_RESERVE,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failure to reserve stack\n");
+ return Status;
+ }
+
+ /* Now set up some basic Initial TEB Parameters */
+ InitialTeb->AllocatedStackBase = (PVOID)Stack;
+ InitialTeb->StackBase = (PVOID)(Stack + StackReserve);
+
+ /* Update the Stack Position */
+ Stack += StackReserve - StackCommit;
+
+ /* Check if we will need a guard page */
+ if (StackReserve > StackCommit)
+ {
+ Stack -= SystemBasicInfo.PageSize;
+ StackCommit += SystemBasicInfo.PageSize;
+ UseGuard = TRUE;
+ }
+
+ DPRINT("AllocatedBase: %p, StackBase: %p, Stack: %p, StackCommit: %lx\n",
+ InitialTeb->AllocatedStackBase, InitialTeb->StackBase, Stack,
+ StackCommit);
+
+ /* Allocate memory for the stack */
+ Status = ZwAllocateVirtualMemory(hProcess,
+ (PVOID*)&Stack,
+ 0,
+ &StackCommit,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failure to allocate stack\n");
+ return Status;
+ }
+
+ /* Now set the current Stack Limit */
+ InitialTeb->StackLimit = (PVOID)Stack;
+ DPRINT("StackLimit: %p\n", Stack);
+
+ /* Create a guard page */
+ if (UseGuard)
+ {
+ ULONG GuardPageSize = SystemBasicInfo.PageSize;
+ ULONG Dummy;
+
+ /* Attempt maximum space possible */
+ Status = ZwProtectVirtualMemory(hProcess,
+ (PVOID*)&Stack,
+ &GuardPageSize,
+ PAGE_GUARD | PAGE_READWRITE,
+ &Dummy);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failure to create guard page\n");
+ return Status;
+ }
+
+ /* Update the Stack Limit keeping in mind the Guard Page */
+ InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit -
+ GuardPageSize);
+ DPRINT1("StackLimit: %p\n", Stack);
+ }
+
+ /* We are done! */
+ return Status;
+}
- InitializeObjectAttributes
- (
- &oaThreadAttribs,
- NULL,
- 0,
- NULL,
- SecurityDescriptor
- );
-
- return RtlRosCreateUserThread
- (
- ProcessHandle,
- &oaThreadAttribs,
- CreateSuspended,
- StackZeroBits,
- &StackReserve,
- &StackCommit,
- StartAddress,
- ThreadHandle,
- ClientId,
- 1,
- (ULONG_PTR *)&Parameter
- );
+NTSTATUS
+STDCALL
+RtlpFreeUserStack(HANDLE hProcess,
+ PINITIAL_TEB InitialTeb)
+{
+ ULONG Dummy = 0;
+
+ /* Free the Stack */
+ return ZwFreeVirtualMemory(hProcess,
+ &InitialTeb->AllocatedStackBase,
+ &Dummy,
+ MEM_RELEASE);
}
+
+/* FUNCTIONS ***************************************************************/
/*
@implemented
*/
-VOID STDCALL
-RtlInitializeContext(
- IN HANDLE ProcessHandle,
- OUT PCONTEXT ThreadContext,
- IN PVOID ThreadStartParam OPTIONAL,
- IN PTHREAD_START_ROUTINE ThreadStartAddress,
- IN PINITIAL_TEB InitialTeb)
+NTSTATUS
+STDCALL
+RtlCreateUserThread(HANDLE ProcessHandle,
+ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ BOOLEAN CreateSuspended,
+ LONG StackZeroBits,
+ ULONG StackReserve,
+ ULONG StackCommit,
+ PTHREAD_START_ROUTINE StartAddress,
+ PVOID Parameter,
+ PHANDLE ThreadHandle,
+ PCLIENT_ID ClientId)
{
- RtlRosInitializeContext
- (
- ProcessHandle,
- ThreadContext,
- ThreadStartAddress,
- InitialTeb,
- 1,
- (ULONG_PTR *)&ThreadStartParam
- );
+ NTSTATUS Status;
+ HANDLE Handle;
+ CLIENT_ID ThreadCid;
+ INITIAL_TEB InitialTeb;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ CONTEXT Context;
+
+ DPRINT("RtlCreateUserThread: (hProcess: %lx, Suspended: %lx,"
+ "ZeroBits: %lx, StackReserve: %lx, StackCommit: %lx,"
+ "StartAddress: %p, Parameter: %lx)\n", ProcessHandle,
+ CreateSuspended, StackZeroBits, StackReserve, StackCommit,
+ StartAddress, Parameter);
+
+ /* First, we'll create the Stack */
+ Status = RtlpCreateUserStack(ProcessHandle,
+ StackReserve,
+ StackCommit,
+ StackZeroBits,
+ &InitialTeb);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failure to create User Stack\n");
+ return Status;
+ }
+
+ /* Next, we'll set up the Initial Context */
+ RtlInitializeContext(ProcessHandle,
+ &Context,
+ Parameter,
+ StartAddress,
+ InitialTeb.StackBase);
+
+ /* We are now ready to create the Kernel Thread Object */
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ SecurityDescriptor);
+ Status = ZwCreateThread(&Handle,
+ THREAD_ALL_ACCESS,
+ &ObjectAttributes,
+ ProcessHandle,
+ &ThreadCid,
+ &Context,
+ &InitialTeb,
+ CreateSuspended);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failure to create Thread\n");
+
+ /* Free the stack */
+ RtlpFreeUserStack(ProcessHandle, &InitialTeb);
+ }
+ else
+ {
+ DPRINT("Thread created: %lx\n", Handle);
+ if (ThreadHandle) *ThreadHandle = Handle;
+ if (ClientId) *ClientId = ThreadCid;
+ }
+
+ /* Return success or the previous failure */
+ return Status;
}
/*
+ * FIXME: Should go in /i386
@implemented
*/
-NTSTATUS STDCALL RtlFreeUserThreadStack
-(
- HANDLE ProcessHandle,
- HANDLE ThreadHandle
-)
+VOID
+STDCALL
+RtlInitializeContext(IN HANDLE ProcessHandle,
+ OUT PCONTEXT ThreadContext,
+ IN PVOID ThreadStartParam OPTIONAL,
+ IN PTHREAD_START_ROUTINE ThreadStartAddress,
+ IN PINITIAL_TEB InitialTeb)
{
- return RtlRosFreeUserThreadStack(ProcessHandle, ThreadHandle);
+ DPRINT("RtlInitializeContext: (hProcess: %lx, ThreadContext: %p, Teb: %p\n",
+ ProcessHandle, ThreadContext, InitialTeb);
+
+ /*
+ * Set the Initial Registers
+ * This is based on NT's default values -- crazy apps might expect this...
+ */
+ ThreadContext->Ebp = 0;
+ ThreadContext->Eax = 0;
+ ThreadContext->Ebx = 1;
+ ThreadContext->Ecx = 2;
+ ThreadContext->Edx = 3;
+ ThreadContext->Esi = 4;
+ ThreadContext->Edi = 5;
+
+ /* Set the Selectors */
+ ThreadContext->SegGs = 0;
+ ThreadContext->SegFs = TEB_SELECTOR;
+ ThreadContext->SegEs = USER_DS;
+ ThreadContext->SegDs = USER_DS;
+ ThreadContext->SegCs = USER_CS;
+ ThreadContext->SegSs = USER_DS;
+
+ /* Enable Interrupts */
+ ThreadContext->EFlags = 0x200; /*X86_EFLAGS_IF */
+
+ /* Settings passed */
+ ThreadContext->Eip = (ULONG)ThreadStartAddress;
+ ThreadContext->Esp = (ULONG)InitialTeb;
+
+ /* Only the basic Context is initialized */
+ ThreadContext->ContextFlags = CONTEXT_CONTROL |
+ CONTEXT_INTEGER |
+ CONTEXT_SEGMENTS;
+
+ /* Set up ESP to the right value */
+ ThreadContext->Esp -= sizeof(PVOID);
+ ZwWriteVirtualMemory(ProcessHandle,
+ (PVOID)ThreadContext->Esp,
+ (PVOID)&ThreadStartParam,
+ sizeof(PVOID),
+ NULL);
+
+ /* Push it down one more notch for RETEIP */
+ ThreadContext->Esp -= sizeof(PVOID);
}
/*
@implemented
*/
[truncated at 1000 lines; 58 more skipped]