use tags for pool allocations, and reformat code Modified: trunk/reactos/ntoskrnl/ps/create.c _____
Modified: trunk/reactos/ntoskrnl/ps/create.c --- trunk/reactos/ntoskrnl/ps/create.c 2005-04-08 12:54:37 UTC (rev 14545) +++ trunk/reactos/ntoskrnl/ps/create.c 2005-04-08 13:02:23 UTC (rev 14546) @@ -4,7 +4,7 @@
* PROJECT: ReactOS kernel * FILE: ntoskrnl/ps/create.c * PURPOSE: Thread managment - * + * * PROGRAMMERS: David Welch (welch@mcmail.com) * Phillip Susi * Skywing @@ -12,10 +12,10 @@
/* * NOTE: - * + * * All of the routines that manipulate the thread queue synchronize on * a single spinlock - * + * */
/* INCLUDES ****************************************************************/ @@ -27,6 +27,7 @@ /* GLOBAL *******************************************************************/
#define MAX_THREAD_NOTIFY_ROUTINE_COUNT 8 +#define TAG_KAPC TAG('k','p','a','p') /* kpap - kernel ps apc */
static ULONG PiThreadNotifyRoutineCount = 0; static PCREATE_THREAD_NOTIFY_ROUTINE @@ -40,462 +41,475 @@ VOID PiBeforeBeginThread(CONTEXT c) { - KeLowerIrql(PASSIVE_LEVEL); + KeLowerIrql(PASSIVE_LEVEL); }
NTSTATUS -PsInitializeThread(PEPROCESS Process, - PETHREAD* ThreadPtr, - POBJECT_ATTRIBUTES ObjectAttributes, - KPROCESSOR_MODE AccessMode, - BOOLEAN First) +PsInitializeThread ( + PEPROCESS Process, + PETHREAD* ThreadPtr, + POBJECT_ATTRIBUTES ObjectAttributes, + KPROCESSOR_MODE AccessMode, + BOOLEAN First ) { - PETHREAD Thread; - NTSTATUS Status; - KIRQL oldIrql; - - PAGED_CODE(); - - if (Process == NULL) - { - Process = PsInitialSystemProcess; - } - - /* + PETHREAD Thread; + NTSTATUS Status; + KIRQL oldIrql; + + PAGED_CODE(); + + if (Process == NULL) + { + Process = PsInitialSystemProcess; + } + + /* * Create and initialize thread */ - Status = ObCreateObject(AccessMode, - PsThreadType, - ObjectAttributes, - KernelMode, - NULL, - sizeof(ETHREAD), - 0, - 0, - (PVOID*)&Thread); - if (!NT_SUCCESS(Status)) - { + Status = ObCreateObject(AccessMode, + PsThreadType, + ObjectAttributes, + KernelMode, + NULL, + sizeof(ETHREAD), + 0, + 0, + (PVOID*)&Thread); + if (!NT_SUCCESS(Status)) + { return(Status); - } + }
- /* + /* * Reference process */ - ObReferenceObjectByPointer(Process, - PROCESS_CREATE_THREAD, - PsProcessType, - KernelMode); + ObReferenceObjectByPointer(Process, + PROCESS_CREATE_THREAD, + PsProcessType, + KernelMode);
- Thread->ThreadsProcess = Process; - Thread->Cid.UniqueThread = NULL; - Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId; + Thread->ThreadsProcess = Process; + Thread->Cid.UniqueThread = NULL; + Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
- DPRINT("Thread = %x\n",Thread); + DPRINT("Thread = %x\n",Thread);
- KeInitializeThread(&Process->Pcb, &Thread->Tcb, First); - InitializeListHead(&Thread->ActiveTimerListHead); - KeInitializeSpinLock(&Thread->ActiveTimerListLock); - InitializeListHead(&Thread->IrpList); - Thread->DeadThread = FALSE; - Thread->HasTerminated = FALSE; - Thread->Tcb.Win32Thread = NULL; - DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread); - + KeInitializeThread(&Process->Pcb, &Thread->Tcb, First); + InitializeListHead(&Thread->ActiveTimerListHead); + KeInitializeSpinLock(&Thread->ActiveTimerListLock); + InitializeListHead(&Thread->IrpList); + Thread->DeadThread = FALSE; + Thread->HasTerminated = FALSE; + Thread->Tcb.Win32Thread = NULL; + DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
- Thread->Tcb.BasePriority = (CHAR)Process->Pcb.BasePriority; - Thread->Tcb.Priority = Thread->Tcb.BasePriority;
- /* + Thread->Tcb.BasePriority = (CHAR)Process->Pcb.BasePriority; + Thread->Tcb.Priority = Thread->Tcb.BasePriority; + + /* * Local Procedure Call facility (LPC) */ - KeInitializeSemaphore (& Thread->LpcReplySemaphore, 0, LONG_MAX); - Thread->LpcReplyMessage = NULL; - Thread->LpcReplyMessageId = 0; /* not valid */ - /* Thread->LpcReceiveMessageId = 0; */ - Thread->LpcExitThreadCalled = FALSE; - Thread->LpcReceivedMsgIdValid = FALSE; + KeInitializeSemaphore (& Thread->LpcReplySemaphore, 0, LONG_MAX); + Thread->LpcReplyMessage = NULL; + Thread->LpcReplyMessageId = 0; /* not valid */ + /* Thread->LpcReceiveMessageId = 0; */ + Thread->LpcExitThreadCalled = FALSE; + Thread->LpcReceivedMsgIdValid = FALSE;
- oldIrql = KeAcquireDispatcherDatabaseLock(); - InsertTailList(&Process->ThreadListHead, - &Thread->ThreadListEntry); - KeReleaseDispatcherDatabaseLock(oldIrql); + oldIrql = KeAcquireDispatcherDatabaseLock(); + InsertTailList(&Process->ThreadListHead, + &Thread->ThreadListEntry); + KeReleaseDispatcherDatabaseLock(oldIrql);
- *ThreadPtr = Thread; + *ThreadPtr = Thread;
- return STATUS_SUCCESS; + return STATUS_SUCCESS; }
static NTSTATUS -PsCreateTeb(HANDLE ProcessHandle, - PTEB *TebPtr, - PETHREAD Thread, - PINITIAL_TEB InitialTeb) +PsCreateTeb ( + HANDLE ProcessHandle, + PTEB *TebPtr, + PETHREAD Thread, + PINITIAL_TEB InitialTeb ) { - PEPROCESS Process; - NTSTATUS Status; - ULONG ByteCount; - ULONG RegionSize; - ULONG TebSize; - PVOID TebBase; - TEB Teb; - - PAGED_CODE(); + PEPROCESS Process; + NTSTATUS Status; + ULONG ByteCount; + ULONG RegionSize; + ULONG TebSize; + PVOID TebBase; + TEB Teb;
- TebSize = PAGE_SIZE; + PAGED_CODE();
- if (NULL == Thread->ThreadsProcess) - { - /* We'll be allocating a 64k block here and only use 4k of it, but this - path should almost never be taken. Actually, I never saw it was taken, - so maybe we should just ASSERT(NULL != Thread->ThreadsProcess) and - move on */ - TebBase = NULL; - Status = ZwAllocateVirtualMemory(ProcessHandle, - &TebBase, - 0, - &TebSize, - MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, - PAGE_READWRITE); - if (! NT_SUCCESS(Status)) - { - DPRINT1("Failed to allocate virtual memory for TEB\n"); - return Status; - } - } - else - { - Process = Thread->ThreadsProcess; - PsLockProcess(Process, FALSE); - if (NULL == Process->TebBlock || - Process->TebBlock == Process->TebLastAllocated) - { - Process->TebBlock = NULL; - RegionSize = MM_VIRTMEM_GRANULARITY; - Status = ZwAllocateVirtualMemory(ProcessHandle, - &Process->TebBlock, - 0, - &RegionSize, - MEM_RESERVE | MEM_TOP_DOWN, - PAGE_READWRITE); - if (! NT_SUCCESS(Status)) - { - PsUnlockProcess(Process); - DPRINT1("Failed to reserve virtual memory for TEB\n"); - return Status; - } - Process->TebLastAllocated = (PVOID) ((char *) Process->TebBlock + RegionSize); - } - TebBase = (PVOID) ((char *) Process->TebLastAllocated - PAGE_SIZE); - Status = ZwAllocateVirtualMemory(ProcessHandle, - &TebBase, - 0, - &TebSize, - MEM_COMMIT, - PAGE_READWRITE); - if (! NT_SUCCESS(Status)) - { - DPRINT1("Failed to commit virtual memory for TEB\n"); - return Status; - } - Process->TebLastAllocated = TebBase; - PsUnlockProcess(Process); - } + TebSize = PAGE_SIZE;
- DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize); - ASSERT(NULL != TebBase && PAGE_SIZE <= TebSize); - - RtlZeroMemory(&Teb, sizeof(TEB)); - /* set all pointers to and from the TEB */ - Teb.Tib.Self = TebBase; - if (Thread->ThreadsProcess) - { - Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */ - } - DPRINT("Teb.Peb %x\n", Teb.Peb); - - /* store stack information from InitialTeb */ - if(InitialTeb != NULL) - { - /* fixed-size stack */ - if(InitialTeb->StackBase && InitialTeb->StackLimit) + if (NULL == Thread->ThreadsProcess) { - Teb.Tib.StackBase = InitialTeb->StackBase; - Teb.Tib.StackLimit = InitialTeb->StackLimit; - Teb.DeallocationStack = InitialTeb->StackLimit; + /* We'll be allocating a 64k block here and only use 4k of it, but this + path should almost never be taken. Actually, I never saw it was taken, + so maybe we should just ASSERT(NULL != Thread->ThreadsProcess) and + move on */ + TebBase = NULL; + Status = ZwAllocateVirtualMemory(ProcessHandle, + &TebBase, + 0, + &TebSize, + MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, + PAGE_READWRITE); + if (! NT_SUCCESS(Status)) + { + DPRINT1("Failed to allocate virtual memory for TEB\n"); + return Status; + } } - /* expandable stack */ else { - Teb.Tib.StackBase = InitialTeb->StackCommit; - Teb.Tib.StackLimit = InitialTeb->StackCommitMax; - Teb.DeallocationStack = InitialTeb->StackReserved; + Process = Thread->ThreadsProcess; + PsLockProcess(Process, FALSE); + if (NULL == Process->TebBlock || + Process->TebBlock == Process->TebLastAllocated) + { + Process->TebBlock = NULL; + RegionSize = MM_VIRTMEM_GRANULARITY; + Status = ZwAllocateVirtualMemory(ProcessHandle, + &Process->TebBlock, + 0, + &RegionSize, + MEM_RESERVE | MEM_TOP_DOWN, + PAGE_READWRITE); + if (! NT_SUCCESS(Status)) + { + PsUnlockProcess(Process); + DPRINT1("Failed to reserve virtual memory for TEB\n"); + return Status; + } + Process->TebLastAllocated = (PVOID) ((char *) Process->TebBlock + RegionSize); + } + TebBase = (PVOID) ((char *) Process->TebLastAllocated - PAGE_SIZE); + Status = ZwAllocateVirtualMemory(ProcessHandle, + &TebBase, + 0, + &TebSize, + MEM_COMMIT, + PAGE_READWRITE); + if (! NT_SUCCESS(Status)) + { + DPRINT1("Failed to commit virtual memory for TEB\n"); + return Status; + } + Process->TebLastAllocated = TebBase; + PsUnlockProcess(Process); } - }
- /* more initialization */ - Teb.Cid.UniqueThread = Thread->Cid.UniqueThread; - Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess; - Teb.CurrentLocale = PsDefaultThreadLocaleId; + DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize); + ASSERT(NULL != TebBase && PAGE_SIZE <= TebSize);
- /* Terminate the exception handler list */ - Teb.Tib.ExceptionList = (PVOID)-1; - - DPRINT("sizeof(TEB) %x\n", sizeof(TEB)); - - /* write TEB data into teb page */ - Status = NtWriteVirtualMemory(ProcessHandle, - TebBase, - &Teb, - sizeof(TEB), - &ByteCount); + RtlZeroMemory(&Teb, sizeof(TEB)); + /* set all pointers to and from the TEB */ + Teb.Tib.Self = TebBase; + if (Thread->ThreadsProcess) + { + Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */ + } + DPRINT("Teb.Peb %x\n", Teb.Peb);
- if (!NT_SUCCESS(Status)) - { + /* store stack information from InitialTeb */ + if(InitialTeb != NULL) + { + /* fixed-size stack */ + if(InitialTeb->StackBase && InitialTeb->StackLimit) + { + Teb.Tib.StackBase = InitialTeb->StackBase; + Teb.Tib.StackLimit = InitialTeb->StackLimit; + Teb.DeallocationStack = InitialTeb->StackLimit; + } + /* expandable stack */ + else + { + Teb.Tib.StackBase = InitialTeb->StackCommit; + Teb.Tib.StackLimit = InitialTeb->StackCommitMax; + Teb.DeallocationStack = InitialTeb->StackReserved; + } + } + + /* more initialization */ + Teb.Cid.UniqueThread = Thread->Cid.UniqueThread; + Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess; + Teb.CurrentLocale = PsDefaultThreadLocaleId; + + /* Terminate the exception handler list */ + Teb.Tib.ExceptionList = (PVOID)-1; + + DPRINT("sizeof(TEB) %x\n", sizeof(TEB)); + + /* write TEB data into teb page */ + Status = NtWriteVirtualMemory(ProcessHandle, + TebBase, + &Teb, + sizeof(TEB), + &ByteCount); + + if (!NT_SUCCESS(Status)) + { /* free TEB */ DPRINT1 ("Writing TEB failed!\n");
RegionSize = 0; NtFreeVirtualMemory(ProcessHandle, - TebBase, - &RegionSize, - MEM_RELEASE); + TebBase, + &RegionSize, + MEM_RELEASE);
return Status; - } + }
- if (TebPtr != NULL) - { + if (TebPtr != NULL) + { *TebPtr = (PTEB)TebBase; - } + }
- DPRINT("TEB allocated at %p\n", TebBase); + DPRINT("TEB allocated at %p\n", TebBase);
- return Status; + return Status; }
VOID STDCALL -LdrInitApcRundownRoutine(PKAPC Apc) +LdrInitApcRundownRoutine ( PKAPC Apc ) { - ExFreePool(Apc); + ExFreePool(Apc); }
VOID STDCALL -LdrInitApcKernelRoutine(PKAPC Apc, - PKNORMAL_ROUTINE* NormalRoutine, - PVOID* NormalContext, - PVOID* SystemArgument1, - PVOID* SystemArgument2) +LdrInitApcKernelRoutine ( + PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArgument2) { - ExFreePool(Apc); + ExFreePool(Apc); }
NTSTATUS STDCALL -NtCreateThread(OUT PHANDLE ThreadHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN HANDLE ProcessHandle, - OUT PCLIENT_ID ClientId, - IN PCONTEXT ThreadContext, - IN PINITIAL_TEB InitialTeb, - IN BOOLEAN CreateSuspended) +NtCreateThread ( + OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ProcessHandle, + OUT PCLIENT_ID ClientId, + IN PCONTEXT ThreadContext, + IN PINITIAL_TEB InitialTeb, + IN BOOLEAN CreateSuspended ) { - HANDLE hThread; - CONTEXT SafeContext; - INITIAL_TEB SafeInitialTeb; - PEPROCESS Process; - PETHREAD Thread; - PTEB TebBase; - PKAPC LdrInitApc; - KIRQL oldIrql; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - if(ThreadContext == NULL) - { - return STATUS_INVALID_PARAMETER; - } - - PreviousMode = ExGetPreviousMode(); + HANDLE hThread; + CONTEXT SafeContext; + INITIAL_TEB SafeInitialTeb; + PEPROCESS Process; + PETHREAD Thread; + PTEB TebBase; + PKAPC LdrInitApc; + KIRQL oldIrql; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS;
- if(PreviousMode != KernelMode) - { - _SEH_TRY + PAGED_CODE(); + + if(ThreadContext == NULL) { - ProbeForWrite(ThreadHandle, - sizeof(HANDLE), - sizeof(ULONG)); - if(ClientId != NULL) - { - ProbeForWrite(ClientId, - sizeof(CLIENT_ID), - sizeof(ULONG)); - } - ProbeForRead(ThreadContext, - sizeof(CONTEXT), - sizeof(ULONG)); - SafeContext = *ThreadContext; - ThreadContext = &SafeContext; - ProbeForRead(InitialTeb, - sizeof(INITIAL_TEB), - sizeof(ULONG)); - SafeInitialTeb = *InitialTeb; - InitialTeb = &SafeInitialTeb; + return STATUS_INVALID_PARAMETER; } - _SEH_HANDLE + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) { - Status = _SEH_GetExceptionCode(); + _SEH_TRY + { + ProbeForWrite(ThreadHandle, + sizeof(HANDLE), + sizeof(ULONG)); + if(ClientId != NULL) + { + ProbeForWrite(ClientId, + sizeof(CLIENT_ID), + sizeof(ULONG)); + } + ProbeForRead(ThreadContext, + sizeof(CONTEXT), + sizeof(ULONG)); + SafeContext = *ThreadContext; + ThreadContext = &SafeContext; + ProbeForRead(InitialTeb, + sizeof(INITIAL_TEB), + sizeof(ULONG)); + SafeInitialTeb = *InitialTeb; + InitialTeb = &SafeInitialTeb; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } } - _SEH_END;
+ DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n", + ThreadHandle,ThreadContext); + + Status = ObReferenceObjectByHandle( + ProcessHandle, + PROCESS_CREATE_THREAD, + PsProcessType, + PreviousMode, + (PVOID*)&Process, + NULL); if(!NT_SUCCESS(Status)) { - return Status; + return(Status); } - }
- DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n", - ThreadHandle,ThreadContext); - - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_CREATE_THREAD, - PsProcessType, - PreviousMode, - (PVOID*)&Process, - NULL); - if(!NT_SUCCESS(Status)) - { - return(Status); - } - - Status = PsLockProcess(Process, FALSE); - if (!NT_SUCCESS(Status)) + Status = PsLockProcess(Process, FALSE); + if (!NT_SUCCESS(Status)) { - ObDereferenceObject(Process); - return(Status); + ObDereferenceObject(Process); + return(Status); }
- if(Process->ExitTime.QuadPart != 0) + if(Process->ExitTime.QuadPart != 0) { - PsUnlockProcess(Process); - return STATUS_PROCESS_IS_TERMINATING; + PsUnlockProcess(Process); + return STATUS_PROCESS_IS_TERMINATING; }
- PsUnlockProcess(Process); + PsUnlockProcess(Process);
- Status = PsInitializeThread(Process, - &Thread, - ObjectAttributes, - PreviousMode, - FALSE); + Status = PsInitializeThread(Process, + &Thread, + ObjectAttributes, + PreviousMode, + FALSE);
- ObDereferenceObject(Process); - - if (!NT_SUCCESS(Status)) + ObDereferenceObject(Process); + + if (!NT_SUCCESS(Status)) { - return(Status); + return(Status); } - - /* create a client id handle */ - Status = PsCreateCidHandle(Thread, PsThreadType, &Thread->Cid.UniqueThread); - if (!NT_SUCCESS(Status)) + + /* create a client id handle */ + Status = PsCreateCidHandle ( + Thread, PsThreadType, &Thread->Cid.UniqueThread); + if (!NT_SUCCESS(Status)) { - ObDereferenceObject(Thread); - return Status; + ObDereferenceObject(Thread); + return Status; }
- Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext); - if (!NT_SUCCESS(Status)) + Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext); + if (!NT_SUCCESS(Status)) { - PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType); - ObDereferenceObject(Thread); - return(Status); + PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType); + ObDereferenceObject(Thread); + return(Status); }
- Status = PsCreateTeb(ProcessHandle, - &TebBase, - Thread, - InitialTeb); - if (!NT_SUCCESS(Status)) + Status = PsCreateTeb(ProcessHandle, + &TebBase, + Thread, + InitialTeb); + if (!NT_SUCCESS(Status)) { - PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType); - ObDereferenceObject(Thread); - return(Status); + PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType); + ObDereferenceObject(Thread); + return(Status); } - Thread->Tcb.Teb = TebBase; + Thread->Tcb.Teb = TebBase;
- Thread->StartAddress = NULL; + Thread->StartAddress = NULL;
- /* - * Maybe send a message to the process's debugger - */ - DbgkCreateThread((PVOID)ThreadContext->Eip); + /* + * Maybe send a message to the process's debugger + */ + DbgkCreateThread((PVOID)ThreadContext->Eip);
- /* - * First, force the thread to be non-alertable for user-mode alerts. - */ - Thread->Tcb.Alertable = FALSE; + /* + * First, force the thread to be non-alertable for user-mode alerts. + */ + Thread->Tcb.Alertable = FALSE;
- /* - * If the thread is to be created suspended then queue an APC to - * do the suspend before we run any userspace code. - */ - if (CreateSuspended) + /* + * If the thread is to be created suspended then queue an APC to + * do the suspend before we run any userspace code. + */ + if (CreateSuspended) { - KeSuspendThread(&Thread->Tcb); + KeSuspendThread(&Thread->Tcb); }
- /* - * Queue an APC to the thread that will execute the ntdll startup - * routine. - */ - LdrInitApc = ExAllocatePool(NonPagedPool, sizeof(KAPC)); - KeInitializeApc(LdrInitApc, &Thread->Tcb, OriginalApcEnvironment, LdrInitApcKernelRoutine, - LdrInitApcRundownRoutine, LdrpGetSystemDllEntryPoint(), - UserMode, NULL); - KeInsertQueueApc(LdrInitApc, NULL, NULL, IO_NO_INCREMENT); - - /* - * The thread is non-alertable, so the APC we added did not set UserApcPending to TRUE. - * We must do this manually. Do NOT attempt to set the Thread to Alertable before the call, - * doing so is a blatant and erronous hack. - */ - Thread->Tcb.ApcState.UserApcPending = TRUE; - Thread->Tcb.Alerted[KernelMode] = TRUE; + /* + * Queue an APC to the thread that will execute the ntdll startup + * routine. + */ + LdrInitApc = ExAllocatePoolWithTag ( + NonPagedPool, sizeof(KAPC), TAG_KAPC ); + KeInitializeApc ( + LdrInitApc, + &Thread->Tcb, + OriginalApcEnvironment, + LdrInitApcKernelRoutine, + LdrInitApcRundownRoutine, + LdrpGetSystemDllEntryPoint(), + UserMode, + NULL ); + KeInsertQueueApc(LdrInitApc, NULL, NULL, IO_NO_INCREMENT);
- oldIrql = KeAcquireDispatcherDatabaseLock (); - KiUnblockThread(&Thread->Tcb, NULL, 0); - KeReleaseDispatcherDatabaseLock(oldIrql); + /* + * The thread is non-alertable, so the APC we added did not set UserApcPending to TRUE. + * We must do this manually. Do NOT attempt to set the Thread to Alertable before the call, + * doing so is a blatant and erronous hack. + */ + Thread->Tcb.ApcState.UserApcPending = TRUE; + Thread->Tcb.Alerted[KernelMode] = TRUE;
- Status = ObInsertObject((PVOID)Thread, - NULL, - DesiredAccess, - 0, - NULL, - &hThread); - if(NT_SUCCESS(Status)) - { - _SEH_TRY + oldIrql = KeAcquireDispatcherDatabaseLock (); + KiUnblockThread(&Thread->Tcb, NULL, 0); + KeReleaseDispatcherDatabaseLock(oldIrql); + + Status = ObInsertObject((PVOID)Thread, + NULL, + DesiredAccess, + 0, + NULL, + &hThread); + if(NT_SUCCESS(Status)) { - if(ClientId != NULL) - { - *ClientId = Thread->Cid; - } - *ThreadHandle = hThread; + _SEH_TRY + { + if(ClientId != NULL) + { + *ClientId = Thread->Cid; + } + *ThreadHandle = hThread; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - - return Status; + + return Status; }
@@ -503,17 +517,18 @@ * @implemented */ NTSTATUS STDCALL -PsCreateSystemThread(PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - HANDLE ProcessHandle, - PCLIENT_ID ClientId, - PKSTART_ROUTINE StartRoutine, - PVOID StartContext) +PsCreateSystemThread ( + PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext ) /* * FUNCTION: Creates a thread which executes in kernel mode * ARGUMENTS: - * ThreadHandle (OUT) = Caller supplied storage for the returned thread + * ThreadHandle (OUT) = Caller supplied storage for the returned thread * handle * DesiredAccess = Requested access to the thread * ObjectAttributes = Object attributes (optional) @@ -527,78 +542,82 @@ * RETURNS: Success or failure status */ { - PETHREAD Thread; - NTSTATUS Status; - KIRQL oldIrql; - - PAGED_CODE(); - - DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n", - ThreadHandle,ProcessHandle); - - Status = PsInitializeThread(NULL, - &Thread, - ObjectAttributes, - KernelMode, - FALSE); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + PETHREAD Thread; + NTSTATUS Status; + KIRQL oldIrql;
+ PAGED_CODE(); + + DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n", + ThreadHandle,ProcessHandle); + + Status = PsInitializeThread( + NULL, + &Thread, + ObjectAttributes, + KernelMode, + FALSE); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + /* Set the thread as a system thread */ Thread->SystemThread = TRUE; - - Status = PsCreateCidHandle(Thread, - PsThreadType, - &Thread->Cid.UniqueThread); - if(!NT_SUCCESS(Status)) - { - ObDereferenceObject(Thread); - return Status; - } - - Thread->StartAddress = StartRoutine; - Status = KiArchInitThread(&Thread->Tcb, StartRoutine, StartContext); - if (!NT_SUCCESS(Status)) - { + + Status = PsCreateCidHandle(Thread, + PsThreadType, + &Thread->Cid.UniqueThread); + if(!NT_SUCCESS(Status)) + { ObDereferenceObject(Thread); + return Status; + } + + Thread->StartAddress = StartRoutine; + Status = KiArchInitThread ( + &Thread->Tcb, StartRoutine, StartContext); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(Thread); return(Status); - } + }
- if (ClientId != NULL) - { - *ClientId=Thread->Cid; - } + if (ClientId != NULL) + { + *ClientId=Thread->Cid; + }
- oldIrql = KeAcquireDispatcherDatabaseLock (); - KiUnblockThread(&Thread->Tcb, NULL, 0); - KeReleaseDispatcherDatabaseLock(oldIrql); - - Status = ObInsertObject((PVOID)Thread, - NULL, - DesiredAccess, - 0, - NULL, - ThreadHandle); - - /* don't dereference the thread, the initial reference serves as the keep-alive - reference which will be removed by the thread reaper */ - - return Status; + oldIrql = KeAcquireDispatcherDatabaseLock (); + KiUnblockThread(&Thread->Tcb, NULL, 0); + KeReleaseDispatcherDatabaseLock(oldIrql); + + Status = ObInsertObject( + (PVOID)Thread, [truncated at 1000 lines; 58 more skipped]