3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/process.c
6 * PURPOSE: Process managment
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
11 /* INCLUDES ******************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ******************************************************************/
19 PEPROCESS EXPORTED PsInitialSystemProcess
= NULL
;
21 POBJECT_TYPE EXPORTED PsProcessType
= NULL
;
23 LIST_ENTRY PsProcessListHead
;
24 static KSPIN_LOCK PsProcessListLock
;
25 static LARGE_INTEGER ShortPsLockDelay
, PsLockTimeout
;
27 static GENERIC_MAPPING PiProcessMapping
= {STANDARD_RIGHTS_READ
| PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
28 STANDARD_RIGHTS_WRITE
| PROCESS_CREATE_PROCESS
| PROCESS_CREATE_THREAD
|
29 PROCESS_VM_OPERATION
| PROCESS_VM_WRITE
| PROCESS_DUP_HANDLE
|
30 PROCESS_TERMINATE
| PROCESS_SET_QUOTA
| PROCESS_SET_INFORMATION
| PROCESS_SET_PORT
,
31 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
34 static const INFORMATION_CLASS_INFO PsProcessInfoClass
[] =
36 ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessBasicInformation */
37 ICI_SQ_SAME( sizeof(QUOTA_LIMITS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessQuotaLimits */
38 ICI_SQ_SAME( sizeof(IO_COUNTERS
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessIoCounters */
39 ICI_SQ_SAME( sizeof(VM_COUNTERS
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessVmCounters */
40 ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessTimes */
41 ICI_SQ_SAME( sizeof(KPRIORITY
), sizeof(ULONG
), ICIF_SET
), /* ProcessBasePriority */
42 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_SET
), /* ProcessRaisePriority */
43 ICI_SQ_SAME( sizeof(HANDLE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessDebugPort */
44 ICI_SQ_SAME( sizeof(HANDLE
), sizeof(ULONG
), ICIF_SET
), /* ProcessExceptionPort */
45 ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN
), sizeof(ULONG
), ICIF_SET
), /* ProcessAccessToken */
46 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessLdtInformation */
47 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_SET
), /* ProcessLdtSize */
48 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessDefaultHardErrorMode */
49 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_SET
), /* ProcessIoPortHandlers */
50 ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessPooledUsageAndLimits */
51 ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessWorkingSetWatch */
52 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_SET
), /* ProcessUserModeIOPL */
53 ICI_SQ_SAME( sizeof(BOOLEAN
), sizeof(ULONG
), ICIF_SET
), /* ProcessEnableAlignmentFaultFixup */
54 ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS
), sizeof(USHORT
), ICIF_SET
), /* ProcessPriorityClass */
55 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessWx86Information */
56 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessHandleCount */
57 ICI_SQ_SAME( sizeof(KAFFINITY
), sizeof(ULONG
), ICIF_SET
), /* ProcessAffinityMask */
58 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessPriorityBoost */
60 ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION
)0x0)->Query
), /* ProcessDeviceMap */
61 /*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION
)0x0)->Set
),
64 ICIF_QUERY
| ICIF_SET
),
66 ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessSessionInformation */
67 ICI_SQ_SAME( sizeof(BOOLEAN
), sizeof(ULONG
), ICIF_SET
), /* ProcessForegroundInformation */
68 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessWow64Information */
69 ICI_SQ_SAME( sizeof(UNICODE_STRING
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SIZE_VARIABLE
), /* ProcessImageFileName */
72 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
73 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
75 static PCREATE_PROCESS_NOTIFY_ROUTINE
76 PiProcessNotifyRoutine
[MAX_PROCESS_NOTIFY_ROUTINE_COUNT
];
77 static PLOAD_IMAGE_NOTIFY_ROUTINE
78 PiLoadImageNotifyRoutine
[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
];
83 WORK_QUEUE_ITEM WorkQueueItem
;
86 BOOLEAN IsWorkerQueue
;
87 } DEL_CONTEXT
, *PDEL_CONTEXT
;
89 /* FUNCTIONS *****************************************************************/
93 PsExitSpecialApc(PKAPC Apc
,
94 PKNORMAL_ROUTINE
*NormalRoutine
,
96 PVOID
*SystemArgument1
,
97 PVOID
*SystemArgument2
)
102 PsGetNextProcess(PEPROCESS OldProcess
)
105 PEPROCESS NextProcess
;
108 if (OldProcess
== NULL
)
110 Status
= ObReferenceObjectByPointer(PsInitialSystemProcess
,
114 if (!NT_SUCCESS(Status
))
116 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsInitialSystemProcess\n");
119 return PsInitialSystemProcess
;
122 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
123 NextProcess
= OldProcess
;
126 if (NextProcess
->ProcessListEntry
.Blink
== &PsProcessListHead
)
128 NextProcess
= CONTAINING_RECORD(PsProcessListHead
.Blink
,
134 NextProcess
= CONTAINING_RECORD(NextProcess
->ProcessListEntry
.Blink
,
138 Status
= ObReferenceObjectByPointer(NextProcess
,
142 if (NT_SUCCESS(Status
))
146 else if (Status
== STATUS_PROCESS_IS_TERMINATING
)
150 else if (!NT_SUCCESS(Status
))
152 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
157 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
158 ObDereferenceObject(OldProcess
);
168 NtOpenProcessToken(IN HANDLE ProcessHandle
,
169 IN ACCESS_MASK DesiredAccess
,
170 OUT PHANDLE TokenHandle
)
172 return NtOpenProcessTokenEx(ProcessHandle
,
184 NtOpenProcessTokenEx(
185 IN HANDLE ProcessHandle
,
186 IN ACCESS_MASK DesiredAccess
,
187 IN ULONG HandleAttributes
,
188 OUT PHANDLE TokenHandle
193 KPROCESSOR_MODE PreviousMode
;
194 NTSTATUS Status
= STATUS_SUCCESS
;
196 PreviousMode
= ExGetPreviousMode();
198 if(PreviousMode
== UserMode
)
202 ProbeForWrite(TokenHandle
,
208 Status
= _SEH_GetExceptionCode();
212 if(!NT_SUCCESS(Status
))
218 Status
= PsOpenTokenOfProcess(ProcessHandle
,
220 if(NT_SUCCESS(Status
))
222 Status
= ObCreateHandle(PsGetCurrentProcess(),
227 ObDereferenceObject(Token
);
231 *TokenHandle
= hToken
;
235 Status
= _SEH_GetExceptionCode();
247 PACCESS_TOKEN STDCALL
248 PsReferencePrimaryToken(PEPROCESS Process
)
250 ObReferenceObjectByPointer(Process
->Token
,
254 return(Process
->Token
);
259 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
260 PACCESS_TOKEN
* Token
)
265 Status
= ObReferenceObjectByHandle(ProcessHandle
,
266 PROCESS_QUERY_INFORMATION
,
271 if(NT_SUCCESS(Status
))
273 *Token
= PsReferencePrimaryToken(Process
);
274 ObDereferenceObject(Process
);
282 PiKillMostProcesses(VOID
)
285 PLIST_ENTRY current_entry
;
288 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
290 current_entry
= PsProcessListHead
.Flink
;
291 while (current_entry
!= &PsProcessListHead
)
293 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
295 current_entry
= current_entry
->Flink
;
297 if (current
->UniqueProcessId
!= PsInitialSystemProcess
->UniqueProcessId
&&
298 current
->UniqueProcessId
!= PsGetCurrentProcessId())
300 PiTerminateProcessThreads(current
, STATUS_SUCCESS
);
304 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
309 PsInitProcessManagment(VOID
)
315 ShortPsLockDelay
.QuadPart
= -100LL;
316 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
318 * Register the process object type
321 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
323 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
324 PsProcessType
->TotalObjects
= 0;
325 PsProcessType
->TotalHandles
= 0;
326 PsProcessType
->PeakObjects
= 0;
327 PsProcessType
->PeakHandles
= 0;
328 PsProcessType
->PagedPoolCharge
= 0;
329 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
330 PsProcessType
->Mapping
= &PiProcessMapping
;
331 PsProcessType
->Dump
= NULL
;
332 PsProcessType
->Open
= NULL
;
333 PsProcessType
->Close
= NULL
;
334 PsProcessType
->Delete
= PiDeleteProcess
;
335 PsProcessType
->Parse
= NULL
;
336 PsProcessType
->Security
= NULL
;
337 PsProcessType
->QueryName
= NULL
;
338 PsProcessType
->OkayToClose
= NULL
;
339 PsProcessType
->Create
= NULL
;
340 PsProcessType
->DuplicationNotify
= NULL
;
342 RtlRosInitUnicodeStringFromLiteral(&PsProcessType
->TypeName
, L
"Process");
344 ObpCreateTypeObject(PsProcessType
);
346 InitializeListHead(&PsProcessListHead
);
347 KeInitializeSpinLock(&PsProcessListLock
);
349 RtlZeroMemory(PiProcessNotifyRoutine
, sizeof(PiProcessNotifyRoutine
));
350 RtlZeroMemory(PiLoadImageNotifyRoutine
, sizeof(PiLoadImageNotifyRoutine
));
353 * Initialize the system process
355 Status
= ObCreateObject(KernelMode
,
363 (PVOID
*)&PsInitialSystemProcess
);
364 if (!NT_SUCCESS(Status
))
369 /* System threads may run on any processor. */
370 PsInitialSystemProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
371 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
372 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[0] = 0;
373 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[1] = 0;
374 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
375 PsInitialSystemProcess
->Pcb
.ThreadQuantum
= 6;
376 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
377 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
381 KProcess
= &PsInitialSystemProcess
->Pcb
;
383 MmInitializeAddressSpace(PsInitialSystemProcess
,
384 &PsInitialSystemProcess
->AddressSpace
);
385 ObCreateHandleTable(NULL
,FALSE
,PsInitialSystemProcess
);
387 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
388 PsInitialSystemProcess
->LockCount
= 0;
389 PsInitialSystemProcess
->LockOwner
= NULL
;
391 #if defined(__GNUC__)
392 KProcess
->DirectoryTableBase
=
393 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
397 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
398 KProcess
->DirectoryTableBase
= dummy
;
402 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
404 Status
= PsCreateCidHandle(PsInitialSystemProcess
,
406 &PsInitialSystemProcess
->UniqueProcessId
);
407 if(!NT_SUCCESS(Status
))
409 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
413 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
415 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
416 InsertHeadList(&PsProcessListHead
,
417 &PsInitialSystemProcess
->ProcessListEntry
);
418 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
419 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
421 SepCreateSystemProcessToken(PsInitialSystemProcess
);
425 PiDeleteProcessWorker(PVOID pContext
)
428 PDEL_CONTEXT Context
;
429 PEPROCESS CurrentProcess
;
432 Context
= (PDEL_CONTEXT
)pContext
;
433 Process
= Context
->Process
;
434 CurrentProcess
= PsGetCurrentProcess();
436 DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process
);
438 if (CurrentProcess
!= Process
)
440 KeAttachProcess(&Process
->Pcb
);
443 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
444 RemoveEntryList(&Process
->ProcessListEntry
);
445 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
448 KDB_DELETEPROCESS_HOOK(Process
);
450 ObDereferenceObject(Process
->Token
);
451 ObDeleteHandleTable(Process
);
453 if (CurrentProcess
!= Process
)
458 MmReleaseMmInfo(Process
);
459 if (Context
->IsWorkerQueue
)
461 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
466 PiDeleteProcess(PVOID ObjectBody
)
470 Context
.Process
= (PEPROCESS
)ObjectBody
;
472 if (PsGetCurrentProcess() == Context
.Process
||
473 PsGetCurrentThread()->ThreadsProcess
== Context
.Process
)
478 if (PsGetCurrentThread()->ThreadsProcess
== PsGetCurrentProcess())
480 Context
.IsWorkerQueue
= FALSE
;
481 PiDeleteProcessWorker(&Context
);
485 Context
.IsWorkerQueue
= TRUE
;
486 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
487 ExInitializeWorkItem (&Context
.WorkQueueItem
, PiDeleteProcessWorker
, &Context
);
488 ExQueueWorkItem(&Context
.WorkQueueItem
, HyperCriticalWorkQueue
);
489 if (KeReadStateEvent(&Context
.Event
) == 0)
491 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
495 if(((PEPROCESS
)ObjectBody
)->Win32Process
!= NULL
)
497 /* delete the W32PROCESS structure if there's one associated */
498 ExFreePool (((PEPROCESS
)ObjectBody
)->Win32Process
);
503 PsCreatePeb(HANDLE ProcessHandle
,
510 LARGE_INTEGER SectionOffset
;
515 /* Allocate the Process Environment Block (PEB) */
516 Process
->TebBlock
= (PVOID
) MM_ROUND_DOWN(PEB_BASE
, MM_VIRTMEM_GRANULARITY
);
517 AllocSize
= MM_VIRTMEM_GRANULARITY
;
518 Status
= NtAllocateVirtualMemory(ProcessHandle
,
524 if (!NT_SUCCESS(Status
))
526 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
529 ASSERT((ULONG_PTR
) Process
->TebBlock
<= PEB_BASE
&&
530 PEB_BASE
+ PAGE_SIZE
<= (ULONG_PTR
) Process
->TebBlock
+ AllocSize
);
531 Peb
= (PPEB
)PEB_BASE
;
533 Status
= NtAllocateVirtualMemory(ProcessHandle
,
539 if (!NT_SUCCESS(Status
))
541 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
544 DPRINT("Peb %p PebSize %lu\n", Peb
, PebSize
);
545 ASSERT((PPEB
) PEB_BASE
== Peb
&& PAGE_SIZE
<= PebSize
);
546 Process
->TebLastAllocated
= (PVOID
) Peb
;
549 SectionOffset
.QuadPart
= (ULONGLONG
)0;
551 Status
= MmMapViewOfSection(NlsSectionObject
,
561 if (!NT_SUCCESS(Status
))
563 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
566 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
568 KeAttachProcess(&Process
->Pcb
);
570 /* Initialize the PEB */
571 RtlZeroMemory(Peb
, sizeof(PEB
));
572 Peb
->ImageBaseAddress
= ImageBase
;
574 Peb
->OSMajorVersion
= 4;
575 Peb
->OSMinorVersion
= 0;
576 Peb
->OSBuildNumber
= 1381;
577 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
578 Peb
->SPMajorVersion
= 6;
580 Peb
->AnsiCodePageData
= (char*)TableBase
+ NlsAnsiTableOffset
;
581 Peb
->OemCodePageData
= (char*)TableBase
+ NlsOemTableOffset
;
582 Peb
->UnicodeCaseTableData
= (char*)TableBase
+ NlsUnicodeTableOffset
;
587 DPRINT("PsCreatePeb: Peb created at %p\n", Peb
);
589 return(STATUS_SUCCESS
);
594 KeGetCurrentProcess(VOID
)
596 * FUNCTION: Returns a pointer to the current process
599 return(&(PsGetCurrentProcess()->Pcb
));
603 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
604 * ULONG ProcessId! (Skywing)
610 PsGetCurrentProcessId(VOID
)
612 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
620 PsGetCurrentProcessSessionId (
624 return PsGetCurrentProcess()->SessionId
;
628 * FUNCTION: Returns a pointer to the current process
633 IoGetCurrentProcess(VOID
)
635 if (PsGetCurrentThread() == NULL
||
636 PsGetCurrentThread()->Tcb
.ApcState
.Process
== NULL
)
638 return(PsInitialSystemProcess
);
642 return(PEPROCESS
)(PsGetCurrentThread()->Tcb
.ApcState
.Process
);
647 PspCreateProcess(OUT PHANDLE ProcessHandle
,
648 IN ACCESS_MASK DesiredAccess
,
649 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
650 IN HANDLE ParentProcess OPTIONAL
,
651 IN BOOLEAN InheritObjectTable
,
652 IN HANDLE SectionHandle OPTIONAL
,
653 IN HANDLE DebugPort OPTIONAL
,
654 IN HANDLE ExceptionPort OPTIONAL
)
658 PEPROCESS pParentProcess
;
661 PVOID LdrStartupAddr
;
663 PMEMORY_AREA MemoryArea
;
664 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
665 KPROCESSOR_MODE PreviousMode
;
666 PVOID ImageBase
= NULL
;
667 PEPORT pDebugPort
= NULL
;
668 PEPORT pExceptionPort
= NULL
;
669 PSECTION_OBJECT SectionObject
= NULL
;
670 NTSTATUS Status
= STATUS_SUCCESS
;
672 DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes
);
674 PreviousMode
= ExGetPreviousMode();
676 BoundaryAddressMultiple
.QuadPart
= 0;
678 if(ParentProcess
!= NULL
)
680 Status
= ObReferenceObjectByHandle(ParentProcess
,
681 PROCESS_CREATE_PROCESS
,
684 (PVOID
*)&pParentProcess
,
686 if (!NT_SUCCESS(Status
))
688 DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status
);
694 pParentProcess
= NULL
;
700 if (DebugPort
!= NULL
)
702 Status
= ObReferenceObjectByHandle(DebugPort
,
708 if (!NT_SUCCESS(Status
))
710 DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status
);
711 goto exitdereferenceobjects
;
716 * Add the exception port
718 if (ExceptionPort
!= NULL
)
720 Status
= ObReferenceObjectByHandle(ExceptionPort
,
724 (PVOID
*)&pExceptionPort
,
726 if (!NT_SUCCESS(Status
))
728 DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status
);
729 goto exitdereferenceobjects
;
733 if (SectionHandle
!= NULL
)
735 Status
= ObReferenceObjectByHandle(SectionHandle
,
739 (PVOID
*)&SectionObject
,
741 if (!NT_SUCCESS(Status
))
743 DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status
);
744 goto exitdereferenceobjects
;
748 Status
= ObCreateObject(PreviousMode
,
757 if (!NT_SUCCESS(Status
))
759 DPRINT1("Failed to create process object, Status: 0x%x\n", Status
);
761 exitdereferenceobjects
:
762 if(SectionObject
!= NULL
)
763 ObDereferenceObject(SectionObject
);
764 if(pExceptionPort
!= NULL
)
765 ObDereferenceObject(pExceptionPort
);
766 if(pDebugPort
!= NULL
)
767 ObDereferenceObject(pDebugPort
);
768 if(pParentProcess
!= NULL
)
769 ObDereferenceObject(pParentProcess
);
773 KProcess
= &Process
->Pcb
;
775 RtlZeroMemory(Process
, sizeof(EPROCESS
));
777 Status
= PsCreateCidHandle(Process
,
779 &Process
->UniqueProcessId
);
780 if(!NT_SUCCESS(Status
))
782 DPRINT1("Failed to create CID handle (unique process ID)! Status: 0x%x\n", Status
);
783 ObDereferenceObject(Process
);
784 goto exitdereferenceobjects
;
787 Process
->DebugPort
= pDebugPort
;
788 Process
->ExceptionPort
= pExceptionPort
;
790 if(SectionObject
!= NULL
)
792 UNICODE_STRING FileName
;
798 * Determine the image file name and save it to the EPROCESS structure
801 FileName
= SectionObject
->FileObject
->FileName
;
802 szSrc
= (PWCHAR
)(FileName
.Buffer
+ (FileName
.Length
/ sizeof(WCHAR
)) - 1);
803 while(szSrc
>= FileName
.Buffer
)
817 /* copy the image file name to the process and truncate it to 15 characters
819 szDest
= Process
->ImageFileName
;
820 lnFName
= min(lnFName
, sizeof(Process
->ImageFileName
) - 1);
823 *(szDest
++) = (UCHAR
)*(szSrc
++);
825 /* *szDest = '\0'; */
828 KeInitializeDispatcherHeader(&KProcess
->DispatcherHeader
,
833 /* Inherit parent process's affinity. */
834 if(pParentProcess
!= NULL
)
836 KProcess
->Affinity
= pParentProcess
->Pcb
.Affinity
;
837 Process
->InheritedFromUniqueProcessId
= pParentProcess
->UniqueProcessId
;
838 Process
->SessionId
= pParentProcess
->SessionId
;
842 KProcess
->Affinity
= KeActiveProcessors
;
845 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
846 KProcess
->IopmOffset
= 0xffff;
847 KProcess
->LdtDescriptor
[0] = 0;
848 KProcess
->LdtDescriptor
[1] = 0;
849 InitializeListHead(&KProcess
->ThreadListHead
);
850 KProcess
->ThreadQuantum
= 6;
851 KProcess
->AutoAlignment
= 0;
852 MmInitializeAddressSpace(Process
,
853 &Process
->AddressSpace
);
855 ObCreateHandleTable(pParentProcess
,
858 MmCopyMmInfo(pParentProcess
? pParentProcess
: PsInitialSystemProcess
, Process
);
860 KeInitializeEvent(&Process
->LockEvent
, SynchronizationEvent
, FALSE
);
861 Process
->LockCount
= 0;
862 Process
->LockOwner
= NULL
;
864 Process
->Win32WindowStation
= (HANDLE
)0;
866 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
867 InsertHeadList(&PsProcessListHead
, &Process
->ProcessListEntry
);
868 InitializeListHead(&Process
->ThreadListHead
);
869 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
871 ExInitializeFastMutex(&Process
->TebLock
);
872 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
875 * Now we have created the process proper
878 MmLockAddressSpace(&Process
->AddressSpace
);
880 /* Protect the highest 64KB of the process address space */
881 BaseAddress
= (PVOID
)MmUserProbeAddress
;
882 Status
= MmCreateMemoryArea(Process
,
883 &Process
->AddressSpace
,
884 MEMORY_AREA_NO_ACCESS
,
891 BoundaryAddressMultiple
);
892 if (!NT_SUCCESS(Status
))
894 MmUnlockAddressSpace(&Process
->AddressSpace
);
895 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
896 ObDereferenceObject(Process
);
897 goto exitdereferenceobjects
;
900 /* Protect the lowest 64KB of the process address space */
902 BaseAddress
= (PVOID
)0x00000000;
903 Status
= MmCreateMemoryArea(Process
,
904 &Process
->AddressSpace
,
905 MEMORY_AREA_NO_ACCESS
,
912 BoundaryAddressMultiple
);
913 if (!NT_SUCCESS(Status
))
915 MmUnlockAddressSpace(&Process
->AddressSpace
);
916 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
917 ObDereferenceObject(Process
);
918 goto exitdereferenceobjects
;
922 /* Protect the 60KB above the shared user page */
923 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
924 Status
= MmCreateMemoryArea(Process
,
925 &Process
->AddressSpace
,
926 MEMORY_AREA_NO_ACCESS
,
933 BoundaryAddressMultiple
);
934 if (!NT_SUCCESS(Status
))
936 MmUnlockAddressSpace(&Process
->AddressSpace
);
937 DPRINT1("Failed to protect the memory above the shared user page\n");
938 ObDereferenceObject(Process
);
939 goto exitdereferenceobjects
;
942 /* Create the shared data page */
943 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
944 Status
= MmCreateMemoryArea(Process
,
945 &Process
->AddressSpace
,
946 MEMORY_AREA_SHARED_DATA
,
953 BoundaryAddressMultiple
);
954 MmUnlockAddressSpace(&Process
->AddressSpace
);
955 if (!NT_SUCCESS(Status
))
957 DPRINT1("Failed to create shared data page\n");
958 ObDereferenceObject(Process
);
959 goto exitdereferenceobjects
;
964 * FIXME - the handle should be created after all things are initialized, NOT HERE!
966 Status
= ObInsertObject ((PVOID
)Process
,
972 if (!NT_SUCCESS(Status
))
974 DPRINT1("Failed to create a handle for the process\n");
975 ObDereferenceObject(Process
);
976 goto exitdereferenceobjects
;
983 Status
= LdrpMapSystemDll(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
985 if (!NT_SUCCESS(Status
))
987 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
988 ObDereferenceObject(Process
);
989 goto exitdereferenceobjects
;
993 * Map the process image
995 if (SectionObject
!= NULL
)
998 DPRINT("Mapping process image\n");
999 Status
= MmMapViewOfSection(SectionObject
,
1009 ObDereferenceObject(SectionObject
);
1010 if (!NT_SUCCESS(Status
))
1012 DbgPrint("Failed to map the process section (Status %x)\n", Status
);
1013 ObDereferenceObject(Process
);
1014 goto exitdereferenceobjects
;
1018 if(pParentProcess
!= NULL
)
1021 * Duplicate the token
1023 Status
= SepInitializeNewProcess(Process
, pParentProcess
);
1024 if (!NT_SUCCESS(Status
))
1026 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
1027 ObDereferenceObject(Process
);
1028 goto exitdereferenceobjects
;
1037 * FIXME - Create PEB
1039 DPRINT("Creating PEB\n");
1040 Status
= PsCreatePeb(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
1043 if (!NT_SUCCESS(Status
))
1045 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
1046 ObDereferenceObject(Process
);
1047 goto exitdereferenceobjects
;
1051 * Maybe send a message to the creator process's debugger
1054 if (pParentProcess
->DebugPort
!= NULL
)
1056 LPC_DBG_MESSAGE Message
;
1059 ObCreateHandle(NULL
, // Debugger Process
1060 NULL
, // SectionHandle
1065 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
1066 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
1067 sizeof(LPC_MESSAGE
);
1068 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
1069 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
1070 Message
.Data
.CreateProcess
.Base
= ImageBase
;
1071 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
1073 Status
= LpcSendDebugMessagePort(pParentProcess
->DebugPort
,
1078 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
1081 * FIXME - the handle should be created not before this point!
1084 Status
= ObInsertObject ((PVOID
)Process
,
1091 if (NT_SUCCESS(Status
))
1095 *ProcessHandle
= hProcess
;
1099 Status
= _SEH_GetExceptionCode();
1105 * don't dereference the debug port, exception port and section object even
1106 * if ObInsertObject() failed, the process is alive! We just couldn't return
1107 * the handle to the caller!
1110 ObDereferenceObject(Process
);
1111 if(pParentProcess
!= NULL
)
1112 ObDereferenceObject(pParentProcess
);
1122 PsCreateSystemProcess(PHANDLE ProcessHandle
,
1123 ACCESS_MASK DesiredAccess
,
1124 POBJECT_ATTRIBUTES ObjectAttributes
)
1126 return PspCreateProcess(ProcessHandle
,
1129 NULL
, /* no parent process */
1141 NtCreateProcess(OUT PHANDLE ProcessHandle
,
1142 IN ACCESS_MASK DesiredAccess
,
1143 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1144 IN HANDLE ParentProcess
,
1145 IN BOOLEAN InheritObjectTable
,
1146 IN HANDLE SectionHandle OPTIONAL
,
1147 IN HANDLE DebugPort OPTIONAL
,
1148 IN HANDLE ExceptionPort OPTIONAL
)
1150 * FUNCTION: Creates a process.
1152 * ProcessHandle (OUT) = Caller supplied storage for the resulting
1154 * DesiredAccess = Specifies the allowed or desired access to the
1155 * process can be a combination of
1156 * STANDARD_RIGHTS_REQUIRED| ..
1157 * ObjectAttribute = Initialized attributes for the object, contains
1158 * the rootdirectory and the filename
1159 * ParentProcess = Handle to the parent process.
1160 * InheritObjectTable = Specifies to inherit the objects of the parent
1162 * SectionHandle = Handle to a section object to back the image file
1163 * DebugPort = Handle to a DebugPort if NULL the system default debug
1164 * port will be used.
1165 * ExceptionPort = Handle to a exception port.
1167 * This function maps to the win32 CreateProcess.
1171 KPROCESSOR_MODE PreviousMode
;
1172 NTSTATUS Status
= STATUS_SUCCESS
;
1174 PreviousMode
= ExGetPreviousMode();
1176 if(PreviousMode
!= KernelMode
)
1180 ProbeForWrite(ProcessHandle
,
1186 Status
= _SEH_GetExceptionCode();
1190 if(!NT_SUCCESS(Status
))
1196 if(ParentProcess
== NULL
)
1198 Status
= STATUS_INVALID_PARAMETER
;
1202 Status
= PspCreateProcess(ProcessHandle
,
1220 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1221 IN ACCESS_MASK DesiredAccess
,
1222 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1223 IN PCLIENT_ID ClientId
)
1225 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1226 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1227 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
1228 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
1232 * Not sure of the exact semantics
1234 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
1235 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
1240 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
1241 ObjectAttributes
->Attributes
,
1248 if (Status
!= STATUS_SUCCESS
)
1253 Status
= ObCreateHandle(PsGetCurrentProcess(),
1258 ObDereferenceObject(Process
);
1265 PLIST_ENTRY current_entry
;
1269 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
1270 current_entry
= PsProcessListHead
.Flink
;
1271 while (current_entry
!= &PsProcessListHead
)
1273 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
1275 if (current
->UniqueProcessId
== ClientId
->UniqueProcess
)
1277 if (current
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
1279 Status
= STATUS_PROCESS_IS_TERMINATING
;
1283 Status
= ObReferenceObjectByPointer(current
,
1288 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1289 if (NT_SUCCESS(Status
))
1291 Status
= ObCreateHandle(PsGetCurrentProcess(),
1296 ObDereferenceObject(current
);
1297 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
1298 DPRINT("NtOpenProcess() = %x\n", Status
);
1302 current_entry
= current_entry
->Flink
;
1304 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1305 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1306 return(STATUS_UNSUCCESSFUL
);
1308 return(STATUS_UNSUCCESSFUL
);
1316 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
1317 IN PROCESSINFOCLASS ProcessInformationClass
,
1318 OUT PVOID ProcessInformation
,
1319 IN ULONG ProcessInformationLength
,
1320 OUT PULONG ReturnLength OPTIONAL
)
1323 KPROCESSOR_MODE PreviousMode
;
1324 NTSTATUS Status
= STATUS_SUCCESS
;
1326 PreviousMode
= ExGetPreviousMode();
1328 DefaultQueryInfoBufferCheck(ProcessInformationClass
,
1331 ProcessInformationLength
,
1335 if(!NT_SUCCESS(Status
))
1337 DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status
);
1342 * TODO: Here we should probably check that ProcessInformationLength
1343 * bytes indeed are writable at address ProcessInformation.
1346 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1347 PROCESS_QUERY_INFORMATION
,
1352 if (!NT_SUCCESS(Status
))
1357 switch (ProcessInformationClass
)
1359 case ProcessBasicInformation
:
1361 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
=
1362 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
1366 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
1367 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
1368 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
1369 ProcessBasicInformationP
->UniqueProcessId
=
1370 Process
->UniqueProcessId
;
1371 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
1372 Process
->InheritedFromUniqueProcessId
;
1373 ProcessBasicInformationP
->BasePriority
=
1374 Process
->Pcb
.BasePriority
;
1378 *ReturnLength
= sizeof(PROCESS_BASIC_INFORMATION
);
1383 Status
= _SEH_GetExceptionCode();
1389 case ProcessQuotaLimits
:
1390 case ProcessIoCounters
:
1391 Status
= STATUS_NOT_IMPLEMENTED
;
1396 PKERNEL_USER_TIMES ProcessTimeP
= (PKERNEL_USER_TIMES
)ProcessInformation
;
1399 ProcessTimeP
->CreateTime
= Process
->CreateTime
;
1400 ProcessTimeP
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
* 100000LL;
1401 ProcessTimeP
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
* 100000LL;
1402 ProcessTimeP
->ExitTime
= Process
->ExitTime
;
1406 *ReturnLength
= sizeof(KERNEL_USER_TIMES
);
1411 Status
= _SEH_GetExceptionCode();
1417 case ProcessDebugPort
:
1421 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
!= NULL
? (HANDLE
)-1 : NULL
);
1424 *ReturnLength
= sizeof(HANDLE
);
1429 Status
= _SEH_GetExceptionCode();
1435 case ProcessLdtInformation
:
1436 case ProcessWorkingSetWatch
:
1437 case ProcessWx86Information
:
1438 Status
= STATUS_NOT_IMPLEMENTED
;
1441 case ProcessHandleCount
:
1443 ULONG HandleCount
= ObpGetHandleCountByHandleTable(&Process
->HandleTable
);
1447 *(PULONG
)ProcessInformation
= HandleCount
;
1450 *ReturnLength
= sizeof(ULONG
);
1455 Status
= _SEH_GetExceptionCode();
1461 case ProcessSessionInformation
:
1463 PPROCESS_SESSION_INFORMATION SessionInfo
= (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1467 SessionInfo
->SessionId
= Process
->SessionId
;
1470 *ReturnLength
= sizeof(PROCESS_SESSION_INFORMATION
);
1475 Status
= _SEH_GetExceptionCode();
1481 case ProcessWow64Information
:
1482 DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
1483 Status
= STATUS_NOT_IMPLEMENTED
;
1486 case ProcessVmCounters
:
1488 PVM_COUNTERS pOut
= (PVM_COUNTERS
)ProcessInformation
;
1492 pOut
->PeakVirtualSize
= Process
->PeakVirtualSize
;
1494 * Here we should probably use VirtualSize.LowPart, but due to
1495 * incompatibilities in current headers (no unnamed union),
1498 pOut
->VirtualSize
= (ULONG
)Process
->VirtualSize
.QuadPart
;
1499 pOut
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
1500 pOut
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
1501 pOut
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
1502 pOut
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[0]; // TODO: Verify!
1503 pOut
->QuotaPagedPoolUsage
= Process
->QuotaPoolUsage
[0]; // TODO: Verify!
1504 pOut
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[1]; // TODO: Verify!
1505 pOut
->QuotaNonPagedPoolUsage
= Process
->QuotaPoolUsage
[1]; // TODO: Verify!
1506 pOut
->PagefileUsage
= Process
->PagefileUsage
;
1507 pOut
->PeakPagefileUsage
= Process
->PeakPagefileUsage
;
1511 *ReturnLength
= sizeof(VM_COUNTERS
);
1516 Status
= _SEH_GetExceptionCode();
1522 case ProcessDefaultHardErrorMode
:
1524 PULONG HardErrMode
= (PULONG
)ProcessInformation
;
1527 *HardErrMode
= Process
->DefaultHardErrorProcessing
;
1530 *ReturnLength
= sizeof(ULONG
);
1535 Status
= _SEH_GetExceptionCode();
1541 case ProcessPriorityBoost
:
1543 PULONG BoostEnabled
= (PULONG
)ProcessInformation
;
1547 *BoostEnabled
= Process
->Pcb
.DisableBoost
? FALSE
: TRUE
;
1551 *ReturnLength
= sizeof(ULONG
);
1556 Status
= _SEH_GetExceptionCode();
1562 case ProcessDeviceMap
:
1564 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
1566 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
1570 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
1573 *ReturnLength
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
1578 Status
= _SEH_GetExceptionCode();
1584 case ProcessPriorityClass
:
1586 PUSHORT Priority
= (PUSHORT
)ProcessInformation
;
1590 *Priority
= Process
->PriorityClass
;
1594 *ReturnLength
= sizeof(USHORT
);
1599 Status
= _SEH_GetExceptionCode();
1605 case ProcessImageFileName
:
1608 * We DO NOT return the file name stored in the EPROCESS structure.
1609 * Propably if we can't find a PEB or ProcessParameters structure for the
1612 if(Process
->Peb
!= NULL
)
1614 PRTL_USER_PROCESS_PARAMETERS ProcParams
= NULL
;
1615 UNICODE_STRING LocalDest
;
1616 ULONG ImagePathLen
= 0;
1617 PUNICODE_STRING DstPath
= (PUNICODE_STRING
)ProcessInformation
;
1619 /* we need to attach to the process to make sure we're in the right context! */
1620 KeAttachProcess(&Process
->Pcb
);
1624 ProcParams
= Process
->Peb
->ProcessParameters
;
1625 ImagePathLen
= ProcParams
->ImagePathName
.Length
;
1629 Status
= _SEH_GetExceptionCode();
1633 if(NT_SUCCESS(Status
))
1635 if(ProcessInformationLength
< sizeof(UNICODE_STRING
) + ImagePathLen
+ sizeof(WCHAR
))
1637 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1641 PWSTR StrSource
= NULL
;
1643 /* create a DstPath structure on the stack */
1646 LocalDest
.Length
= ImagePathLen
;
1647 LocalDest
.MaximumLength
= ImagePathLen
+ sizeof(WCHAR
);
1648 LocalDest
.Buffer
= (PWSTR
)(DstPath
+ 1);
1650 /* save a copy of the pointer to the source buffer */
1651 StrSource
= ProcParams
->ImagePathName
.Buffer
;
1655 Status
= _SEH_GetExceptionCode();
1659 if(NT_SUCCESS(Status
))
1661 /* now, let's allocate some anonymous memory to copy the string to.
1662 we can't just copy it to the buffer the caller pointed as it might
1663 be user memory in another context */
1664 PWSTR PathCopy
= ExAllocatePool(PagedPool
, LocalDest
.Length
+ sizeof(WCHAR
));
1665 if(PathCopy
!= NULL
)
1667 /* make a copy of the buffer to the temporary buffer */
1670 RtlCopyMemory(PathCopy
, StrSource
, LocalDest
.Length
);
1671 PathCopy
[LocalDest
.Length
/ sizeof(WCHAR
)] = L
'\0';
1675 Status
= _SEH_GetExceptionCode();
1679 /* detach from the process */
1682 /* only copy the string back to the caller if we were able to
1683 copy it into the temporary buffer! */
1684 if(NT_SUCCESS(Status
))
1686 /* now let's copy the buffer back to the caller */
1689 *DstPath
= LocalDest
;
1690 RtlCopyMemory(LocalDest
.Buffer
, PathCopy
, LocalDest
.Length
+ sizeof(WCHAR
));
1693 *ReturnLength
= sizeof(UNICODE_STRING
) + LocalDest
.Length
+ sizeof(WCHAR
);
1698 Status
= _SEH_GetExceptionCode();
1703 /* we're done with the copy operation, free the temporary kernel buffer */
1704 ExFreePool(PathCopy
);
1706 /* we need to bail because we're already detached from the process */
1711 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1717 /* don't forget to detach from the process!!! */
1722 /* FIXME - what to do here? */
1723 Status
= STATUS_UNSUCCESSFUL
;
1729 * Note: The following 10 information classes are verified to not be
1730 * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
1732 case ProcessBasePriority
:
1733 case ProcessRaisePriority
:
1734 case ProcessExceptionPort
:
1735 case ProcessAccessToken
:
1736 case ProcessLdtSize
:
1737 case ProcessIoPortHandlers
:
1738 case ProcessUserModeIOPL
:
1739 case ProcessEnableAlignmentFaultFixup
:
1740 case ProcessAffinityMask
:
1741 case ProcessForegroundInformation
:
1743 Status
= STATUS_INVALID_INFO_CLASS
;
1746 ObDereferenceObject(Process
);
1752 PspAssignPrimaryToken(PEPROCESS Process
,
1755 PACCESS_TOKEN Token
;
1756 PACCESS_TOKEN OldToken
;
1759 Status
= ObReferenceObjectByHandle(TokenHandle
,
1765 if (!NT_SUCCESS(Status
))
1769 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
1770 if (NT_SUCCESS(Status
))
1772 ObDereferenceObject(OldToken
);
1774 ObDereferenceObject(Token
);
1782 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1783 IN PROCESSINFOCLASS ProcessInformationClass
,
1784 IN PVOID ProcessInformation
,
1785 IN ULONG ProcessInformationLength
)
1788 KPROCESSOR_MODE PreviousMode
;
1790 NTSTATUS Status
= STATUS_SUCCESS
;
1792 PreviousMode
= ExGetPreviousMode();
1794 DefaultSetInfoBufferCheck(ProcessInformationClass
,
1797 ProcessInformationLength
,
1800 if(!NT_SUCCESS(Status
))
1802 DPRINT1("NtSetInformationProcess() %d %x %x called\n", ProcessInformationClass
, ProcessInformation
, ProcessInformationLength
);
1803 DPRINT1("NtSetInformationProcess() %x failed, Status: 0x%x\n", Status
);
1807 switch(ProcessInformationClass
)
1809 case ProcessSessionInformation
:
1810 Access
= PROCESS_SET_INFORMATION
| PROCESS_SET_SESSIONID
;
1812 case ProcessExceptionPort
:
1813 case ProcessDebugPort
:
1814 Access
= PROCESS_SET_INFORMATION
| PROCESS_SET_PORT
;
1818 Access
= PROCESS_SET_INFORMATION
;
1822 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1828 if (!NT_SUCCESS(Status
))
1833 switch (ProcessInformationClass
)
1835 case ProcessQuotaLimits
:
1836 case ProcessBasePriority
:
1837 case ProcessRaisePriority
:
1838 Status
= STATUS_NOT_IMPLEMENTED
;
1841 case ProcessDebugPort
:
1843 if(ProcessInformationLength
!= sizeof(HANDLE
))
1845 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1849 HANDLE PortHandle
= NULL
;
1851 /* make a safe copy of the buffer on the stack */
1854 PortHandle
= *(PHANDLE
)ProcessInformation
;
1855 Status
= (PortHandle
!= NULL
? STATUS_SUCCESS
: STATUS_INVALID_PARAMETER
);
1859 Status
= _SEH_GetExceptionCode();
1863 if(NT_SUCCESS(Status
))
1867 /* in case we had success reading from the buffer, verify the provided
1870 Status
= ObReferenceObjectByHandle(PortHandle
,
1876 if(NT_SUCCESS(Status
))
1878 /* lock the process to be thread-safe! */
1880 Status
= PsLockProcess(Process
, FALSE
);
1881 if(NT_SUCCESS(Status
))
1884 * according to "NT Native API" documentation, setting the debug
1885 * port is only permitted once!
1887 if(Process
->DebugPort
== NULL
)
1889 /* keep the reference to the handle! */
1890 Process
->DebugPort
= DebugPort
;
1894 /* we're now debugging the process, so set the flag in the PEB
1895 structure. However, to access it we need to attach to the
1896 process so we're sure we're in the right context! */
1898 KeAttachProcess(&Process
->Pcb
);
1901 Process
->Peb
->BeingDebugged
= TRUE
;
1905 DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process
, _SEH_GetExceptionCode());
1910 Status
= STATUS_SUCCESS
;
1914 ObDereferenceObject(DebugPort
);
1915 Status
= STATUS_PORT_ALREADY_SET
;
1917 PsUnlockProcess(Process
);
1921 ObDereferenceObject(DebugPort
);
1929 case ProcessExceptionPort
:
1931 if(ProcessInformationLength
!= sizeof(HANDLE
))
1933 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1937 HANDLE PortHandle
= NULL
;
1939 /* make a safe copy of the buffer on the stack */
1942 PortHandle
= *(PHANDLE
)ProcessInformation
;
1943 Status
= STATUS_SUCCESS
;
1947 Status
= _SEH_GetExceptionCode();
1951 if(NT_SUCCESS(Status
))
1953 PEPORT ExceptionPort
;
1955 /* in case we had success reading from the buffer, verify the provided
1958 Status
= ObReferenceObjectByHandle(PortHandle
,
1962 (PVOID
)&ExceptionPort
,
1964 if(NT_SUCCESS(Status
))
1966 /* lock the process to be thread-safe! */
1968 Status
= PsLockProcess(Process
, FALSE
);
1969 if(NT_SUCCESS(Status
))
1972 * according to "NT Native API" documentation, setting the exception
1973 * port is only permitted once!
1975 if(Process
->ExceptionPort
== NULL
)
1977 /* keep the reference to the handle! */
1978 Process
->ExceptionPort
= ExceptionPort
;
1979 Status
= STATUS_SUCCESS
;
1983 ObDereferenceObject(ExceptionPort
);
1984 Status
= STATUS_PORT_ALREADY_SET
;
1986 PsUnlockProcess(Process
);
1990 ObDereferenceObject(ExceptionPort
);
1998 case ProcessAccessToken
:
2000 if(ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
2002 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2006 HANDLE TokenHandle
= NULL
;
2008 /* make a safe copy of the buffer on the stack */
2011 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->Token
;
2012 Status
= STATUS_SUCCESS
;
2016 Status
= _SEH_GetExceptionCode();
2020 if(NT_SUCCESS(Status
))
2022 /* in case we had success reading from the buffer, perform the actual task */
2023 Status
= PspAssignPrimaryToken(Process
, TokenHandle
);
2029 case ProcessDefaultHardErrorMode
:
2031 if(ProcessInformationLength
!= sizeof(UINT
))
2033 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2039 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
2040 *(PLONG
)ProcessInformation
);
2041 Status
= STATUS_SUCCESS
;
2045 Status
= _SEH_GetExceptionCode();
2052 case ProcessSessionInformation
:
2054 if(ProcessInformationLength
!= sizeof(UINT
))
2056 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2060 PROCESS_SESSION_INFORMATION SessionInfo
;
2061 Status
= STATUS_SUCCESS
;
2065 /* copy the structure to the stack */
2066 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
2070 Status
= _SEH_GetExceptionCode();
2074 if(NT_SUCCESS(Status
))
2076 /* we successfully copied the structure to the stack, continue processing */
2079 * setting the session id requires the SeTcbPrivilege!
2081 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
2084 DPRINT1("NtSetInformationProcess: Caller requires the SeTcbPrivilege privilege for setting ProcessSessionInformation!\n");
2085 /* can't set the session id, bail! */
2086 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2090 /* FIXME - update the session id for the process token */
2092 Status
= PsLockProcess(Process
, FALSE
);
2093 if(NT_SUCCESS(Status
))
2095 Process
->SessionId
= SessionInfo
.SessionId
;
2097 /* Update the session id in the PEB structure */
2098 if(Process
->Peb
!= NULL
)
2100 /* we need to attach to the process to make sure we're in the right
2101 context to access the PEB structure */
2102 KeAttachProcess(&Process
->Pcb
);
2106 /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
2108 Status
= STATUS_SUCCESS
;
2112 Status
= _SEH_GetExceptionCode();
2119 PsUnlockProcess(Process
);
2126 case ProcessLdtInformation
:
2127 case ProcessLdtSize
:
2128 case ProcessIoPortHandlers
:
2129 case ProcessWorkingSetWatch
:
2130 case ProcessUserModeIOPL
:
2131 case ProcessEnableAlignmentFaultFixup
:
2132 case ProcessPriorityClass
:
2133 case ProcessAffinityMask
:
2134 Status
= STATUS_NOT_IMPLEMENTED
;
2137 case ProcessBasicInformation
:
2138 case ProcessIoCounters
:
2140 case ProcessPooledUsageAndLimits
:
2141 case ProcessWx86Information
:
2142 case ProcessHandleCount
:
2143 case ProcessWow64Information
:
2145 Status
= STATUS_INVALID_INFO_CLASS
;
2147 ObDereferenceObject(Process
);
2152 /**********************************************************************
2154 * PiQuerySystemProcessInformation
2157 * Compute the size of a process+thread snapshot as
2158 * expected by NtQuerySystemInformation.
2161 * 0 on error; otherwise the size, in bytes of the buffer
2162 * required to write a full snapshot.
2165 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
2168 PiQuerySystemProcessInformation(PVOID Buffer
,
2172 return STATUS_NOT_IMPLEMENTED
;
2176 PLIST_ENTRY CurrentEntryP
;
2178 PLIST_ENTRY CurrentEntryT
;
2181 ULONG RequiredSize
= 0L;
2182 BOOLEAN SizeOnly
= FALSE
;
2186 PSYSTEM_PROCESS_INFORMATION pInfoP
= (PSYSTEM_PROCESS_INFORMATION
) SnapshotBuffer
;
2187 PSYSTEM_PROCESS_INFORMATION pInfoPLast
= NULL
;
2188 PSYSTEM_THREAD_INFO pInfoT
= NULL
;
2191 /* Lock the process list. */
2192 KeAcquireSpinLock(&PsProcessListLock
,
2196 * Scan the process list. Since the
2197 * list is circular, the guard is false
2198 * after the last process.
2200 for ( CurrentEntryP
= PsProcessListHead
.Flink
;
2201 (CurrentEntryP
!= & PsProcessListHead
);
2202 CurrentEntryP
= CurrentEntryP
->Flink
2206 * Compute how much space is
2207 * occupied in the snapshot
2208 * by adding this process info.
2209 * (at least one thread).
2211 SpiSizeCurrent
= sizeof (SYSTEM_PROCESS_INFORMATION
);
2212 RequiredSize
+= SpiSizeCurrent
;
2214 * Do not write process data in the
2215 * buffer if it is too small.
2217 if (TRUE
== SizeOnly
) continue;
2219 * Check if the buffer can contain
2220 * the full snapshot.
2222 if (Size
< RequiredSize
)
2228 * Get a reference to the
2229 * process descriptor we are
2232 CurrentP
= CONTAINING_RECORD(
2238 * Write process data in the buffer.
2240 RtlZeroMemory (pInfoP
, sizeof (SYSTEM_PROCESS_INFORMATION
));
2242 pInfoP
->ThreadCount
= 0L;
2243 pInfoP
->ProcessId
= CurrentP
->UniqueProcessId
;
2244 RtlInitUnicodeString (
2246 CurrentP
->ImageFileName
2249 for ( pInfoT
= & CurrentP
->ThreadSysInfo
[0],
2250 CurrentEntryT
= CurrentP
->ThreadListHead
.Flink
;
2252 (CurrentEntryT
!= & CurrentP
->ThreadListHead
);
2254 pInfoT
= & CurrentP
->ThreadSysInfo
[pInfoP
->ThreadCount
],
2255 CurrentEntryT
= CurrentEntryT
->Flink
2259 * Recalculate the size of the
2260 * information block.
2262 if (0 < pInfoP
->ThreadCount
)
2264 RequiredSize
+= sizeof (SYSTEM_THREAD_INFORMATION
);
2267 * Do not write thread data in the
2268 * buffer if it is too small.
2270 if (TRUE
== SizeOnly
) continue;
2272 * Check if the buffer can contain
2273 * the full snapshot.
2275 if (Size
< RequiredSize
)
2281 * Get a reference to the
2282 * thread descriptor we are
2285 CurrentT
= CONTAINING_RECORD(
2291 * Write thread data.
2295 sizeof (SYSTEM_THREAD_INFORMATION
)
2297 pInfoT
->KernelTime
= CurrentT
-> ; /* TIME */
2298 pInfoT
->UserTime
= CurrentT
-> ; /* TIME */
2299 pInfoT
->CreateTime
= CurrentT
-> ; /* TIME */
2300 pInfoT
->TickCount
= CurrentT
-> ; /* ULONG */
2301 pInfoT
->StartEIP
= CurrentT
-> ; /* ULONG */
2302 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2303 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2304 pInfoT
->DynamicPriority
= CurrentT
-> ; /* ULONG */
2305 pInfoT
->BasePriority
= CurrentT
-> ; /* ULONG */
2306 pInfoT
->nSwitches
= CurrentT
-> ; /* ULONG */
2307 pInfoT
->State
= CurrentT
-> ; /* DWORD */
2308 pInfoT
->WaitReason
= CurrentT
-> ; /* KWAIT_REASON */
2310 * Count the number of threads
2313 ++ pInfoP
->ThreadCount
;
2316 * Save the size of information
2317 * stored in the buffer for the
2320 pInfoP
->RelativeOffset
= SpiSize
;
2322 * Save a reference to the last
2323 * valid information block.
2325 pInfoPLast
= pInfoP
;
2327 * Compute the offset of the
2328 * SYSTEM_PROCESS_INFORMATION
2329 * descriptor in the snapshot
2330 * buffer for the next process.
2332 (ULONG
) pInfoP
+= SpiSize
;
2335 * Unlock the process list.
2338 & PsProcessListLock
,
2342 * Return the proper error status code,
2343 * if the buffer was too small.
2345 if (TRUE
== SizeOnly
)
2347 if (NULL
!= RequiredSize
)
2349 *pRequiredSize
= RequiredSize
;
2351 return STATUS_INFO_LENGTH_MISMATCH
;
2354 * Mark the end of the snapshot.
2356 pInfoP
->RelativeOffset
= 0L;
2358 return STATUS_SUCCESS
;
2365 LARGE_INTEGER STDCALL
2366 PsGetProcessExitTime(VOID
)
2369 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
2378 PsGetProcessCreateTimeQuadPart(
2382 return Process
->CreateTime
.QuadPart
;
2390 PsGetProcessDebugPort(
2394 return Process
->DebugPort
;
2402 PsGetProcessExitProcessCalled(
2406 return Process
->ExitProcessCalled
;
2414 PsGetProcessExitStatus(
2418 return Process
->ExitStatus
;
2430 return (HANDLE
)Process
->UniqueProcessId
;
2438 PsGetProcessImageFileName(
2442 return (LPSTR
)Process
->ImageFileName
;
2450 PsGetProcessInheritedFromUniqueProcessId(
2454 return Process
->InheritedFromUniqueProcessId
;
2466 return Process
->Job
;
2478 return Process
->Peb
;
2486 PsGetProcessPriorityClass(
2490 return Process
->PriorityClass
;
2498 PsGetProcessSectionBaseAddress(
2502 return Process
->SectionBaseAddress
;
2510 PsGetProcessSecurityPort(
2514 return Process
->SecurityPort
;
2522 PsGetProcessSessionId(
2526 return (HANDLE
)Process
->SessionId
;
2534 PsGetProcessWin32Process(
2538 return Process
->Win32Process
;
2546 PsGetProcessWin32WindowStation(
2550 return Process
->Win32WindowStation
;
2558 PsIsProcessBeingDebugged(
2562 return FALSE
/*Process->IsProcessBeingDebugged*/;
2570 PsLookupProcessByProcessId(IN HANDLE ProcessId
,
2571 OUT PEPROCESS
*Process
)
2574 PLIST_ENTRY current_entry
;
2577 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
2579 current_entry
= PsProcessListHead
.Flink
;
2580 while (current_entry
!= &PsProcessListHead
)
2582 current
= CONTAINING_RECORD(current_entry
,
2585 if (current
->UniqueProcessId
== ProcessId
)
2588 ObReferenceObject(current
);
2589 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
2590 return(STATUS_SUCCESS
);
2592 current_entry
= current_entry
->Flink
;
2595 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
2597 return(STATUS_INVALID_PARAMETER
);
2602 PspRunCreateProcessNotifyRoutines
2604 PEPROCESS CurrentProcess
,
2609 HANDLE ProcessId
= (HANDLE
)CurrentProcess
->UniqueProcessId
;
2610 HANDLE ParentId
= CurrentProcess
->InheritedFromUniqueProcessId
;
2612 for(i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2613 if(PiProcessNotifyRoutine
[i
])
2614 PiProcessNotifyRoutine
[i
](ParentId
, ProcessId
, Create
);
2621 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
2628 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2630 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
2632 PiProcessNotifyRoutine
[i
] = NULL
;
2637 return(STATUS_SUCCESS
);
2641 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2643 if (PiProcessNotifyRoutine
[i
] == NULL
)
2645 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
2650 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2652 return STATUS_INSUFFICIENT_RESOURCES
;
2655 return STATUS_SUCCESS
;
2659 PspRunLoadImageNotifyRoutines(
2660 PUNICODE_STRING FullImageName
,
2662 PIMAGE_INFO ImageInfo
)
2666 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2667 if (PiLoadImageNotifyRoutine
[i
])
2668 PiLoadImageNotifyRoutine
[i
](FullImageName
, ProcessId
, ImageInfo
);
2676 PsRemoveLoadImageNotifyRoutine(
2677 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
2681 return STATUS_NOT_IMPLEMENTED
;
2688 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
2692 for (i
= 0; i
< MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
; i
++)
2694 if (PiLoadImageNotifyRoutine
[i
] == NULL
)
2696 PiLoadImageNotifyRoutine
[i
] = NotifyRoutine
;
2701 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2703 return STATUS_INSUFFICIENT_RESOURCES
;
2706 return STATUS_SUCCESS
;
2714 PsSetProcessPriorityClass(
2719 Process
->PriorityClass
= PriorityClass
;
2727 PsSetProcessSecurityPort(
2732 Process
->SecurityPort
= SecurityPort
;
2740 PsSetProcessWin32Process(
2745 Process
->Win32Process
= Win32Process
;
2753 PsSetProcessWin32WindowStation(
2758 Process
->Win32WindowStation
= WindowStation
;
2768 IN PEPROCESS Process
,
2769 IN POOL_TYPE PoolType
,
2775 /* Charge the usage */
2776 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
2778 /* Raise Exception */
2779 if (!NT_SUCCESS(Status
)) {
2780 ExRaiseStatus(Status
);
2789 PsChargeProcessNonPagedPoolQuota (
2790 IN PEPROCESS Process
,
2794 /* Call the general function */
2795 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
2803 PsChargeProcessPagedPoolQuota (
2804 IN PEPROCESS Process
,
2808 /* Call the general function */
2809 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
2817 PsChargeProcessPoolQuota(
2818 IN PEPROCESS Process
,
2819 IN POOL_TYPE PoolType
,
2823 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
2827 /* Get current Quota Block */
2828 QuotaBlock
= Process
->QuotaBlock
;
2830 /* Quota Operations are not to be done on the SYSTEM Process */
2831 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
2833 /* New Size in use */
2834 NewUsageSize
= QuotaBlock
->QuotaEntry
[PoolType
].Usage
+ Amount
;
2836 /* Does this size respect the quota? */
2837 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Limit
) {
2839 /* It doesn't, so keep raising the Quota */
2840 while (MiRaisePoolQuota(PoolType
, QuotaBlock
->QuotaEntry
[PoolType
].Limit
, &NewMaxQuota
)) {
2841 /* Save new Maximum Quota */
2842 QuotaBlock
->QuotaEntry
[PoolType
].Limit
= NewMaxQuota
;
2844 /* See if the new Maximum Quota fulfills our need */
2845 if (NewUsageSize
<= NewMaxQuota
) goto QuotaChanged
;
2848 return STATUS_QUOTA_EXCEEDED
;
2852 /* Save new Usage */
2853 QuotaBlock
->QuotaEntry
[PoolType
].Usage
= NewUsageSize
;
2855 /* Is this a new peak? */
2856 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Peak
) {
2857 QuotaBlock
->QuotaEntry
[PoolType
].Peak
= NewUsageSize
;
2861 return STATUS_SUCCESS
;
2870 IN PEPROCESS Process
,
2871 IN POOL_TYPE PoolType
,
2883 PsReturnProcessNonPagedPoolQuota(
2884 IN PEPROCESS Process
,
2896 PsReturnProcessPagedPoolQuota(
2897 IN PEPROCESS Process
,
2905 PsLockProcess(PEPROCESS Process
, BOOL Timeout
)
2908 PKTHREAD PrevLockOwner
;
2909 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2910 PLARGE_INTEGER Delay
= (Timeout
? &PsLockTimeout
: NULL
);
2911 PKTHREAD CallingThread
= KeGetCurrentThread();
2913 KeEnterCriticalRegion();
2917 if(Process
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
2919 KeLeaveCriticalRegion();
2920 return STATUS_PROCESS_IS_TERMINATING
;
2923 PrevLockOwner
= (PKTHREAD
)InterlockedCompareExchangePointer(
2924 &Process
->LockOwner
, CallingThread
, NULL
);
2925 if(PrevLockOwner
== NULL
|| PrevLockOwner
== CallingThread
)
2927 /* we got the lock or already locked it */
2928 if(InterlockedIncrementUL(&Process
->LockCount
) == 1)
2930 KeClearEvent(&Process
->LockEvent
);
2933 return STATUS_SUCCESS
;
2939 Status
= KeWaitForSingleObject(&Process
->LockEvent
,
2944 if(!NT_SUCCESS(Status
) || Status
== STATUS_TIMEOUT
)
2947 if(Status
== STATUS_TIMEOUT
)
2949 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process
);
2952 KeLeaveCriticalRegion();
2959 KeDelayExecutionThread(KernelMode
, FALSE
, &ShortPsLockDelay
);
2968 PsUnlockProcess(PEPROCESS Process
)
2970 ASSERT(Process
->LockOwner
== KeGetCurrentThread());
2972 if(InterlockedDecrementUL(&Process
->LockCount
) == 0)
2974 InterlockedExchangePointer(&Process
->LockOwner
, NULL
);
2975 KeSetEvent(&Process
->LockEvent
, IO_NO_INCREMENT
, FALSE
);
2978 KeLeaveCriticalRegion();