-/* $Id: create.c,v 1.12 2000/03/22 18:35:57 dwelch Exp $
+/* $Id: create.c,v 1.73 2004/03/24 22:00:39 ea Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* REVISION HISTORY:
* 23/06/98: Created
* 12/10/99: Phillip Susi: Thread priorities, and APC work
+ * 09/08/03: Skywing: ThreadEventPair support (delete)
*/
/*
/* INCLUDES ****************************************************************/
-#include <ddk/ntddk.h>
+#include <limits.h>
+
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
#include <internal/ke.h>
#include <internal/ob.h>
-#include <string.h>
-#include <internal/string.h>
-#include <internal/hal.h>
#include <internal/ps.h>
-#include <internal/ob.h>
+#include <internal/se.h>
+#include <internal/id.h>
+#include <internal/dbg.h>
+#include <internal/ldr.h>
#define NDEBUG
#include <internal/debug.h>
extern LIST_ENTRY PiThreadListHead;
+#define MAX_THREAD_NOTIFY_ROUTINE_COUNT 8
+
+static ULONG PiThreadNotifyRoutineCount = 0;
+static PCREATE_THREAD_NOTIFY_ROUTINE
+PiThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT];
+
/* FUNCTIONS ***************************************************************/
-NTSTATUS PsAssignImpersonationToken(PETHREAD Thread,
- HANDLE TokenHandle)
+NTSTATUS STDCALL
+PsAssignImpersonationToken(PETHREAD Thread,
+ HANDLE TokenHandle)
{
PACCESS_TOKEN Token;
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
NTSTATUS Status;
-
+
if (TokenHandle != NULL)
{
Status = ObReferenceObjectByHandle(TokenHandle,
0,
- SeTokenType,
+ SepTokenObjectType,
UserMode,
(PVOID*)&Token,
NULL);
Token = NULL;
ImpersonationLevel = 0;
}
-
+
PsImpersonateClient(Thread,
Token,
0,
return(STATUS_SUCCESS);
}
-VOID PsRevertToSelf(PETHREAD Thread)
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+PsRevertToSelf (VOID)
{
- if (Thread->ActiveImpersonationInfo != 0)
- {
- Thread->ActiveImpersonationInfo = 0;
- ObDereferenceObject(Thread->ImpersonationInfo->Token);
- }
+ PETHREAD Thread;
+
+ Thread = PsGetCurrentThread ();
+
+ if (Thread->ActiveImpersonationInfo == TRUE)
+ {
+ ObDereferenceObject (Thread->ImpersonationInfo->Token);
+ Thread->ActiveImpersonationInfo = FALSE;
+ }
}
-VOID PsImpersonateClient(PETHREAD Thread,
- PACCESS_TOKEN Token,
- UCHAR b,
- UCHAR c,
- SECURITY_IMPERSONATION_LEVEL Level)
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+PsImpersonateClient (IN PETHREAD Thread,
+ IN PACCESS_TOKEN Token,
+ IN BOOLEAN CopyOnOpen,
+ IN BOOLEAN EffectiveOnly,
+ IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
{
- if (Token == 0)
- {
- if (Thread->ActiveImpersonationInfo != 0)
- {
- Thread->ActiveImpersonationInfo = 0;
- if (Thread->ImpersonationInfo->Token != NULL)
- {
- ObDereferenceObject(Thread->ImpersonationInfo->Token);
- }
- }
- return;
- }
- if (Thread->ActiveImpersonationInfo == 0 ||
- Thread->ImpersonationInfo == NULL)
- {
- Thread->ImpersonationInfo = ExAllocatePool(NonPagedPool,
- sizeof(PS_IMPERSONATION_INFO));
- }
- Thread->ImpersonationInfo->Level = Level;
- Thread->ImpersonationInfo->Unknown2 = c;
- Thread->ImpersonationInfo->Unknown1 = b;
- Thread->ImpersonationInfo->Token = Token;
- ObReferenceObjectByPointer(Token,
+ if (Token == NULL)
+ {
+ if (Thread->ActiveImpersonationInfo == TRUE)
+ {
+ Thread->ActiveImpersonationInfo = FALSE;
+ if (Thread->ImpersonationInfo->Token != NULL)
+ {
+ ObDereferenceObject (Thread->ImpersonationInfo->Token);
+ }
+ }
+ return;
+ }
+
+ if (Thread->ImpersonationInfo == NULL)
+ {
+ Thread->ImpersonationInfo = ExAllocatePool (NonPagedPool,
+ sizeof(PS_IMPERSONATION_INFO));
+ }
+
+ Thread->ImpersonationInfo->Level = ImpersonationLevel;
+ Thread->ImpersonationInfo->CopyOnOpen = CopyOnOpen;
+ Thread->ImpersonationInfo->EffectiveOnly = EffectiveOnly;
+ Thread->ImpersonationInfo->Token = Token;
+ ObReferenceObjectByPointer (Token,
0,
- SeTokenType,
+ SepTokenObjectType,
KernelMode);
- Thread->ActiveImpersonationInfo = 1;
+ Thread->ActiveImpersonationInfo = TRUE;
}
-PACCESS_TOKEN PsReferenceEffectiveToken(PETHREAD Thread,
- PTOKEN_TYPE TokenType,
- PUCHAR b,
- PSECURITY_IMPERSONATION_LEVEL Level)
+
+PACCESS_TOKEN
+PsReferenceEffectiveToken(PETHREAD Thread,
+ PTOKEN_TYPE TokenType,
+ PBOOLEAN EffectiveOnly,
+ PSECURITY_IMPERSONATION_LEVEL Level)
{
PEPROCESS Process;
PACCESS_TOKEN Token;
- if (Thread->ActiveImpersonationInfo == 0)
+ if (Thread->ActiveImpersonationInfo == FALSE)
{
Process = Thread->ThreadsProcess;
*TokenType = TokenPrimary;
- *b = 0;
+ *EffectiveOnly = FALSE;
Token = Process->Token;
}
else
{
Token = Thread->ImpersonationInfo->Token;
*TokenType = TokenImpersonation;
- *b = Thread->ImpersonationInfo->Unknown2;
- *Level = Thread->ImpersonationInfo->Level;
+ *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
+ *Level = Thread->ImpersonationInfo->Level;
}
return(Token);
}
-NTSTATUS STDCALL NtImpersonateThread (IN HANDLE ThreadHandle,
- IN HANDLE ThreadToImpersonateHandle,
- IN PSECURITY_QUALITY_OF_SERVICE
- SecurityQualityOfService)
+
+NTSTATUS STDCALL
+NtImpersonateThread(IN HANDLE ThreadHandle,
+ IN HANDLE ThreadToImpersonateHandle,
+ IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService)
{
- PETHREAD Thread;
- PETHREAD ThreadToImpersonate;
- NTSTATUS Status;
- SE_SOME_STRUCT2 b;
-
- Status = ObReferenceObjectByHandle(ThreadHandle,
+ SECURITY_CLIENT_CONTEXT ClientContext;
+ PETHREAD Thread;
+ PETHREAD ThreadToImpersonate;
+ NTSTATUS Status;
+
+ Status = ObReferenceObjectByHandle (ThreadHandle,
0,
PsThreadType,
UserMode,
(PVOID*)&Thread,
NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle,
+ if (!NT_SUCCESS (Status))
+ {
+ return Status;
+ }
+
+ Status = ObReferenceObjectByHandle (ThreadToImpersonateHandle,
0,
PsThreadType,
UserMode,
(PVOID*)&ThreadToImpersonate,
NULL);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Thread);
- return(Status);
- }
-
- Status = SeCreateClientSecurity(ThreadToImpersonate,
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (Thread);
+ return Status;
+ }
+
+ Status = SeCreateClientSecurity (ThreadToImpersonate,
SecurityQualityOfService,
0,
- &b);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Thread);
- ObDereferenceObject(ThreadToImpersonate);
- return(Status);
+ &ClientContext);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (ThreadToImpersonate);
+ ObDereferenceObject (Thread);
+ return Status;
}
-
- SeImpersonateClient(&b, Thread);
- if (b.Token != NULL)
- {
- ObDereferenceObject(b.Token);
- }
- return(STATUS_SUCCESS);
+
+ SeImpersonateClient (&ClientContext,
+ Thread);
+ if (ClientContext.Token != NULL)
+ {
+ ObDereferenceObject (ClientContext.Token);
+ }
+
+ ObDereferenceObject (ThreadToImpersonate);
+ ObDereferenceObject (Thread);
+
+ return STATUS_SUCCESS;
}
-NTSTATUS STDCALL NtOpenThreadToken(IN HANDLE ThreadHandle,
- IN ACCESS_MASK DesiredAccess,
- IN BOOLEAN OpenAsSelf,
- OUT PHANDLE TokenHandle)
+
+NTSTATUS STDCALL
+NtOpenThreadToken (IN HANDLE ThreadHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN OpenAsSelf,
+ OUT PHANDLE TokenHandle)
{
-#if 0
- PETHREAD Thread;
- NTSTATUS Status;
- PACCESS_TOKEN Token;
-
- Status = ObReferenceObjectByHandle(ThreadHandle,
+ PACCESS_TOKEN Token;
+ PETHREAD Thread;
+ NTSTATUS Status;
+
+ Status = ObReferenceObjectByHandle (ThreadHandle,
0,
PsThreadType,
UserMode,
{
return(Status);
}
-
- Token = PsReferencePrimaryToken(Thread->ThreadsProcess);
- SepCreateImpersonationTokenDacl(Token);
-#endif
- return(STATUS_UNSUCCESSFUL);
+
+ if (OpenAsSelf)
+ {
+ if (Thread->ActiveImpersonationInfo == FALSE)
+ {
+ ObDereferenceObject (Thread);
+ return STATUS_NO_TOKEN;
+ }
+
+ Token = Thread->ImpersonationInfo->Token;
+ }
+ else
+ {
+ Token = Thread->ThreadsProcess->Token;
+ }
+
+ if (Token == NULL)
+ {
+ ObDereferenceObject (Thread);
+ return STATUS_NO_TOKEN;
+ }
+
+ Status = ObCreateHandle (PsGetCurrentProcess(),
+ Token,
+ DesiredAccess,
+ FALSE,
+ TokenHandle);
+
+ ObDereferenceObject (Thread);
+
+ return Status;
}
-PACCESS_TOKEN PsReferenceImpersonationToken(PETHREAD Thread,
- PULONG Unknown1,
- PULONG Unknown2,
- SECURITY_IMPERSONATION_LEVEL*
- Level)
+
+/*
+ * @implemented
+ */
+PACCESS_TOKEN STDCALL
+PsReferenceImpersonationToken(IN PETHREAD Thread,
+ OUT PBOOLEAN CopyOnOpen,
+ OUT PBOOLEAN EffectiveOnly,
+ OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
{
- if (Thread->ActiveImpersonationInfo == 0)
- {
- return(NULL);
- }
-
- *Level = Thread->ImpersonationInfo->Level;
- *Unknown1 = Thread->ImpersonationInfo->Unknown1;
- *Unknown2 = Thread->ImpersonationInfo->Unknown2;
- ObReferenceObjectByPointer(Thread->ImpersonationInfo->Token,
- GENERIC_ALL,
- SeTokenType,
+ if (Thread->ActiveImpersonationInfo == FALSE)
+ {
+ return NULL;
+ }
+
+ *ImpersonationLevel = Thread->ImpersonationInfo->Level;
+ *CopyOnOpen = Thread->ImpersonationInfo->CopyOnOpen;
+ *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
+ ObReferenceObjectByPointer (Thread->ImpersonationInfo->Token,
+ TOKEN_ALL_ACCESS,
+ SepTokenObjectType,
KernelMode);
- return(Thread->ImpersonationInfo->Token);
-}
-static VOID PiTimeoutThread(struct _KDPC *dpc,
- PVOID Context,
- PVOID arg1,
- PVOID arg2 )
-{
- // wake up the thread, and tell it it timed out
- NTSTATUS Status = STATUS_TIMEOUT;
-
- DPRINT("PiTimeoutThread()\n");
-
- KeRemoveAllWaitsThread((PETHREAD)Context, Status);
+ return Thread->ImpersonationInfo->Token;
}
-VOID PiBeforeBeginThread(VOID)
-{
- DPRINT("PiBeforeBeginThread()\n");
- //KeReleaseSpinLock(&PiThreadListLock, PASSIVE_LEVEL);
- KeLowerIrql(PASSIVE_LEVEL);
-}
-VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
+VOID
+PiBeforeBeginThread(CONTEXT c)
{
- NTSTATUS Ret;
-
-// KeReleaseSpinLock(&PiThreadListLock,PASSIVE_LEVEL);
KeLowerIrql(PASSIVE_LEVEL);
- Ret = StartRoutine(StartContext);
- PsTerminateSystemThread(Ret);
- KeBugCheck(0);
}
-VOID PiDeleteThread(PVOID ObjectBody)
-{
- KIRQL oldIrql;
-
- DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
-
- KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
- DPRINT("Process %x(%d)\n", ((PETHREAD)ObjectBody)->ThreadsProcess,
- ObGetReferenceCount(((PETHREAD)ObjectBody)->ThreadsProcess));
- ObDereferenceObject(((PETHREAD)ObjectBody)->ThreadsProcess);
- ((PETHREAD)ObjectBody)->ThreadsProcess = NULL;
- PiNrThreads--;
- RemoveEntryList(&((PETHREAD)ObjectBody)->Tcb.ThreadListEntry);
- HalReleaseTask((PETHREAD)ObjectBody);
- KeReleaseSpinLock(&PiThreadListLock, oldIrql);
- DPRINT("PiDeleteThread() finished\n");
-}
-VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount)
+VOID STDCALL
+PiDeleteThread(PVOID ObjectBody)
{
- DPRINT("PiCloseThread(ObjectBody %x)\n", ObjectBody);
- DPRINT("ObGetReferenceCount(ObjectBody) %d "
- "ObGetHandleCount(ObjectBody) %d\n",
- ObGetReferenceCount(ObjectBody),
- ObGetHandleCount(ObjectBody));
+ KIRQL oldIrql;
+ PETHREAD Thread;
+
+ Thread = (PETHREAD)ObjectBody;
+
+ DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
+
+ ObDereferenceObject(Thread->ThreadsProcess);
+ Thread->ThreadsProcess = NULL;
+
+ KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
+ PiNrThreads--;
+ RemoveEntryList(&Thread->Tcb.ThreadListEntry);
+ KeReleaseSpinLock(&PiThreadListLock, oldIrql);
+
+ KeReleaseThread(Thread);
+ DPRINT("PiDeleteThread() finished\n");
}
-NTSTATUS PsInitializeThread(HANDLE ProcessHandle,
- PETHREAD* ThreadPtr,
- PHANDLE ThreadHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ThreadAttributes)
+
+NTSTATUS
+PsInitializeThread(HANDLE ProcessHandle,
+ PETHREAD* ThreadPtr,
+ PHANDLE ThreadHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ThreadAttributes,
+ BOOLEAN First)
{
PETHREAD Thread;
NTSTATUS Status;
KIRQL oldIrql;
PEPROCESS Process;
-
+
/*
* Reference process
*/
DPRINT("Failed at %s:%d\n",__FILE__,__LINE__);
return(Status);
}
+ DPRINT( "Creating thread in process %x\n", Process );
}
else
{
- Process = SystemProcess;
+ Process = PsInitialSystemProcess;
ObReferenceObjectByPointer(Process,
PROCESS_CREATE_THREAD,
PsProcessType,
/*
* Create and initialize thread
*/
- Thread = ObCreateObject(ThreadHandle,
- DesiredAccess,
+ Status = ObCreateObject(UserMode,
+ PsThreadType,
ThreadAttributes,
- PsThreadType);
+ UserMode,
+ NULL,
+ sizeof(ETHREAD),
+ 0,
+ 0,
+ (PVOID*)&Thread);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ Status = ObInsertObject ((PVOID)Thread,
+ NULL,
+ DesiredAccess,
+ 0,
+ NULL,
+ ThreadHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (Thread);
+ return Status;
+ }
+
DPRINT("Thread = %x\n",Thread);
PiNrThreads++;
- Thread->Tcb.State = THREAD_STATE_SUSPENDED;
- Thread->Tcb.SuspendCount = 0;
- Thread->Tcb.FreezeCount = 1;
- InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[0]);
- InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[1]);
- Thread->Tcb.KernelApcDisable = 1;
- Thread->Tcb.WaitIrql = PASSIVE_LEVEL;
+ KeInitializeThread(&Process->Pcb, &Thread->Tcb, First);
Thread->ThreadsProcess = Process;
- KeInitializeDpc(&Thread->Tcb.TimerDpc, PiTimeoutThread, Thread);
- Thread->Tcb.WaitBlockList = NULL;
- InsertTailList(&Thread->ThreadsProcess->Pcb.ThreadListHead,
- &Thread->Tcb.ProcessThreadListEntry );
-// DPRINT1("Inserting %x into process %x list\n",
-// Thread, Thread->ThreadsProcess);
- KeInitializeDispatcherHeader(&Thread->Tcb.DispatcherHeader,
- InternalThreadType,
- sizeof(ETHREAD),
- FALSE);
-
+ /*
+ * FIXME: What lock protects this?
+ */
+ InsertTailList(&Thread->ThreadsProcess->ThreadListHead,
+ &Thread->Tcb.ProcessThreadListEntry);
+ InitializeListHead(&Thread->TerminationPortList);
+ KeInitializeSpinLock(&Thread->ActiveTimerListLock);
InitializeListHead(&Thread->IrpList);
Thread->Cid.UniqueThread = (HANDLE)InterlockedIncrement(
- &PiNextThreadUniqueId);
+ (LONG *)&PiNextThreadUniqueId);
Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
+ Thread->DeadThread = 0;
+ Thread->Win32Thread = 0;
DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
*ThreadPtr = Thread;
InsertTailList(&PiThreadListHead, &Thread->Tcb.ThreadListEntry);
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
- Thread->Tcb.BasePriority = Thread->ThreadsProcess->Pcb.BasePriority;
+ Thread->Tcb.BasePriority = (CHAR)Thread->ThreadsProcess->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;
+
return(STATUS_SUCCESS);
}
-static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
- PNT_TEB *TebPtr,
- PETHREAD Thread,
- PINITIAL_TEB InitialTeb)
+static NTSTATUS
+PsCreateTeb(HANDLE ProcessHandle,
+ PTEB *TebPtr,
+ PETHREAD Thread,
+ PUSER_STACK UserStack)
{
-// MEMORY_BASIC_INFORMATION Info;
+ MEMORY_BASIC_INFORMATION Info;
NTSTATUS Status;
ULONG ByteCount;
ULONG RegionSize;
ULONG TebSize;
PVOID TebBase;
- NT_TEB Teb;
+ TEB Teb;
+ ULONG ResultLength;
TebBase = (PVOID)0x7FFDE000;
- TebSize = PAGESIZE;
+ TebSize = PAGE_SIZE;
while (TRUE)
{
- /* The TEB must reside in user space */
- Status = NtAllocateVirtualMemory(ProcessHandle,
- &TebBase,
- 0,
- &TebSize,
- MEM_COMMIT,
- PAGE_READWRITE);
- if (NT_SUCCESS(Status))
- {
-// DPRINT1 ("TEB allocated at %x\n", TebBase);
- break;
- }
- else
- {
- DPRINT ("TEB allocation failed! Status %x\n",Status);
- for(;;);
- return(Status);
- }
-
-// TebBase = Info.BaseAddress - TebSize;
- TebBase = TebBase - TebSize;
- }
+ Status = NtQueryVirtualMemory(ProcessHandle,
+ TebBase,
+ MemoryBasicInformation,
+ &Info,
+ sizeof(Info),
+ &ResultLength);
+ if (!NT_SUCCESS(Status))
+ {
+ CPRINT("NtQueryVirtualMemory (Status %x)\n", Status);
+ KEBUGCHECK(0);
+ }
+ /* FIXME: Race between this and the above check */
+ if (Info.State == MEM_FREE)
+ {
+ /* The TEB must reside in user space */
+ Status = NtAllocateVirtualMemory(ProcessHandle,
+ &TebBase,
+ 0,
+ &TebSize,
+ MEM_RESERVE | MEM_COMMIT,
+ PAGE_READWRITE);
+ if (NT_SUCCESS(Status))
+ {
+ break;
+ }
+ }
+
+ TebBase = (char*)TebBase - TebSize;
+ }
DPRINT ("TebBase %p TebSize %lu\n", TebBase, 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!! */
}
-// DPRINT1("Teb.Peb %x\n", Teb.Peb);
-
- /* store stack information from InitialTeb */
- if (InitialTeb != NULL)
- {
- Teb.Tib.StackBase = InitialTeb->StackBase;
- Teb.Tib.StackLimit = InitialTeb->StackLimit;
-
- /*
- * I don't know if this is really stored in a WNT-TEB,
- * but it's needed to free the thread stack. (Eric Kohl)
- */
- Teb.StackCommit = InitialTeb->StackCommit;
- Teb.StackCommitMax = InitialTeb->StackCommitMax;
- Teb.StackReserved = InitialTeb->StackReserved;
- }
-
+ DPRINT("Teb.Peb %x\n", Teb.Peb);
+
+ /* store stack information from UserStack */
+ if(UserStack != NULL)
+ {
+ /* fixed-size stack */
+ if(UserStack->FixedStackBase && UserStack->FixedStackLimit)
+ {
+ Teb.Tib.StackBase = UserStack->FixedStackBase;
+ Teb.Tib.StackLimit = UserStack->FixedStackLimit;
+ Teb.DeallocationStack = UserStack->FixedStackLimit;
+ }
+ /* expandable stack */
+ else
+ {
+ Teb.Tib.StackBase = UserStack->ExpandableStackBase;
+ Teb.Tib.StackLimit = UserStack->ExpandableStackLimit;
+ Teb.DeallocationStack = UserStack->ExpandableStackBottom;
+ }
+ }
/* 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(NT_TEB) %x\n", sizeof(NT_TEB));
+ DPRINT("sizeof(TEB) %x\n", sizeof(TEB));
/* write TEB data into teb page */
Status = NtWriteVirtualMemory(ProcessHandle,
TebBase,
&Teb,
- sizeof(NT_TEB),
+ sizeof(TEB),
&ByteCount);
if (!NT_SUCCESS(Status))
if (TebPtr != NULL)
{
- *TebPtr = (PNT_TEB)TebBase;
+ *TebPtr = (PTEB)TebBase;
}
-// DPRINT1 ("TEB allocated at %p\n", TebBase);
+ DPRINT("TEB allocated at %p\n", TebBase);
return Status;
}
-NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- HANDLE ProcessHandle,
- PCLIENT_ID Client,
- PCONTEXT ThreadContext,
- PINITIAL_TEB InitialTeb,
- BOOLEAN CreateSuspended)
+VOID STDCALL
+LdrInitApcRundownRoutine(PKAPC Apc)
{
- PETHREAD Thread;
- PNT_TEB TebBase;
- NTSTATUS Status;
-
- DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
- ThreadHandle,ThreadContext);
-
- Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
- DesiredAccess,ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- Status = HalInitTaskWithContext(Thread,ThreadContext);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
+ ExFreePool(Apc);
+}
- Status = PsCreateTeb (ProcessHandle,
- &TebBase,
- Thread,
- InitialTeb);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- /* Attention: TebBase is in user memory space */
- Thread->Tcb.Teb = TebBase;
+VOID STDCALL
+LdrInitApcKernelRoutine(PKAPC Apc,
+ PKNORMAL_ROUTINE* NormalRoutine,
+ PVOID* NormalContext,
+ PVOID* SystemArgument1,
+ PVOID* SystemArgument2)
+{
+ ExFreePool(Apc);
+}
- Thread->StartAddress=NULL;
- if (Client!=NULL)
- {
- *Client=Thread->Cid;
- }
-
- if (!CreateSuspended)
- {
- DPRINT("Not creating suspended\n");
- PsUnfreezeThread(Thread, NULL);
- }
- DPRINT("Thread %x\n", Thread);
- DPRINT("ObGetReferenceCount(Thread) %d ObGetHandleCount(Thread) %x\n",
- ObGetReferenceCount(Thread), ObGetHandleCount(Thread));
- DPRINT("Finished PsCreateThread()\n");
- return(STATUS_SUCCESS);
+NTSTATUS STDCALL
+NtCreateThread(PHANDLE ThreadHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ HANDLE ProcessHandle,
+ PCLIENT_ID Client,
+ PCONTEXT ThreadContext,
+ PUSER_STACK UserStack,
+ BOOLEAN CreateSuspended)
+{
+ PETHREAD Thread;
+ PTEB TebBase;
+ NTSTATUS Status;
+ PKAPC LdrInitApc;
+
+ DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
+ ThreadHandle,ThreadContext);
+
+ Status = PsInitializeThread(ProcessHandle,
+ &Thread,
+ ThreadHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ Status = PsCreateTeb(ProcessHandle,
+ &TebBase,
+ Thread,
+ UserStack);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+ Thread->Tcb.Teb = TebBase;
+
+ Thread->StartAddress = NULL;
+
+ if (Client != NULL)
+ {
+ *Client = Thread->Cid;
+ }
+
+ /*
+ * 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;
+
+ /*
+ * If the thread is to be created suspended then queue an APC to
+ * do the suspend before we run any userspace code.
+ */
+ if (CreateSuspended)
+ {
+ PsSuspendThread(Thread, NULL);
+ }
+
+ /*
+ * 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);
+
+ /*
+ * Start the thread running and force it to execute the APC(s) we just
+ * queued before it runs anything else in user-mode.
+ */
+ Thread->Tcb.Alertable = TRUE;
+ Thread->Tcb.Alerted[0] = 1;
+ PsUnblockThread(Thread, NULL);
+
+ return(STATUS_SUCCESS);
}
-NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- HANDLE ProcessHandle,
- PCLIENT_ID ClientId,
- PKSTART_ROUTINE StartRoutine,
- PVOID StartContext)
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+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:
DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
ThreadHandle,ProcessHandle);
- Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
- DesiredAccess,ObjectAttributes);
+ Status = PsInitializeThread(ProcessHandle,
+ &Thread,
+ ThreadHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ FALSE);
if (!NT_SUCCESS(Status))
{
return(Status);
}
- Thread->StartAddress=StartRoutine;
- Status = HalInitTask(Thread,StartRoutine,StartContext);
+ Thread->StartAddress = StartRoutine;
+ Status = KiArchInitThread(&Thread->Tcb, StartRoutine, StartContext);
if (!NT_SUCCESS(Status))
{
return(Status);
}
- if (ClientId!=NULL)
+ if (ClientId != NULL)
{
*ClientId=Thread->Cid;
- }
+ }
- PsUnfreezeThread(Thread, NULL);
+ PsUnblockThread(Thread, NULL);
return(STATUS_SUCCESS);
}
+
+VOID STDCALL
+PspRunCreateThreadNotifyRoutines(PETHREAD CurrentThread,
+ BOOLEAN Create)
+{
+ ULONG i;
+ CLIENT_ID Cid = CurrentThread->Cid;
+
+ for (i = 0; i < PiThreadNotifyRoutineCount; i++)
+ {
+ PiThreadNotifyRoutine[i](Cid.UniqueProcess, Cid.UniqueThread, Create);
+ }
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+PsSetCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine)
+{
+ if (PiThreadNotifyRoutineCount >= MAX_THREAD_NOTIFY_ROUTINE_COUNT)
+ {
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ PiThreadNotifyRoutine[PiThreadNotifyRoutineCount] = NotifyRoutine;
+ PiThreadNotifyRoutineCount++;
+
+ return(STATUS_SUCCESS);
+}
+
+/* EOF */