mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 10:45:24 +00:00
- Acquire Process lock when touching the thread list entry and incrementing the process' active threads.
- Set the Thread Create Time on creation, I had forgotten this! - Handle failures for thread-safety/race conditions. If the process was deleted or the thread terminated behind our back, then go through a manual un-initalization code path. - Just like previous process patch, add code to now create an access state with SeCreateAccessStateEx. - Handle failure of ObInsertObject. svn path=/trunk/; revision=23249
This commit is contained in:
parent
78ffb6aecc
commit
3774a4b259
|
@ -291,6 +291,12 @@ KeInitializeThread(
|
||||||
IN PVOID KernelStack
|
IN PVOID KernelStack
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
KeUninitThread(
|
||||||
|
IN PKTHREAD Thread
|
||||||
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
KeInitThread(
|
KeInitThread(
|
||||||
|
|
|
@ -193,6 +193,13 @@ ObpDeleteObject(
|
||||||
IN PVOID Object
|
IN PVOID Object
|
||||||
);
|
);
|
||||||
|
|
||||||
|
LONG
|
||||||
|
FASTCALL
|
||||||
|
ObDereferenceObjectEx(
|
||||||
|
IN PVOID Object,
|
||||||
|
IN ULONG Count
|
||||||
|
);
|
||||||
|
|
||||||
LONG
|
LONG
|
||||||
FASTCALL
|
FASTCALL
|
||||||
ObReferenceObjectEx(
|
ObReferenceObjectEx(
|
||||||
|
|
|
@ -728,6 +728,15 @@ KeCapturePersistentThreadState(IN PVOID CurrentThread,
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
KeUninitThread(IN PKTHREAD Thread)
|
||||||
|
{
|
||||||
|
/* Delete the stack */
|
||||||
|
MmDeleteKernelStack(Thread->StackBase, FALSE);
|
||||||
|
Thread->InitialStack = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
KeInitThread(IN OUT PKTHREAD Thread,
|
KeInitThread(IN OUT PKTHREAD Thread,
|
||||||
|
|
|
@ -146,6 +146,9 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
HANDLE_TABLE_ENTRY CidEntry;
|
HANDLE_TABLE_ENTRY CidEntry;
|
||||||
|
ACCESS_STATE LocalAccessState;
|
||||||
|
PACCESS_STATE AccessState = &LocalAccessState;
|
||||||
|
AUX_DATA AuxData;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* If we were called from PsCreateSystemThread, then we're kernel mode */
|
/* If we were called from PsCreateSystemThread, then we're kernel mode */
|
||||||
|
@ -299,7 +302,21 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Acquire exclusive pushlock */
|
/* Lock the process */
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
ExAcquirePushLockExclusive(&Process->ProcessLock);
|
||||||
|
|
||||||
|
/* Make sure the proces didn't just die on us */
|
||||||
|
if (Process->ProcessDelete) goto Quickie;
|
||||||
|
|
||||||
|
/* Check if the thread was ours, terminated and it was user mode */
|
||||||
|
if ((Thread->Terminated) &&
|
||||||
|
(ThreadContext) &&
|
||||||
|
(Thread->ThreadsProcess == Process))
|
||||||
|
{
|
||||||
|
/* Cleanup, we don't want to start it up and context switch */
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert the Thread into the Process's Thread List
|
* Insert the Thread into the Process's Thread List
|
||||||
|
@ -312,7 +329,9 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
||||||
/* Start the thread */
|
/* Start the thread */
|
||||||
KeStartThread(&Thread->Tcb);
|
KeStartThread(&Thread->Tcb);
|
||||||
|
|
||||||
/* FIXME: Wake pushlock */
|
/* Release the process lock */
|
||||||
|
ExReleasePushLockExclusive(&Process->ProcessLock);
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
|
||||||
/* Release rundown */
|
/* Release rundown */
|
||||||
ExReleaseRundownProtection(&Process->RundownProtect);
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||||
|
@ -333,13 +352,43 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
||||||
/* Check if we were already terminated */
|
/* Check if we were already terminated */
|
||||||
if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb);
|
if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb);
|
||||||
|
|
||||||
|
/* Create an access state */
|
||||||
|
Status = SeCreateAccessStateEx(NULL,
|
||||||
|
ThreadContext ?
|
||||||
|
PsGetCurrentProcess() : Process,
|
||||||
|
&LocalAccessState,
|
||||||
|
&AuxData,
|
||||||
|
DesiredAccess,
|
||||||
|
&PsThreadType->TypeInfo.GenericMapping);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Access state failed, thread is dead */
|
||||||
|
InterlockedOr(&Thread->CrossThreadFlags, CT_DEAD_THREAD_BIT);
|
||||||
|
|
||||||
|
/* If we were suspended, wake it up */
|
||||||
|
if (CreateSuspended) KeResumeThread(&Thread->Tcb);
|
||||||
|
|
||||||
|
/* Dispatch thread */
|
||||||
|
OldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||||
|
KiReadyThread(&Thread->Tcb);
|
||||||
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
|
|
||||||
|
/* Dereference completely to kill it */
|
||||||
|
ObDereferenceObjectEx(Thread, 2);
|
||||||
|
}
|
||||||
|
|
||||||
/* Insert the Thread into the Object Manager */
|
/* Insert the Thread into the Object Manager */
|
||||||
Status = ObInsertObject(Thread,
|
Status = ObInsertObject(Thread,
|
||||||
NULL,
|
AccessState,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
&hThread);
|
&hThread);
|
||||||
|
|
||||||
|
/* Delete the access state if we had one */
|
||||||
|
if (AccessState) SeDeleteAccessState(AccessState);
|
||||||
|
|
||||||
|
/* Check for success */
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Wrap in SEH to protect against bad user-mode pointers */
|
/* Wrap in SEH to protect against bad user-mode pointers */
|
||||||
|
@ -356,6 +405,18 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
||||||
}
|
}
|
||||||
_SEH_END;
|
_SEH_END;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Thread insertion failed, thread is dead */
|
||||||
|
InterlockedOr(&Thread->CrossThreadFlags, CT_DEAD_THREAD_BIT);
|
||||||
|
|
||||||
|
/* If we were suspended, wake it up */
|
||||||
|
if (CreateSuspended) KeResumeThread(&Thread->Tcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the create time */
|
||||||
|
KeQuerySystemTime(&Thread->CreateTime);
|
||||||
|
ASSERT(!(Thread->CreateTime.HighPart & 0xF0000000));
|
||||||
|
|
||||||
/* Set the thread access mask */
|
/* Set the thread access mask */
|
||||||
Thread->GrantedAccess = THREAD_ALL_ACCESS;
|
Thread->GrantedAccess = THREAD_ALL_ACCESS;
|
||||||
|
@ -370,6 +431,24 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
||||||
|
|
||||||
/* Return */
|
/* Return */
|
||||||
return Status;
|
return Status;
|
||||||
|
|
||||||
|
/* Most annoying failure case ever, where we undo almost all manually */
|
||||||
|
Quickie:
|
||||||
|
/* When we get here, the process is locked, unlock it */
|
||||||
|
ExReleasePushLockExclusive(&Process->ProcessLock);
|
||||||
|
|
||||||
|
/* Uninitailize it */
|
||||||
|
KeUninitThread(&Thread->Tcb);
|
||||||
|
|
||||||
|
/* If we had a TEB, delete it */
|
||||||
|
if (TebBase) MmDeleteTeb(Process, TebBase);
|
||||||
|
|
||||||
|
/* Release rundown protection, which we also hold */
|
||||||
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||||
|
|
||||||
|
/* Dereference the thread and return failure */
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
return STATUS_PROCESS_IS_TERMINATING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PUBLIC FUNCTIONS **********************************************************/
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
|
|
Loading…
Reference in a new issue