- 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 #endif
} }
VOID
NTAPI
DbgkExitProcess(IN NTSTATUS ExitStatus)
{
/* FIXME */
}
VOID
NTAPI
DbgkExitThread(IN NTSTATUS ExitStatus)
{
/* FIXME */
}
/* EOF */ /* EOF */

View file

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

View file

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

View file

@ -5,6 +5,21 @@ VOID
STDCALL STDCALL
DbgkCreateThread(PVOID StartAddress); 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 #endif
/* EOF */ /* EOF */

View file

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

View file

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

View file

@ -619,7 +619,7 @@ MmShowOutOfSpaceMessagePagingFile(VOID);
NTSTATUS NTSTATUS
STDCALL STDCALL
MmCreateProcessAddressSpace( MmCreateProcessAddressSpace(
IN struct _EPROCESS* Process, IN PEPROCESS Process,
IN PROS_SECTION_OBJECT Section OPTIONAL IN PROS_SECTION_OBJECT Section OPTIONAL
); );
@ -627,7 +627,7 @@ NTSTATUS
STDCALL STDCALL
MmCreatePeb(struct _EPROCESS *Process); MmCreatePeb(struct _EPROCESS *Process);
struct _TEB* PTEB
STDCALL STDCALL
MmCreateTeb( MmCreateTeb(
struct _EPROCESS *Process, struct _EPROCESS *Process,
@ -639,9 +639,21 @@ VOID
STDCALL STDCALL
MmDeleteTeb( MmDeleteTeb(
struct _EPROCESS *Process, 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 *************************************************************/ /* i386/pfault.c *************************************************************/
NTSTATUS NTSTATUS

View file

@ -101,6 +101,26 @@ InterlockedAnd(IN OUT LONG volatile *Target,
return j; 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 * generic information class probing code
*/ */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -22,7 +22,7 @@ extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY]; LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY];
static ULONG PriorityListMask = 0; static ULONG PriorityListMask = 0;
ULONG IdleProcessorMask = 0; ULONG IdleProcessorMask = 0;
extern PETHREAD PspReaperList; extern LIST_ENTRY PspReaperListHead;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -1383,34 +1383,56 @@ KeTerminateThread(IN KPRIORITY Increment)
{ {
KIRQL OldIrql; KIRQL OldIrql;
PKTHREAD Thread = KeGetCurrentThread(); 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 */ /* Lock the Dispatcher Database and the APC Queue */
DPRINT("Terminating\n"); ASSERT_IRQL(DISPATCH_LEVEL);
OldIrql = KeAcquireDispatcherDatabaseLock(); OldIrql = KeAcquireDispatcherDatabaseLock();
ASSERT(Thread->SwapBusy == FALSE);
/* Remove the thread from the list */ /* Make sure we won't get Swapped */
RemoveEntryList(&Thread->ThreadListEntry); Thread->SwapBusy = TRUE;
/* Insert into the Reaper List */ /* Save the Kernel and User Times */
DPRINT("List: %p\n", PspReaperList); Process->KernelTime += Thread->KernelTime;
((PETHREAD)Thread)->ReaperLink = PspReaperList; Process->UserTime += Thread->UserTime;
PspReaperList = (PETHREAD)Thread;
DPRINT("List: %p\n", PspReaperList);
/* Check if it's active */ /* Get the current entry and our Port */
if (PspReaping == FALSE) { Entry = (PETHREAD)PspReaperListHead.Flink;
ThreadAddr = &((PETHREAD)Thread)->ReaperLink;
/* Activate it. We use the internal function for speed, and use the Hyper Critical Queue */ /* Add it to the reaper's list */
PspReaping = TRUE; do
DPRINT("Terminating\n"); {
/* 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, KiInsertQueue(&ExWorkerQueue[HyperCriticalWorkQueue].WorkerQueue,
&PspReaperWorkItem.List, &PspReaperWorkItem.List,
FALSE); FALSE);
} }
/* Handle Kernel Queues */ /* Handle Kernel Queues */
if (Thread->Queue) { if (Thread->Queue)
{
DPRINT("Waking Queue\n"); DPRINT("Waking Queue\n");
RemoveEntryList(&Thread->QueueListEntry); RemoveEntryList(&Thread->QueueListEntry);
KiWakeQueue(Thread->Queue); KiWakeQueue(Thread->Queue);
@ -1418,12 +1440,19 @@ KeTerminateThread(IN KPRIORITY Increment)
/* Signal the thread */ /* Signal the thread */
Thread->DispatcherHeader.SignalState = TRUE; Thread->DispatcherHeader.SignalState = TRUE;
if (IsListEmpty(&Thread->DispatcherHeader.WaitListHead) != TRUE) { if (IsListEmpty(&Thread->DispatcherHeader.WaitListHead) != TRUE)
{
/* Satisfy waits */ /* Satisfy waits */
KiWaitTest((PVOID)Thread, Increment); 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 */ /* Find a new Thread */
KiDispatchThreadNoLock(Terminated); KiDispatchThreadNoLock(Terminated);
} }

View file

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

View file

@ -16,6 +16,24 @@
/* FUNCTIONS *****************************************************************/ /* 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 * NAME
* *

View file

@ -15,37 +15,6 @@
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #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 * NAME
* LpcSendDebugMessagePort/3 * LpcSendDebugMessagePort/3

View file

@ -22,66 +22,12 @@ ULONG MmUserProbeAddress = 0;
PVOID MmHighestUserAddress = NULL; PVOID MmHighestUserAddress = NULL;
PBOOLEAN Mm64BitPhysicalAddress = FALSE; PBOOLEAN Mm64BitPhysicalAddress = FALSE;
PVOID MmSystemRangeStart = NULL; PVOID MmSystemRangeStart = NULL;
ULONG MmReadClusterSize;
MM_STATS MmStats; MM_STATS MmStats;
/* FUNCTIONS ****************************************************************/ /* 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 * @implemented
*/ */

View file

@ -23,6 +23,33 @@ extern ULONG NtGlobalFlag;
/* FUNCTIONS *****************************************************************/ /* 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 PVOID
STDCALL STDCALL
MiCreatePebOrTeb(PEPROCESS Process, MiCreatePebOrTeb(PEPROCESS Process,
@ -489,6 +516,9 @@ MmCreateProcessAddressSpace(IN PEPROCESS Process,
goto exit; goto exit;
} }
/* The process now has an address space */
Process->HasAddressSpace = TRUE;
/* Check if there's a Section Object */ /* Check if there's a Section Object */
if (Section) if (Section)
{ {
@ -559,3 +589,64 @@ exit:
/* Return status to caller */ /* Return status to caller */
return Status; 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 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 MessageId=0x96
Severity=Success Severity=Success
Facility=System Facility=System
@ -1085,6 +1093,23 @@ Language=English
certain\n conditions. There is absolutely no warranty for ReactOS.\n 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 MessageId=0xFC
Severity=Success Severity=Success
Facility=System Facility=System

View file

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

View file

@ -11,6 +11,7 @@
/* INCLUDES ******************************************************************/ /* INCLUDES ******************************************************************/
#define NTDDI_VERSION NTDDI_WINXP
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
@ -20,6 +21,49 @@ POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
/* PRIVATE FUNCTIONS *********************************************************/ /* 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 * @name ObpDeleteNameCheck
* *

View file

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

View file

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

View file

@ -4,16 +4,14 @@
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/job.c * FILE: ntoskrnl/ps/job.c
* PURPOSE: Job Native Functions * PURPOSE: Job Native Functions
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) (stubs) * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) (stubs)
* Thomas Weidenmueller <w3seek@reactos.com> * Thomas Weidenmueller <w3seek@reactos.com>
*/ */
/* Note: Jobs are only supported on Win2K+ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#define NDEBUG
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
#if defined (ALLOC_PRAGMA) #if defined (ALLOC_PRAGMA)
@ -39,7 +37,8 @@ static GENERIC_MAPPING PiJobMapping =
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID STDCALL VOID
NTAPI
PiDeleteJob ( PVOID ObjectBody ) PiDeleteJob ( PVOID ObjectBody )
{ {
PEJOB Job = (PEJOB)ObjectBody; PEJOB Job = (PEJOB)ObjectBody;
@ -89,8 +88,7 @@ PsInitJobManagment ( VOID )
NTSTATUS NTSTATUS
NTAPI NTAPI
PspAssignProcessToJob ( PspAssignProcessToJob(PEPROCESS Process,
PEPROCESS Process,
PEJOB Job) PEJOB Job)
{ {
DPRINT("PspAssignProcessToJob() is unimplemented!\n"); DPRINT("PspAssignProcessToJob() is unimplemented!\n");
@ -99,8 +97,7 @@ PspAssignProcessToJob (
NTSTATUS NTSTATUS
NTAPI NTAPI
PspTerminateJobObject ( PspTerminateJobObject(PEJOB Job,
PEJOB Job,
KPROCESSOR_MODE AccessMode, KPROCESSOR_MODE AccessMode,
NTSTATUS ExitStatus ) NTSTATUS ExitStatus )
{ {
@ -108,6 +105,21 @@ PspTerminateJobObject (
return STATUS_NOT_IMPLEMENTED; 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 * @unimplemented
@ -547,8 +559,7 @@ PsGetJobUIRestrictionsClass ( PEJOB Job )
*/ */
VOID VOID
STDCALL STDCALL
PsSetJobUIRestrictionsClass ( PsSetJobUIRestrictionsClass(PEJOB Job,
PEJOB Job,
ULONG UIRestrictionsClass) ULONG UIRestrictionsClass)
{ {
ASSERT(Job); 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 * FILE: ntoskrnl/ps/process.c
* PURPOSE: Process managment * PURPOSE: Process Manager: Process Management
* * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) * Thomas Weidenmueller (w3seek@reactos.org
* David Welch (welch@cwcom.net)
*/ */
/* INCLUDES ******************************************************************/ /* INCLUDES ******************************************************************/
@ -24,15 +23,34 @@ PEPROCESS PsInitialSystemProcess = NULL;
PEPROCESS PsIdleProcess = NULL; PEPROCESS PsIdleProcess = NULL;
POBJECT_TYPE PsProcessType = NULL; POBJECT_TYPE PsProcessType = NULL;
extern PHANDLE_TABLE PspCidTable; extern PHANDLE_TABLE PspCidTable;
extern POBJECT_TYPE DbgkDebugObjectType;
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock; EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
ULONG PsMinimumWorkingSet, PsMaximumWorkingSet;
LIST_ENTRY PsActiveProcessHead; LIST_ENTRY PsActiveProcessHead;
FAST_MUTEX PspActiveProcessMutex; FAST_MUTEX PspActiveProcessMutex;
LARGE_INTEGER ShortPsLockDelay, PsLockTimeout; LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
/* INTERNAL FUNCTIONS *****************************************************************/ /* INTERNAL FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
PspDeleteLdt(PEPROCESS Process)
{
/* FIXME */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
PspDeleteVdmObjects(PEPROCESS Process)
{
/* FIXME */
return STATUS_SUCCESS;
}
NTSTATUS NTSTATUS
NTAPI NTAPI
PsLockProcess(PEPROCESS Process, BOOLEAN Timeout) PsLockProcess(PEPROCESS Process, BOOLEAN Timeout)
@ -109,12 +127,59 @@ PsUnlockProcess(PEPROCESS Process)
KeLeaveCriticalRegion(); 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 PEPROCESS
STDCALL NTAPI
PsGetNextProcess(PEPROCESS OldProcess) PsGetNextProcess(PEPROCESS OldProcess)
{ {
PEPROCESS NextProcess; PEPROCESS NextProcess;
NTSTATUS Status; NTSTATUS Status;
PAGED_CODE();
/* Check if we have a previous process */ /* Check if we have a previous process */
if (OldProcess == NULL) if (OldProcess == NULL)
@ -176,59 +241,77 @@ PsGetNextProcess(PEPROCESS OldProcess)
} }
NTSTATUS NTSTATUS
STDCALL NTAPI
PspCreateProcess(OUT PHANDLE ProcessHandle, PspCreateProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess OPTIONAL, IN HANDLE ParentProcess OPTIONAL,
IN BOOLEAN InheritObjectTable, IN DWORD Flags,
IN HANDLE SectionHandle OPTIONAL, IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL, IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL) IN HANDLE ExceptionPort OPTIONAL,
IN BOOLEAN InJob)
{ {
HANDLE hProcess; HANDLE hProcess;
PEPROCESS Process = NULL; PEPROCESS Process, Parent;
PEPROCESS pParentProcess = NULL; PEPORT ExceptionPortObject;
PEPORT pDebugPort = NULL; PDBGK_DEBUG_OBJECT DebugObject;
PEPORT pExceptionPort = NULL; PSECTION_OBJECT SectionObject;
PSECTION_OBJECT SectionObject = NULL; NTSTATUS Status;
NTSTATUS Status = STATUS_SUCCESS; KPROCESSOR_MODE PreviousMode;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PHYSICAL_ADDRESS DirectoryTableBase; PHYSICAL_ADDRESS DirectoryTableBase;
KAFFINITY Affinity; KAFFINITY Affinity;
HANDLE_TABLE_ENTRY CidEntry; 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 */ /* Check for parent */
if(ParentProcess != NULL) if(ParentProcess)
{ {
/* Reference it */
Status = ObReferenceObjectByHandle(ParentProcess, Status = ObReferenceObjectByHandle(ParentProcess,
PROCESS_CREATE_PROCESS, PROCESS_CREATE_PROCESS,
PsProcessType, PsProcessType,
PreviousMode, PreviousMode,
(PVOID*)&pParentProcess, (PVOID*)&Parent,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to reference the parent process: Status: 0x%x\n", 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. */ /* Inherit Parent process's Affinity. */
Affinity = pParentProcess->Pcb.Affinity; Affinity = Parent->Pcb.Affinity;
} }
else else
{ {
pParentProcess = NULL; /* We have no parent */
Parent = NULL;
#ifdef CONFIG_SMP #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; Affinity = 0xffffffff;
#else #else
@ -236,57 +319,11 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
#endif #endif
} }
/* Add the debug port */ /* Save working set data */
if (DebugPort != NULL) MinWs = PsMinimumWorkingSet;
{ MaxWs = PsMaximumWorkingSet;
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;
}
}
/* Create the Object */ /* Create the Object */
DPRINT("Creating Process Object\n");
Status = ObCreateObject(PreviousMode, Status = ObCreateObject(PreviousMode,
PsProcessType, PsProcessType,
ObjectAttributes, ObjectAttributes,
@ -296,7 +333,6 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
0, 0,
0, 0,
(PVOID*)&Process); (PVOID*)&Process);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to create process object, Status: 0x%x\n", Status); DPRINT1("Failed to create process object, Status: 0x%x\n", Status);
@ -304,157 +340,294 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
} }
/* Clean up the Object */ /* Clean up the Object */
DPRINT("Cleaning Process Object\n");
RtlZeroMemory(Process, sizeof(EPROCESS)); RtlZeroMemory(Process, sizeof(EPROCESS));
/* Inherit stuff from the Parent since we now have the object created */ /* Setup the Thread List Head */
if (pParentProcess) InitializeListHead(&Process->ThreadListHead);
{
Process->InheritedFromUniqueProcessId = pParentProcess->UniqueProcessId;
Process->Session = pParentProcess->Session;
}
/* Set up the Quota Block from the Parent */ /* Set up the Quota Block from the Parent */
PspInheritQuota(Process, pParentProcess); PspInheritQuota(Process, Parent);
/* FIXME: Set up Dos Device Map from the Parent /* Set up Dos Device Map from the Parent */
ObInheritDeviceMap(Parent, Process) */ ObInheritDeviceMap(Parent, Process);
/* Set the Process' LPC Ports */ /* Check if we have a parent */
Process->DebugPort = pDebugPort; if (Parent)
Process->ExceptionPort = pExceptionPort; {
/* 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 */ /* Save the pointer to the section object */
Process->SectionObject = SectionObject; Process->SectionObject = SectionObject;
/* Setup the Lock Event */ /* Setup the Lock Event */
DPRINT("Initialzing Process Lock\n");
Process->LockEvent = ExAllocatePoolWithTag(PagedPool, Process->LockEvent = ExAllocatePoolWithTag(PagedPool,
sizeof(KEVENT), sizeof(KEVENT),
TAG('P', 's', 'L', 'k')); TAG('P', 's', 'L', 'k'));
KeInitializeEvent(Process->LockEvent, SynchronizationEvent, FALSE); KeInitializeEvent(Process->LockEvent, SynchronizationEvent, FALSE);
/* Setup the Thread List Head */ /* Set default exit code */
DPRINT("Initialzing Process ThreadListHead\n"); Process->ExitStatus = STATUS_TIMEOUT;
InitializeListHead(&Process->ThreadListHead);
/* Create or Clone the Handle Table */ /* Create or Clone the Handle Table */
DPRINT("Initialzing Process Handle Table\n"); ObpCreateHandleTable(Parent, Process);
ObpCreateHandleTable(pParentProcess, Process);
DPRINT("Handle Table: %x\n", Process->ObjectTable);
/* Set Process's Directory Base */ /* Set Process's Directory Base */
DPRINT("Initialzing Process Directory Base\n"); MmCopyMmInfo(Parent ? Parent : PsInitialSystemProcess,
MmCopyMmInfo((pParentProcess ? pParentProcess : PsInitialSystemProcess),
Process, Process,
&DirectoryTableBase); &DirectoryTableBase);
/* We now have an address space */
InterlockedOr(&Process->Flags, 0x40000);
/* Set the maximum WS */
Process->Vm.MaximumWorkingSetSize = MaxWs;
/* Now initialize the Kernel Process */ /* Now initialize the Kernel Process */
DPRINT("Initialzing Kernel Process\n");
KeInitializeProcess(&Process->Pcb, KeInitializeProcess(&Process->Pcb,
PROCESS_PRIORITY_NORMAL, PROCESS_PRIORITY_NORMAL,
Affinity, Affinity,
DirectoryTableBase); DirectoryTableBase);
/* Duplicate Parent Token */ /* Duplicate Parent Token */
DPRINT("Initialzing Process Token\n"); Status = PspInitializeProcessSecurity(Process, Parent);
Status = PspInitializeProcessSecurity(Process, pParentProcess);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DbgPrint("PspInitializeProcessSecurity failed (Status %x)\n", Status); DPRINT1("PspInitializeProcessSecurity failed (Status %x)\n", Status);
goto Cleanup; goto CleanupWithRef;
} }
/* Set default priority class */
Process->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
/* Create the Process' Address Space */ /* Create the Process' Address Space */
DPRINT("Initialzing Process Address Space\n");
Status = MmCreateProcessAddressSpace(Process, (PROS_SECTION_OBJECT)SectionObject); Status = MmCreateProcessAddressSpace(Process, (PROS_SECTION_OBJECT)SectionObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to create Address Space\n"); 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) if (SectionObject)
{ {
/* Map the System Dll */ /* Map the System Dll */
DPRINT("Mapping System DLL\n");
PspMapSystemDll(Process, NULL); PspMapSystemDll(Process, NULL);
} }
/* Create a handle for the Process */ /* Create a handle for the Process */
DPRINT("Initialzing Process CID Handle\n");
CidEntry.Object = Process; CidEntry.Object = Process;
CidEntry.GrantedAccess = 0; CidEntry.GrantedAccess = 0;
Process->UniqueProcessId = ExCreateHandle(PspCidTable, &CidEntry); Process->UniqueProcessId = ExCreateHandle(PspCidTable, &CidEntry);
DPRINT("Created CID: %d\n", Process->UniqueProcessId);
if(!Process->UniqueProcessId) if(!Process->UniqueProcessId)
{ {
DPRINT1("Failed to create CID handle\n"); DPRINT1("Failed to create CID handle\n");
Status = STATUS_UNSUCCESSFUL; /* FIXME - what error should we return? */ Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup; goto CleanupWithRef;
} }
/* FIXME: Insert into Job Object */ /* FIXME: Insert into Job Object */
/* Create PEB only for User-Mode Processes */ /* Create PEB only for User-Mode Processes */
if (pParentProcess) if (Parent)
{ {
DPRINT("Creating PEB\n");
Status = MmCreatePeb(Process); Status = MmCreatePeb(Process);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status); DPRINT("NtCreateProcess() Peb creation failed: Status %x\n",Status);
goto Cleanup; goto CleanupWithRef;
} }
} }
/* W00T! The process can now be activated */ /* The process can now be activated */
DPRINT("Inserting into Active Process List\n");
ExAcquireFastMutex(&PspActiveProcessMutex); ExAcquireFastMutex(&PspActiveProcessMutex);
InsertTailList(&PsActiveProcessHead, &Process->ActiveProcessLinks); InsertTailList(&PsActiveProcessHead, &Process->ActiveProcessLinks);
ExReleaseFastMutex(&PspActiveProcessMutex); ExReleaseFastMutex(&PspActiveProcessMutex);
ProcessCreated = TRUE;
/* FIXME: SeCreateAccessStateEx */ /* FIXME: SeCreateAccessStateEx */
/* Insert the Process into the Object Directory */ /* Insert the Process into the Object Directory */
DPRINT("Inserting Process Object\n");
Status = ObInsertObject(Process, Status = ObInsertObject(Process,
NULL, NULL,
DesiredAccess, DesiredAccess,
1, 1,
(PVOID*)&Process, (PVOID*)&Process,
&hProcess); &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)) if (NT_SUCCESS(Status))
{ {
/* Set the Creation Time */ /* Set the Creation Time */
KeQuerySystemTime(&Process->CreateTime); KeQuerySystemTime(&Process->CreateTime);
DPRINT("Done. Returning handle: %x\n", hProcess); /* Protect against bad user-mode pointer */
_SEH_TRY _SEH_TRY
{ {
/* Save the process handle */
*ProcessHandle = hProcess; *ProcessHandle = hProcess;
} }
_SEH_HANDLE _SEH_HANDLE
{ {
Status = _SEH_GetExceptionCode(); 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: Cleanup:
if(pParentProcess != NULL) ObDereferenceObject(pParentProcess); /* Dereference the parent */
if(SectionObject != NULL) ObDereferenceObject(SectionObject); if (Parent) ObDereferenceObject(Parent);
if (!ProcessCreated)
{
if(pExceptionPort != NULL) ObDereferenceObject(pExceptionPort);
if(pDebugPort != NULL) ObDereferenceObject(pDebugPort);
if(Process != NULL) ObDereferenceObject(Process);
}
/* Return status to caller */
return Status; return Status;
} }
@ -464,7 +637,7 @@ Cleanup:
* @implemented * @implemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
PsCreateSystemProcess(PHANDLE ProcessHandle, PsCreateSystemProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess, ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes) POBJECT_ATTRIBUTES ObjectAttributes)
@ -472,18 +645,19 @@ PsCreateSystemProcess(PHANDLE ProcessHandle,
return PspCreateProcess(ProcessHandle, return PspCreateProcess(ProcessHandle,
DesiredAccess, DesiredAccess,
ObjectAttributes, ObjectAttributes,
NULL, /* no parent process */ NULL,
FALSE, 0,
NULL, NULL,
NULL, NULL,
NULL); NULL,
FALSE);
} }
/* /*
* @implemented * @implemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
PsLookupProcessByProcessId(IN HANDLE ProcessId, PsLookupProcessByProcessId(IN HANDLE ProcessId,
OUT PEPROCESS *Process) OUT PEPROCESS *Process)
{ {
@ -491,7 +665,6 @@ PsLookupProcessByProcessId(IN HANDLE ProcessId,
PEPROCESS FoundProcess; PEPROCESS FoundProcess;
NTSTATUS Status = STATUS_INVALID_PARAMETER; NTSTATUS Status = STATUS_INVALID_PARAMETER;
PAGED_CODE(); PAGED_CODE();
KeEnterCriticalRegion(); KeEnterCriticalRegion();
/* Get the CID Handle Entry */ /* Get the CID Handle Entry */
@ -514,9 +687,8 @@ PsLookupProcessByProcessId(IN HANDLE ProcessId,
ExUnlockHandleTableEntry(PspCidTable, CidEntry); ExUnlockHandleTableEntry(PspCidTable, CidEntry);
} }
KeLeaveCriticalRegion();
/* Return to caller */ /* Return to caller */
KeLeaveCriticalRegion();
return Status; return Status;
} }
@ -524,7 +696,7 @@ PsLookupProcessByProcessId(IN HANDLE ProcessId,
* @implemented * @implemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
PsLookupProcessThreadByCid(IN PCLIENT_ID Cid, PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
OUT PEPROCESS *Process OPTIONAL, OUT PEPROCESS *Process OPTIONAL,
OUT PETHREAD *Thread) OUT PETHREAD *Thread)
@ -533,7 +705,6 @@ PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
PETHREAD FoundThread; PETHREAD FoundThread;
NTSTATUS Status = STATUS_INVALID_CID; NTSTATUS Status = STATUS_INVALID_CID;
PAGED_CODE(); PAGED_CODE();
KeEnterCriticalRegion(); KeEnterCriticalRegion();
/* Get the CID Handle Entry */ /* Get the CID Handle Entry */
@ -565,9 +736,8 @@ PsLookupProcessThreadByCid(IN PCLIENT_ID Cid,
ExUnlockHandleTableEntry(PspCidTable, CidEntry); ExUnlockHandleTableEntry(PspCidTable, CidEntry);
} }
KeLeaveCriticalRegion();
/* Return to caller */ /* Return to caller */
KeLeaveCriticalRegion();
return Status; return Status;
} }
@ -605,7 +775,7 @@ PsGetProcessExitTime(VOID)
* @implemented * @implemented
*/ */
LONGLONG LONGLONG
STDCALL NTAPI
PsGetProcessCreateTimeQuadPart(PEPROCESS Process) PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
{ {
return Process->CreateTime.QuadPart; return Process->CreateTime.QuadPart;
@ -615,7 +785,7 @@ PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
* @implemented * @implemented
*/ */
PVOID PVOID
STDCALL NTAPI
PsGetProcessDebugPort(PEPROCESS Process) PsGetProcessDebugPort(PEPROCESS Process)
{ {
return Process->DebugPort; return Process->DebugPort;
@ -625,7 +795,7 @@ PsGetProcessDebugPort(PEPROCESS Process)
* @implemented * @implemented
*/ */
BOOLEAN BOOLEAN
STDCALL NTAPI
PsGetProcessExitProcessCalled(PEPROCESS Process) PsGetProcessExitProcessCalled(PEPROCESS Process)
{ {
return Process->ProcessExiting; return Process->ProcessExiting;
@ -635,7 +805,7 @@ PsGetProcessExitProcessCalled(PEPROCESS Process)
* @implemented * @implemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
PsGetProcessExitStatus(PEPROCESS Process) PsGetProcessExitStatus(PEPROCESS Process)
{ {
return Process->ExitStatus; return Process->ExitStatus;
@ -645,7 +815,7 @@ PsGetProcessExitStatus(PEPROCESS Process)
* @implemented * @implemented
*/ */
HANDLE HANDLE
STDCALL NTAPI
PsGetProcessId(PEPROCESS Process) PsGetProcessId(PEPROCESS Process)
{ {
return (HANDLE)Process->UniqueProcessId; return (HANDLE)Process->UniqueProcessId;
@ -655,7 +825,7 @@ PsGetProcessId(PEPROCESS Process)
* @implemented * @implemented
*/ */
LPSTR LPSTR
STDCALL NTAPI
PsGetProcessImageFileName(PEPROCESS Process) PsGetProcessImageFileName(PEPROCESS Process)
{ {
return (LPSTR)Process->ImageFileName; return (LPSTR)Process->ImageFileName;
@ -665,7 +835,7 @@ PsGetProcessImageFileName(PEPROCESS Process)
* @implemented * @implemented
*/ */
HANDLE HANDLE
STDCALL NTAPI
PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process) PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
{ {
return Process->InheritedFromUniqueProcessId; return Process->InheritedFromUniqueProcessId;
@ -675,7 +845,7 @@ PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
* @implemented * @implemented
*/ */
PEJOB PEJOB
STDCALL NTAPI
PsGetProcessJob(PEPROCESS Process) PsGetProcessJob(PEPROCESS Process)
{ {
return Process->Job; return Process->Job;
@ -685,7 +855,7 @@ PsGetProcessJob(PEPROCESS Process)
* @implemented * @implemented
*/ */
PPEB PPEB
STDCALL NTAPI
PsGetProcessPeb(PEPROCESS Process) PsGetProcessPeb(PEPROCESS Process)
{ {
return Process->Peb; return Process->Peb;
@ -695,7 +865,7 @@ PsGetProcessPeb(PEPROCESS Process)
* @implemented * @implemented
*/ */
ULONG ULONG
STDCALL NTAPI
PsGetProcessPriorityClass(PEPROCESS Process) PsGetProcessPriorityClass(PEPROCESS Process)
{ {
return Process->PriorityClass; return Process->PriorityClass;
@ -714,7 +884,7 @@ PsGetCurrentProcessId(VOID)
* @implemented * @implemented
*/ */
ULONG ULONG
STDCALL NTAPI
PsGetCurrentProcessSessionId(VOID) PsGetCurrentProcessSessionId(VOID)
{ {
return PsGetCurrentProcess()->Session; return PsGetCurrentProcess()->Session;
@ -724,7 +894,7 @@ PsGetCurrentProcessSessionId(VOID)
* @implemented * @implemented
*/ */
PVOID PVOID
STDCALL NTAPI
PsGetProcessSectionBaseAddress(PEPROCESS Process) PsGetProcessSectionBaseAddress(PEPROCESS Process)
{ {
return Process->SectionBaseAddress; return Process->SectionBaseAddress;
@ -734,7 +904,7 @@ PsGetProcessSectionBaseAddress(PEPROCESS Process)
* @implemented * @implemented
*/ */
PVOID PVOID
STDCALL NTAPI
PsGetProcessSecurityPort(PEPROCESS Process) PsGetProcessSecurityPort(PEPROCESS Process)
{ {
return Process->SecurityPort; return Process->SecurityPort;
@ -744,7 +914,7 @@ PsGetProcessSecurityPort(PEPROCESS Process)
* @implemented * @implemented
*/ */
HANDLE HANDLE
STDCALL NTAPI
PsGetProcessSessionId(PEPROCESS Process) PsGetProcessSessionId(PEPROCESS Process)
{ {
return (HANDLE)Process->Session; return (HANDLE)Process->Session;
@ -768,7 +938,7 @@ PsGetWin32Process(VOID)
* @implemented * @implemented
*/ */
PVOID PVOID
STDCALL NTAPI
PsGetProcessWin32Process(PEPROCESS Process) PsGetProcessWin32Process(PEPROCESS Process)
{ {
return Process->Win32Process; return Process->Win32Process;
@ -778,7 +948,7 @@ PsGetProcessWin32Process(PEPROCESS Process)
* @implemented * @implemented
*/ */
PVOID PVOID
STDCALL NTAPI
PsGetProcessWin32WindowStation(PEPROCESS Process) PsGetProcessWin32WindowStation(PEPROCESS Process)
{ {
return Process->Win32WindowStation; return Process->Win32WindowStation;
@ -798,7 +968,7 @@ PsIsProcessBeingDebugged(PEPROCESS Process)
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
PsSetProcessPriorityClass(PEPROCESS Process, PsSetProcessPriorityClass(PEPROCESS Process,
ULONG PriorityClass) ULONG PriorityClass)
{ {
@ -809,7 +979,7 @@ PsSetProcessPriorityClass(PEPROCESS Process,
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
PsSetProcessSecurityPort(PEPROCESS Process, PsSetProcessSecurityPort(PEPROCESS Process,
PVOID SecurityPort) PVOID SecurityPort)
{ {
@ -820,7 +990,7 @@ PsSetProcessSecurityPort(PEPROCESS Process,
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
PsSetProcessWin32Process(PEPROCESS Process, PsSetProcessWin32Process(PEPROCESS Process,
PVOID Win32Process) PVOID Win32Process)
{ {
@ -831,7 +1001,7 @@ PsSetProcessWin32Process(PEPROCESS Process,
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
PsSetProcessWindowStation(PEPROCESS Process, PsSetProcessWindowStation(PEPROCESS Process,
PVOID WindowStation) PVOID WindowStation)
{ {
@ -842,7 +1012,7 @@ PsSetProcessWindowStation(PEPROCESS Process,
* @unimplemented * @unimplemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
PsSetProcessPriorityByClass(IN PEPROCESS Process, PsSetProcessPriorityByClass(IN PEPROCESS Process,
IN ULONG Type) 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 * @implemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
NtCreateProcess(OUT PHANDLE ProcessHandle, NtCreateProcessEx(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess, IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable, IN ULONG Flags,
IN HANDLE SectionHandle OPTIONAL, IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL, IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL) IN HANDLE ExceptionPort OPTIONAL,
IN BOOLEAN InJob)
{ {
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
@ -906,7 +1057,7 @@ NtCreateProcess(OUT PHANDLE ProcessHandle,
} }
/* Make sure there's a parent process */ /* Make sure there's a parent process */
if(ParentProcess == NULL) if(!ParentProcess)
{ {
/* Can't create System Processes like this */ /* Can't create System Processes like this */
Status = STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
@ -918,10 +1069,11 @@ NtCreateProcess(OUT PHANDLE ProcessHandle,
DesiredAccess, DesiredAccess,
ObjectAttributes, ObjectAttributes,
ParentProcess, ParentProcess,
InheritObjectTable, Flags,
SectionHandle, SectionHandle,
DebugPort, DebugPort,
ExceptionPort); ExceptionPort,
InJob);
} }
/* Return Status */ /* Return Status */
@ -932,7 +1084,40 @@ NtCreateProcess(OUT PHANDLE ProcessHandle,
* @implemented * @implemented
*/ */
NTSTATUS 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, NtOpenProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_ATTRIBUTES ObjectAttributes,
@ -997,11 +1182,9 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
} }
/* Open by name if one was given */ /* Open by name if one was given */
DPRINT("Checking type\n");
if (HasObjectName) if (HasObjectName)
{ {
/* Open it */ /* Open it */
DPRINT("Opening by name\n");
Status = ObOpenObjectByName(ObjectAttributes, Status = ObOpenObjectByName(ObjectAttributes,
PsProcessType, PsProcessType,
PreviousMode, PreviousMode,
@ -1021,7 +1204,6 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
if (ClientId->UniqueThread) if (ClientId->UniqueThread)
{ {
/* Get the Process */ /* Get the Process */
DPRINT("Opening by Thread ID: %x\n", ClientId->UniqueThread);
Status = PsLookupProcessThreadByCid(ClientId, Status = PsLookupProcessThreadByCid(ClientId,
&Process, &Process,
&Thread); &Thread);
@ -1029,7 +1211,6 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
else else
{ {
/* Get the Process */ /* Get the Process */
DPRINT("Opening by Process ID: %x\n", ClientId->UniqueProcess);
Status = PsLookupProcessByProcessId(ClientId->UniqueProcess, Status = PsLookupProcessByProcessId(ClientId->UniqueProcess,
&Process); &Process);
} }

View file

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

View file

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

View file

@ -16,8 +16,8 @@
/* GLOBALS ******************************************************************/ /* GLOBALS ******************************************************************/
static PKWIN32_PROCESS_CALLOUT PspWin32ProcessCallback = NULL; PKWIN32_PROCESS_CALLOUT PspW32ProcessCallout = NULL;
static PKWIN32_THREAD_CALLOUT PspWin32ThreadCallback = NULL; PKWIN32_THREAD_CALLOUT PspW32ThreadCallout = NULL;
extern PKWIN32_PARSEMETHOD_CALLOUT ExpWindowStationObjectParse; extern PKWIN32_PARSEMETHOD_CALLOUT ExpWindowStationObjectParse;
extern PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete; extern PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete;
extern PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete; extern PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete;
@ -53,8 +53,8 @@ VOID
STDCALL STDCALL
PsEstablishWin32Callouts(PWIN32_CALLOUTS_FPNS CalloutData) PsEstablishWin32Callouts(PWIN32_CALLOUTS_FPNS CalloutData)
{ {
PspWin32ProcessCallback = CalloutData->ProcessCallout; PspW32ProcessCallout = CalloutData->ProcessCallout;
PspWin32ThreadCallback = CalloutData->ThreadCallout; PspW32ThreadCallout = CalloutData->ThreadCallout;
ExpWindowStationObjectParse = CalloutData->WindowStationParseProcedure; ExpWindowStationObjectParse = CalloutData->WindowStationParseProcedure;
ExpWindowStationObjectDelete = CalloutData->WindowStationDeleteProcedure; ExpWindowStationObjectDelete = CalloutData->WindowStationDeleteProcedure;
ExpDesktopObjectDelete = CalloutData->DesktopDeleteProcedure; ExpDesktopObjectDelete = CalloutData->DesktopDeleteProcedure;
@ -79,7 +79,7 @@ PsConvertToGuiThread(VOID)
} }
/* Make sure win32k is here */ /* Make sure win32k is here */
if (!PspWin32ProcessCallback) if (!PspW32ProcessCallout)
{ {
DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n"); DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n");
return STATUS_ACCESS_DENIED; return STATUS_ACCESS_DENIED;
@ -122,7 +122,7 @@ PsConvertToGuiThread(VOID)
if (!Process->Win32Process) if (!Process->Win32Process)
{ {
/* Now tell win32k about us */ /* Now tell win32k about us */
Status = PspWin32ProcessCallback(Process, TRUE); Status = PspW32ProcessCallout(Process, TRUE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Danger: Win32k wasn't happy about us!\n"); DPRINT1("Danger: Win32k wasn't happy about us!\n");
@ -135,7 +135,7 @@ PsConvertToGuiThread(VOID)
ASSERT(Thread->Tcb.Win32Thread == 0); ASSERT(Thread->Tcb.Win32Thread == 0);
/* Tell Win32k about our thread */ /* Tell Win32k about our thread */
Status = PspWin32ThreadCallback(Thread, PsW32ThreadCalloutInitialize); Status = PspW32ThreadCallout(Thread, PsW32ThreadCalloutInitialize);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* Revert our table */ /* Revert our table */
@ -147,39 +147,6 @@ PsConvertToGuiThread(VOID)
return Status; 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 NTSTATUS
STDCALL STDCALL
NtW32Call(IN ULONG RoutineIndex, NtW32Call(IN ULONG RoutineIndex,

View file

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