Second part of patch, implements the new RTL functions which will be
used (not used by kernel yet).
- RtlCreateUserProcess:
* Created RtlpInitEnvironment to manage Environment Block
creation. Rougly based on
old KlInitPeb code but with some optimizations.
* Don't ignore Process Security Descriptor if one was specified.
* Don't ignore ZeroBits, get correct entrypoint, and don't
assume PEB address.
* Don't close handle of section before closing process handle on
failure.
* Support new undocumented flag which pre-allocates 1MB of
memory for Native Processes
* FIXME: Hande duplication should be done, but wasn't and still
isn't.
- RtlpCreateUserStack:
* New function to create a stack for a Thread, similar to
BasepCreateStack but
has some differences related to StackCommit/StackReserve.
* Also create Guard Page
- RtlpFreeUserStack:
* Undoes what the function above does, in case of failure in
code using it.
- RtlCreateUserThread:
* Use the new functions instead of rosrtl.
- RtlInitializeContext:
* New function similar to BasepInitializeContext but;
Uses a single entrypoint, not many possible thunks
like
Kernel32 (no need)
The starting EFLAGS is Interrupts Enabled, not IOPL
3.
We don't initialize the same Context Flags
The initial context registers are different
- RtlFreeUserThreadStack
* Don't assume the TEB address
- RtlExitUserThread
* Remove deprecated stack-switching semantics and use new TEB
flag to tell the Kernel
to deallocate the stack for us.
Modified: trunk/reactos/lib/kernel32/process/create.c
Modified: trunk/reactos/lib/ntdll/rtl/process.c
Modified: trunk/reactos/lib/rtl/process.c
Modified: trunk/reactos/lib/rtl/thread.c
Modified: trunk/reactos/ntoskrnl/mm/pe.c
_____
Modified: trunk/reactos/lib/kernel32/process/create.c
--- trunk/reactos/lib/kernel32/process/create.c 2005-07-12 02:45:33 UTC
(rev 16541)
+++ trunk/reactos/lib/kernel32/process/create.c 2005-07-12 04:41:41 UTC
(rev 16542)
@@ -16,7 +16,7 @@
/* FIXME */
#include <rosrtl/thread.h>
-//#define NDEBUG
+#define NDEBUG
#include "../include/debug.h"
/* FUNCTIONS
****************************************************************/
@@ -1378,11 +1378,11 @@
* Create the thread for the kernel
*/
DPRINT("Creating thread for process (EntryPoint = 0x%.08x)\n",
- (PVOID)((ULONG_PTR)ImageBaseAddress +
(ULONG_PTR)Sii.TransferAddress));
+ Sii.TransferAddress);
hThread = KlCreateFirstThread(hProcess,
lpThreadAttributes,
&Sii,
- (PVOID)((ULONG_PTR)ImageBaseAddress +
(ULONG_PTR)Sii.TransferAddress),
+ Sii.TransferAddress,
dwCreationFlags,
&lpProcessInformation->dwThreadId);
if (hThread == NULL)
_____
Modified: trunk/reactos/lib/ntdll/rtl/process.c
--- trunk/reactos/lib/ntdll/rtl/process.c 2005-07-12 02:45:33 UTC
(rev 16541)
+++ trunk/reactos/lib/ntdll/rtl/process.c 2005-07-12 04:41:41 UTC
(rev 16542)
@@ -90,4 +90,19 @@
return STATUS_INVALID_PARAMETER;
}
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+RtlExitUserThread(NTSTATUS Status)
+{
+ /* Call the Loader and tell him to notify the DLLs */
+ LdrShutdownThread();
+
+ /* Shut us down */
+ NtCurrentTeb()->FreeStackOnTermination = TRUE;
+ NtTerminateThread(NtCurrentThread(), Status);
+}
+
/* EOF */
_____
Modified: trunk/reactos/lib/rtl/process.c
--- 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 */
_____
Modified: trunk/reactos/lib/rtl/thread.c
--- 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(a)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]