- Massive re-write of some parts of Ps, based on a patch I wrote almost a year ago and peer-reviewed with Thomas and Filip. Causes some shutdown regressions and process leaks (will fix). Needs more work. Changelog:

- Architectural changes to match information in Windows Internals 4 and other documented sources of information (Windows Internals II by Probert). Code should match Win2003 layout.
    - Handle almost any possible process/thread sub structure and add its cleanup code stubs, so that when we actually implement them, we won't forget to clean them up in the process code.
    - Add interlocked usage of process and thread flags in order to make everything more thread-safe.
    - Better handle cases where threads die instantly, race conditions, and other weird issues.
    - Better handle process termination and thread termination.
    - Implement NtCreateProcessEx and update PspCreateProcess/NtCreateProcess.
    - Improve cleanup of process object in PspProcessDelete.
    - Optimize some things like User Thread startup.
    - Add some extra asserts, paged_code checks and also user-mode security check.
    - Implement helper API PsGetNextProcessThread
    - Optimize thread reaper (thanks Filip)
    - Do proper referencing/dereferencing of thread/processes (thanks Thomas)
    - Document FIXMEs needed for Ps code to be up to standards and complete.

svn path=/trunk/; revision=22976
This commit is contained in:
Alex Ionescu 2006-07-09 18:54:13 +00:00
parent d5dbbd1211
commit f4539b7037
32 changed files with 1941 additions and 1022 deletions

View file

@ -54,4 +54,18 @@ DbgkCreateThread(PVOID StartAddress)
#endif
}
VOID
NTAPI
DbgkExitProcess(IN NTSTATUS ExitStatus)
{
/* FIXME */
}
VOID
NTAPI
DbgkExitThread(IN NTSTATUS ExitStatus)
{
/* FIXME */
}
/* EOF */

View file

@ -14,8 +14,17 @@
#include <internal/debug.h>
POBJECT_TYPE DbgkDebugObjectType;
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
DbgkCopyProcessDebugPort(IN PEPROCESS Process,
IN PEPROCESS Parent)
{
/* FIXME: Implement */
}
NTSTATUS
NTAPI
NtCreateDebugObject(OUT PHANDLE DebugHandle,

View file

@ -153,7 +153,7 @@ ShutdownThreadMain(PVOID Context)
sizeof(PCH))]);
}
PiShutdownProcessManager();
PspShutdownProcessManager();
Waittime.QuadPart = (LONGLONG)-10000000; /* 1sec */
KeDelayExecutionThread(KernelMode, FALSE, &Waittime);

View file

@ -5,6 +5,21 @@ VOID
STDCALL
DbgkCreateThread(PVOID StartAddress);
VOID
NTAPI
DbgkExitProcess(IN NTSTATUS ExitStatus);
VOID
NTAPI
DbgkExitThread(IN NTSTATUS ExitStatus);
VOID
NTAPI
DbgkCopyProcessDebugPort(
IN PEPROCESS Process,
IN PEPROCESS Parent
);
#endif
/* EOF */

View file

@ -498,7 +498,8 @@ ULONG
STDCALL
KeSetProcess(
struct _KPROCESS* Process,
KPRIORITY Increment
KPRIORITY Increment,
BOOLEAN InWait
);
VOID

View file

@ -88,7 +88,7 @@ LpcSendTerminationPort(
LARGE_INTEGER CreationTime
);
/* Code in ntoskrnl/lpc/close.h */
/* Code in ntoskrnl/lpc/close.c */
VOID
STDCALL
@ -104,6 +104,10 @@ VOID
STDCALL
LpcpDeletePort(IN PVOID ObjectBody);
VOID
NTAPI
LpcExitThread(IN PETHREAD Thread);
/* Code in ntoskrnl/lpc/queue.c */
VOID

View file

