- 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

View file

@ -1,11 +1,10 @@
/*
* 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/process.c
* PURPOSE: Process managment
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* David Welch (welch@cwcom.net)
* PURPOSE: Process Manager: Process Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Thomas Weidenmueller (w3seek@reactos.org
*/
/* INCLUDES ******************************************************************/
@ -24,15 +23,34 @@ PEPROCESS PsInitialSystemProcess = NULL;
PEPROCESS PsIdleProcess = NULL;
POBJECT_TYPE PsProcessType = NULL;
extern PHANDLE_TABLE PspCidTable;
extern POBJECT_TYPE DbgkDebugObjectType;
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
ULONG PsMinimumWorkingSet, PsMaximumWorkingSet;
LIST_ENTRY PsActiveProcessHead;
FAST_MUTEX PspActiveProcessMutex;
LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
/* INTERNAL FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
PspDeleteLdt(PEPROCESS Process)
{
/* FIXME */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PspDeleteVdmObjects(PEPROCESS Process)
{
/* FIXME */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PsLockProcess(PEPROCESS Process, BOOLEAN Timeout)
@ -109,12 +127,59 @@ PsUnlockProcess(PEPROCESS Process)
KeLeaveCriticalRegion();
}
PETHREAD
NTAPI
PsGetNextProcessThread(IN PEPROCESS Process,
IN PETHREAD Thread OPTIONAL)
{
PETHREAD FoundThread = NULL;
PLIST_ENTRY ListHead, Entry;
PAGED_CODE();
/* Lock the process */
PsLockProcess(Process, FALSE);
/* Check if we're already starting somewhere */
if (Thread)
{
/* Start where we left off */
Entry = Thread->ThreadListEntry.Flink;
}
else
{
/* Start at the beginning */
Entry = Process->ThreadListHead.Flink;
}
/* Set the list head and start looping */
ListHead = &Process->ThreadListHead;
while (ListHead != Entry)
{
/* Get the Thread */
FoundThread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
/* Reference the thread. FIXME: Race, use ObSafeReferenceObject */
ObReferenceObject(FoundThread);
break;
}
/* Unlock the process */
PsUnlockProcess(Process);
/* Check if we had a starting thread, and dereference it */
if (Thread) ObDereferenceObject(Thread);
/* Return what we found */
return FoundThread;
}
PEPROCESS
STDCALL
NTAPI
PsGetNextProcess(PEPROCESS OldProcess)
{
PEPROCESS NextProcess;
NTSTATUS Status;
PAGED_CODE();
/* Check if we have a previous process */
if (OldProcess == NULL)
@ -176,59 +241,77 @@ PsGetNextProcess(PEPROCESS OldProcess)
}
NTSTATUS
STDCALL
NTAPI
PspCreateProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess OPTIONAL,
IN BOOLEAN InheritObjectTable,
IN DWORD Flags,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL)
IN HANDLE ExceptionPort OPTIONAL,
IN BOOLEAN InJob)
{
HANDLE hProcess;
PEPROCESS Process = NULL;
PEPROCESS pParentProcess = NULL;
PEPORT pDebugPort = NULL;
PEPORT pExceptionPort = NULL;
PSECTION_OBJECT SectionObject = NULL;
NTSTATUS Status = STATUS_SUCCESS;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PEPROCESS Process, Parent;
PEPORT ExceptionPortObject;
PDBGK_DEBUG_OBJECT DebugObject;
PSECTION_OBJECT SectionObject;
NTSTATUS Status;
KPROCESSOR_MODE PreviousMode;
PHYSICAL_ADDRESS DirectoryTableBase;
KAFFINITY Affinity;
HANDLE_TABLE_ENTRY CidEntry;
BOOLEAN ProcessCreated = FALSE;
PETHREAD CurrentThread;
PEPROCESS CurrentProcess;
ULONG MinWs, MaxWs;
PAGED_CODE();
DirectoryTableBase.QuadPart = 0;
DirectoryTableBase.QuadPart = (ULONGLONG)0;
/* Get the current thread, process and cpu ring mode */
CurrentThread = PsGetCurrentThread();
ASSERT(&CurrentThread->Tcb == KeGetCurrentThread());
PreviousMode = ExGetPreviousMode();
ASSERT((CurrentThread) == PsGetCurrentThread());
CurrentProcess = (PEPROCESS)CurrentThread->Tcb.ApcState.Process;
DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes);
/* Validate flags */
if (Flags & ~PS_ALL_FLAGS) return STATUS_INVALID_PARAMETER;
/* Reference the Parent if there is one */
if(ParentProcess != NULL)
/* Check for parent */
if(ParentProcess)
{
/* Reference it */
Status = ObReferenceObjectByHandle(ParentProcess,
PROCESS_CREATE_PROCESS,
PsProcessType,
PreviousMode,
(PVOID*)&pParentProcess,
(PVOID*)&Parent,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status);
goto Cleanup;
return Status;
}
/* If this process should be in a job but the parent isn't */
if ((InJob) && (!Parent->Job))
{
/* This is illegal. Dereference the parent and fail */
ObDereferenceObject(Parent);
return STATUS_INVALID_PARAMETER;
}
/* Inherit Parent process's Affinity. */
Affinity = pParentProcess->Pcb.Affinity;
Affinity = Parent->Pcb.Affinity;
}
else
{
pParentProcess = NULL;
/* We have no parent */
Parent = NULL;
#ifdef CONFIG_SMP
/* FIXME:
* Only the boot cpu is initialized in the early boot phase.
/*
* FIXME: Only the boot cpu is initialized in the early boot phase.
*/
Affinity = 0xffffffff;
#else
@ -236,57 +319,11 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
#endif
}
/* Add the debug port */
if (DebugPort != NULL)
{
Status = ObReferenceObjectByHandle(DebugPort,
PORT_ALL_ACCESS,
LpcPortObjectType,
PreviousMode,
(PVOID*)&pDebugPort,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status);
goto Cleanup;
}
}
/* Add the exception port */
if (ExceptionPort != NULL)
{
Status = ObReferenceObjectByHandle(ExceptionPort,
PORT_ALL_ACCESS,
LpcPortObjectType,
PreviousMode,
(PVOID*)&pExceptionPort,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status);
goto Cleanup;
}
}
/* Add the Section */
if (SectionHandle != NULL)
{
Status = ObReferenceObjectByHandle(SectionHandle,
SECTION_MAP_EXECUTE,
MmSectionObjectType,
PreviousMode,
(PVOID*)&SectionObject,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status);
goto Cleanup;
}
}
/* Save working set data */
MinWs = PsMinimumWorkingSet;
MaxWs = PsMaximumWorkingSet;
/* Create the Object */
DPRINT("Creating Process Object\n");
Status = ObCreateObject(PreviousMode,
PsProcessType,
ObjectAttributes,
@ -296,7 +333,6 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
0,
0,
(PVOID*)&Process);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create process object, Status: 0x%x\n", Status);
@ -304,157 +340,294 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
}
/* Clean up the Object */
DPRINT("Cleaning Process Object\n");
RtlZeroMemory(Process, sizeof(EPROCESS));
/* Inherit stuff from the Parent since we now have the object created */
if (pParentProcess)
{
Process->InheritedFromUniqueProcessId = pParentProcess->UniqueProcessId;
Process->Session = pParentProcess->Session;
}
/* Setup the Thread List Head */
InitializeListHead(&Process->ThreadListHead);
/* Set up the Quota Block from the Parent */
PspInheritQuota(Process, pParentProcess);
PspInheritQuota(Process, Parent);
/* FIXME: Set up Dos Device Map from the Parent
ObInheritDeviceMap(Parent, Process) */
/* Set up Dos Device Map from the Parent */
ObInheritDeviceMap(Parent, Process);
/* Set the Process' LPC Ports */
Process->DebugPort = pDebugPort;
Process->ExceptionPort = pExceptionPort;
/* Check if we have a parent */
if (Parent)
{
/* Ineherit PID and Hard Error Processing */
Process->InheritedFromUniqueProcessId = Parent->UniqueProcessId;
Process->DefaultHardErrorProcessing = Parent->DefaultHardErrorProcessing;
}
else
{
/* Use default hard error processing */
Process->DefaultHardErrorProcessing = TRUE;
}
/* Check for a section handle */
if (SectionHandle)
{
/* Get a pointer to it */
Status = ObReferenceObjectByHandle(SectionHandle,
SECTION_MAP_EXECUTE,
MmSectionObjectType,
PreviousMode,
(PVOID*)&SectionObject,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status);
goto CleanupWithRef;
}
}
else
{
/* Is the parent the initial process? */
if (Parent != PsInitialSystemProcess)
{
/* It's not, so acquire the process rundown */
// FIXME
/* If the parent has a section, use it */
SectionObject = Parent->SectionObject;
if (SectionObject) ObReferenceObject(SectionObject);
/* Release process rundown */
// FIXME
/* If we don't have a section object */
if (!SectionObject)
{
/* Then the process is in termination, so fail */
Status = STATUS_PROCESS_IS_TERMINATING;
goto CleanupWithRef;
}
}
}
/* Save the pointer to the section object */
Process->SectionObject = SectionObject;
/* Check for the debug port */
if (DebugPort)
{
/* Reference it */
Status = ObReferenceObjectByHandle(DebugPort,
DEBUG_OBJECT_ADD_REMOVE_PROCESS,
DbgkDebugObjectType,
PreviousMode,
(PVOID*)&DebugObject,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status);
goto CleanupWithRef;
}
/* Save the debug object */
Process->DebugPort = DebugObject;
/* Check if the caller doesn't want the debug stuff inherited */
if (Flags & PS_NO_DEBUG_INHERIT) InterlockedOr(&Process->Flags, 2);
}
else
{
/* Do we have a parent? Copy his debug port */
if (Parent) DbgkCopyProcessDebugPort(Process, Parent);
}
/* Now check for an exception port */
if (ExceptionPort)
{
/* Reference it */
Status = ObReferenceObjectByHandle(ExceptionPort,
PORT_ALL_ACCESS,
LpcPortObjectType,
PreviousMode,
(PVOID*)&ExceptionPortObject,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status);
goto CleanupWithRef;
}
/* Save the exception port */
Process->ExceptionPort = ExceptionPortObject;
}
/* Save the pointer to the section object */
Process->SectionObject = SectionObject;
/* Setup the Lock Event */
DPRINT("Initialzing Process Lock\n");
Process->LockEvent = ExAllocatePoolWithTag(PagedPool,
sizeof(KEVENT),
TAG('P', 's', 'L', 'k'));
KeInitializeEvent(Process->LockEvent, SynchronizationEvent, FALSE);
/* Setup the Thread List Head */
DPRINT("Initialzing Process ThreadListHead\n");
InitializeListHead(&Process->ThreadListHead);
/* Set default exit code */
Process->ExitStatus = STATUS_TIMEOUT;
/* Create or Clone the Handle Table */
DPRINT("Initialzing Process Handle Table\n");
ObpCreateHandleTable(pParentProcess, Process);
DPRINT("Handle Table: %x\n", Process->ObjectTable);
ObpCreateHandleTable(Parent, Process);
/* Set Process's Directory Base */
DPRINT("Initialzing Process Directory Base\n");
MmCopyMmInfo((pParentProcess ? pParentProcess : PsInitialSystemProcess),
MmCopyMmInfo(Parent ? Parent : PsInitialSystemProcess,
Process,
&DirectoryTableBase);
/* We now have an address space */
InterlockedOr(&Process->Flags, 0x40000);
/* Set the maximum WS */
Process->Vm.MaximumWorkingSetSize = MaxWs;
/* Now initialize the Kernel Process */
DPRINT("Initialzing Kernel Process\n");
KeInitializeProcess(&Process->Pcb,
PROCESS_PRIORITY_NORMAL,
Affinity,
DirectoryTableBase);
/* Duplicate Parent Token */
DPRINT("Initialzing Process Token\n");
Status = PspInitializeProcessSecurity(Process, pParentProcess);
Status = PspInitializeProcessSecurity(Process, Parent);
if (!NT_SUCCESS(Status))
{
DbgPrint("PspInitializeProcessSecurity failed (Status %x)\n", Status);
goto Cleanup;
DPRINT1("PspInitializeProcessSecurity failed (Status %x)\n", Status);
goto CleanupWithRef;
}
/* Set default priority class */
Process->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
/* Create the Process' Address Space */
DPRINT("Initialzing Process Address Space\n");
Status = MmCreateProcessAddressSpace(Process, (PROS_SECTION_OBJECT)SectionObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create Address Space\n");
goto Cleanup;
goto CleanupWithRef;
}
/* Check for parent again */
#if 0
if (!Parent)
{
/* Allocate our Audit info */
Process->SeAuditProcessCreationInfo.ImageFileName =
ExAllocatePoolWithTag(PagedPool,
sizeof(SE_AUDIT_PROCESS_CREATION_INFO),
TAG_SEPA);
RtlZeroMemory(Process->SeAuditProcessCreationInfo.ImageFileName,
sizeof(SE_AUDIT_PROCESS_CREATION_INFO));
}
else
{
/* Allocate our Audit info */
Process->SeAuditProcessCreationInfo.ImageFileName =
ExAllocatePoolWithTag(PagedPool,
sizeof(SE_AUDIT_PROCESS_CREATION_INFO) +
Parent->SeAuditProcessCreationInfo.
ImageFileName->Name.MaximumLength,
TAG_SEPA);
/* Copy from parent */
RtlCopyMemory(Process->SeAuditProcessCreationInfo.ImageFileName,
Parent->SeAuditProcessCreationInfo.ImageFileName,
sizeof(SE_AUDIT_PROCESS_CREATION_INFO) +
Parent->SeAuditProcessCreationInfo.ImageFileName->
Name.MaximumLength);
/* Update buffer pointer */
Process->SeAuditProcessCreationInfo.ImageFileName->Name.Buffer =
(PVOID)(Process->SeAuditProcessCreationInfo.ImageFileName + 1);
}
#endif
/* Check if we have a section object */
if (SectionObject)
{
/* Map the System Dll */
DPRINT("Mapping System DLL\n");
PspMapSystemDll(Process, NULL);
}
/* Create a handle for the Process */
DPRINT("Initialzing Process CID Handle\n");
CidEntry.Object = Process;
CidEntry.GrantedAccess = 0;
Process->UniqueProcessId = ExCreateHandle(PspCidTable, &CidEntry);
DPRINT("Created CID: %d\n", Process->UniqueProcessId);
if(!Process->UniqueProcessId)
{
DPRINT1("Failed to create CID handle\n");
Status = STATUS_UNSUCCESSFUL; /* FIXME - what error should we return? */
goto Cleanup;
Status = STATUS_INSUFFICIENT_RESOURCES;
goto CleanupWithRef;
}
/* FIXME: Insert into Job Object */
/* Create PEB only for User-Mode Processes */
if (pParentProcess)
if (Parent)
{
DPRINT("Creating PEB\n");
Status = MmCreatePeb(Process);
if (!NT_SUCCESS(Status))
{
DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
goto Cleanup;
DPRINT("NtCreateProcess() Peb creation failed: Status %x\n",Status);
goto CleanupWithRef;
}
}
/* W00T! The process can now be activated */
DPRINT("Inserting into Active Process List\n");
/* The process can now be activated */
ExAcquireFastMutex(&PspActiveProcessMutex);
InsertTailList(&PsActiveProcessHead, &Process->ActiveProcessLinks);
ExReleaseFastMutex(&PspActiveProcessMutex);
ProcessCreated = TRUE;
/* FIXME: SeCreateAccessStateEx */
/* Insert the Process into the Object Directory */
DPRINT("Inserting Process Object\n");
Status = ObInsertObject(Process,
NULL,
DesiredAccess,
1,
(PVOID*)&Process,
&hProcess);
/* FIXME: Compute Quantum and Priority */
/*
* FIXME: ObGetObjectSecurity(Process, &SecurityDescriptor)
* SeAccessCheck
*/
ObReferenceObject(Process); // <- Act as if we called ObGetObjectSecurity
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Set the Creation Time */
KeQuerySystemTime(&Process->CreateTime);
DPRINT("Done. Returning handle: %x\n", hProcess);
/* Protect against bad user-mode pointer */
_SEH_TRY
{
/* Save the process handle */
*ProcessHandle = hProcess;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
} _SEH_END;
/* FIXME: ObGetObjectSecurity(Process, &SecurityDescriptor)
SeAccessCheck
*/
}
_SEH_END;
}
CleanupWithRef:
/*
* Dereference the process. For failures, kills the process and does
* cleanup present in PspDeleteProcess. For success, kills the extra
* reference added by ObGetObjectSecurity
*/
ObDereferenceObject(Process);
Cleanup:
if(pParentProcess != NULL) ObDereferenceObject(pParentProcess);
if(SectionObject != NULL) ObDereferenceObject(SectionObject);
if (!ProcessCreated)
{
if(pExceptionPort != NULL) ObDereferenceObject(pExceptionPort);
if(pDebugPort != NULL) ObDereferenceObject(pDebugPort);
if(Process != NULL) ObDereferenceObject(Process);
}
/* Dereference the parent */
if (Parent) ObDereferenceObject(Parent);
/* Return status to caller */
return Status;
}
@ -464,7 +637,7 @@ Cleanup:
* @implemented
*/
NTSTATUS
STDCALL
NTAPI
PsCreateSystemProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes)
@ -472,18 +645,19 @@ PsCreateSystemProcess(PHANDLE ProcessHandle,
return PspCreateProcess(ProcessHandle,
DesiredAccess,
ObjectAttributes,
NULL, /* no parent process */
FALSE,
NULL,
0,
NULL,
NULL,
NULL);
NULL,
FALSE);
}
/*
* @implemented
*/
NTSTATUS
STDCALL
NTAPI
PsLookupProcessByProcessId(IN HANDLE ProcessId,
OUT PEPROCESS *Process)
{
@ -491,7 +665,6 @@ PsLookupProcessByProcessId(IN HANDLE ProcessId,
PEPROCESS FoundProcess;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
PAGED_CODE();
KeEnterCriticalRegion();
/* Get the CID Handle Entry */
@ -514,9 +687,8 @@ PsLookupProcessByProcessId(IN HANDLE ProcessId,
ExUnlockHandleTableEntry(PspCidTable, CidEntry);
}
KeLeaveCriticalRegion();
/* Return to caller */
KeLeaveCriticalRegion();
return Status;
}
@ -524,7 +696,7 @@ PsLookupProcessByProcessId(IN HANDLE ProcessId,
* @implemented
*/
NTSTATUS
STDCALL
NTAPI
PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
OUT PEPROCESS *Process OPTIONAL,
OUT PETHREAD *Thread)
@ -533,7 +705,6 @@ PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
PETHREAD FoundThread;
NTSTATUS Status = STATUS_INVALID_CID;
PAGED_CODE();
KeEnterCriticalRegion();
/* Get the CID Handle Entry */
@ -565,9 +736,8 @@ PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
ExUnlockHandleTableEntry(PspCidTable, CidEntry);
}
KeLeaveCriticalRegion();
/* Return to caller */
KeLeaveCriticalRegion();
return Status;
}
@ -605,7 +775,7 @@ PsGetProcessExitTime(VOID)
* @implemented
*/
LONGLONG
STDCALL
NTAPI
PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
{
return Process->CreateTime.QuadPart;
@ -615,7 +785,7 @@ PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
* @implemented
*/
PVOID
STDCALL
NTAPI
PsGetProcessDebugPort(PEPROCESS Process)
{
return Process->DebugPort;
@ -625,7 +795,7 @@ PsGetProcessDebugPort(PEPROCESS Process)
* @implemented
*/
BOOLEAN
STDCALL
NTAPI
PsGetProcessExitProcessCalled(PEPROCESS Process)
{
return Process->ProcessExiting;
@ -635,7 +805,7 @@ PsGetProcessExitProcessCalled(PEPROCESS Process)
* @implemented
*/
NTSTATUS
STDCALL
NTAPI
PsGetProcessExitStatus(PEPROCESS Process)
{
return Process->ExitStatus;
@ -645,7 +815,7 @@ PsGetProcessExitStatus(PEPROCESS Process)
* @implemented
*/
HANDLE
STDCALL
NTAPI
PsGetProcessId(PEPROCESS Process)
{
return (HANDLE)Process->UniqueProcessId;
@ -655,7 +825,7 @@ PsGetProcessId(PEPROCESS Process)
* @implemented
*/
LPSTR
STDCALL
NTAPI
PsGetProcessImageFileName(PEPROCESS Process)
{
return (LPSTR)Process->ImageFileName;
@ -665,7 +835,7 @@ PsGetProcessImageFileName(PEPROCESS Process)
* @implemented
*/
HANDLE
STDCALL
NTAPI
PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
{
return Process->InheritedFromUniqueProcessId;
@ -675,7 +845,7 @@ PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
* @implemented
*/
PEJOB
STDCALL
NTAPI
PsGetProcessJob(PEPROCESS Process)
{
return Process->Job;
@ -685,7 +855,7 @@ PsGetProcessJob(PEPROCESS Process)
* @implemented
*/
PPEB
STDCALL
NTAPI
PsGetProcessPeb(PEPROCESS Process)
{
return Process->Peb;
@ -695,7 +865,7 @@ PsGetProcessPeb(PEPROCESS Process)
* @implemented
*/
ULONG
STDCALL
NTAPI
PsGetProcessPriorityClass(PEPROCESS Process)
{
return Process->PriorityClass;
@ -714,7 +884,7 @@ PsGetCurrentProcessId(VOID)
* @implemented
*/
ULONG
STDCALL
NTAPI
PsGetCurrentProcessSessionId(VOID)
{
return PsGetCurrentProcess()->Session;
@ -724,7 +894,7 @@ PsGetCurrentProcessSessionId(VOID)
* @implemented
*/
PVOID
STDCALL
NTAPI
PsGetProcessSectionBaseAddress(PEPROCESS Process)
{
return Process->SectionBaseAddress;
@ -734,7 +904,7 @@ PsGetProcessSectionBaseAddress(PEPROCESS Process)
* @implemented
*/
PVOID
STDCALL
NTAPI
PsGetProcessSecurityPort(PEPROCESS Process)
{
return Process->SecurityPort;
@ -744,7 +914,7 @@ PsGetProcessSecurityPort(PEPROCESS Process)
* @implemented
*/
HANDLE
STDCALL
NTAPI
PsGetProcessSessionId(PEPROCESS Process)
{
return (HANDLE)Process->Session;
@ -768,7 +938,7 @@ PsGetWin32Process(VOID)
* @implemented
*/
PVOID
STDCALL
NTAPI
PsGetProcessWin32Process(PEPROCESS Process)
{
return Process->Win32Process;
@ -778,7 +948,7 @@ PsGetProcessWin32Process(PEPROCESS Process)
* @implemented
*/
PVOID
STDCALL
NTAPI
PsGetProcessWin32WindowStation(PEPROCESS Process)
{
return Process->Win32WindowStation;
@ -798,7 +968,7 @@ PsIsProcessBeingDebugged(PEPROCESS Process)
* @implemented
*/
VOID
STDCALL
NTAPI
PsSetProcessPriorityClass(PEPROCESS Process,
ULONG PriorityClass)
{
@ -809,7 +979,7 @@ PsSetProcessPriorityClass(PEPROCESS Process,
* @implemented
*/
VOID
STDCALL
NTAPI
PsSetProcessSecurityPort(PEPROCESS Process,
PVOID SecurityPort)
{
@ -820,7 +990,7 @@ PsSetProcessSecurityPort(PEPROCESS Process,
* @implemented
*/
VOID
STDCALL
NTAPI
PsSetProcessWin32Process(PEPROCESS Process,
PVOID Win32Process)
{
@ -831,7 +1001,7 @@ PsSetProcessWin32Process(PEPROCESS Process,
* @implemented
*/
VOID
STDCALL
NTAPI
PsSetProcessWindowStation(PEPROCESS Process,
PVOID WindowStation)
{
@ -842,7 +1012,7 @@ PsSetProcessWindowStation(PEPROCESS Process,
* @unimplemented
*/
NTSTATUS
STDCALL
NTAPI
PsSetProcessPriorityByClass(IN PEPROCESS Process,
IN ULONG Type)
{
@ -851,38 +1021,19 @@ PsSetProcessPriorityByClass(IN PEPROCESS Process,
}
/*
* FUNCTION: Creates a process.
* ARGUMENTS:
* ProcessHandle (OUT) = Caller supplied storage for the resulting
* handle
* DesiredAccess = Specifies the allowed or desired access to the
* process can be a combination of
* STANDARD_RIGHTS_REQUIRED| ..
* ObjectAttribute = Initialized attributes for the object, contains
* the rootdirectory and the filename
* ParentProcess = Handle to the parent process.
* InheritObjectTable = Specifies to inherit the objects of the parent
* process if true.
* SectionHandle = Handle to a section object to back the image file
* DebugPort = Handle to a DebugPort if NULL the system default debug
* port will be used.
* ExceptionPort = Handle to a exception port.
* REMARKS:
* This function maps to the win32 CreateProcess.
* RETURNS: Status
*
* @implemented
*/
NTSTATUS
STDCALL
NtCreateProcess(OUT PHANDLE ProcessHandle,
NTAPI
NtCreateProcessEx(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN ULONG Flags,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL)
IN HANDLE ExceptionPort OPTIONAL,
IN BOOLEAN InJob)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
@ -906,7 +1057,7 @@ NtCreateProcess(OUT PHANDLE ProcessHandle,
}
/* Make sure there's a parent process */
if(ParentProcess == NULL)
if(!ParentProcess)
{
/* Can't create System Processes like this */
Status = STATUS_INVALID_PARAMETER;
@ -918,10 +1069,11 @@ NtCreateProcess(OUT PHANDLE ProcessHandle,
DesiredAccess,
ObjectAttributes,
ParentProcess,
InheritObjectTable,
Flags,
SectionHandle,
DebugPort,
ExceptionPort);
ExceptionPort,
InJob);
}
/* Return Status */
@ -932,7 +1084,40 @@ NtCreateProcess(OUT PHANDLE ProcessHandle,
* @implemented
*/
NTSTATUS
STDCALL
NTAPI
NtCreateProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL)
{
ULONG Flags = 0;
/* Set new-style flags */
if ((ULONG)SectionHandle & 1) Flags = PS_REQUEST_BREAKAWAY;
if ((ULONG)DebugPort & 1) Flags |= PS_NO_DEBUG_INHERIT;
if (InheritObjectTable) Flags |= PS_INHERIT_HANDLES;
/* Call the new API */
return NtCreateProcessEx(ProcessHandle,
DesiredAccess,
ObjectAttributes,
ParentProcess,
Flags,
SectionHandle,
DebugPort,
ExceptionPort,
FALSE);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
NtOpenProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
@ -997,11 +1182,9 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
}
/* Open by name if one was given */
DPRINT("Checking type\n");
if (HasObjectName)
{
/* Open it */
DPRINT("Opening by name\n");
Status = ObOpenObjectByName(ObjectAttributes,
PsProcessType,
PreviousMode,
@ -1021,7 +1204,6 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
if (ClientId->UniqueThread)
{
/* Get the Process */
DPRINT("Opening by Thread ID: %x\n", ClientId->UniqueThread);
Status = PsLookupProcessThreadByCid(ClientId,
&Process,
&Thread);
@ -1029,7 +1211,6 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
else
{
/* Get the Process */
DPRINT("Opening by Process ID: %x\n", ClientId->UniqueProcess);
Status = PsLookupProcessByProcessId(ClientId->UniqueProcess,
&Process);
}

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);
/* 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);
if(NT_SUCCESS(Status))
{
/* Wrap in SEH to protect against bad user-mode pointers */
_SEH_TRY
{
/* Return Cid and Handle */
DPRINT("All worked great!\n");
if(NT_SUCCESS(Status)) {
_SEH_TRY {
if(ClientId != NULL) {
*ClientId = Thread->Cid;
}
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,11 +762,7 @@ 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)
{
@ -736,7 +770,6 @@ NtOpenThread(OUT PHANDLE ThreadHandle,
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 ****************************************************************/