2005-04-18 12:46:06 +08:00
|
|
|
/*
|
2006-07-10 02:54:13 +08:00
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2005-01-26 21:58:37 +08:00
|
|
|
* FILE: ntoskrnl/ps/thread.c
|
2006-07-10 02:54:13 +08:00
|
|
|
* PURPOSE: Process Manager: Thread Management
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
2006-07-17 01:19:21 +08:00
|
|
|
* Thomas Weidenmueller (w3seek@reactos.org)
|
2006-07-10 02:54:13 +08:00
|
|
|
*/
|
|
|
|
|
1999-01-17 05:03:00 +08:00
|
|
|
/* INCLUDES ****************************************************************/
|
|
|
|
|
2004-08-16 00:39:12 +08:00
|
|
|
#include <ntoskrnl.h>
|
1999-01-17 05:03:00 +08:00
|
|
|
#define NDEBUG
|
2008-08-31 00:31:06 +08:00
|
|
|
#include <debug.h>
|
1999-01-17 05:03:00 +08:00
|
|
|
|
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
extern BOOLEAN CcPfEnablePrefetcher;
|
|
|
|
extern ULONG MmReadClusterSize;
|
2005-11-22 10:30:18 +08:00
|
|
|
POBJECT_TYPE PsThreadType = NULL;
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-20 13:33:03 +08:00
|
|
|
/* PRIVATE FUNCTIONS *********************************************************/
|
1999-01-17 05:03:00 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
VOID
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:33:03 +08:00
|
|
|
PspUserThreadStartup(IN PKSTART_ROUTINE StartRoutine,
|
|
|
|
IN PVOID StartContext)
|
2004-07-19 14:08:21 +08:00
|
|
|
{
|
2006-07-10 02:54:13 +08:00
|
|
|
PETHREAD Thread;
|
|
|
|
PTEB Teb;
|
|
|
|
BOOLEAN DeadThread = FALSE;
|
2008-02-07 15:10:13 +08:00
|
|
|
KIRQL OldIrql;
|
2006-07-10 02:54:13 +08:00
|
|
|
PAGED_CODE();
|
2006-07-24 03:45:16 +08:00
|
|
|
PSTRACE(PS_THREAD_DEBUG,
|
|
|
|
"StartRoutine: %p StartContext: %p\n", StartRoutine, StartContext);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Go to Passive Level */
|
|
|
|
KeLowerIrql(PASSIVE_LEVEL);
|
|
|
|
Thread = PsGetCurrentThread();
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Check if the thread is dead */
|
|
|
|
if (Thread->DeadThread)
|
|
|
|
{
|
|
|
|
/* Remember that we're dead */
|
|
|
|
DeadThread = TRUE;
|
2006-07-17 09:40:10 +08:00
|
|
|
}
|
2006-07-10 02:54:13 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Get the Locale ID and save Preferred Proc */
|
2006-07-16 04:10:13 +08:00
|
|
|
Teb = NtCurrentTeb();
|
|
|
|
Teb->CurrentLocale = MmGetSessionLocaleId();
|
|
|
|
Teb->IdealProcessor = Thread->Tcb.IdealProcessor;
|
2006-07-10 02:54:13 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2007-01-18 17:44:49 +08:00
|
|
|
/* Check if this is a dead thread, or if we're hiding */
|
|
|
|
if (!(Thread->DeadThread) && !(Thread->HideFromDebugger))
|
2006-07-17 01:19:21 +08:00
|
|
|
{
|
|
|
|
/* We're not, so notify the debugger */
|
2009-01-15 21:14:37 +08:00
|
|
|
DbgkCreateThread(Thread, StartContext);
|
2006-07-10 02:54:13 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Make sure we're not already dead */
|
|
|
|
if (!DeadThread)
|
|
|
|
{
|
|
|
|
/* Check if the Prefetcher is enabled */
|
|
|
|
if (CcPfEnablePrefetcher)
|
|
|
|
{
|
|
|
|
/* FIXME: Prepare to prefetch this process */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Raise to APC */
|
2008-02-07 15:10:13 +08:00
|
|
|
KeRaiseIrql(APC_LEVEL, &OldIrql);
|
2006-07-10 02:54:13 +08:00
|
|
|
|
|
|
|
/* Queue the User APC */
|
2009-12-18 04:58:58 +08:00
|
|
|
KiInitializeUserApc(KeGetExceptionFrame(&Thread->Tcb),
|
|
|
|
KeGetTrapFrame(&Thread->Tcb),
|
2006-07-10 02:54:13 +08:00
|
|
|
PspSystemDllEntryPoint,
|
2006-07-17 01:19:21 +08:00
|
|
|
NULL,
|
2006-07-10 02:54:13 +08:00
|
|
|
PspSystemDllBase,
|
2006-07-17 01:19:21 +08:00
|
|
|
NULL);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Lower it back to passive */
|
|
|
|
KeLowerIrql(PASSIVE_LEVEL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* We're dead, kill us now */
|
2006-07-17 01:19:21 +08:00
|
|
|
PspTerminateThreadByPointer(Thread,
|
|
|
|
STATUS_THREAD_IS_TERMINATING,
|
|
|
|
TRUE);
|
2005-04-22 20:52:25 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Do we have a cookie set yet? */
|
2010-09-11 05:13:06 +08:00
|
|
|
while (!SharedUserData->Cookie)
|
2006-07-10 02:54:13 +08:00
|
|
|
{
|
2006-07-28 02:28:26 +08:00
|
|
|
LARGE_INTEGER SystemTime;
|
|
|
|
ULONG NewCookie;
|
|
|
|
PKPRCB Prcb;
|
|
|
|
|
|
|
|
/* Generate a new cookie */
|
|
|
|
KeQuerySystemTime(&SystemTime);
|
|
|
|
Prcb = KeGetCurrentPrcb();
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 21:11:45 +08:00
|
|
|
NewCookie = (Prcb->MmPageFaultCount ^ Prcb->InterruptTime ^
|
2006-07-28 02:28:26 +08:00
|
|
|
SystemTime.u.LowPart ^ SystemTime.u.HighPart ^
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 21:11:45 +08:00
|
|
|
(ULONG)(ULONG_PTR)&SystemTime);
|
2006-07-28 02:28:26 +08:00
|
|
|
|
|
|
|
/* Set the new cookie*/
|
|
|
|
InterlockedCompareExchange((LONG*)&SharedUserData->Cookie,
|
|
|
|
NewCookie,
|
|
|
|
0);
|
2006-07-10 02:54:13 +08:00
|
|
|
}
|
2004-07-19 14:08:21 +08:00
|
|
|
}
|
|
|
|
|
2009-07-16 01:50:50 +08:00
|
|
|
LONG
|
2008-11-24 21:40:26 +08:00
|
|
|
PspUnhandledExceptionInSystemThread(PEXCEPTION_POINTERS ExceptionPointers)
|
2007-01-18 17:44:49 +08:00
|
|
|
{
|
|
|
|
/* Print debugging information */
|
|
|
|
DPRINT1("PS: Unhandled Kernel Mode Exception Pointers = 0x%p\n",
|
|
|
|
ExceptionPointers);
|
|
|
|
DPRINT1("Code %x Addr %p Info0 %p Info1 %p Info2 %p Info3 %p\n",
|
|
|
|
ExceptionPointers->ExceptionRecord->ExceptionCode,
|
|
|
|
ExceptionPointers->ExceptionRecord->ExceptionAddress,
|
|
|
|
ExceptionPointers->ExceptionRecord->ExceptionInformation[0],
|
|
|
|
ExceptionPointers->ExceptionRecord->ExceptionInformation[1],
|
|
|
|
ExceptionPointers->ExceptionRecord->ExceptionInformation[2],
|
|
|
|
ExceptionPointers->ExceptionRecord->ExceptionInformation[3]);
|
|
|
|
|
|
|
|
/* Bugcheck the system */
|
2008-09-27 06:11:10 +08:00
|
|
|
KeBugCheckEx(SYSTEM_THREAD_EXCEPTION_NOT_HANDLED,
|
2007-01-18 17:44:49 +08:00
|
|
|
ExceptionPointers->ExceptionRecord->ExceptionCode,
|
|
|
|
(ULONG_PTR)ExceptionPointers->ExceptionRecord->ExceptionAddress,
|
|
|
|
(ULONG_PTR)ExceptionPointers->ExceptionRecord,
|
|
|
|
(ULONG_PTR)ExceptionPointers->ContextRecord);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
VOID
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:33:03 +08:00
|
|
|
PspSystemThreadStartup(IN PKSTART_ROUTINE StartRoutine,
|
|
|
|
IN PVOID StartContext)
|
2004-07-19 14:08:21 +08:00
|
|
|
{
|
2007-04-02 23:08:54 +08:00
|
|
|
PETHREAD Thread;
|
2006-07-24 03:45:16 +08:00
|
|
|
PSTRACE(PS_THREAD_DEBUG,
|
|
|
|
"StartRoutine: %p StartContext: %p\n", StartRoutine, StartContext);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Unlock the dispatcher Database */
|
2005-04-18 12:46:06 +08:00
|
|
|
KeLowerIrql(PASSIVE_LEVEL);
|
2006-07-10 02:54:13 +08:00
|
|
|
Thread = PsGetCurrentThread();
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Make sure the thread isn't gone */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2007-01-18 17:44:49 +08:00
|
|
|
{
|
|
|
|
if (!(Thread->Terminated) && !(Thread->DeadThread))
|
|
|
|
{
|
2008-08-13 16:02:52 +08:00
|
|
|
/* Call the Start Routine */
|
2007-01-18 17:44:49 +08:00
|
|
|
StartRoutine(StartContext);
|
|
|
|
}
|
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_EXCEPT(PspUnhandledExceptionInSystemThread(_SEH2_GetExceptionInformation()))
|
2006-07-10 02:54:13 +08:00
|
|
|
{
|
2007-01-18 17:44:49 +08:00
|
|
|
/* Bugcheck if we got here */
|
|
|
|
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
|
2005-04-22 20:52:25 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-23 12:19:35 +08:00
|
|
|
/* Exit the thread */
|
2006-07-10 02:54:13 +08:00
|
|
|
PspTerminateThreadByPointer(Thread, STATUS_SUCCESS, TRUE);
|
2004-07-19 14:08:21 +08:00
|
|
|
}
|
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
NTSTATUS
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2005-04-22 20:52:25 +08:00
|
|
|
PspCreateThread(OUT PHANDLE ThreadHandle,
|
|
|
|
IN ACCESS_MASK DesiredAccess,
|
2006-07-24 03:45:16 +08:00
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
2005-04-22 20:52:25 +08:00
|
|
|
IN HANDLE ProcessHandle,
|
|
|
|
IN PEPROCESS TargetProcess,
|
|
|
|
OUT PCLIENT_ID ClientId,
|
|
|
|
IN PCONTEXT ThreadContext,
|
|
|
|
IN PINITIAL_TEB InitialTeb,
|
|
|
|
IN BOOLEAN CreateSuspended,
|
|
|
|
IN PKSTART_ROUTINE StartRoutine OPTIONAL,
|
|
|
|
IN PVOID StartContext OPTIONAL)
|
2004-07-19 14:08:21 +08:00
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
HANDLE hThread;
|
|
|
|
PEPROCESS Process;
|
2005-04-18 12:46:06 +08:00
|
|
|
PETHREAD Thread;
|
2006-07-17 09:40:10 +08:00
|
|
|
PTEB TebBase = NULL;
|
2005-04-22 20:52:25 +08:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2006-07-24 01:56:57 +08:00
|
|
|
NTSTATUS Status, AccessStatus;
|
2005-08-08 06:48:07 +08:00
|
|
|
HANDLE_TABLE_ENTRY CidEntry;
|
2006-07-24 01:45:30 +08:00
|
|
|
ACCESS_STATE LocalAccessState;
|
|
|
|
PACCESS_STATE AccessState = &LocalAccessState;
|
2008-06-16 16:54:21 +08:00
|
|
|
AUX_ACCESS_DATA AuxData;
|
2006-07-24 01:56:57 +08:00
|
|
|
BOOLEAN Result, SdAllocated;
|
|
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
|
|
|
SECURITY_SUBJECT_CONTEXT SubjectContext;
|
2006-07-10 02:54:13 +08:00
|
|
|
PAGED_CODE();
|
2006-07-24 03:45:16 +08:00
|
|
|
PSTRACE(PS_THREAD_DEBUG,
|
|
|
|
"ThreadContext: %p TargetProcess: %p ProcessHandle: %p\n",
|
|
|
|
ThreadContext, TargetProcess, ProcessHandle);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* If we were called from PsCreateSystemThread, then we're kernel mode */
|
|
|
|
if (StartRoutine) PreviousMode = KernelMode;
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Reference the Process by handle or pointer, depending on what we got */
|
|
|
|
if (ProcessHandle)
|
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Normal thread or System Thread */
|
|
|
|
Status = ObReferenceObjectByHandle(ProcessHandle,
|
|
|
|
PROCESS_CREATE_THREAD,
|
|
|
|
PsProcessType,
|
|
|
|
PreviousMode,
|
|
|
|
(PVOID*)&Process,
|
|
|
|
NULL);
|
2006-07-24 03:45:16 +08:00
|
|
|
PSREFTRACE(Process);
|
2006-07-10 02:54:13 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
/* System thread inside System Process, or Normal Thread with a bug */
|
2006-07-10 02:54:13 +08:00
|
|
|
if (StartRoutine)
|
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Reference the Process by Pointer */
|
|
|
|
ObReferenceObject(TargetProcess);
|
|
|
|
Process = TargetProcess;
|
|
|
|
Status = STATUS_SUCCESS;
|
2006-07-10 02:54:13 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Fake ObReference returning this */
|
|
|
|
Status = STATUS_INVALID_HANDLE;
|
|
|
|
}
|
2005-04-18 12:46:06 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Check for success */
|
2006-07-16 04:10:13 +08:00
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
2006-07-10 02:54:13 +08:00
|
|
|
|
|
|
|
/* Also make sure that User-Mode isn't trying to create a system thread */
|
|
|
|
if ((PreviousMode != KernelMode) && (Process == PsInitialSystemProcess))
|
|
|
|
{
|
2006-07-24 03:45:16 +08:00
|
|
|
/* Fail */
|
2006-07-10 02:54:13 +08:00
|
|
|
ObDereferenceObject(Process);
|
|
|
|
return STATUS_INVALID_HANDLE;
|
2005-04-18 12:46:06 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Create Thread Object */
|
|
|
|
Status = ObCreateObject(PreviousMode,
|
|
|
|
PsThreadType,
|
|
|
|
ObjectAttributes,
|
2006-07-17 01:19:21 +08:00
|
|
|
PreviousMode,
|
2005-04-22 20:52:25 +08:00
|
|
|
NULL,
|
|
|
|
sizeof(ETHREAD),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(PVOID*)&Thread);
|
2006-07-10 02:54:13 +08:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* We failed; dereference the process and exit */
|
2005-04-22 20:52:25 +08:00
|
|
|
ObDereferenceObject(Process);
|
2006-07-10 02:54:13 +08:00
|
|
|
return Status;
|
2005-04-22 20:52:25 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Zero the Object entirely */
|
|
|
|
RtlZeroMemory(Thread, sizeof(ETHREAD));
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-17 01:19:21 +08:00
|
|
|
/* Initialize rundown protection */
|
|
|
|
ExInitializeRundownProtection(&Thread->RundownProtect);
|
|
|
|
|
2006-08-09 20:46:41 +08:00
|
|
|
/* Initialize exit code */
|
|
|
|
Thread->ExitStatus = STATUS_PENDING;
|
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Set the Process CID */
|
|
|
|
Thread->ThreadsProcess = Process;
|
|
|
|
Thread->Cid.UniqueProcess = Process->UniqueProcessId;
|
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Create Cid Handle */
|
2006-05-19 08:32:50 +08:00
|
|
|
CidEntry.Object = Thread;
|
|
|
|
CidEntry.GrantedAccess = 0;
|
2005-08-08 06:48:07 +08:00
|
|
|
Thread->Cid.UniqueThread = ExCreateHandle(PspCidTable, &CidEntry);
|
2006-07-10 02:54:13 +08:00
|
|
|
if (!Thread->Cid.UniqueThread)
|
|
|
|
{
|
2006-07-17 01:19:21 +08:00
|
|
|
/* We couldn't create the CID, dereference the thread and fail */
|
2005-04-22 20:52:25 +08:00
|
|
|
ObDereferenceObject(Thread);
|
2005-08-08 06:48:07 +08:00
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
2005-04-22 20:52:25 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Save the read cluster size */
|
|
|
|
Thread->ReadClusterSize = MmReadClusterSize;
|
|
|
|
|
|
|
|
/* Initialize the LPC Reply Semaphore */
|
2006-07-17 01:19:21 +08:00
|
|
|
KeInitializeSemaphore(&Thread->LpcReplySemaphore, 0, 1);
|
2006-07-10 02:54:13 +08:00
|
|
|
|
|
|
|
/* Initialize the list heads and locks */
|
2005-04-22 20:52:25 +08:00
|
|
|
InitializeListHead(&Thread->LpcReplyChain);
|
|
|
|
InitializeListHead(&Thread->IrpList);
|
2006-07-10 02:54:13 +08:00
|
|
|
InitializeListHead(&Thread->PostBlockList);
|
2005-04-18 12:46:06 +08:00
|
|
|
InitializeListHead(&Thread->ActiveTimerListHead);
|
|
|
|
KeInitializeSpinLock(&Thread->ActiveTimerListLock);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-17 01:19:21 +08:00
|
|
|
/* Acquire rundown protection */
|
2007-01-18 17:44:49 +08:00
|
|
|
if (!ExAcquireRundownProtection (&Process->RundownProtect))
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
ObDereferenceObject(Thread);
|
|
|
|
return STATUS_PROCESS_IS_TERMINATING;
|
|
|
|
}
|
2006-07-17 01:19:21 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Now let the kernel initialize the context */
|
2006-07-10 02:54:13 +08:00
|
|
|
if (ThreadContext)
|
|
|
|
{
|
|
|
|
/* User-mode Thread, create Teb */
|
2009-10-15 13:56:41 +08:00
|
|
|
Status = MmCreateTeb(Process, &Thread->Cid, InitialTeb, &TebBase);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2006-07-17 01:19:21 +08:00
|
|
|
{
|
|
|
|
/* Failed to create the TEB. Release rundown and dereference */
|
|
|
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
|
|
|
ObDereferenceObject(Thread);
|
2009-10-15 13:56:41 +08:00
|
|
|
return Status;
|
2006-07-17 01:19:21 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2013-09-28 16:37:47 +08:00
|
|
|
/* Set the Start Addresses from the untrusted ThreadContext */
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
Thread->StartAddress = (PVOID)KeGetContextPc(ThreadContext);
|
|
|
|
Thread->Win32StartAddress = (PVOID)KeGetContextReturnRegister(ThreadContext);
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
Status = _SEH2_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Let the kernel intialize the Thread */
|
2013-09-28 16:37:47 +08:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Status = KeInitThread(&Thread->Tcb,
|
|
|
|
NULL,
|
|
|
|
PspUserThreadStartup,
|
|
|
|
NULL,
|
|
|
|
Thread->StartAddress,
|
|
|
|
ThreadContext,
|
|
|
|
TebBase,
|
|
|
|
&Process->Pcb);
|
|
|
|
}
|
2006-07-10 02:54:13 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
/* System Thread */
|
|
|
|
Thread->StartAddress = StartRoutine;
|
2006-07-24 05:38:31 +08:00
|
|
|
PspSetCrossThreadFlag(Thread, CT_SYSTEM_THREAD_BIT);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Let the kernel intialize the Thread */
|
2006-07-17 09:40:10 +08:00
|
|
|
Status = KeInitThread(&Thread->Tcb,
|
|
|
|
NULL,
|
|
|
|
PspSystemThreadStartup,
|
|
|
|
StartRoutine,
|
|
|
|
StartContext,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Process->Pcb);
|
2005-04-22 20:52:25 +08:00
|
|
|
}
|
2005-04-18 12:46:06 +08:00
|
|
|
|
2006-07-17 09:40:10 +08:00
|
|
|
/* Check if we failed */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Delete the TEB if we had done */
|
|
|
|
if (TebBase) MmDeleteTeb(Process, TebBase);
|
|
|
|
|
|
|
|
/* Release rundown and dereference */
|
|
|
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
|
|
|
ObDereferenceObject(Thread);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2006-07-24 01:45:30 +08:00
|
|
|
/* 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;
|
|
|
|
}
|
2006-07-17 09:40:10 +08:00
|
|
|
|
2005-05-09 09:38:29 +08:00
|
|
|
/*
|
|
|
|
* Insert the Thread into the Process's Thread List
|
2005-04-24 00:23:57 +08:00
|
|
|
* Note, this is the ETHREAD Thread List. It is removed in
|
|
|
|
* ps/kill.c!PspExitThread.
|
|
|
|
*/
|
2005-04-22 20:52:25 +08:00
|
|
|
InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
|
2006-07-10 02:54:13 +08:00
|
|
|
Process->ActiveThreads++;
|
|
|
|
|
2006-07-17 09:40:10 +08:00
|
|
|
/* Start the thread */
|
|
|
|
KeStartThread(&Thread->Tcb);
|
|
|
|
|
2006-07-24 01:45:30 +08:00
|
|
|
/* Release the process lock */
|
|
|
|
ExReleasePushLockExclusive(&Process->ProcessLock);
|
|
|
|
KeLeaveCriticalRegion();
|
2006-07-17 09:40:10 +08:00
|
|
|
|
2006-07-17 01:19:21 +08:00
|
|
|
/* Release rundown */
|
|
|
|
ExReleaseRundownProtection(&Process->RundownProtect);
|
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Notify WMI */
|
|
|
|
//WmiTraceProcess(Process, TRUE);
|
|
|
|
//WmiTraceThread(Thread, InitialTeb, TRUE);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Notify Thread Creation */
|
|
|
|
PspRunCreateThreadNotifyRoutines(Thread, TRUE);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Reference ourselves as a keep-alive */
|
|
|
|
ObReferenceObjectEx(Thread, 2);
|
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Suspend the Thread if we have to */
|
2006-07-17 09:40:10 +08:00
|
|
|
if (CreateSuspended) KeSuspendThread(&Thread->Tcb);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Check if we were already terminated */
|
2006-07-20 13:33:03 +08:00
|
|
|
if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-24 01:45:30 +08:00
|
|
|
/* 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 */
|
2006-07-24 05:38:31 +08:00
|
|
|
PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);
|
2006-07-24 01:45:30 +08:00
|
|
|
|
|
|
|
/* If we were suspended, wake it up */
|
|
|
|
if (CreateSuspended) KeResumeThread(&Thread->Tcb);
|
|
|
|
|
|
|
|
/* Dispatch thread */
|
2006-09-14 20:13:32 +08:00
|
|
|
KeReadyThread(&Thread->Tcb);
|
2006-07-24 01:45:30 +08:00
|
|
|
|
|
|
|
/* Dereference completely to kill it */
|
|
|
|
ObDereferenceObjectEx(Thread, 2);
|
2007-01-18 17:44:49 +08:00
|
|
|
return Status;
|
2006-07-24 01:45:30 +08:00
|
|
|
}
|
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Insert the Thread into the Object Manager */
|
2006-07-20 13:33:03 +08:00
|
|
|
Status = ObInsertObject(Thread,
|
2006-07-24 01:45:30 +08:00
|
|
|
AccessState,
|
2005-04-22 20:52:25 +08:00
|
|
|
DesiredAccess,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
&hThread);
|
2006-07-24 01:45:30 +08:00
|
|
|
|
|
|
|
/* Delete the access state if we had one */
|
|
|
|
if (AccessState) SeDeleteAccessState(AccessState);
|
|
|
|
|
|
|
|
/* Check for success */
|
2006-07-20 13:33:03 +08:00
|
|
|
if (NT_SUCCESS(Status))
|
2006-07-10 02:54:13 +08:00
|
|
|
{
|
|
|
|
/* Wrap in SEH to protect against bad user-mode pointers */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2006-07-10 02:54:13 +08:00
|
|
|
{
|
|
|
|
/* Return Cid and Handle */
|
2006-07-20 13:33:03 +08:00
|
|
|
if (ClientId) *ClientId = Thread->Cid;
|
2005-04-22 20:52:25 +08:00
|
|
|
*ThreadHandle = hThread;
|
2006-07-10 02:54:13 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2006-07-10 02:54:13 +08:00
|
|
|
{
|
2006-07-24 01:56:57 +08:00
|
|
|
/* Thread insertion failed, thread is dead */
|
2006-07-24 05:38:31 +08:00
|
|
|
PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);
|
2006-07-24 01:56:57 +08:00
|
|
|
|
|
|
|
/* If we were suspended, wake it up */
|
|
|
|
if (CreateSuspended) KeResumeThread(&Thread->Tcb);
|
|
|
|
|
|
|
|
/* Dispatch thread */
|
2006-09-14 20:13:32 +08:00
|
|
|
KeReadyThread(&Thread->Tcb);
|
2006-07-24 01:56:57 +08:00
|
|
|
|
|
|
|
/* Dereference it, leaving only the keep-alive */
|
|
|
|
ObDereferenceObject(Thread);
|
|
|
|
|
|
|
|
/* Close its handle, killing it */
|
2015-02-18 04:41:40 +08:00
|
|
|
ObCloseHandle(hThread, PreviousMode);
|
2009-08-27 01:31:02 +08:00
|
|
|
|
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2006-07-10 02:54:13 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-04-22 20:52:25 +08:00
|
|
|
}
|
2006-07-24 01:45:30 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Thread insertion failed, thread is dead */
|
2006-07-24 05:38:31 +08:00
|
|
|
PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);
|
2006-07-24 01:45:30 +08:00
|
|
|
|
|
|
|
/* If we were suspended, wake it up */
|
|
|
|
if (CreateSuspended) KeResumeThread(&Thread->Tcb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the create time */
|
|
|
|
KeQuerySystemTime(&Thread->CreateTime);
|
|
|
|
ASSERT(!(Thread->CreateTime.HighPart & 0xF0000000));
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-24 01:56:57 +08:00
|
|
|
/* Make sure the thread isn't dead */
|
|
|
|
if (!Thread->DeadThread)
|
|
|
|
{
|
|
|
|
/* Get the thread's SD */
|
|
|
|
Status = ObGetObjectSecurity(Thread,
|
|
|
|
&SecurityDescriptor,
|
|
|
|
&SdAllocated);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Thread insertion failed, thread is dead */
|
2006-07-24 05:38:31 +08:00
|
|
|
PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT);
|
2006-07-24 01:56:57 +08:00
|
|
|
|
|
|
|
/* If we were suspended, wake it up */
|
|
|
|
if (CreateSuspended) KeResumeThread(&Thread->Tcb);
|
|
|
|
|
|
|
|
/* Dispatch thread */
|
2006-09-14 20:13:32 +08:00
|
|
|
KeReadyThread(&Thread->Tcb);
|
2006-07-24 01:56:57 +08:00
|
|
|
|
|
|
|
/* Dereference it, leaving only the keep-alive */
|
|
|
|
ObDereferenceObject(Thread);
|
|
|
|
|
|
|
|
/* Close its handle, killing it */
|
2015-02-18 04:41:40 +08:00
|
|
|
ObCloseHandle(hThread, PreviousMode);
|
2006-07-24 01:56:57 +08:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the subject context */
|
|
|
|
SubjectContext.ProcessAuditId = Process;
|
|
|
|
SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process);
|
|
|
|
SubjectContext.ClientToken = NULL;
|
|
|
|
|
|
|
|
/* Do the access check */
|
|
|
|
Result = SeAccessCheck(SecurityDescriptor,
|
|
|
|
&SubjectContext,
|
|
|
|
FALSE,
|
|
|
|
MAXIMUM_ALLOWED,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
&PsThreadType->TypeInfo.GenericMapping,
|
|
|
|
PreviousMode,
|
|
|
|
&Thread->GrantedAccess,
|
|
|
|
&AccessStatus);
|
|
|
|
|
|
|
|
/* Dereference the token and let go the SD */
|
|
|
|
ObFastDereferenceObject(&Process->Token,
|
|
|
|
SubjectContext.PrimaryToken);
|
|
|
|
ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
|
|
|
|
|
|
|
|
/* Remove access if it failed */
|
|
|
|
if (!Result) Process->GrantedAccess = 0;
|
|
|
|
|
|
|
|
/* Set least some minimum access */
|
|
|
|
Thread->GrantedAccess |= (THREAD_TERMINATE |
|
|
|
|
THREAD_SET_INFORMATION |
|
|
|
|
THREAD_QUERY_INFORMATION);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set the thread access mask to maximum */
|
|
|
|
Thread->GrantedAccess = THREAD_ALL_ACCESS;
|
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Dispatch thread */
|
2006-09-14 20:13:32 +08:00
|
|
|
KeReadyThread(&Thread->Tcb);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Dereference it, leaving only the keep-alive */
|
|
|
|
ObDereferenceObject(Thread);
|
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Return */
|
|
|
|
return Status;
|
2006-07-24 01:45:30 +08:00
|
|
|
|
|
|
|
/* 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);
|
2008-07-15 21:44:14 +08:00
|
|
|
KeLeaveCriticalRegion();
|
2006-07-24 01:45:30 +08:00
|
|
|
|
|
|
|
/* 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;
|
2004-07-19 14:08:21 +08:00
|
|
|
}
|
|
|
|
|
2006-07-20 13:33:03 +08:00
|
|
|
/* PUBLIC FUNCTIONS **********************************************************/
|
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 09:38:29 +08:00
|
|
|
NTSTATUS
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:33:03 +08:00
|
|
|
PsCreateSystemThread(OUT PHANDLE ThreadHandle,
|
|
|
|
IN ACCESS_MASK DesiredAccess,
|
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|
|
|
IN HANDLE ProcessHandle,
|
|
|
|
IN PCLIENT_ID ClientId,
|
|
|
|
IN PKSTART_ROUTINE StartRoutine,
|
|
|
|
IN PVOID StartContext)
|
1999-01-17 05:03:00 +08:00
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
PEPROCESS TargetProcess = NULL;
|
2005-05-09 09:38:29 +08:00
|
|
|
HANDLE Handle = ProcessHandle;
|
2006-07-10 02:54:13 +08:00
|
|
|
PAGED_CODE();
|
2006-07-24 03:45:16 +08:00
|
|
|
PSTRACE(PS_THREAD_DEBUG,
|
|
|
|
"ProcessHandle: %p StartRoutine: %p StartContext: %p\n",
|
|
|
|
ProcessHandle, StartRoutine, StartContext);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Check if we have a handle. If not, use the System Process */
|
2006-07-10 02:54:13 +08:00
|
|
|
if (!ProcessHandle)
|
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
Handle = NULL;
|
|
|
|
TargetProcess = PsInitialSystemProcess;
|
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Call the shared function */
|
|
|
|
return PspCreateThread(ThreadHandle,
|
|
|
|
DesiredAccess,
|
|
|
|
ObjectAttributes,
|
|
|
|
Handle,
|
|
|
|
TargetProcess,
|
|
|
|
ClientId,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
FALSE,
|
|
|
|
StartRoutine,
|
|
|
|
StartContext);
|
1999-12-03 04:53:55 +08:00
|
|
|
}
|
|
|
|
|
2005-08-08 06:48:07 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
NTSTATUS
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2005-08-08 06:48:07 +08:00
|
|
|
PsLookupThreadByThreadId(IN HANDLE ThreadId,
|
|
|
|
OUT PETHREAD *Thread)
|
|
|
|
{
|
|
|
|
PHANDLE_TABLE_ENTRY CidEntry;
|
|
|
|
PETHREAD FoundThread;
|
|
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
|
|
PAGED_CODE();
|
2006-07-24 03:45:16 +08:00
|
|
|
PSTRACE(PS_THREAD_DEBUG, "ThreadId: %p\n", ThreadId);
|
2005-08-08 18:54:32 +08:00
|
|
|
KeEnterCriticalRegion();
|
2005-08-08 06:48:07 +08:00
|
|
|
|
|
|
|
/* Get the CID Handle Entry */
|
2006-07-20 13:33:03 +08:00
|
|
|
CidEntry = ExMapHandleToPointer(PspCidTable, ThreadId);
|
|
|
|
if (CidEntry)
|
2005-08-08 06:48:07 +08:00
|
|
|
{
|
2015-12-15 07:20:10 +08:00
|
|
|
/* Get the Thread */
|
2006-05-19 08:32:50 +08:00
|
|
|
FoundThread = CidEntry->Object;
|
2005-08-08 06:48:07 +08:00
|
|
|
|
2015-12-15 07:20:10 +08:00
|
|
|
/* Make sure it's really a thread */
|
2011-10-08 00:18:52 +08:00
|
|
|
if (FoundThread->Tcb.Header.Type == ThreadObject)
|
2005-08-08 06:48:07 +08:00
|
|
|
{
|
2006-07-21 02:47:35 +08:00
|
|
|
/* Safe Reference and return it */
|
|
|
|
if (ObReferenceObjectSafe(FoundThread))
|
|
|
|
{
|
|
|
|
*Thread = FoundThread;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
2005-08-08 06:48:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Unlock the Entry */
|
|
|
|
ExUnlockHandleTableEntry(PspCidTable, CidEntry);
|
|
|
|
}
|
2006-07-20 13:33:03 +08:00
|
|
|
|
2005-08-08 06:48:07 +08:00
|
|
|
/* Return to caller */
|
2006-07-10 02:54:13 +08:00
|
|
|
KeLeaveCriticalRegion();
|
2005-08-08 06:48:07 +08:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-07-23 15:44:26 +08:00
|
|
|
ULONG
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:37:12 +08:00
|
|
|
PsGetThreadFreezeCount(IN PETHREAD Thread)
|
2004-07-23 15:44:26 +08:00
|
|
|
{
|
2005-04-18 12:46:06 +08:00
|
|
|
return Thread->Tcb.FreezeCount;
|
2004-07-23 15:44:26 +08:00
|
|
|
}
|
|
|
|
|
2004-07-19 14:08:21 +08:00
|
|
|
/*
|
2005-04-18 12:46:06 +08:00
|
|
|
* @implemented
|
2005-03-13 22:21:47 +08:00
|
|
|
*/
|
2005-04-18 12:46:06 +08:00
|
|
|
BOOLEAN
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:37:12 +08:00
|
|
|
PsGetThreadHardErrorsAreDisabled(IN PETHREAD Thread)
|
2004-07-19 14:08:21 +08:00
|
|
|
{
|
2007-08-04 16:49:47 +08:00
|
|
|
return Thread->HardErrorsAreDisabled ? TRUE : FALSE;
|
2004-07-19 14:08:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2005-04-18 12:46:06 +08:00
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
HANDLE
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:37:12 +08:00
|
|
|
PsGetThreadId(IN PETHREAD Thread)
|
2004-07-19 14:08:21 +08:00
|
|
|
{
|
2005-04-18 12:46:06 +08:00
|
|
|
return Thread->Cid.UniqueThread;
|
2004-07-19 14:08:21 +08:00
|
|
|
}
|
|
|
|
|
2013-09-22 04:46:42 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
HANDLE
|
|
|
|
NTAPI
|
|
|
|
PsGetCurrentThreadId(VOID)
|
|
|
|
{
|
|
|
|
return PsGetCurrentThread()->Cid.UniqueThread;
|
|
|
|
}
|
|
|
|
|
2004-07-19 14:08:21 +08:00
|
|
|
/*
|
Implemented PsGetThreadFreezeCount, PsGetThreadHardErrorsAreDisabled, PsGetThreadId, PsGetThreadProcess, PsGetThreadProcessId, PsGetThreadSessionId, PsGetThreadTeb, PsGetThreadWin32Thread, PsGetCurrentThreadPreviousMode, PsGetCurrentThreadStackBase, PsGetCurrentThreadStackLimit, PsSetThreadHardErrorsAreDisabled, PsSetThreadWin32Thread
svn path=/trunk/; revision=10238
2004-07-21 09:05:26 +08:00
|
|
|
* @implemented
|
2005-04-18 12:46:06 +08:00
|
|
|
*/
|
|
|
|
PEPROCESS
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:37:12 +08:00
|
|
|
PsGetThreadProcess(IN PETHREAD Thread)
|
2004-07-19 14:08:21 +08:00
|
|
|
{
|
2005-04-18 12:46:06 +08:00
|
|
|
return Thread->ThreadsProcess;
|
2004-07-19 14:08:21 +08:00
|
|
|
}
|
|
|
|
|
2013-09-22 04:46:42 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PEPROCESS
|
|
|
|
NTAPI
|
|
|
|
PsGetCurrentThreadProcess(VOID)
|
|
|
|
{
|
|
|
|
return PsGetCurrentThread()->ThreadsProcess;
|
|
|
|
}
|
|
|
|
|
2004-07-19 14:08:21 +08:00
|
|
|
/*
|
Implemented PsGetThreadFreezeCount, PsGetThreadHardErrorsAreDisabled, PsGetThreadId, PsGetThreadProcess, PsGetThreadProcessId, PsGetThreadSessionId, PsGetThreadTeb, PsGetThreadWin32Thread, PsGetCurrentThreadPreviousMode, PsGetCurrentThreadStackBase, PsGetCurrentThreadStackLimit, PsSetThreadHardErrorsAreDisabled, PsSetThreadWin32Thread
svn path=/trunk/; revision=10238
2004-07-21 09:05:26 +08:00
|
|
|
* @implemented
|
2005-04-18 12:46:06 +08:00
|
|
|
*/
|
|
|
|
HANDLE
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:37:12 +08:00
|
|
|
PsGetThreadProcessId(IN PETHREAD Thread)
|
2004-07-19 14:08:21 +08:00
|
|
|
{
|
2005-04-18 12:46:06 +08:00
|
|
|
return Thread->Cid.UniqueProcess;
|
2004-07-19 14:08:21 +08:00
|
|
|
}
|
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
HANDLE
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2013-09-22 04:46:42 +08:00
|
|
|
PsGetCurrentThreadProcessId(VOID)
|
|
|
|
{
|
|
|
|
return PsGetCurrentThread()->Cid.UniqueProcess;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
ULONG
|
|
|
|
NTAPI
|
2006-07-20 13:37:12 +08:00
|
|
|
PsGetThreadSessionId(IN PETHREAD Thread)
|
2001-04-17 12:11:01 +08:00
|
|
|
{
|
2013-09-22 04:46:42 +08:00
|
|
|
return MmGetSessionId(Thread->ThreadsProcess);
|
2001-04-17 12:11:01 +08:00
|
|
|
}
|
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PTEB
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:37:12 +08:00
|
|
|
PsGetThreadTeb(IN PETHREAD Thread)
|
2001-04-17 12:11:01 +08:00
|
|
|
{
|
2005-04-18 12:46:06 +08:00
|
|
|
return Thread->Tcb.Teb;
|
2001-04-17 12:11:01 +08:00
|
|
|
}
|
|
|
|
|
2013-09-22 04:46:42 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2018-12-31 05:47:36 +08:00
|
|
|
PVOID
|
2013-09-22 04:46:42 +08:00
|
|
|
NTAPI
|
|
|
|
PsGetCurrentThreadTeb(VOID)
|
|
|
|
{
|
|
|
|
return PsGetCurrentThread()->Tcb.Teb;
|
|
|
|
}
|
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PVOID
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:37:12 +08:00
|
|
|
PsGetThreadWin32Thread(IN PETHREAD Thread)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2005-04-18 12:46:06 +08:00
|
|
|
return Thread->Tcb.Win32Thread;
|
2005-04-18 10:12:30 +08:00
|
|
|
}
|
|
|
|
|
2013-09-22 04:46:42 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PVOID
|
|
|
|
NTAPI
|
|
|
|
PsGetCurrentThreadWin32Thread(VOID)
|
|
|
|
{
|
|
|
|
return PsGetCurrentThread()->Tcb.Win32Thread;
|
|
|
|
}
|
|
|
|
|
2013-09-23 02:54:58 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PVOID
|
|
|
|
NTAPI
|
2013-10-24 03:31:41 +08:00
|
|
|
PsGetCurrentThreadWin32ThreadAndEnterCriticalRegion(
|
|
|
|
_Out_ HANDLE* OutProcessId)
|
2013-09-23 02:54:58 +08:00
|
|
|
{
|
2013-10-24 03:31:41 +08:00
|
|
|
PETHREAD CurrentThread;
|
|
|
|
|
|
|
|
/* Get the current thread */
|
|
|
|
CurrentThread = PsGetCurrentThread();
|
|
|
|
|
|
|
|
/* Return the process id */
|
|
|
|
*OutProcessId = CurrentThread->Cid.UniqueProcess;
|
|
|
|
|
|
|
|
/* Enter critical region */
|
2013-09-23 02:54:58 +08:00
|
|
|
KeEnterCriticalRegion();
|
2013-10-24 03:31:41 +08:00
|
|
|
|
|
|
|
/* Return the win32 thread */
|
|
|
|
return CurrentThread->Tcb.Win32Thread;
|
2013-09-23 02:54:58 +08:00
|
|
|
}
|
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
KPROCESSOR_MODE
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2005-04-18 12:46:06 +08:00
|
|
|
PsGetCurrentThreadPreviousMode(VOID)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2005-04-18 12:46:06 +08:00
|
|
|
return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode;
|
|
|
|
}
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PVOID
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2005-04-18 12:46:06 +08:00
|
|
|
PsGetCurrentThreadStackBase(VOID)
|
|
|
|
{
|
|
|
|
return PsGetCurrentThread()->Tcb.StackBase;
|
|
|
|
}
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
PVOID
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2005-04-18 12:46:06 +08:00
|
|
|
PsGetCurrentThreadStackLimit(VOID)
|
|
|
|
{
|
|
|
|
return (PVOID)PsGetCurrentThread()->Tcb.StackLimit;
|
|
|
|
}
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 09:38:29 +08:00
|
|
|
BOOLEAN
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2005-04-18 12:46:06 +08:00
|
|
|
PsIsThreadTerminating(IN PETHREAD Thread)
|
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
return Thread->Terminated ? TRUE : FALSE;
|
2005-04-18 12:46:06 +08:00
|
|
|
}
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOLEAN
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:33:03 +08:00
|
|
|
PsIsSystemThread(IN PETHREAD Thread)
|
2005-04-18 12:46:06 +08:00
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
return Thread->SystemThread ? TRUE: FALSE;
|
2005-04-18 12:46:06 +08:00
|
|
|
}
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOLEAN
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:33:03 +08:00
|
|
|
PsIsThreadImpersonating(IN PETHREAD Thread)
|
2005-04-18 12:46:06 +08:00
|
|
|
{
|
2007-08-04 16:49:47 +08:00
|
|
|
return Thread->ActiveImpersonationInfo ? TRUE : FALSE;
|
2005-04-18 12:46:06 +08:00
|
|
|
}
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
2005-05-09 09:38:29 +08:00
|
|
|
*/
|
2005-04-18 12:46:06 +08:00
|
|
|
VOID
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2006-07-20 13:33:03 +08:00
|
|
|
PsSetThreadHardErrorsAreDisabled(IN PETHREAD Thread,
|
|
|
|
IN BOOLEAN HardErrorsAreDisabled)
|
2005-04-18 12:46:06 +08:00
|
|
|
{
|
|
|
|
Thread->HardErrorsAreDisabled = HardErrorsAreDisabled;
|
2005-04-18 10:12:30 +08:00
|
|
|
}
|
|
|
|
|
2005-04-18 12:46:06 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
2005-05-09 09:38:29 +08:00
|
|
|
*/
|
2013-11-12 02:52:59 +08:00
|
|
|
PVOID
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2013-11-12 02:52:59 +08:00
|
|
|
PsSetThreadWin32Thread(
|
|
|
|
_Inout_ PETHREAD Thread,
|
|
|
|
_In_ PVOID Win32Thread,
|
|
|
|
_In_ PVOID OldWin32Thread)
|
2005-04-18 12:46:06 +08:00
|
|
|
{
|
2013-11-12 02:52:59 +08:00
|
|
|
/* Are we setting the win32 process? */
|
|
|
|
if (Win32Thread != NULL)
|
|
|
|
{
|
|
|
|
/* Just exchange it */
|
|
|
|
return InterlockedExchangePointer(&Thread->Tcb.Win32Thread,
|
|
|
|
Win32Thread);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* We are resetting, only exchange when the old win32 thread matches */
|
|
|
|
return InterlockedCompareExchangePointer(&Thread->Tcb.Win32Thread,
|
|
|
|
Win32Thread,
|
|
|
|
OldWin32Thread);
|
|
|
|
}
|
2005-04-18 12:46:06 +08:00
|
|
|
}
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2015-09-09 04:14:39 +08:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
PsWrapApcWow64Thread(IN OUT PVOID *ApcContext,
|
|
|
|
IN OUT PVOID *ApcRoutine)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2005-05-09 09:38:29 +08:00
|
|
|
NTSTATUS
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2005-04-22 20:52:25 +08:00
|
|
|
NtCreateThread(OUT PHANDLE ThreadHandle,
|
|
|
|
IN ACCESS_MASK DesiredAccess,
|
2006-07-20 13:33:03 +08:00
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
2005-04-22 20:52:25 +08:00
|
|
|
IN HANDLE ProcessHandle,
|
|
|
|
OUT PCLIENT_ID ClientId,
|
|
|
|
IN PCONTEXT ThreadContext,
|
|
|
|
IN PINITIAL_TEB InitialTeb,
|
|
|
|
IN BOOLEAN CreateSuspended)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
INITIAL_TEB SafeInitialTeb;
|
2005-04-18 10:12:30 +08:00
|
|
|
PAGED_CODE();
|
2006-07-24 03:45:16 +08:00
|
|
|
PSTRACE(PS_THREAD_DEBUG,
|
|
|
|
"ProcessHandle: %p Context: %p\n", ProcessHandle, ThreadContext);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Check if this was from user-mode */
|
2007-01-18 17:44:49 +08:00
|
|
|
if (KeGetPreviousMode() != KernelMode)
|
2006-07-10 02:54:13 +08:00
|
|
|
{
|
|
|
|
/* Make sure that we got a context */
|
2006-07-16 04:10:13 +08:00
|
|
|
if (!ThreadContext) return STATUS_INVALID_PARAMETER;
|
2005-10-30 05:33:57 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Protect checks */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2006-07-10 02:54:13 +08:00
|
|
|
{
|
|
|
|
/* Make sure the handle pointer we got is valid */
|
2005-08-21 23:38:47 +08:00
|
|
|
ProbeForWriteHandle(ThreadHandle);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Check if the caller wants a client id */
|
2009-08-27 01:31:02 +08:00
|
|
|
if (ClientId)
|
2006-07-10 02:54:13 +08:00
|
|
|
{
|
|
|
|
/* Make sure we can write to it */
|
|
|
|
ProbeForWrite(ClientId, sizeof(CLIENT_ID), sizeof(ULONG));
|
2005-04-22 20:52:25 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Make sure that the entire context is readable */
|
|
|
|
ProbeForRead(ThreadContext, sizeof(CONTEXT), sizeof(ULONG));
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Check the Initial TEB */
|
|
|
|
ProbeForRead(InitialTeb, sizeof(INITIAL_TEB), sizeof(ULONG));
|
2005-10-30 05:33:57 +08:00
|
|
|
SafeInitialTeb = *InitialTeb;
|
2007-01-18 17:44:49 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2006-07-10 02:54:13 +08:00
|
|
|
{
|
2009-08-27 01:31:02 +08:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2006-07-10 02:54:13 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-10-30 05:33:57 +08:00
|
|
|
}
|
2006-07-10 02:54:13 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Use the Initial TEB as is */
|
|
|
|
SafeInitialTeb = *InitialTeb;
|
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Call the shared function */
|
2005-10-30 05:33:57 +08:00
|
|
|
return PspCreateThread(ThreadHandle,
|
2005-04-22 20:52:25 +08:00
|
|
|
DesiredAccess,
|
|
|
|
ObjectAttributes,
|
|
|
|
ProcessHandle,
|
|
|
|
NULL,
|
2005-10-30 05:33:57 +08:00
|
|
|
ClientId,
|
|
|
|
ThreadContext,
|
2006-07-10 02:54:13 +08:00
|
|
|
&SafeInitialTeb,
|
2005-04-22 20:52:25 +08:00
|
|
|
CreateSuspended,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
2005-04-18 10:12:30 +08:00
|
|
|
}
|
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-05-09 09:38:29 +08:00
|
|
|
NTSTATUS
|
2006-07-10 02:54:13 +08:00
|
|
|
NTAPI
|
2005-04-22 20:52:25 +08:00
|
|
|
NtOpenThread(OUT PHANDLE ThreadHandle,
|
|
|
|
IN ACCESS_MASK DesiredAccess,
|
2005-10-30 05:33:57 +08:00
|
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
2006-07-20 13:33:03 +08:00
|
|
|
IN PCLIENT_ID ClientId OPTIONAL)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
2005-04-22 20:52:25 +08:00
|
|
|
CLIENT_ID SafeClientId;
|
2005-10-30 05:33:57 +08:00
|
|
|
ULONG Attributes = 0;
|
|
|
|
HANDLE hThread = NULL;
|
2009-08-27 01:31:02 +08:00
|
|
|
NTSTATUS Status;
|
2005-04-22 20:52:25 +08:00
|
|
|
PETHREAD Thread;
|
2005-10-30 05:33:57 +08:00
|
|
|
BOOLEAN HasObjectName = FALSE;
|
2006-07-20 13:33:03 +08:00
|
|
|
ACCESS_STATE AccessState;
|
2008-06-16 16:54:21 +08:00
|
|
|
AUX_ACCESS_DATA AuxData;
|
2005-04-18 10:12:30 +08:00
|
|
|
PAGED_CODE();
|
2006-07-24 03:45:16 +08:00
|
|
|
PSTRACE(PS_THREAD_DEBUG,
|
|
|
|
"ClientId: %p ObjectAttributes: %p\n", ClientId, ObjectAttributes);
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Check if we were called from user mode */
|
|
|
|
if (PreviousMode != KernelMode)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Enter SEH for probing */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Probe the thread handle */
|
2005-08-21 23:38:47 +08:00
|
|
|
ProbeForWriteHandle(ThreadHandle);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Check for a CID structure */
|
|
|
|
if (ClientId)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Probe and capture it */
|
|
|
|
ProbeForRead(ClientId, sizeof(CLIENT_ID), sizeof(ULONG));
|
2005-04-22 20:52:25 +08:00
|
|
|
SafeClientId = *ClientId;
|
|
|
|
ClientId = &SafeClientId;
|
2005-04-18 10:12:30 +08:00
|
|
|
}
|
2005-10-30 05:33:57 +08:00
|
|
|
|
2006-07-20 13:33:03 +08:00
|
|
|
/*
|
|
|
|
* Just probe the object attributes structure, don't capture it
|
|
|
|
* completely. This is done later if necessary
|
|
|
|
*/
|
2005-10-30 05:33:57 +08:00
|
|
|
ProbeForRead(ObjectAttributes,
|
|
|
|
sizeof(OBJECT_ATTRIBUTES),
|
|
|
|
sizeof(ULONG));
|
|
|
|
HasObjectName = (ObjectAttributes->ObjectName != NULL);
|
2015-09-24 10:40:30 +08:00
|
|
|
|
|
|
|
/* Validate user attributes */
|
|
|
|
Attributes = ObpValidateAttributes(ObjectAttributes->Attributes, PreviousMode);
|
2005-04-18 10:12:30 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2009-08-27 01:31:02 +08:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2005-05-09 09:38:29 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-04-18 10:12:30 +08:00
|
|
|
}
|
2005-10-30 05:33:57 +08:00
|
|
|
else
|
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Otherwise just get the data directly */
|
2005-10-30 05:33:57 +08:00
|
|
|
HasObjectName = (ObjectAttributes->ObjectName != NULL);
|
2015-09-24 10:40:30 +08:00
|
|
|
|
|
|
|
/* Still have to sanitize attributes */
|
|
|
|
Attributes = ObpValidateAttributes(ObjectAttributes->Attributes, PreviousMode);
|
2005-10-30 05:33:57 +08:00
|
|
|
}
|
2006-07-20 13:33:03 +08:00
|
|
|
|
|
|
|
/* Can't pass both, fail */
|
|
|
|
if ((HasObjectName) && (ClientId)) return STATUS_INVALID_PARAMETER_MIX;
|
|
|
|
|
|
|
|
/* Create an access state */
|
|
|
|
Status = SeCreateAccessState(&AccessState,
|
|
|
|
&AuxData,
|
|
|
|
DesiredAccess,
|
2015-11-27 16:49:57 +08:00
|
|
|
&PsThreadType->TypeInfo.GenericMapping);
|
2006-07-20 13:33:03 +08:00
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
|
|
|
|
|
|
|
/* Check if this is a debugger */
|
|
|
|
if (SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode))
|
2005-10-30 05:33:57 +08:00
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Did he want full access? */
|
|
|
|
if (AccessState.RemainingDesiredAccess & MAXIMUM_ALLOWED)
|
|
|
|
{
|
|
|
|
/* Give it to him */
|
|
|
|
AccessState.PreviouslyGrantedAccess |= THREAD_ALL_ACCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise just give every other access he could want */
|
|
|
|
AccessState.PreviouslyGrantedAccess |=
|
|
|
|
AccessState.RemainingDesiredAccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The caller desires nothing else now */
|
|
|
|
AccessState.RemainingDesiredAccess = 0;
|
2005-10-30 05:33:57 +08:00
|
|
|
}
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Open by name if one was given */
|
2005-10-30 05:33:57 +08:00
|
|
|
if (HasObjectName)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Open it */
|
|
|
|
Status = ObOpenObjectByName(ObjectAttributes,
|
|
|
|
PsThreadType,
|
|
|
|
PreviousMode,
|
2006-07-20 13:33:03 +08:00
|
|
|
&AccessState,
|
|
|
|
0,
|
2005-04-22 20:52:25 +08:00
|
|
|
NULL,
|
2005-08-09 12:03:14 +08:00
|
|
|
&hThread);
|
2006-07-20 13:33:03 +08:00
|
|
|
|
|
|
|
/* Get rid of the access state */
|
|
|
|
SeDeleteAccessState(&AccessState);
|
2006-07-16 04:10:13 +08:00
|
|
|
}
|
|
|
|
else if (ClientId)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Open by Thread ID */
|
2005-10-30 05:33:57 +08:00
|
|
|
if (ClientId->UniqueProcess)
|
2005-04-22 20:52:25 +08:00
|
|
|
{
|
|
|
|
/* Get the Process */
|
2006-07-20 13:33:03 +08:00
|
|
|
Status = PsLookupProcessThreadByCid(ClientId, NULL, &Thread);
|
2005-05-09 09:38:29 +08:00
|
|
|
}
|
|
|
|
else
|
2005-04-22 20:52:25 +08:00
|
|
|
{
|
|
|
|
/* Get the Process */
|
2006-07-20 13:33:03 +08:00
|
|
|
Status = PsLookupThreadByThreadId(ClientId->UniqueThread, &Thread);
|
2005-04-22 20:52:25 +08:00
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Check if we didn't find anything */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Get rid of the access state and return */
|
|
|
|
SeDeleteAccessState(&AccessState);
|
|
|
|
return Status;
|
|
|
|
}
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Open the Thread Object */
|
|
|
|
Status = ObOpenObjectByPointer(Thread,
|
2005-10-30 05:33:57 +08:00
|
|
|
Attributes,
|
2006-07-20 13:33:03 +08:00
|
|
|
&AccessState,
|
|
|
|
0,
|
2005-04-22 20:52:25 +08:00
|
|
|
PsThreadType,
|
|
|
|
PreviousMode,
|
2005-08-09 12:03:14 +08:00
|
|
|
&hThread);
|
2005-05-09 09:38:29 +08:00
|
|
|
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Delete the access state and dereference the thread */
|
|
|
|
SeDeleteAccessState(&AccessState);
|
2005-04-18 10:12:30 +08:00
|
|
|
ObDereferenceObject(Thread);
|
|
|
|
}
|
2005-10-30 05:33:57 +08:00
|
|
|
else
|
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Neither an object name nor a client id was passed */
|
2005-10-30 05:33:57 +08:00
|
|
|
return STATUS_INVALID_PARAMETER_MIX;
|
|
|
|
}
|
2005-04-18 10:12:30 +08:00
|
|
|
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Check for success */
|
2006-07-16 04:10:13 +08:00
|
|
|
if (NT_SUCCESS(Status))
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Protect against bad user-mode pointers */
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_TRY
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2006-07-10 02:54:13 +08:00
|
|
|
/* Write back the handle */
|
2005-04-18 10:12:30 +08:00
|
|
|
*ThreadHandle = hThread;
|
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2005-04-18 10:12:30 +08:00
|
|
|
{
|
2006-07-20 13:33:03 +08:00
|
|
|
/* Get the exception code */
|
2008-11-24 21:40:26 +08:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2005-04-18 10:12:30 +08:00
|
|
|
}
|
2008-11-24 21:40:26 +08:00
|
|
|
_SEH2_END;
|
2005-04-18 10:12:30 +08:00
|
|
|
}
|
|
|
|
|
2005-04-22 20:52:25 +08:00
|
|
|
/* Return status */
|
2005-04-18 10:12:30 +08:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
1999-08-29 14:59:11 +08:00
|
|
|
/* EOF */
|