@ -619,7 +619,7 @@ MmShowOutOfSpaceMessagePagingFile(VOID);
NTSTATUS
STDCALL
MmCreateProcessAddressSpace(
IN struct _EPROCESS* Process,
IN PEPROCESS Process,
IN PROS_SECTION_OBJECT Section OPTIONAL
);
@ -627,7 +627,7 @@ NTSTATUS
STDCALL
MmCreatePeb(struct _EPROCESS *Process);
struct _TEB*
PTEB
STDCALL
MmCreateTeb(
struct _EPROCESS *Process,
@ -639,9 +639,21 @@ VOID
STDCALL
MmDeleteTeb(
struct _EPROCESS *Process,
struct _TEB* Teb
PTEB Teb
);
VOID
NTAPI
MmCleanProcessAddressSpace(IN PEPROCESS Process);
NTSTATUS
NTAPI
MmDeleteProcessAddressSpace(IN PEPROCESS Process);
ULONG
NTAPI
MmGetSessionLocaleId(VOID);
/* i386/pfault.c *************************************************************/
NTSTATUS

View file

@ -101,6 +101,26 @@ InterlockedAnd(IN OUT LONG volatile *Target,
return j;
}
FORCEINLINE
LONG
InterlockedOr(IN OUT LONG volatile *Target,
IN LONG Set)
{
LONG i;
LONG j;
j = *Target;
do {
i = j;
j = InterlockedCompareExchange((PLONG)Target,
i | Set,
i);
} while (i != j);
return j;
}
/*
* generic information class probing code
*/

View file

@ -198,6 +198,17 @@ ObpReapObject(
IN PVOID Unused
);
VOID
NTAPI
ObDereferenceDeviceMap(IN PEPROCESS Process);
VOID
NTAPI
ObInheritDeviceMap(
IN PEPROCESS Parent,
IN PEPROCESS Process
);
VOID
FASTCALL
ObpSetPermanentObject(
@ -211,9 +222,12 @@ ObpDeleteNameCheck(
IN PVOID Object
);
//
// Security functions
//
VOID
NTAPI
ObClearProcessHandleTable(IN PEPROCESS Process);
/* Security descriptor cache functions */
NTSTATUS
NTAPI
ObpInitSdCache(

View file

@ -14,4 +14,8 @@ NTSTATUS
NTAPI
PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState);
VOID
NTAPI
PopCleanupPowerState(IN PPOWER_STATE PowerState);
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_PO_H */

View file

@ -40,7 +40,7 @@ PiInitProcessManager(VOID);
VOID
NTAPI
PiShutdownProcessManager(VOID);
PspShutdownProcessManager(VOID);
VOID
NTAPI
@ -172,6 +172,13 @@ PspAssignPrimaryToken(
HANDLE TokenHandle
);
PETHREAD
NTAPI
PsGetNextProcessThread(
IN PEPROCESS Process,
IN PETHREAD Thread OPTIONAL
);
VOID
STDCALL
PsExitSpecialApc(
@ -218,14 +225,15 @@ VOID
STDCALL
PspExitThread(NTSTATUS ExitStatus);
VOID
NTSTATUS
STDCALL
PspTerminateThreadByPointer(
PETHREAD Thread,
NTSTATUS ExitStatus
NTSTATUS ExitStatus,
BOOLEAN bSelf
);
VOID
NTSTATUS
NTAPI
PsUnfreezeOtherThread(PETHREAD Thread);
@ -287,9 +295,10 @@ VOID
NTAPI
PsInitialiseSuspendImplementation(VOID);
NTSTATUS
VOID
STDCALL
PspExitProcess(PEPROCESS Process);
PspExitProcess(BOOLEAN LastThread,
PEPROCESS Process);
VOID
STDCALL
@ -376,4 +385,34 @@ VOID
NTAPI
PsUnlockProcess(PEPROCESS Process);
VOID
NTAPI
PspRemoveProcessFromJob(
IN PEPROCESS Process,
IN PEJOB Job
);
NTSTATUS
NTAPI
PspDeleteLdt(IN PEPROCESS Process);
NTSTATUS
NTAPI
PspDeleteVdmObjects(IN PEPROCESS Process);
VOID
NTAPI
PspDeleteProcessSecurity(IN PEPROCESS Process);
VOID
NTAPI
PspDeleteThreadSecurity(IN PETHREAD Thread);
VOID
NTAPI
PspExitProcessFromJob(
IN PEJOB Job,
IN PEPROCESS Process
);
#endif /* __INCLUDE_INTERNAL_PS_H */

View file

@ -136,6 +136,14 @@ PTOKEN
STDCALL
SepCreateSystemProcessToken(VOID);
BOOLEAN
NTAPI
SeDetailedAuditingWithToken(IN PTOKEN Token);
VOID
NTAPI
SeAuditProcessExit(IN PEPROCESS Process);
NTSTATUS
NTAPI
SeExchangePrimaryToken(

View file

@ -156,4 +156,7 @@
#define TAG_LPC_MESSAGE TAG('L', 'p', 'c', 'M')
#define TAG_LPC_ZONE TAG('L', 'p', 'c', 'Z')
/* Se Process Audit */
#define TAG_SEPA TAG('S', 'e', 'P', 'a')
#endif /* _NTOSKRNL_TAG_H */

View file

@ -22,7 +22,7 @@ extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
static ULONG PriorityListMask = 0;
ULONG IdleProcessorMask = 0;
extern PETHREAD PspReaperList;
extern LIST_ENTRY PspReaperListHead;
/* FUNCTIONS *****************************************************************/
@ -1383,34 +1383,56 @@ KeTerminateThread(IN KPRIORITY Increment)
{
KIRQL OldIrql;
PKTHREAD Thread = KeGetCurrentThread();
PKPROCESS Process = Thread->ApcState.Process;
PLIST_ENTRY *ListHead;
PETHREAD Entry, SavedEntry;
PETHREAD *ThreadAddr;
DPRINT("Terminating\n");
/* Lock the Dispatcher Database and the APC Queue */
DPRINT("Terminating\n");
ASSERT_IRQL(DISPATCH_LEVEL);
OldIrql = KeAcquireDispatcherDatabaseLock();
ASSERT(Thread->SwapBusy == FALSE);
/* Remove the thread from the list */
RemoveEntryList(&Thread->ThreadListEntry);
/* Make sure we won't get Swapped */
Thread->SwapBusy = TRUE;
/* Insert into the Reaper List */
DPRINT("List: %p\n", PspReaperList);
((PETHREAD)Thread)->ReaperLink = PspReaperList;
PspReaperList = (PETHREAD)Thread;
DPRINT("List: %p\n", PspReaperList);
/* Save the Kernel and User Times */
Process->KernelTime += Thread->KernelTime;
Process->UserTime += Thread->UserTime;
/* Check if it's active */
if (PspReaping == FALSE) {
/* Get the current entry and our Port */
Entry = (PETHREAD)PspReaperListHead.Flink;
ThreadAddr = &((PETHREAD)Thread)->ReaperLink;
/* Activate it. We use the internal function for speed, and use the Hyper Critical Queue */
PspReaping = TRUE;
DPRINT("Terminating\n");
/* Add it to the reaper's list */
do
{
/* Get the list head */
ListHead = &PspReaperListHead.Flink;
/* Link ourselves */
*ThreadAddr = Entry;
SavedEntry = Entry;
/* Now try to do the exchange */
Entry = InterlockedCompareExchangePointer(ListHead, ThreadAddr, Entry);
/* Break out if the change was succesful */
} while (Entry != SavedEntry);
/* Check if the reaper wasn't active */
if (!Entry)
{
/* Activate it as a work item, directly through its Queue */
KiInsertQueue(&ExWorkerQueue[HyperCriticalWorkQueue].WorkerQueue,
&PspReaperWorkItem.List,
FALSE);
}
/* Handle Kernel Queues */
if (Thread->Queue) {
if (Thread->Queue)
{
DPRINT("Waking Queue\n");
RemoveEntryList(&Thread->QueueListEntry);
KiWakeQueue(Thread->Queue);
@ -1418,12 +1440,19 @@ KeTerminateThread(IN KPRIORITY Increment)
/* Signal the thread */
Thread->DispatcherHeader.SignalState = TRUE;
if (IsListEmpty(&Thread->DispatcherHeader.WaitListHead) != TRUE) {
if (IsListEmpty(&Thread->DispatcherHeader.WaitListHead) != TRUE)
{
/* Satisfy waits */
KiWaitTest((PVOID)Thread, Increment);
}
/* Remove the thread from the list */
RemoveEntryList(&Thread->ThreadListEntry);
/* Set us as terminated, decrease the Process's stack count */
Thread->State = Terminated;
Process->StackCount--;
/* Find a new Thread */
KiDispatchThreadNoLock(Terminated);
}

View file

@ -145,7 +145,8 @@ KeInitializeProcess(PKPROCESS Process,
ULONG
NTAPI
KeSetProcess(PKPROCESS Process,
KPRIORITY Increment)
KPRIORITY Increment,
BOOLEAN InWait)
{
KIRQL OldIrql;
ULONG OldState;

View file

@ -16,6 +16,24 @@
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
LpcExitThread(IN PETHREAD Thread)
{
/* Make sure that the Reply Chain is empty */
if (!IsListEmpty(&Thread->LpcReplyChain))
{
/* It's not, remove the entry */
RemoveEntryList(&Thread->LpcReplyChain);
}
/* Set the thread in exit mode */
Thread->LpcExitThreadCalled = TRUE;
Thread->LpcReplyMessageId = 0;
/* FIXME: Reply to the LpcReplyMessage */
}
/**********************************************************************
* NAME
*

View file

@ -15,37 +15,6 @@
#define NDEBUG
#include <internal/debug.h>
/**********************************************************************
* NAME
* LpcSendTerminationPort/2
*
* DESCRIPTION
*
* ARGUMENTS
*
* RETURN VALUE
*
* REVISIONS
*/
NTSTATUS STDCALL
LpcSendTerminationPort (IN PEPORT Port,
IN LARGE_INTEGER CreateTime)
{
NTSTATUS Status;
CLIENT_DIED_MSG Msg;
#ifdef __USE_NT_LPC__
Msg.h.u2.s2.Type = LPC_CLIENT_DIED;
#endif
Msg.h.u1.s1.TotalLength = sizeof(Msg);
Msg.h.u1.s1.DataLength = sizeof(Msg) - sizeof(PORT_MESSAGE);
Msg.CreateTime = CreateTime;
Status = LpcRequestPort (Port, &Msg.h);
return(Status);
}
/**********************************************************************
* NAME
* LpcSendDebugMessagePort/3

View file

@ -22,66 +22,12 @@ ULONG MmUserProbeAddress = 0;
PVOID MmHighestUserAddress = NULL;
PBOOLEAN Mm64BitPhysicalAddress = FALSE;
PVOID MmSystemRangeStart = NULL;
ULONG MmReadClusterSize;
MM_STATS MmStats;
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
MmReleaseMmInfo(PEPROCESS Process)
{
PVOID Address;
PMEMORY_AREA MemoryArea;
DPRINT("MmReleaseMmInfo(Process %x (%s))\n", Process,
Process->ImageFileName);
MmLockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
while ((MemoryArea = ((PMADDRESS_SPACE)&Process->VadRoot)->MemoryAreaRoot) != NULL)
{
switch (MemoryArea->Type)
{
case MEMORY_AREA_SECTION_VIEW:
Address = (PVOID)MemoryArea->StartingAddress;
MmUnlockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
MmUnmapViewOfSection((PEPROCESS)Process, Address);
MmLockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
break;
case MEMORY_AREA_VIRTUAL_MEMORY:
case MEMORY_AREA_PEB_OR_TEB:
MmFreeVirtualMemory(Process, MemoryArea);
break;
case MEMORY_AREA_SHARED_DATA:
case MEMORY_AREA_NO_ACCESS:
MmFreeMemoryArea((PMADDRESS_SPACE)&Process->VadRoot,
MemoryArea,
NULL,
NULL);
break;
case MEMORY_AREA_MDL_MAPPING:
KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
break;
default:
KEBUGCHECK(0);
}
}
Mmi386ReleaseMmInfo(Process);
MmUnlockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
MmDestroyAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
DPRINT("Finished MmReleaseMmInfo()\n");
return(STATUS_SUCCESS);
}
/*
* @implemented
*/

View file

@ -23,6 +23,33 @@ extern ULONG NtGlobalFlag;
/* FUNCTIONS *****************************************************************/
LCID
NTAPI
MmGetSessionLocaleId(VOID)
{
PEPROCESS Process;
PAGED_CODE();
/* Get the current process */
Process = PsGetCurrentProcess();
/* Check if it's the Session Leader */
if (Process->Vm.Flags.SessionLeader)
{
/* Make sure it has a valid Session */
if (Process->Session)
{
/* Get the Locale ID */
#if ROS_HAS_SESSIONS
return ((PMM_SESSION_SPACE)Process->Session)->LocaleId;
#endif
}
}
/* Not a session leader, return the default */
return PsDefaultThreadLocaleId;
}
PVOID
STDCALL
MiCreatePebOrTeb(PEPROCESS Process,
@ -489,6 +516,9 @@ MmCreateProcessAddressSpace(IN PEPROCESS Process,
goto exit;
}
/* The process now has an address space */
Process->HasAddressSpace = TRUE;
/* Check if there's a Section Object */
if (Section)
{
@ -559,3 +589,64 @@ exit:
/* Return status to caller */
return Status;
}
VOID
NTAPI
MmCleanProcessAddressSpace(IN PEPROCESS Process)
{
/* FIXME: Add part of MmDeleteProcessAddressSpace here */
}
NTSTATUS
NTAPI
MmDeleteProcessAddressSpace(PEPROCESS Process)
{
PVOID Address;
PMEMORY_AREA MemoryArea;
DPRINT("MmDeleteProcessAddressSpace(Process %x (%s))\n", Process,
Process->ImageFileName);
MmLockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
while ((MemoryArea = ((PMADDRESS_SPACE)&Process->VadRoot)->MemoryAreaRoot) != NULL)
{
switch (MemoryArea->Type)
{
case MEMORY_AREA_SECTION_VIEW:
Address = (PVOID)MemoryArea->StartingAddress;
MmUnlockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
MmUnmapViewOfSection(Process, Address);
MmLockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
break;
case MEMORY_AREA_VIRTUAL_MEMORY:
case MEMORY_AREA_PEB_OR_TEB:
MmFreeVirtualMemory(Process, MemoryArea);
break;
case MEMORY_AREA_SHARED_DATA:
case MEMORY_AREA_NO_ACCESS:
MmFreeMemoryArea((PMADDRESS_SPACE)&Process->VadRoot,
MemoryArea,
NULL,
NULL);
break;
case MEMORY_AREA_MDL_MAPPING:
KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
break;
default:
KEBUGCHECK(0);
}
}
Mmi386ReleaseMmInfo(Process);
MmUnlockAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
MmDestroyAddressSpace((PMADDRESS_SPACE)&Process->VadRoot);
DPRINT("Finished MmReleaseMmInfo()\n");
return(STATUS_SUCCESS);
}

View file

@ -979,6 +979,14 @@ Language=English
SPIN_LOCK_INIT_FAILURE
.
MessageId=0x94
Severity=Success
Facility=System
SymbolicName=KERNEL_STACK_LOCKED_AT_EXIT
Language=English
KERNEL_STACK_LOCKED_AT_EXIT
.
MessageId=0x96
Severity=Success
Facility=System
@ -1085,6 +1093,23 @@ Language=English
certain\n conditions. There is absolutely no warranty for ReactOS.\n
.
MessageId=0xE9
Severity=Success
Facility=System
SymbolicName=ACTIVE_EX_WORKER_THREAD_TERMINATION
Language=English
ACTIVE_EX_WORKER_THREAD_TERMINATION
.
MessageId=0xEF
Severity=Success
Facility=System
SymbolicName=CRITICAL_PROCESS_DIED
Language=English
CRITICAL_PROCESS_DIED
.
MessageId=0xFC
Severity=Success
Facility=System

View file

@ -244,7 +244,7 @@ ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
//
// WE DONT CLOSE REGISTRY HANDLES BECAUSE CM IS BRAINDEAD
//
DPRINT1("NOT CLOSING THE KEY\n");
DPRINT("NOT CLOSING THE KEY\n");
}
else
{
@ -1119,6 +1119,13 @@ ObpDuplicateHandleCallback(IN PHANDLE_TABLE HandleTable,
return Ret;
}
VOID
NTAPI
ObClearProcessHandleTable(IN PEPROCESS Process)
{
/* FIXME */
}
/*++
* @name ObpCreateHandleTable
*

View file

@ -11,6 +11,7 @@
/* INCLUDES ******************************************************************/
#define NTDDI_VERSION NTDDI_WINXP
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
@ -20,6 +21,49 @@ POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
ObDereferenceDeviceMap(IN PEPROCESS Process)
{
//KIRQL OldIrql;
PDEVICE_MAP DeviceMap = Process->DeviceMap;
/* FIXME: We don't use Process Devicemaps yet */
if (DeviceMap)
{
/* FIXME: Acquire the DeviceMap Spinlock */
// KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
/* Delete the device map link and dereference it */
Process->DeviceMap = NULL;
if (--DeviceMap->ReferenceCount)
{
/* Nobody is referencing it anymore, unlink the DOS directory */
DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
/* FIXME: Release the DeviceMap Spinlock */
// KeReleasepinLock(DeviceMap->Lock, OldIrql);
/* Dereference the DOS Devices Directory and free the Device Map */
ObDereferenceObject(DeviceMap->DosDevicesDirectory);
ExFreePool(DeviceMap);
}
else
{
/* FIXME: Release the DeviceMap Spinlock */
// KeReleasepinLock(DeviceMap->Lock, OldIrql);
}
}
}
VOID
NTAPI
ObInheritDeviceMap(IN PEPROCESS Parent,
IN PEPROCESS Process)
{
/* FIXME: Devicemap Support */
}
/*++
* @name ObpDeleteNameCheck
*

View file

@ -90,7 +90,7 @@ ObfDereferenceObject(IN PVOID Object)
if (Header->PointerCount < Header->HandleCount)
{
DPRINT1("Misbehaving object: %wZ\n", &Header->Type->Name);
DPRINT("Misbehaving object: %wZ\n", &Header->Type->Name);
return;
}
@ -100,7 +100,7 @@ ObfDereferenceObject(IN PVOID Object)
/* Sanity check */
if (Header->HandleCount)
{
DPRINT1("Misbehaving object: %wZ\n", &Header->Type->Name);
DPRINT("Misbehaving object: %wZ\n", &Header->Type->Name);
return;
}

View file

@ -183,6 +183,13 @@ PoSetDeviceBusy(
{
}
VOID
NTAPI
PopCleanupPowerState(IN PPOWER_STATE PowerState)
{
/* FIXME */
}
/*
* @unimplemented
*/

View file

@ -4,16 +4,14 @@
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/job.c
* PURPOSE: Job Native Functions
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) (stubs)
* Thomas Weidenmueller <w3seek@reactos.com>
*/
/* Note: Jobs are only supported on Win2K+ */
/* INCLUDES *****************************************************************/
#define NDEBUG
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
#if defined (ALLOC_PRAGMA)
@ -39,7 +37,8 @@ static GENERIC_MAPPING PiJobMapping =
/* FUNCTIONS *****************************************************************/
VOID STDCALL
VOID
NTAPI
PiDeleteJob ( PVOID ObjectBody )
{
PEJOB Job = (PEJOB)ObjectBody;
@ -89,8 +88,7 @@ PsInitJobManagment ( VOID )
NTSTATUS
NTAPI
PspAssignProcessToJob (
PEPROCESS Process,
PspAssignProcessToJob(PEPROCESS Process,
PEJOB Job)
{
DPRINT("PspAssignProcessToJob() is unimplemented!\n");
@ -99,8 +97,7 @@ PspAssignProcessToJob (
NTSTATUS
NTAPI
PspTerminateJobObject (
PEJOB Job,
PspTerminateJobObject(PEJOB Job,
KPROCESSOR_MODE AccessMode,
NTSTATUS ExitStatus )
{
@ -108,6 +105,21 @@ PspTerminateJobObject (
return STATUS_NOT_IMPLEMENTED;
}
VOID
NTAPI
PspRemoveProcessFromJob(IN PEPROCESS Process,
IN PEJOB Job)
{
/* FIXME */
}
VOID
NTAPI
PspExitProcessFromJob(IN PEJOB Job,
IN PEPROCESS Process)
{
/* FIXME */
}
/*
* @unimplemented
@ -547,8 +559,7 @@ PsGetJobUIRestrictionsClass ( PEJOB Job )
*/
VOID
STDCALL
PsSetJobUIRestrictionsClass (
PEJOB Job,
PsSetJobUIRestrictionsClass(PEJOB Job,
ULONG UIRestrictionsClass)
{
ASSERT(Job);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -64,15 +64,6 @@ NTSTATUS STDCALL INIT_FUNCTION PspLookupKernelUserEntryPoints(VOID);
/* FUNCTIONS ***************************************************************/
VOID
NTAPI
PiShutdownProcessManager(VOID)
{
DPRINT("PiShutdownProcessManager()\n");
PspKillMostProcesses();
}
VOID
INIT_FUNCTION
NTAPI

View file

@ -39,6 +39,40 @@ PspUnlockProcessSecurityShared(PEPROCESS Process)
KeLeaveGuardedRegion();
}
VOID
NTAPI
PspDeleteProcessSecurity(IN PEPROCESS Process)
{
/* Check if we have a token */
if (Process->Token.Object)
{
/* Deassign it */
SeDeassignPrimaryToken(Process);
Process->Token.Object = NULL;
}
}
VOID
NTAPI
PspDeleteThreadSecurity(IN PETHREAD Thread)
{
/* Check if we have active impersonation info */
if (Thread->ActiveImpersonationInfo)
{
/* Dereference its token */
ObDereferenceObject(Thread->ImpersonationInfo->Token);
}
/* Check if we have impersonation info */
if (Thread->ImpersonationInfo)
{
/* Free it */
ExFreePool(Thread->ImpersonationInfo);
Thread->ActiveImpersonationInfo = FALSE;
Thread->ImpersonationInfo = NULL;
}
}
/* FUNCTIONS *****************************************************************/
/*

View file

@ -1,11 +1,23 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ps/thread.c
* PURPOSE: Thread managment
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
* Phillip Susi
* PURPOSE: Process Manager: Thread Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Thomas Weidenmueller (w3seek@reactos.org
*/
/*
* Alex FIXMEs:
* - CRITICAL: NtCurrentTeb returns KPCR.
* - CRITICAL: Verify rundown APIs (ex/rundown.c) and use them where necessary.
* - MAJOR: Implement Pushlocks and use them as process lock.
* - MAJOR: Implement Safe Referencing (See PsGetNextProcess/Thread).
* - MAJOR: Implement Fast Referencing (mostly for tokens).
* - MAJOR: Use Guarded Mutex instead of Fast Mutex for Active Process Locks.
* - Generate process cookie for user-more thread.
* - Add security calls where necessary.
* - KeInit/StartThread for better isolation of code
*/
/* INCLUDES ****************************************************************/
@ -19,83 +31,112 @@
extern LIST_ENTRY PsActiveProcessHead;
extern PEPROCESS PsIdleProcess;
extern PVOID PspSystemDllEntryPoint;
extern PVOID PspSystemDllBase;
extern PHANDLE_TABLE PspCidTable;
extern BOOLEAN CcPfEnablePrefetcher;
extern ULONG MmReadClusterSize;
POBJECT_TYPE PsThreadType = NULL;
/* FUNCTIONS ***************************************************************/
VOID
STDCALL
PspThreadSpecialApc(PKAPC Apc,
PKNORMAL_ROUTINE* NormalRoutine,
PVOID* NormalContext,
PVOID* SystemArgument1,
PVOID* SystemArgument2)
{
ExFreePool(Apc);
}
VOID
STDCALL
NTAPI
PspUserThreadStartup(PKSTART_ROUTINE StartRoutine,
PVOID StartContext)
{
PKAPC ThreadApc;
PETHREAD Thread = PsGetCurrentThread();
PETHREAD Thread;
PTEB Teb;
BOOLEAN DeadThread = FALSE;
PAGED_CODE();
DPRINT("I am a new USER thread. This is my start routine: %p. This my context: %p."
"This is my IRQL: %d. This is my Thread Pointer: %x.\n", StartRoutine,
StartContext, KeGetCurrentIrql(), Thread);
/* Go to Passive Level */
KeLowerIrql(PASSIVE_LEVEL);
Thread = PsGetCurrentThread();
if (!Thread->Terminated) {
/* Allocate the APC */
ThreadApc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG('T', 'h', 'r','d'));
/* Initialize it */
KeInitializeApc(ThreadApc,
&Thread->Tcb,
OriginalApcEnvironment,
PspThreadSpecialApc,
NULL,
PspSystemDllEntryPoint,
UserMode,
NULL);
/* Insert it into the queue */
KeInsertQueueApc(ThreadApc, NULL, NULL, IO_NO_INCREMENT);
Thread->Tcb.ApcState.UserApcPending = TRUE;
/* Check if the thread is dead */
if (Thread->DeadThread)
{
/* Remember that we're dead */
DPRINT1("This thread is already dead\n");
DeadThread = TRUE;
}
else
{
/* Get the Locale ID and save Preferred Proc */
Teb = NtCurrentTeb(); /* FIXME: This returns KPCR!!! */
//Teb->CurrentLocale = MmGetSessionLocaleId();
//Teb->IdealProcessor = Thread->Tcb.IdealProcessor;
}
/* Go to Passive Level and notify debugger */
KeLowerIrql(PASSIVE_LEVEL);
DbgkCreateThread(StartContext);
/* Check if this is a system thread, or if we're hiding */
if ((Thread->SystemThread) || (Thread->HideFromDebugger))
{
/* Notify the debugger */
DbgkCreateThread(StartContext);
}
/* 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 */
KfRaiseIrql(APC_LEVEL);
/* Queue the User APC */
KiInitializeUserApc(NULL,
(PVOID)((ULONG_PTR)Thread->Tcb.InitialStack -
sizeof(KTRAP_FRAME) -
sizeof(FX_SAVE_AREA)),
PspSystemDllEntryPoint,
NULL,
PspSystemDllBase,
NULL);
/* Lower it back to passive */
KeLowerIrql(PASSIVE_LEVEL);
}
else
{
/* We're dead, kill us now */
PspTerminateThreadByPointer(Thread, STATUS_THREAD_IS_TERMINATING, TRUE);
}
/* Do we have a cookie set yet? */
if (!SharedUserData->Cookie)
{
/* FIXME: Generate cookie */
}
}
VOID
STDCALL
NTAPI
PspSystemThreadStartup(PKSTART_ROUTINE StartRoutine,
PVOID StartContext)
{
PETHREAD Thread = PsGetCurrentThread();
PETHREAD Thread;
/* Unlock the dispatcher Database */
KeLowerIrql(PASSIVE_LEVEL);
Thread = PsGetCurrentThread();
/* Make sure it's not terminated by now */
if (!Thread->Terminated) {
/* Call it */
(StartRoutine)(StartContext);
/* Make sure the thread isn't gone */
if (!(Thread->Terminated) || !(Thread->DeadThread))
{
/* Call it the Start Routine */
StartRoutine(StartContext);
}
/* Exit the thread */
PspExitThread(STATUS_SUCCESS);
PspTerminateThreadByPointer(Thread, STATUS_SUCCESS, TRUE);
}
NTSTATUS
STDCALL
NTAPI
PspCreateThread(OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
@ -117,46 +158,54 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
NTSTATUS Status;
HANDLE_TABLE_ENTRY CidEntry;
ULONG_PTR KernelStack;
PAGED_CODE();
/* If we were called from PsCreateSystemThread, then we're kernel mode */
if (StartRoutine) PreviousMode = KernelMode;
/* Reference the Process by handle or pointer, depending on what we got */
DPRINT("PspCreateThread: %x, %x, %x\n", ProcessHandle, TargetProcess, ThreadContext);
if (ProcessHandle) {
if (ProcessHandle)
{
/* Normal thread or System Thread */
DPRINT("Referencing Parent Process\n");
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_CREATE_THREAD,
PsProcessType,
PreviousMode,
(PVOID*)&Process,
NULL);
} else {
}
else
{
/* System thread inside System Process, or Normal Thread with a bug */
if (StartRoutine) {
if (StartRoutine)
{
/* Reference the Process by Pointer */
DPRINT("Referencing Parent System Process\n");
ObReferenceObject(TargetProcess);
Process = TargetProcess;
Status = STATUS_SUCCESS;
} else {
}
else
{
/* Fake ObReference returning this */
Status = STATUS_INVALID_HANDLE;
}
}
/* Check for success */
if(!NT_SUCCESS(Status)) {
if(!NT_SUCCESS(Status))
{
DPRINT1("Invalid Process Handle, or no handle given\n");
return(Status);
return Status;
}
/* Also make sure that User-Mode isn't trying to create a system thread */
if ((PreviousMode != KernelMode) && (Process == PsInitialSystemProcess))
{
ObDereferenceObject(Process);
return STATUS_INVALID_HANDLE;
}
/* Create Thread Object */
DPRINT("Creating Thread Object\n");
Status = ObCreateObject(PreviousMode,
PsThreadType,
ObjectAttributes,
@ -166,69 +215,61 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
0,
0,
(PVOID*)&Thread);
/* Check for success */
if (!NT_SUCCESS(Status)) {
/* Dereference the Process */
if (!NT_SUCCESS(Status))
{
/* We failed; dereference the process and exit */
DPRINT1("Failed to Create Thread Object\n");
ObDereferenceObject(Process);
return(Status);
return Status;
}
/* Zero the Object entirely */
DPRINT("Cleaning Thread Object\n");
RtlZeroMemory(Thread, sizeof(ETHREAD));
/* Set the Process CID */
Thread->ThreadsProcess = Process;
Thread->Cid.UniqueProcess = Process->UniqueProcessId;
/* Create Cid Handle */
DPRINT("Creating Thread Handle (CID)\n");
CidEntry.Object = Thread;
CidEntry.GrantedAccess = 0;
Thread->Cid.UniqueThread = ExCreateHandle(PspCidTable, &CidEntry);
if (!Thread->Cid.UniqueThread) {
if (!Thread->Cid.UniqueThread)
{
/* We couldn't create the CID, dereference everything and fail */
DPRINT1("Failed to create Thread Handle (CID)\n");
ObDereferenceObject(Process);
ObDereferenceObject(Thread);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Initialize Lists */
DPRINT("Initialliazing Thread Lists and Locks\n");
/* Save the read cluster size */
Thread->ReadClusterSize = MmReadClusterSize;
/* Initialize the LPC Reply Semaphore */
KeInitializeSemaphore(&Thread->LpcReplySemaphore, 0, MAXLONG);
/* Initialize the list heads and locks */
InitializeListHead(&Thread->LpcReplyChain);
InitializeListHead(&Thread->IrpList);
InitializeListHead(&Thread->PostBlockList);
InitializeListHead(&Thread->ActiveTimerListHead);
KeInitializeSpinLock(&Thread->ActiveTimerListLock);
/* Initialize LPC */
DPRINT("Initialliazing Thread Semaphore\n");
KeInitializeSemaphore(&Thread->LpcReplySemaphore, 0, MAXLONG);
/* Allocate Stack for non-GUI Thread */
DPRINT("Initialliazing Thread Stack\n");
KernelStack = (ULONG_PTR)MmCreateKernelStack(FALSE) + KERNEL_STACK_SIZE;
/* Set the Process CID */
DPRINT("Initialliazing Thread PID and Parent Process\n");
Thread->Cid.UniqueProcess = Process->UniqueProcessId;
Thread->ThreadsProcess = Process;
/* Now let the kernel initialize the context */
if (ThreadContext) {
/* User-mode Thread */
/* Create Teb */
DPRINT("Initialliazing Thread PEB\n");
if (ThreadContext)
{
/* User-mode Thread, create Teb */
TebBase = MmCreateTeb(Process, &Thread->Cid, InitialTeb);
/* Set the Start Addresses */
DPRINT("Initialliazing Thread Start Addresses :%x, %x\n", ThreadContext->Eip, ThreadContext->Eax);
Thread->StartAddress = (PVOID)ThreadContext->Eip;
Thread->Win32StartAddress = (PVOID)ThreadContext->Eax;
/* Let the kernel intialize the Thread */
DPRINT("Initialliazing Kernel Thread\n");
KeInitializeThread(&Process->Pcb,
&Thread->Tcb,
PspUserThreadStartup,
@ -237,16 +278,14 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
ThreadContext,
TebBase,
(PVOID)KernelStack);
} else {
}
else
{
/* System Thread */
DPRINT("Initialliazing Thread Start Address :%x\n", StartRoutine);
Thread->StartAddress = StartRoutine;
Thread->SystemThread = TRUE;
InterlockedOr(&Thread->CrossThreadFlags, 0x10);
/* Let the kernel intialize the Thread */
DPRINT("Initialliazing Kernel Thread\n");
KeInitializeThread(&Process->Pcb,
&Thread->Tcb,
PspSystemThreadStartup,
@ -262,61 +301,63 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
* Note, this is the ETHREAD Thread List. It is removed in
* ps/kill.c!PspExitThread.
*/
DPRINT("Inserting into Process Thread List \n");
InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
Process->ActiveThreads++;
/* Notify WMI */
//WmiTraceProcess(Process, TRUE);
//WmiTraceThread(Thread, InitialTeb, TRUE);
/* Notify Thread Creation */
DPRINT("Running Thread Notify \n");
PspRunCreateThreadNotifyRoutines(Thread, TRUE);
/* Suspend the Thread if we have to */
if (CreateSuspended) {
DPRINT("Suspending Thread\n");
if (CreateSuspended)
{
KeSuspendThread(&Thread->Tcb);
}
/* Check if we were already terminated */
if (Thread->Terminated)
{
/* Force us to wake up to terminate */
KeForceResumeThread(&Thread->Tcb);
}
/* Reference ourselves as a keep-alive */
ObReferenceObject(Thread);
/* Insert the Thread into the Object Manager */
DPRINT("Inserting Thread\n");
Status = ObInsertObject((PVOID)Thread,
NULL,
DesiredAccess,
0,
NULL,
&hThread);
/* Return Cid and Handle */
DPRINT("All worked great!\n");
if(NT_SUCCESS(Status)) {
_SEH_TRY {
if(ClientId != NULL) {
*ClientId = Thread->Cid;
}
if(NT_SUCCESS(Status))
{
/* Wrap in SEH to protect against bad user-mode pointers */
_SEH_TRY
{
/* Return Cid and Handle */
if(ClientId) *ClientId = Thread->Cid;
*ThreadHandle = hThread;
} _SEH_HANDLE {
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
_SEH_END;
}
/* FIXME: SECURITY */
/* Dispatch thread */
DPRINT("About to dispatch the thread: %x!\n", &Thread->Tcb);
OldIrql = KeAcquireDispatcherDatabaseLock ();
KiUnblockThread(&Thread->Tcb, NULL, 0);
KeReleaseDispatcherDatabaseLock(OldIrql);
/* Return */
DPRINT("Returning\n");
return Status;
}
@ -324,7 +365,7 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
* @implemented
*/
NTSTATUS
STDCALL
NTAPI
PsCreateSystemThread(PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
@ -335,10 +376,11 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
{
PEPROCESS TargetProcess = NULL;
HANDLE Handle = ProcessHandle;
PAGED_CODE();
/* Check if we have a handle. If not, use the System Process */
if (!ProcessHandle) {
if (!ProcessHandle)
{
Handle = NULL;
TargetProcess = PsInitialSystemProcess;
}
@ -361,7 +403,7 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
* @implemented
*/
NTSTATUS
STDCALL
NTAPI
PsLookupThreadByThreadId(IN HANDLE ThreadId,
OUT PETHREAD *Thread)
{
@ -369,7 +411,6 @@ PsLookupThreadByThreadId(IN HANDLE ThreadId,
PETHREAD FoundThread;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
PAGED_CODE();
KeEnterCriticalRegion();
/* Get the CID Handle Entry */
@ -392,9 +433,8 @@ PsLookupThreadByThreadId(IN HANDLE ThreadId,
ExUnlockHandleTableEntry(PspCidTable, CidEntry);
}
KeLeaveCriticalRegion();
/* Return to caller */
KeLeaveCriticalRegion();
return Status;
}
@ -402,7 +442,7 @@ PsLookupThreadByThreadId(IN HANDLE ThreadId,
* @implemented
*/
HANDLE
STDCALL
NTAPI
PsGetCurrentThreadId(VOID)
{
return(PsGetCurrentThread()->Cid.UniqueThread);
@ -412,7 +452,7 @@ PsGetCurrentThreadId(VOID)
* @implemented
*/
ULONG
STDCALL
NTAPI
PsGetThreadFreezeCount(PETHREAD Thread)
{
return Thread->Tcb.FreezeCount;
@ -422,7 +462,7 @@ PsGetThreadFreezeCount(PETHREAD Thread)
* @implemented
*/
BOOLEAN
STDCALL
NTAPI
PsGetThreadHardErrorsAreDisabled(PETHREAD Thread)
{
return Thread->HardErrorsAreDisabled;
@ -432,7 +472,7 @@ PsGetThreadHardErrorsAreDisabled(PETHREAD Thread)
* @implemented
*/
HANDLE
STDCALL
NTAPI
PsGetThreadId(PETHREAD Thread)
{
return Thread->Cid.UniqueThread;
@ -442,7 +482,7 @@ PsGetThreadId(PETHREAD Thread)
* @implemented
*/
PEPROCESS
STDCALL
NTAPI
PsGetThreadProcess(PETHREAD Thread)
{
return Thread->ThreadsProcess;
@ -452,7 +492,7 @@ PsGetThreadProcess(PETHREAD Thread)
* @implemented
*/
HANDLE
STDCALL
NTAPI
PsGetThreadProcessId(PETHREAD Thread)
{
return Thread->Cid.UniqueProcess;
@ -462,7 +502,7 @@ PsGetThreadProcessId(PETHREAD Thread)
* @implemented
*/
HANDLE
STDCALL
NTAPI
PsGetThreadSessionId(PETHREAD Thread)
{
return (HANDLE)Thread->ThreadsProcess->Session;
@ -472,7 +512,7 @@ PsGetThreadSessionId(PETHREAD Thread)
* @implemented
*/
PTEB
STDCALL
NTAPI
PsGetThreadTeb(PETHREAD Thread)
{
return Thread->Tcb.Teb;
@ -482,7 +522,7 @@ PsGetThreadTeb(PETHREAD Thread)
* @implemented
*/
PVOID
STDCALL
NTAPI
PsGetThreadWin32Thread(PETHREAD Thread)
{
return Thread->Tcb.Win32Thread;
@ -492,7 +532,7 @@ PsGetThreadWin32Thread(PETHREAD Thread)
* @implemented
*/
KPROCESSOR_MODE
STDCALL
NTAPI
PsGetCurrentThreadPreviousMode(VOID)
{
return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode;
@ -502,7 +542,7 @@ PsGetCurrentThreadPreviousMode(VOID)
* @implemented
*/
PVOID
STDCALL
NTAPI
PsGetCurrentThreadStackBase(VOID)
{
return PsGetCurrentThread()->Tcb.StackBase;
@ -512,7 +552,7 @@ PsGetCurrentThreadStackBase(VOID)
* @implemented
*/
PVOID
STDCALL
NTAPI
PsGetCurrentThreadStackLimit(VOID)
{
return (PVOID)PsGetCurrentThread()->Tcb.StackLimit;
@ -522,7 +562,7 @@ PsGetCurrentThreadStackLimit(VOID)
* @implemented
*/
BOOLEAN
STDCALL
NTAPI
PsIsThreadTerminating(IN PETHREAD Thread)
{
return (Thread->Terminated ? TRUE : FALSE);
@ -532,7 +572,7 @@ PsIsThreadTerminating(IN PETHREAD Thread)
* @implemented
*/
BOOLEAN
STDCALL
NTAPI
PsIsSystemThread(PETHREAD Thread)
{
return (Thread->SystemThread ? TRUE: FALSE);
@ -542,7 +582,7 @@ PsIsSystemThread(PETHREAD Thread)
* @implemented
*/
BOOLEAN
STDCALL
NTAPI
PsIsThreadImpersonating(PETHREAD Thread)
{
return Thread->ActiveImpersonationInfo;
@ -552,7 +592,7 @@ PsIsThreadImpersonating(PETHREAD Thread)
* @implemented
*/
VOID
STDCALL
NTAPI
PsSetThreadHardErrorsAreDisabled(PETHREAD Thread,
BOOLEAN HardErrorsAreDisabled)
{
@ -563,7 +603,7 @@ PsSetThreadHardErrorsAreDisabled(PETHREAD Thread,
* @implemented
*/
VOID
STDCALL
NTAPI
PsSetThreadWin32Thread(PETHREAD Thread,
PVOID Win32Thread)
{
@ -571,7 +611,7 @@ PsSetThreadWin32Thread(PETHREAD Thread,
}
NTSTATUS
STDCALL
NTAPI
NtCreateThread(OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
@ -582,55 +622,53 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
IN BOOLEAN CreateSuspended)
{
INITIAL_TEB SafeInitialTeb;
CONTEXT SafeContext;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
ThreadHandle,ThreadContext);
if(KeGetPreviousMode() != KernelMode) {
if (ThreadContext == NULL) {
/* Check if this was from user-mode */
if(KeGetPreviousMode() != KernelMode)
{
/* Make sure that we got a context */
if (!ThreadContext)
{
DPRINT1("No context for User-Mode Thread!!\n");
return STATUS_INVALID_PARAMETER;
}
_SEH_TRY {
/* Protect checks */
_SEH_TRY
{
/* Make sure the handle pointer we got is valid */
ProbeForWriteHandle(ThreadHandle);
if(ClientId != NULL) {
ProbeForWrite(ClientId,
sizeof(CLIENT_ID),
sizeof(ULONG));
/* Check if the caller wants a client id */
if(ClientId)
{
/* Make sure we can write to it */
ProbeForWrite(ClientId, sizeof(CLIENT_ID), sizeof(ULONG));
}
if(ThreadContext != NULL) {
/* Make sure that the entire context is readable */
ProbeForRead(ThreadContext, sizeof(CONTEXT), sizeof(ULONG));
ProbeForRead(ThreadContext,
sizeof(CONTEXT),
sizeof(ULONG));
SafeContext = *ThreadContext;
ThreadContext = &SafeContext;
}
ProbeForRead(InitialTeb,
sizeof(INITIAL_TEB),
sizeof(ULONG));
/* Check the Initial TEB */
ProbeForRead(InitialTeb, sizeof(INITIAL_TEB), sizeof(ULONG));
SafeInitialTeb = *InitialTeb;
InitialTeb = &SafeInitialTeb;
} _SEH_HANDLE {
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
} _SEH_END;
/* Handle any failures in our SEH checks */
if (!NT_SUCCESS(Status)) return Status;
}
else
{
/* Use the Initial TEB as is */
SafeInitialTeb = *InitialTeb;
}
/* Call the shared function */
return PspCreateThread(ThreadHandle,
@ -640,7 +678,7 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
NULL,
ClientId,
ThreadContext,
InitialTeb,
&SafeInitialTeb,
CreateSuspended,
NULL,
NULL);
@ -650,7 +688,7 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
* @implemented
*/
NTSTATUS
STDCALL
NTAPI
NtOpenThread(OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
@ -724,19 +762,14 @@ NtOpenThread(OUT PHANDLE ThreadHandle,
DesiredAccess,
NULL,
&hThread);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not open object by name\n");
if (!NT_SUCCESS(Status)) DPRINT1("Could not open object by name\n");
}
}
else if (ClientId != NULL)
{
/* Open by Thread ID */
if (ClientId->UniqueProcess)
{
/* Get the Process */
DPRINT("Opening by Process ID: %x\n", ClientId->UniqueProcess);
Status = PsLookupProcessThreadByCid(ClientId,
NULL,
&Thread);
@ -744,7 +777,6 @@ NtOpenThread(OUT PHANDLE ThreadHandle,
else
{
/* Get the Process */
DPRINT("Opening by Thread ID: %x\n", ClientId->UniqueThread);
Status = PsLookupThreadByThreadId(ClientId->UniqueThread,
&Thread);
}
@ -777,11 +809,13 @@ NtOpenThread(OUT PHANDLE ThreadHandle,
return STATUS_INVALID_PARAMETER_MIX;
}
/* Write back the handle */
/* Check for success */
if(NT_SUCCESS(Status))
{
/* Protect against bad user-mode pointers */
_SEH_TRY
{
/* Write back the handle */
*ThreadHandle = hThread;
}
_SEH_HANDLE
@ -796,7 +830,7 @@ NtOpenThread(OUT PHANDLE ThreadHandle,
}
NTSTATUS
STDCALL
NTAPI
NtYieldExecution(VOID)
{
KiDispatchThread(Ready);
@ -804,7 +838,7 @@ NtYieldExecution(VOID)
}
NTSTATUS
STDCALL
NTAPI
NtTestAlert(VOID)
{
/* Check and Alert Thread if needed */
@ -815,7 +849,7 @@ NtTestAlert(VOID)
* @implemented
*/
KPROCESSOR_MODE
STDCALL
NTAPI
ExGetPreviousMode (VOID)
{
return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode;

View file

@ -16,8 +16,8 @@
/* GLOBALS ******************************************************************/
static PKWIN32_PROCESS_CALLOUT PspWin32ProcessCallback = NULL;
static PKWIN32_THREAD_CALLOUT PspWin32ThreadCallback = NULL;
PKWIN32_PROCESS_CALLOUT PspW32ProcessCallout = NULL;
PKWIN32_THREAD_CALLOUT PspW32ThreadCallout = NULL;
extern PKWIN32_PARSEMETHOD_CALLOUT ExpWindowStationObjectParse;
extern PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete;
extern PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete;
@ -53,8 +53,8 @@ VOID
STDCALL
PsEstablishWin32Callouts(PWIN32_CALLOUTS_FPNS CalloutData)
{
PspWin32ProcessCallback = CalloutData->ProcessCallout;
PspWin32ThreadCallback = CalloutData->ThreadCallout;
PspW32ProcessCallout = CalloutData->ProcessCallout;
PspW32ThreadCallout = CalloutData->ThreadCallout;
ExpWindowStationObjectParse = CalloutData->WindowStationParseProcedure;
ExpWindowStationObjectDelete = CalloutData->WindowStationDeleteProcedure;
ExpDesktopObjectDelete = CalloutData->DesktopDeleteProcedure;
@ -79,7 +79,7 @@ PsConvertToGuiThread(VOID)
}
/* Make sure win32k is here */
if (!PspWin32ProcessCallback)
if (!PspW32ProcessCallout)
{
DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n");
return STATUS_ACCESS_DENIED;
@ -122,7 +122,7 @@ PsConvertToGuiThread(VOID)
if (!Process->Win32Process)
{
/* Now tell win32k about us */
Status = PspWin32ProcessCallback(Process, TRUE);
Status = PspW32ProcessCallout(Process, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Danger: Win32k wasn't happy about us!\n");
@ -135,7 +135,7 @@ PsConvertToGuiThread(VOID)
ASSERT(Thread->Tcb.Win32Thread == 0);
/* Tell Win32k about our thread */
Status = PspWin32ThreadCallback(Thread, PsW32ThreadCalloutInitialize);
Status = PspW32ThreadCallout(Thread, PsW32ThreadCalloutInitialize);
if (!NT_SUCCESS(Status))
{
/* Revert our table */
@ -147,39 +147,6 @@ PsConvertToGuiThread(VOID)
return Status;
}
VOID
NTAPI
PsTerminateWin32Process (PEPROCESS Process)
{
if (Process->Win32Process == NULL)
return;
if (PspWin32ProcessCallback != NULL)
{
PspWin32ProcessCallback (Process, FALSE);
}
/* don't delete the W32PROCESS structure at this point, wait until the
EPROCESS structure is being freed */
}
VOID
NTAPI
PsTerminateWin32Thread (PETHREAD Thread)
{
if (Thread->Tcb.Win32Thread != NULL)
{
if (PspWin32ThreadCallback != NULL)
{
PspWin32ThreadCallback (Thread, PsW32ThreadCalloutExit);
}
/* don't delete the W32THREAD structure at this point, wait until the
ETHREAD structure is being freed */
}
}
NTSTATUS
STDCALL
NtW32Call(IN ULONG RoutineIndex,

View file

@ -13,6 +13,22 @@
#include <ntoskrnl.h>
#include <internal/debug.h>
/* INTERNAL *****************************************************************/
BOOLEAN
NTAPI
SeDetailedAuditingWithToken(IN PTOKEN Token)
{
/* FIXME */
return FALSE;
}
VOID
NTAPI
SeAuditProcessExit(IN PEPROCESS Process)
{
/* FIXME */
}
/* FUNCTIONS ****************************************************************/