mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 06:43:01 +00:00
Added creation of full user stack (including guard page).
svn path=/trunk/; revision=652
This commit is contained in:
parent
1fc6701c79
commit
fe27d316df
1 changed files with 152 additions and 245 deletions
|
@ -1,128 +1,25 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
#include <ddk/ntddk.h>
|
#include <ddk/ntddk.h>
|
||||||
#include <internal/i386/segment.h>
|
#include <internal/i386/segment.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
//#define NDEBUG
|
|
||||||
#include <ntdll/ntdll.h>
|
#include <ntdll/ntdll.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ***************************************************************/
|
||||||
static NTSTATUS
|
|
||||||
RtlpAllocateThreadStack(HANDLE ProcessHandle,
|
|
||||||
PULONG StackReserve,
|
|
||||||
PULONG StackCommit,
|
|
||||||
ULONG StackZeroBits,
|
|
||||||
PINITIAL_TEB InitialTeb)
|
|
||||||
{
|
|
||||||
PVOID StackBase; /* ebp-4 */
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS Status; /* register */
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
Status = NtQuerySystemInformation(...);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
if (ProcessHandle == CurrentProcess)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ... */
|
|
||||||
|
|
||||||
Status = NtAllocateVirtualMemory(ProcessHandle,
|
|
||||||
&StackBase,
|
|
||||||
ZeroBits,
|
|
||||||
StackReserve,
|
|
||||||
MEM_RESERVE,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
/* ... */
|
|
||||||
|
|
||||||
Status = NtAllocateVirtualMemory(ProcessHandle,
|
|
||||||
&StackBase,
|
|
||||||
0,
|
|
||||||
StackCommit,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
InitialTeb->... = StackBase; /* + 0x0C */
|
|
||||||
|
|
||||||
if (bProtect)
|
|
||||||
{
|
|
||||||
|
|
||||||
Status = NtProtectVirtualMemory(ProcessHandle,
|
|
||||||
&StackBase,
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
/* ... */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* NOTE: This is a simplified implementation */
|
|
||||||
|
|
||||||
StackBase = 0;
|
|
||||||
|
|
||||||
Status = NtAllocateVirtualMemory(ProcessHandle,
|
|
||||||
&StackBase,
|
|
||||||
0,
|
|
||||||
StackCommit,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
InitialTeb->StackBase = StackBase;
|
|
||||||
InitialTeb->StackCommit = StackCommit;
|
|
||||||
|
|
||||||
/* End of simplified implementation */
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS
|
|
||||||
RtlpFreeThreadStack(HANDLE ProcessHandle,
|
|
||||||
PINITIAL_TEB InitialTeb)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
ULONG RegionSize;
|
|
||||||
|
|
||||||
RegionSize = 0;
|
|
||||||
|
|
||||||
Status = NtFreeVirtualMemory(ProcessHandle,
|
|
||||||
InitialTeb->StackBase,
|
|
||||||
&RegionSize,
|
|
||||||
MEM_RELEASE);
|
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
InitialTeb->StackBase = NULL;
|
|
||||||
/* ... */
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS STDCALL
|
||||||
|
@ -137,76 +34,97 @@ RtlCreateUserThread(HANDLE ProcessHandle,
|
||||||
PHANDLE ThreadHandle,
|
PHANDLE ThreadHandle,
|
||||||
PCLIENT_ID ClientId)
|
PCLIENT_ID ClientId)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
HANDLE LocalThreadHandle;
|
|
||||||
CLIENT_ID LocalClientId;
|
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
||||||
INITIAL_TEB InitialTeb;
|
|
||||||
CONTEXT Context;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
DPRINT("Checkpoint\n");
|
|
||||||
/* create thread stack */
|
|
||||||
Status = RtlpAllocateThreadStack(ProcessHandle,
|
|
||||||
StackReserved,
|
|
||||||
StackCommit,
|
|
||||||
StackZeroBits,
|
|
||||||
&InitialTeb);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return Status;
|
|
||||||
|
|
||||||
DPRINT("Checkpoint\n");
|
|
||||||
|
|
||||||
/* initialize thread context */
|
|
||||||
RtlInitializeContext (ProcessHandle,
|
|
||||||
&Context,
|
|
||||||
DebugPort,
|
|
||||||
StartAddress,
|
|
||||||
&InitialTeb);
|
|
||||||
DPRINT("Checkpoint\n");
|
|
||||||
|
|
||||||
/* initalize object attributes */
|
|
||||||
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
|
||||||
ObjectAttributes.RootDirectory = NULL;
|
|
||||||
ObjectAttributes.ObjectName = NULL;
|
|
||||||
ObjectAttributes.Attributes = 0;
|
|
||||||
ObjectAttributes.SecurityDescriptor = SecurityDescriptor;
|
|
||||||
ObjectAttributes.SecurityQualityOfService = NULL;
|
|
||||||
|
|
||||||
Status = NtCreateThread (&LocalThreadHandle,
|
|
||||||
0x1F03FF, /* ??? */
|
|
||||||
&ObjectAttributes,
|
|
||||||
ProcessHandle,
|
|
||||||
&LocalClientId,
|
|
||||||
&Context,
|
|
||||||
&InitialTeb,
|
|
||||||
CreateSuspended);
|
|
||||||
DPRINT("Checkpoint\n");
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* free thread stack */
|
|
||||||
RtlpFreeThreadStack (ProcessHandle,
|
|
||||||
&InitialTeb);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Begin of test code */
|
|
||||||
|
|
||||||
HANDLE LocalThreadHandle;
|
HANDLE LocalThreadHandle;
|
||||||
CLIENT_ID LocalClientId;
|
CLIENT_ID LocalClientId;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
INITIAL_TEB InitialTeb;
|
INITIAL_TEB InitialTeb;
|
||||||
CONTEXT ThreadContext;
|
CONTEXT ThreadContext;
|
||||||
PVOID BaseAddress;
|
ULONG ReservedSize;
|
||||||
ULONG LocalStackCommit;
|
ULONG CommitSize;
|
||||||
ULONG LocalStackReserve;
|
ULONG GuardSize;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* initialize initial teb */
|
||||||
|
if ((StackCommit != NULL) && (*StackCommit > PAGESIZE))
|
||||||
|
CommitSize = *StackCommit;
|
||||||
|
else
|
||||||
|
CommitSize = PAGESIZE;
|
||||||
|
|
||||||
|
if ((StackReserved != NULL) && (*StackReserved > 0x100000))
|
||||||
|
ReservedSize = *StackReserved;
|
||||||
|
else
|
||||||
|
ReservedSize = 0x100000; /* 1MByte */
|
||||||
|
|
||||||
|
GuardSize = PAGESIZE;
|
||||||
|
|
||||||
|
/* Reserve stack */
|
||||||
|
InitialTeb.StackReserved = NULL;
|
||||||
|
Status = NtAllocateVirtualMemory(ProcessHandle,
|
||||||
|
&InitialTeb.StackReserved,
|
||||||
|
0,
|
||||||
|
&ReservedSize,
|
||||||
|
MEM_RESERVE,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Error reserving stack space!\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("StackReserved: %p ReservedSize: 0x%lx\n",
|
||||||
|
InitialTeb.StackReserved, ReservedSize);
|
||||||
|
|
||||||
|
InitialTeb.StackBase = (PVOID)(InitialTeb.StackReserved + ReservedSize);
|
||||||
|
InitialTeb.StackCommit = (PVOID)(InitialTeb.StackBase - CommitSize);
|
||||||
|
InitialTeb.StackLimit = (PVOID)(InitialTeb.StackCommit - PAGESIZE);
|
||||||
|
InitialTeb.StackCommitMax = (PVOID)(InitialTeb.StackReserved + PAGESIZE);
|
||||||
|
|
||||||
|
DPRINT("StackBase: %p\n",
|
||||||
|
InitialTeb.StackBase);
|
||||||
|
|
||||||
|
/* Commit stack page */
|
||||||
|
Status = NtAllocateVirtualMemory(ProcessHandle,
|
||||||
|
&InitialTeb.StackCommit,
|
||||||
|
0,
|
||||||
|
&CommitSize,
|
||||||
|
MEM_COMMIT,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Error committing stack page!\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("StackCommit: %p CommitSize: 0x%lx\n",
|
||||||
|
InitialTeb.StackCommit, CommitSize);
|
||||||
|
|
||||||
|
/* Commit guard page */
|
||||||
|
Status = NtAllocateVirtualMemory(ProcessHandle,
|
||||||
|
&InitialTeb.StackLimit,
|
||||||
|
0,
|
||||||
|
&GuardSize,
|
||||||
|
MEM_COMMIT,
|
||||||
|
PAGE_GUARD);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Error committing guard page!\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("StackLimit: %p GuardSize: 0x%lx\n",
|
||||||
|
InitialTeb.StackLimit, GuardSize);
|
||||||
|
|
||||||
|
/* initialize thread context */
|
||||||
|
RtlInitializeContext (ProcessHandle,
|
||||||
|
&ThreadContext,
|
||||||
|
Parameter,
|
||||||
|
StartAddress,
|
||||||
|
&InitialTeb);
|
||||||
|
|
||||||
|
/* create the thread */
|
||||||
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
||||||
ObjectAttributes.RootDirectory = NULL;
|
ObjectAttributes.RootDirectory = NULL;
|
||||||
ObjectAttributes.ObjectName = NULL;
|
ObjectAttributes.ObjectName = NULL;
|
||||||
|
@ -215,33 +133,6 @@ DPRINT("Checkpoint\n");
|
||||||
ObjectAttributes.SecurityDescriptor = SecurityDescriptor;
|
ObjectAttributes.SecurityDescriptor = SecurityDescriptor;
|
||||||
ObjectAttributes.SecurityQualityOfService = NULL;
|
ObjectAttributes.SecurityQualityOfService = NULL;
|
||||||
|
|
||||||
|
|
||||||
if ((StackCommit != NULL) && (*StackCommit > 4096))
|
|
||||||
LocalStackCommit = *StackCommit;
|
|
||||||
else
|
|
||||||
LocalStackCommit = 4096;
|
|
||||||
|
|
||||||
BaseAddress = 0;
|
|
||||||
ZwAllocateVirtualMemory(ProcessHandle,
|
|
||||||
&BaseAddress,
|
|
||||||
0,
|
|
||||||
&LocalStackCommit,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
|
|
||||||
|
|
||||||
memset(&ThreadContext,0,sizeof(CONTEXT));
|
|
||||||
ThreadContext.Eip = (LONG)StartAddress;
|
|
||||||
ThreadContext.SegGs = USER_DS;
|
|
||||||
ThreadContext.SegFs = USER_DS;
|
|
||||||
ThreadContext.SegEs = USER_DS;
|
|
||||||
ThreadContext.SegDs = USER_DS;
|
|
||||||
ThreadContext.SegCs = USER_CS;
|
|
||||||
ThreadContext.SegSs = USER_DS;
|
|
||||||
ThreadContext.Esp = (ULONG)(BaseAddress + LocalStackCommit);
|
|
||||||
ThreadContext.EFlags = (1<<1) + (1<<9);
|
|
||||||
|
|
||||||
|
|
||||||
Status = NtCreateThread(&LocalThreadHandle,
|
Status = NtCreateThread(&LocalThreadHandle,
|
||||||
THREAD_ALL_ACCESS,
|
THREAD_ALL_ACCESS,
|
||||||
&ObjectAttributes,
|
&ObjectAttributes,
|
||||||
|
@ -251,14 +142,26 @@ DPRINT("Checkpoint\n");
|
||||||
&InitialTeb,
|
&InitialTeb,
|
||||||
CreateSuspended);
|
CreateSuspended);
|
||||||
|
|
||||||
/* End of test code */
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ULONG RegionSize = 0;
|
||||||
|
|
||||||
DPRINT("Checkpoint\n");
|
/* release the stack space */
|
||||||
|
NtFreeVirtualMemory(ProcessHandle,
|
||||||
|
InitialTeb.StackReserved,
|
||||||
|
&RegionSize,
|
||||||
|
MEM_RELEASE);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return committed stack size */
|
||||||
if (StackCommit)
|
if (StackCommit)
|
||||||
*StackCommit = LocalStackCommit;
|
*StackCommit = CommitSize;
|
||||||
|
|
||||||
|
/* return reserved stack size */
|
||||||
|
if (StackCommit)
|
||||||
|
*StackCommit = ReservedSize;
|
||||||
|
|
||||||
/* return thread handle */
|
/* return thread handle */
|
||||||
if (ThreadHandle)
|
if (ThreadHandle)
|
||||||
|
@ -271,8 +174,6 @@ DPRINT("Checkpoint\n");
|
||||||
ClientId->UniqueThread = LocalClientId.UniqueThread;
|
ClientId->UniqueThread = LocalClientId.UniqueThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("Checkpoint\n");
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,36 +185,42 @@ RtlInitializeContext(HANDLE ProcessHandle,
|
||||||
PTHREAD_START_ROUTINE StartAddress,
|
PTHREAD_START_ROUTINE StartAddress,
|
||||||
PINITIAL_TEB InitialTeb)
|
PINITIAL_TEB InitialTeb)
|
||||||
{
|
{
|
||||||
|
ULONG Buffer[2];
|
||||||
|
ULONG BytesWritten;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* NOTE: This is a simplified implementation */
|
|
||||||
|
|
||||||
memset (Context, 0, sizeof(CONTEXT));
|
memset (Context, 0, sizeof(CONTEXT));
|
||||||
|
|
||||||
/* #if __X86__ */
|
Context->Eip = (LONG)StartAddress;
|
||||||
Context->Eip = (ULONG)StartAddress;
|
|
||||||
Context->SegGs = USER_DS;
|
Context->SegGs = USER_DS;
|
||||||
Context->SegFs = USER_DS; /* USER_FS */
|
Context->SegFs = USER_DS;
|
||||||
Context->SegEs = USER_DS;
|
Context->SegEs = USER_DS;
|
||||||
Context->SegDs = USER_DS;
|
Context->SegDs = USER_DS;
|
||||||
Context->SegCs = USER_CS;
|
Context->SegCs = USER_CS;
|
||||||
Context->SegSs = USER_DS;
|
Context->SegSs = USER_DS;
|
||||||
Context->Esp = (ULONG)InitialTeb->StackBase +
|
Context->Esp = (ULONG)InitialTeb->StackBase - 8;
|
||||||
(DWORD)InitialTeb->StackCommit - 8;
|
Context->EFlags = (1<<1) + (1<<9);
|
||||||
Context->EFlags = (1<<1)+(1<<9);
|
|
||||||
|
|
||||||
|
/* prepare the thread stack for execution */
|
||||||
|
if (ProcessHandle == NtCurrentProcess())
|
||||||
|
{
|
||||||
|
*((PULONG)(InitialTeb->StackBase - 4)) = (ULONG)Parameter;
|
||||||
|
*((PULONG)(InitialTeb->StackBase - 8)) = 0xdeadbeef;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Buffer[0] = (ULONG)Parameter;
|
||||||
|
Buffer[1] = 0xdeadbeef;
|
||||||
|
|
||||||
/* copy Parameter to thread stack */
|
Status = NtWriteVirtualMemory(ProcessHandle,
|
||||||
*((PULONG)(InitialTeb->StackBase + (DWORD)InitialTeb->StackCommit - 4))
|
(PVOID)(InitialTeb->StackBase - 4),
|
||||||
= (DWORD)Parameter;
|
Buffer,
|
||||||
|
2 * sizeof(ULONG),
|
||||||
|
&BytesWritten);
|
||||||
/* #endif */
|
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
/* End of simplified implementation */
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue