reactos/reactos/lib/ntdll/rtl/thread.c
Casper Hornstrup 1e847489e4 2002-10-01 Casper S. Hornstrup <chorns@users.sourceforge.net>
* drivers/dd/floppy/floppy.c: Changed PAGESIZE to PAGE_SIZE.
	* drivers/fs/cdfs/fcb.c: Ditto.
	* drivers/fs/cdfs/fsctl.c: Ditto.
	* drivers/fs/cdfs/rw.c: Ditto.
	* drivers/fs/ext2/dir.c: Ditto.
	* drivers/fs/ext2/inode.c: Ditto.
	* drivers/fs/ext2/rw.c: Ditto.
	* drivers/fs/ext2/super.c: Ditto.
	* drivers/fs/minix/blockdev.c: Ditto.
	* drivers/fs/minix/cache.c: Ditto.
	* drivers/fs/minix/inode.c: Ditto.
	* drivers/fs/minix/rw.c: Ditto.
	* drivers/fs/ntfs/fcb.c: Ditto.
	* drivers/fs/ntfs/ntfs.h: Ditto.
	* drivers/fs/vfat/create.c: Ditto.
	* drivers/fs/vfat/direntry.c: Ditto.
	* drivers/fs/vfat/dirwr.c: Ditto.
	* drivers/fs/vfat/fat.c: Ditto.
	* drivers/fs/vfat/fcb.c: Ditto.
	* drivers/fs/vfat/fsctl.c: Ditto.
	* drivers/fs/vfat/rw.c: Ditto.
	* drivers/storage/class2/class2.c: Ditto.
	* drivers/storage/scsiport/scsiport.c: Ditto.
	* hal/halx86/adapter.c: Ditto.
	* hal/halx86/mp.c: Ditto.
	* include/ddk/mmfuncs.h: Ditto.
	* include/ddk/mmtypes.h: Ditto.
	* include/ddk/i386/pagesize.h: Ditto.
	* include/ntdll/pagesize.h: Ditto.
	* lib/kernel32/process/create.c: Ditto.
	* lib/kernel32/thread/thread.c: Ditto.
	* lib/ntdll/ldr/utils.c: Ditto.
	* lib/ntdll/rtl/env.c: Ditto.
	* lib/ntdll/rtl/heap.c: Ditto.
	* lib/ntdll/rtl/ppb.c: Ditto.
	* lib/ntdll/rtl/process.c: Ditto.
	* lib/ntdll/rtl/thread.c: Ditto.
	* ntoskrnl/cc/copy.c: Ditto.
	* ntoskrnl/cc/view.c: Ditto.
	* ntoskrnl/ex/sysinfo.c: Ditto.
	* ntoskrnl/include/internal/i386/mm.h: Ditto.
	* ntoskrnl/io/mdl.c: Ditto.
	* ntoskrnl/ke/kthread.c: Ditto.
	* ntoskrnl/ke/i386/kernel.c: Ditto.
	* ntoskrnl/ldr/init.c: Ditto.
	* ntoskrnl/ldr/loader.c: Ditto.
	* ntoskrnl/mm/anonmem.c: Ditto.
	* ntoskrnl/mm/cont.c: Ditto.
	* ntoskrnl/mm/freelist.c: Ditto.
	* ntoskrnl/mm/iospace.c: Ditto.
	* ntoskrnl/mm/kmap.c: Ditto.
	* ntoskrnl/mm/marea.c: Ditto.
	* ntoskrnl/mm/mdl.c: Ditto.
	* ntoskrnl/mm/mminit.c: Ditto.
	* ntoskrnl/mm/ncache.c: Ditto.
	* ntoskrnl/mm/npool.c: Ditto.
	* ntoskrnl/mm/pagefile.c: Ditto.
	* ntoskrnl/mm/pageop.c: Ditto.
	* ntoskrnl/mm/section.c: Ditto.
	* ntoskrnl/mm/slab.c: Ditto.
	* ntoskrnl/mm/i386/page.c: Ditto.
	* ntoskrnl/ob/handle.c: Ditto.
	* ntoskrnl/ps/create.c: Ditto.
	* ntoskrnl/ps/process.c: Ditto.
	* ntoskrnl/ps/w32call.c: Ditto.
	* subsys/win32k/include/object.h: Ditto.

svn path=/trunk/; revision=3594
2002-10-01 19:27:25 +00:00

273 lines
7.2 KiB
C

/*
* 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 <napi/i386/segment.h>
#include <napi/teb.h>
#include <ntdll/rtl.h>
#define NDEBUG
#include <ntdll/ntdll.h>
/* FUNCTIONS ***************************************************************/
NTSTATUS STDCALL
RtlCreateUserThread(HANDLE ProcessHandle,
PSECURITY_DESCRIPTOR SecurityDescriptor,
BOOLEAN CreateSuspended,
LONG StackZeroBits,
PULONG StackReserve,
PULONG StackCommit,
PTHREAD_START_ROUTINE StartAddress,
PVOID Parameter,
PHANDLE ThreadHandle,
PCLIENT_ID ClientId)
{
HANDLE LocalThreadHandle;
CLIENT_ID LocalClientId;
OBJECT_ATTRIBUTES ObjectAttributes;
INITIAL_TEB InitialTeb;
CONTEXT ThreadContext;
ULONG OldPageProtection;
NTSTATUS Status;
/* initialize initial teb */
if ((StackReserve != NULL) && (*StackReserve > 0x100000))
InitialTeb.StackReserve = *StackReserve;
else
InitialTeb.StackReserve = 0x100000; /* 1MByte */
/* FIXME: use correct commit size */
#if 0
if ((StackCommit != NULL) && (*StackCommit > PAGE_SIZE))
InitialTeb.StackCommit = *StackCommit;
else
InitialTeb.StackCommit = PAGE_SIZE;
#endif
InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE;
/* add size of guard page */
InitialTeb.StackCommit += PAGE_SIZE;
/* Reserve stack */
InitialTeb.StackAllocate = NULL;
Status = NtAllocateVirtualMemory(ProcessHandle,
&InitialTeb.StackAllocate,
0,
&InitialTeb.StackReserve,
MEM_RESERVE,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT("Error reserving stack space!\n");
return(Status);
}
DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
InitialTeb.StackAllocate, InitialTeb.StackReserve);
InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve);
InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit);
DPRINT("StackBase: %p StackCommit: 0x%lX\n",
InitialTeb.StackBase, InitialTeb.StackCommit);
/* Commit stack */
Status = NtAllocateVirtualMemory(ProcessHandle,
&InitialTeb.StackLimit,
0,
&InitialTeb.StackCommit,
MEM_COMMIT,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
/* release the stack space */
NtFreeVirtualMemory(ProcessHandle,
InitialTeb.StackAllocate,
&InitialTeb.StackReserve,
MEM_RELEASE);
DPRINT("Error comitting stack page!\n");
return(Status);
}
DPRINT("StackLimit: %p\nStackCommit: 0x%lX\n",
InitialTeb.StackLimit,
InitialTeb.StackCommit);
/* Protect guard page */
Status = NtProtectVirtualMemory(ProcessHandle,
InitialTeb.StackLimit,
PAGE_SIZE,
PAGE_GUARD | PAGE_READWRITE,
&OldPageProtection);
if (!NT_SUCCESS(Status))
{
/* release the stack space */
NtFreeVirtualMemory(ProcessHandle,
InitialTeb.StackAllocate,
&InitialTeb.StackReserve,
MEM_RELEASE);
DPRINT("Error protecting guard page!\n");
return(Status);
}
/* initialize thread context */
RtlInitializeContext(ProcessHandle,
&ThreadContext,
Parameter,
StartAddress,
&InitialTeb);
/* create the thread */
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.ObjectName = NULL;
ObjectAttributes.Attributes = OBJ_INHERIT;
ObjectAttributes.SecurityDescriptor = SecurityDescriptor;
ObjectAttributes.SecurityQualityOfService = NULL;
Status = NtCreateThread(&LocalThreadHandle,
THREAD_ALL_ACCESS,
&ObjectAttributes,
ProcessHandle,
&LocalClientId,
&ThreadContext,
&InitialTeb,
CreateSuspended);
if (!NT_SUCCESS(Status))
{
/* release the stack space */
NtFreeVirtualMemory(ProcessHandle,
InitialTeb.StackAllocate,
&InitialTeb.StackReserve,
MEM_RELEASE);
DPRINT("Error creating thread!\n");
return(Status);
}
/* return committed stack size */
if (StackCommit)
*StackCommit = InitialTeb.StackCommit;
/* return reserved stack size */
if (StackReserve)
*StackReserve = InitialTeb.StackReserve;
/* return thread handle */
if (ThreadHandle)
*ThreadHandle = LocalThreadHandle;
/* return client id */
if (ClientId)
{
ClientId->UniqueProcess = LocalClientId.UniqueProcess;
ClientId->UniqueThread = LocalClientId.UniqueThread;
}
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
RtlInitializeContext(HANDLE ProcessHandle,
PCONTEXT Context,
PVOID Parameter,
PTHREAD_START_ROUTINE StartAddress,
PINITIAL_TEB InitialTeb)
{
ULONG Buffer[2];
ULONG BytesWritten;
NTSTATUS Status;
memset (Context, 0, sizeof(CONTEXT));
Context->Eip = (LONG)StartAddress;
Context->SegGs = USER_DS;
Context->SegFs = TEB_SELECTOR;
Context->SegEs = USER_DS;
Context->SegDs = USER_DS;
Context->SegCs = USER_CS;
Context->SegSs = USER_DS;
Context->Esp = (ULONG)InitialTeb->StackBase - 8;
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;
Status = NtWriteVirtualMemory(ProcessHandle,
(PVOID)((ULONG)InitialTeb->StackBase - 8),
Buffer,
2 * sizeof(ULONG),
&BytesWritten);
return Status;
}
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
RtlFreeUserThreadStack(HANDLE ProcessHandle,
HANDLE ThreadHandle)
{
THREAD_BASIC_INFORMATION ThreadInfo;
NTSTATUS Status;
ULONG BytesRead;
ULONG RegionSize;
PVOID StackBase;
PTEB Teb;
Status = NtQueryInformationThread(ThreadHandle,
ThreadBasicInformation,
&ThreadInfo,
sizeof(THREAD_BASIC_INFORMATION),
NULL);
if (!NT_SUCCESS(Status))
return(Status);
if (ThreadInfo.TebBaseAddress == NULL)
return(Status);
Teb = (PTEB)ThreadInfo.TebBaseAddress;
Status = NtReadVirtualMemory(ProcessHandle,
&Teb->DeallocationStack,
&StackBase,
sizeof(PVOID),
&BytesRead);
if (!NT_SUCCESS(Status))
return(Status);
if (StackBase == NULL)
return(Status);
RegionSize = 0;
Status = NtFreeVirtualMemory(ProcessHandle,
StackBase,
&RegionSize,
MEM_RELEASE);
return(Status);
}
/* EOF */