Implemented the ability to create suspended threads.

svn path=/trunk/; revision=3206
This commit is contained in:
Eric Kohl 2002-07-10 15:17:35 +00:00
parent cae7cd6a6c
commit aaf641d620
2 changed files with 168 additions and 141 deletions

View file

@ -1,4 +1,4 @@
/* $Id: create.c,v 1.46 2002/03/05 00:20:54 ekohl Exp $ /* $Id: create.c,v 1.47 2002/07/10 15:17:34 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -546,77 +546,96 @@ PsCreateTeb(HANDLE ProcessHandle,
NTSTATUS STDCALL NTSTATUS STDCALL
NtCreateThread (PHANDLE ThreadHandle, NtCreateThread(PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess, ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes, POBJECT_ATTRIBUTES ObjectAttributes,
HANDLE ProcessHandle, HANDLE ProcessHandle,
PCLIENT_ID Client, PCLIENT_ID Client,
PCONTEXT ThreadContext, PCONTEXT ThreadContext,
PINITIAL_TEB InitialTeb, PINITIAL_TEB InitialTeb,
BOOLEAN CreateSuspended) BOOLEAN CreateSuspended)
{ {
PETHREAD Thread; PETHREAD Thread;
PTEB TebBase; PTEB TebBase;
NTSTATUS Status; NTSTATUS Status;
DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
ThreadHandle,ThreadContext);
Status = PsInitializeThread(ProcessHandle,
&Thread,
ThreadHandle,
DesiredAccess,
ObjectAttributes,
FALSE);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = Ke386InitThreadWithContext(&Thread->Tcb,
ThreadContext);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = PsCreateTeb(ProcessHandle,
&TebBase,
Thread,
InitialTeb);
if (!NT_SUCCESS(Status))
{
return(Status);
}
/* Attention: TebBase is in user memory space */
Thread->Tcb.Teb = TebBase;
Thread->StartAddress=NULL; DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
ThreadHandle,ThreadContext);
if (Client != NULL) Status = PsInitializeThread(ProcessHandle,
{ &Thread,
*Client=Thread->Cid; ThreadHandle,
} DesiredAccess,
ObjectAttributes,
/* FALSE);
* Maybe send a message to the process's debugger if (!NT_SUCCESS(Status))
*/ {
DbgkCreateThread((PVOID)ThreadContext->Eip); return(Status);
}
/*
* Start the thread running Status = Ke386InitThreadWithContext(&Thread->Tcb,
*/ ThreadContext);
if (!CreateSuspended) if (!NT_SUCCESS(Status))
{ {
DPRINT("Not creating suspended\n"); return(Status);
PsUnblockThread(Thread, NULL); }
}
else Status = PsCreateTeb(ProcessHandle,
{ &TebBase,
KeBugCheck(0); Thread,
} InitialTeb);
return(STATUS_SUCCESS); if (!NT_SUCCESS(Status))
{
return(Status);
}
/* Attention: TebBase is in user memory space */
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);
/*
* Start the thread running
*/
if (!CreateSuspended)
{
DPRINT("Not creating suspended\n");
PsUnblockThread(Thread, NULL);
}
else
{
DPRINT("Creating suspended\n");
/*
* Simulate a call to NtWaitForSingleObject() upon thread startup
*/
/* Increment the suspend counter */
Thread->Tcb.SuspendCount++;
/* Add one wait-block for suspend semaphore */
Thread->Tcb.WaitStatus = STATUS_UNSUCCESSFUL;
Thread->Tcb.WaitBlockList = &Thread->Tcb.WaitBlock[0];
Thread->Tcb.WaitBlock[0].Object = (POBJECT)&Thread->Tcb.SuspendSemaphore;
Thread->Tcb.WaitBlock[0].Thread = &Thread->Tcb;
Thread->Tcb.WaitBlock[0].WaitKey = STATUS_WAIT_0;
Thread->Tcb.WaitBlock[0].WaitType = WaitAny;
Thread->Tcb.WaitBlock[0].NextWaitBlock = NULL;
InsertTailList(&Thread->Tcb.SuspendSemaphore.Header.WaitListHead,
&Thread->Tcb.WaitBlock[0].WaitListEntry);
}
return(STATUS_SUCCESS);
} }

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: suspend.c,v 1.6 2001/08/27 01:22:22 ekohl Exp $ /* $Id: suspend.c,v 1.7 2002/07/10 15:17:35 ekohl Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/suspend.c * FILE: ntoskrnl/ps/suspend.c
@ -46,6 +46,7 @@ PiSuspendThreadRundownRoutine(PKAPC Apc)
{ {
} }
VOID STDCALL VOID STDCALL
PiSuspendThreadKernelRoutine(PKAPC Apc, PiSuspendThreadKernelRoutine(PKAPC Apc,
PKNORMAL_ROUTINE* NormalRoutine, PKNORMAL_ROUTINE* NormalRoutine,
@ -55,48 +56,55 @@ PiSuspendThreadKernelRoutine(PKAPC Apc,
{ {
} }
VOID STDCALL VOID STDCALL
PiSuspendThreadNormalRoutine(PVOID NormalContext, PiSuspendThreadNormalRoutine(PVOID NormalContext,
PVOID SystemArgument1, PVOID SystemArgument1,
PVOID SystemArgument2) PVOID SystemArgument2)
{ {
KeWaitForSingleObject(&PsGetCurrentThread()->Tcb.SuspendSemaphore, KeWaitForSingleObject(&PsGetCurrentThread()->Tcb.SuspendSemaphore,
0, 0,
UserMode, UserMode,
TRUE, TRUE,
NULL); NULL);
} }
NTSTATUS NTSTATUS
PsResumeThread(PETHREAD Thread, PULONG SuspendCount) PsResumeThread(PETHREAD Thread, PULONG SuspendCount)
{ {
*SuspendCount = InterlockedDecrement((PULONG)&Thread->Tcb.SuspendCount);
KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT, 1, FALSE); KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT, 1, FALSE);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
NTSTATUS
NTSTATUS
PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount) PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount)
{ {
ULONG OldValue; ULONG OldValue;
OldValue = InterlockedIncrement((PULONG)&Thread->Tcb.SuspendCount); OldValue = InterlockedIncrement((PULONG)&Thread->Tcb.SuspendCount);
if (OldValue == 0) if (OldValue == 0)
{ {
KeInsertQueueApc(&Thread->Tcb.SuspendApc, KeInsertQueueApc(&Thread->Tcb.SuspendApc,
NULL, NULL,
NULL, NULL,
0); 0);
} }
else else
{ {
InterlockedDecrement(&Thread->Tcb.SuspendSemaphore.Header.SignalState); InterlockedDecrement(&Thread->Tcb.SuspendSemaphore.Header.SignalState);
} }
return(STATUS_SUCCESS);
return(STATUS_SUCCESS);
} }
NTSTATUS STDCALL
NtResumeThread (IN HANDLE ThreadHandle, NTSTATUS STDCALL
IN PULONG SuspendCount) NtResumeThread(IN HANDLE ThreadHandle,
IN PULONG SuspendCount)
/* /*
* FUNCTION: Decrements a thread's resume count * FUNCTION: Decrements a thread's resume count
* ARGUMENTS: * ARGUMENTS:
@ -105,36 +113,39 @@ NtResumeThread (IN HANDLE ThreadHandle,
* RETURNS: Status * RETURNS: Status
*/ */
{ {
PETHREAD Thread; PETHREAD Thread;
NTSTATUS Status; NTSTATUS Status;
ULONG Count; ULONG Count;
Status = ObReferenceObjectByHandle(ThreadHandle, DPRINT("NtResumeThead(ThreadHandle %lx SuspendCount %p)\n",
THREAD_SUSPEND_RESUME, ThreadHandle, SuspendCount);
PsThreadType,
UserMode,
(PVOID*)&Thread,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = PsResumeThread(Thread, &Count); Status = ObReferenceObjectByHandle(ThreadHandle,
if (SuspendCount != NULL) THREAD_SUSPEND_RESUME,
{ PsThreadType,
*SuspendCount = Count; UserMode,
} (PVOID*)&Thread,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
ObDereferenceObject((PVOID)Thread); Status = PsResumeThread(Thread, &Count);
if (SuspendCount != NULL)
{
*SuspendCount = Count;
}
return STATUS_SUCCESS; ObDereferenceObject((PVOID)Thread);
return(STATUS_SUCCESS);
} }
NTSTATUS STDCALL NTSTATUS STDCALL
NtSuspendThread (IN HANDLE ThreadHandle, NtSuspendThread(IN HANDLE ThreadHandle,
IN PULONG PreviousSuspendCount) IN PULONG PreviousSuspendCount)
/* /*
* FUNCTION: Increments a thread's suspend count * FUNCTION: Increments a thread's suspend count
* ARGUMENTS: * ARGUMENTS:
@ -147,35 +158,32 @@ NtSuspendThread (IN HANDLE ThreadHandle,
* The suspend count is not increased if it is greater than * The suspend count is not increased if it is greater than
* MAXIMUM_SUSPEND_COUNT. * MAXIMUM_SUSPEND_COUNT.
* RETURNS: Status * RETURNS: Status
*/ */
{ {
PETHREAD Thread; PETHREAD Thread;
NTSTATUS Status; NTSTATUS Status;
ULONG Count; ULONG Count;
Status = ObReferenceObjectByHandle(ThreadHandle, Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SUSPEND_RESUME, THREAD_SUSPEND_RESUME,
PsThreadType, PsThreadType,
UserMode, UserMode,
(PVOID*)&Thread, (PVOID*)&Thread,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return(Status); return(Status);
} }
Status = PsSuspendThread(Thread, &Count); Status = PsSuspendThread(Thread, &Count);
if (PreviousSuspendCount != NULL) if (PreviousSuspendCount != NULL)
{ {
*PreviousSuspendCount = Count; *PreviousSuspendCount = Count;
} }
ObDereferenceObject((PVOID)Thread); ObDereferenceObject((PVOID)Thread);
return STATUS_SUCCESS; return(STATUS_SUCCESS);
} }
/* EOF */