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 PsActiveProcessHead
;
24 FAST_MUTEX PspActiveProcessMutex
;
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_QUERY
| 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
)
104 PEPROCESS NextProcess
;
107 if (OldProcess
== NULL
)
109 Status
= ObReferenceObjectByPointer(PsInitialSystemProcess
,
113 if (!NT_SUCCESS(Status
))
115 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsInitialSystemProcess\n");
118 return PsInitialSystemProcess
;
121 ExAcquireFastMutex(&PspActiveProcessMutex
);
122 NextProcess
= OldProcess
;
125 if (NextProcess
->ProcessListEntry
.Blink
== &PsActiveProcessHead
)
127 NextProcess
= CONTAINING_RECORD(PsActiveProcessHead
.Blink
,
133 NextProcess
= CONTAINING_RECORD(NextProcess
->ProcessListEntry
.Blink
,
137 Status
= ObReferenceObjectByPointer(NextProcess
,
141 if (NT_SUCCESS(Status
))
145 else if (Status
== STATUS_PROCESS_IS_TERMINATING
)
149 else if (!NT_SUCCESS(Status
))
151 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
156 ExReleaseFastMutex(&PspActiveProcessMutex
);
157 ObDereferenceObject(OldProcess
);
167 NtOpenProcessToken(IN HANDLE ProcessHandle
,
168 IN ACCESS_MASK DesiredAccess
,
169 OUT PHANDLE TokenHandle
)
171 return NtOpenProcessTokenEx(ProcessHandle
,
183 NtOpenProcessTokenEx(
184 IN HANDLE ProcessHandle
,
185 IN ACCESS_MASK DesiredAccess
,
186 IN ULONG HandleAttributes
,
187 OUT PHANDLE TokenHandle
192 KPROCESSOR_MODE PreviousMode
;
193 NTSTATUS Status
= STATUS_SUCCESS
;
197 PreviousMode
= ExGetPreviousMode();
199 if(PreviousMode
== UserMode
)
203 ProbeForWrite(TokenHandle
,
209 Status
= _SEH_GetExceptionCode();
213 if(!NT_SUCCESS(Status
))
219 Status
= PsOpenTokenOfProcess(ProcessHandle
,
221 if(NT_SUCCESS(Status
))
223 Status
= ObCreateHandle(PsGetCurrentProcess(),
228 ObDereferenceObject(Token
);
232 *TokenHandle
= hToken
;
236 Status
= _SEH_GetExceptionCode();
248 PACCESS_TOKEN STDCALL
249 PsReferencePrimaryToken(PEPROCESS Process
)
251 ObReferenceObjectByPointer(Process
->Token
,
255 return(Process
->Token
);
260 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
261 PACCESS_TOKEN
* Token
)
266 Status
= ObReferenceObjectByHandle(ProcessHandle
,
267 PROCESS_QUERY_INFORMATION
,
272 if(NT_SUCCESS(Status
))
274 *Token
= PsReferencePrimaryToken(Process
);
275 ObDereferenceObject(Process
);
283 PiKillMostProcesses(VOID
)
285 PLIST_ENTRY current_entry
;
288 ExAcquireFastMutex(&PspActiveProcessMutex
);
290 current_entry
= PsActiveProcessHead
.Flink
;
291 while (current_entry
!= &PsActiveProcessHead
)
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 ExReleaseFastMutex(&PspActiveProcessMutex
);
309 PsInitProcessManagment(VOID
)
314 ShortPsLockDelay
.QuadPart
= -100LL;
315 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
317 * Register the process object type
320 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
322 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
323 PsProcessType
->TotalObjects
= 0;
324 PsProcessType
->TotalHandles
= 0;
325 PsProcessType
->PeakObjects
= 0;
326 PsProcessType
->PeakHandles
= 0;
327 PsProcessType
->PagedPoolCharge
= 0;
328 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
329 PsProcessType
->Mapping
= &PiProcessMapping
;
330 PsProcessType
->Dump
= NULL
;
331 PsProcessType
->Open
= NULL
;
332 PsProcessType
->Close
= NULL
;
333 PsProcessType
->Delete
= PiDeleteProcess
;
334 PsProcessType
->Parse
= NULL
;
335 PsProcessType
->Security
= NULL
;
336 PsProcessType
->QueryName
= NULL
;
337 PsProcessType
->OkayToClose
= NULL
;
338 PsProcessType
->Create
= NULL
;
339 PsProcessType
->DuplicationNotify
= NULL
;
341 RtlInitUnicodeString(&PsProcessType
->TypeName
, L
"Process");
343 ObpCreateTypeObject(PsProcessType
);
345 InitializeListHead(&PsActiveProcessHead
);
346 ExInitializeFastMutex(&PspActiveProcessMutex
);
348 RtlZeroMemory(PiProcessNotifyRoutine
, sizeof(PiProcessNotifyRoutine
));
349 RtlZeroMemory(PiLoadImageNotifyRoutine
, sizeof(PiLoadImageNotifyRoutine
));
352 * Initialize the system process
354 Status
= ObCreateObject(KernelMode
,
362 (PVOID
*)&PsInitialSystemProcess
);
363 if (!NT_SUCCESS(Status
))
368 /* System threads may run on any processor. */
369 PsInitialSystemProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
370 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
371 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[0] = 0;
372 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[1] = 0;
373 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
374 PsInitialSystemProcess
->Pcb
.ThreadQuantum
= 6;
375 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
376 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
380 KProcess
= &PsInitialSystemProcess
->Pcb
;
382 MmInitializeAddressSpace(PsInitialSystemProcess
,
383 &PsInitialSystemProcess
->AddressSpace
);
384 ObCreateHandleTable(NULL
,FALSE
,PsInitialSystemProcess
);
386 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
387 PsInitialSystemProcess
->LockCount
= 0;
388 PsInitialSystemProcess
->LockOwner
= NULL
;
390 #if defined(__GNUC__)
391 KProcess
->DirectoryTableBase
=
392 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
396 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
397 KProcess
->DirectoryTableBase
= dummy
;
401 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
403 Status
= PsCreateCidHandle(PsInitialSystemProcess
,
405 &PsInitialSystemProcess
->UniqueProcessId
);
406 if(!NT_SUCCESS(Status
))
408 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
412 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
414 InsertHeadList(&PsActiveProcessHead
,
415 &PsInitialSystemProcess
->ProcessListEntry
);
416 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
418 SepCreateSystemProcessToken(PsInitialSystemProcess
);
422 PiDeleteProcessWorker(PVOID pContext
)
424 PDEL_CONTEXT Context
;
425 PEPROCESS CurrentProcess
;
428 Context
= (PDEL_CONTEXT
)pContext
;
429 Process
= Context
->Process
;
430 CurrentProcess
= PsGetCurrentProcess();
432 DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process
);
434 if (CurrentProcess
!= Process
)
436 KeAttachProcess(&Process
->Pcb
);
439 ExAcquireFastMutex(&PspActiveProcessMutex
);
440 RemoveEntryList(&Process
->ProcessListEntry
);
441 ExReleaseFastMutex(&PspActiveProcessMutex
);
444 KDB_DELETEPROCESS_HOOK(Process
);
446 ObDereferenceObject(Process
->Token
);
447 ObDeleteHandleTable(Process
);
449 if (CurrentProcess
!= Process
)
454 MmReleaseMmInfo(Process
);
455 if (Context
->IsWorkerQueue
)
457 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
462 PiDeleteProcess(PVOID ObjectBody
)
466 Context
.Process
= (PEPROCESS
)ObjectBody
;
468 if (PsGetCurrentProcess() == Context
.Process
||
469 PsGetCurrentThread()->ThreadsProcess
== Context
.Process
)
474 if (PsGetCurrentThread()->ThreadsProcess
== PsGetCurrentProcess())
476 Context
.IsWorkerQueue
= FALSE
;
477 PiDeleteProcessWorker(&Context
);
481 Context
.IsWorkerQueue
= TRUE
;
482 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
483 ExInitializeWorkItem (&Context
.WorkQueueItem
, PiDeleteProcessWorker
, &Context
);
484 ExQueueWorkItem(&Context
.WorkQueueItem
, HyperCriticalWorkQueue
);
485 if (KeReadStateEvent(&Context
.Event
) == 0)
487 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
491 if(((PEPROCESS
)ObjectBody
)->Win32Process
!= NULL
)
493 /* delete the W32PROCESS structure if there's one associated */
494 ExFreePool (((PEPROCESS
)ObjectBody
)->Win32Process
);
499 PsCreatePeb(HANDLE ProcessHandle
,
506 LARGE_INTEGER SectionOffset
;
513 /* Allocate the Process Environment Block (PEB) */
514 Process
->TebBlock
= (PVOID
) MM_ROUND_DOWN(PEB_BASE
, MM_VIRTMEM_GRANULARITY
);
515 AllocSize
= MM_VIRTMEM_GRANULARITY
;
516 Status
= NtAllocateVirtualMemory(ProcessHandle
,
522 if (!NT_SUCCESS(Status
))
524 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
527 ASSERT((ULONG_PTR
) Process
->TebBlock
<= PEB_BASE
&&
528 PEB_BASE
+ PAGE_SIZE
<= (ULONG_PTR
) Process
->TebBlock
+ AllocSize
);
529 Peb
= (PPEB
)PEB_BASE
;
531 Status
= NtAllocateVirtualMemory(ProcessHandle
,
537 if (!NT_SUCCESS(Status
))
539 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
542 DPRINT("Peb %p PebSize %lu\n", Peb
, PebSize
);
543 ASSERT((PPEB
) PEB_BASE
== Peb
&& PAGE_SIZE
<= PebSize
);
544 Process
->TebLastAllocated
= (PVOID
) Peb
;
547 SectionOffset
.QuadPart
= (ULONGLONG
)0;
549 Status
= MmMapViewOfSection(NlsSectionObject
,
559 if (!NT_SUCCESS(Status
))
561 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
564 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
566 KeAttachProcess(&Process
->Pcb
);
568 /* Initialize the PEB */
569 RtlZeroMemory(Peb
, sizeof(PEB
));
570 Peb
->ImageBaseAddress
= ImageBase
;
572 Peb
->OSMajorVersion
= 4;
573 Peb
->OSMinorVersion
= 0;
574 Peb
->OSBuildNumber
= 1381;
575 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
576 Peb
->OSCSDVersion
= 6 << 8;
578 Peb
->AnsiCodePageData
= (char*)TableBase
+ NlsAnsiTableOffset
;
579 Peb
->OemCodePageData
= (char*)TableBase
+ NlsOemTableOffset
;
580 Peb
->UnicodeCaseTableData
= (char*)TableBase
+ NlsUnicodeTableOffset
;
585 DPRINT("PsCreatePeb: Peb created at %p\n", Peb
);
587 return(STATUS_SUCCESS
);
592 KeGetCurrentProcess(VOID
)
594 * FUNCTION: Returns a pointer to the current process
597 return(&(PsGetCurrentProcess()->Pcb
));
601 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
602 * ULONG ProcessId! (Skywing)
608 PsGetCurrentProcessId(VOID
)
610 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
618 PsGetCurrentProcessSessionId (
622 return PsGetCurrentProcess()->SessionId
;
626 * FUNCTION: Returns a pointer to the current process
631 IoGetCurrentProcess(VOID
)
633 if (PsGetCurrentThread() == NULL
||
634 PsGetCurrentThread()->Tcb
.ApcState
.Process
== NULL
)
636 return(PsInitialSystemProcess
);
640 return(PEPROCESS
)(PsGetCurrentThread()->Tcb
.ApcState
.Process
);
645 PspCreateProcess(OUT PHANDLE ProcessHandle
,
646 IN ACCESS_MASK DesiredAccess
,
647 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
648 IN HANDLE ParentProcess OPTIONAL
,
649 IN BOOLEAN InheritObjectTable
,
650 IN HANDLE SectionHandle OPTIONAL
,
651 IN HANDLE DebugPort OPTIONAL
,
652 IN HANDLE ExceptionPort OPTIONAL
)
656 PEPROCESS pParentProcess
;
658 PVOID LdrStartupAddr
;
660 PMEMORY_AREA MemoryArea
;
661 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
662 KPROCESSOR_MODE PreviousMode
;
663 PVOID ImageBase
= NULL
;
664 PEPORT pDebugPort
= NULL
;
665 PEPORT pExceptionPort
= NULL
;
666 PSECTION_OBJECT SectionObject
= NULL
;
667 NTSTATUS Status
= STATUS_SUCCESS
;
669 DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes
);
671 PreviousMode
= ExGetPreviousMode();
673 BoundaryAddressMultiple
.QuadPart
= 0;
675 if(ParentProcess
!= NULL
)
677 Status
= ObReferenceObjectByHandle(ParentProcess
,
678 PROCESS_CREATE_PROCESS
,
681 (PVOID
*)&pParentProcess
,
683 if (!NT_SUCCESS(Status
))
685 DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status
);
691 pParentProcess
= NULL
;
697 if (DebugPort
!= NULL
)
699 Status
= ObReferenceObjectByHandle(DebugPort
,
705 if (!NT_SUCCESS(Status
))
707 DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status
);
708 goto exitdereferenceobjects
;
713 * Add the exception port
715 if (ExceptionPort
!= NULL
)
717 Status
= ObReferenceObjectByHandle(ExceptionPort
,
721 (PVOID
*)&pExceptionPort
,
723 if (!NT_SUCCESS(Status
))
725 DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status
);
726 goto exitdereferenceobjects
;
730 if (SectionHandle
!= NULL
)
732 Status
= ObReferenceObjectByHandle(SectionHandle
,
736 (PVOID
*)&SectionObject
,
738 if (!NT_SUCCESS(Status
))
740 DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status
);
741 goto exitdereferenceobjects
;
745 Status
= ObCreateObject(PreviousMode
,
754 if (!NT_SUCCESS(Status
))
756 DPRINT1("Failed to create process object, Status: 0x%x\n", Status
);
758 exitdereferenceobjects
:
759 if(SectionObject
!= NULL
)
760 ObDereferenceObject(SectionObject
);
761 if(pExceptionPort
!= NULL
)
762 ObDereferenceObject(pExceptionPort
);
763 if(pDebugPort
!= NULL
)
764 ObDereferenceObject(pDebugPort
);
765 if(pParentProcess
!= NULL
)
766 ObDereferenceObject(pParentProcess
);
770 KProcess
= &Process
->Pcb
;
772 RtlZeroMemory(Process
, sizeof(EPROCESS
));
774 Status
= PsCreateCidHandle(Process
,
776 &Process
->UniqueProcessId
);
777 if(!NT_SUCCESS(Status
))
779 DPRINT1("Failed to create CID handle (unique process ID)! Status: 0x%x\n", Status
);
780 ObDereferenceObject(Process
);
781 goto exitdereferenceobjects
;
784 Process
->DebugPort
= pDebugPort
;
785 Process
->ExceptionPort
= pExceptionPort
;
787 if(SectionObject
!= NULL
)
789 UNICODE_STRING FileName
;
795 * Determine the image file name and save it to the EPROCESS structure
798 FileName
= SectionObject
->FileObject
->FileName
;
799 szSrc
= (PWCHAR
)(FileName
.Buffer
+ (FileName
.Length
/ sizeof(WCHAR
)) - 1);
800 while(szSrc
>= FileName
.Buffer
)
814 /* copy the image file name to the process and truncate it to 15 characters
816 szDest
= Process
->ImageFileName
;
817 lnFName
= min(lnFName
, sizeof(Process
->ImageFileName
) - 1);
820 *(szDest
++) = (UCHAR
)*(szSrc
++);
822 /* *szDest = '\0'; */
825 KeInitializeDispatcherHeader(&KProcess
->DispatcherHeader
,
830 /* Inherit parent process's affinity. */
831 if(pParentProcess
!= NULL
)
833 KProcess
->Affinity
= pParentProcess
->Pcb
.Affinity
;
834 Process
->InheritedFromUniqueProcessId
= pParentProcess
->UniqueProcessId
;
835 Process
->SessionId
= pParentProcess
->SessionId
;
839 KProcess
->Affinity
= KeActiveProcessors
;
842 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
843 KProcess
->IopmOffset
= 0xffff;
844 KProcess
->LdtDescriptor
[0] = 0;
845 KProcess
->LdtDescriptor
[1] = 0;
846 InitializeListHead(&KProcess
->ThreadListHead
);
847 KProcess
->ThreadQuantum
= 6;
848 KProcess
->AutoAlignment
= 0;
849 MmInitializeAddressSpace(Process
,
850 &Process
->AddressSpace
);
852 ObCreateHandleTable(pParentProcess
,
855 MmCopyMmInfo(pParentProcess
? pParentProcess
: PsInitialSystemProcess
, Process
);
857 KeInitializeEvent(&Process
->LockEvent
, SynchronizationEvent
, FALSE
);
858 Process
->LockCount
= 0;
859 Process
->LockOwner
= NULL
;
861 Process
->Win32WindowStation
= (HANDLE
)0;
863 ExAcquireFastMutex(&PspActiveProcessMutex
);
864 InsertHeadList(&PsActiveProcessHead
, &Process
->ProcessListEntry
);
865 InitializeListHead(&Process
->ThreadListHead
);
866 ExReleaseFastMutex(&PspActiveProcessMutex
);
868 ExInitializeFastMutex(&Process
->TebLock
);
869 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
872 * Now we have created the process proper
875 MmLockAddressSpace(&Process
->AddressSpace
);
877 /* Protect the highest 64KB of the process address space */
878 BaseAddress
= (PVOID
)MmUserProbeAddress
;
879 Status
= MmCreateMemoryArea(Process
,
880 &Process
->AddressSpace
,
881 MEMORY_AREA_NO_ACCESS
,
888 BoundaryAddressMultiple
);
889 if (!NT_SUCCESS(Status
))
891 MmUnlockAddressSpace(&Process
->AddressSpace
);
892 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
893 ObDereferenceObject(Process
);
894 goto exitdereferenceobjects
;
897 /* Protect the lowest 64KB of the process address space */
899 BaseAddress
= (PVOID
)0x00000000;
900 Status
= MmCreateMemoryArea(Process
,
901 &Process
->AddressSpace
,
902 MEMORY_AREA_NO_ACCESS
,
909 BoundaryAddressMultiple
);
910 if (!NT_SUCCESS(Status
))
912 MmUnlockAddressSpace(&Process
->AddressSpace
);
913 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
914 ObDereferenceObject(Process
);
915 goto exitdereferenceobjects
;
919 /* Protect the 60KB above the shared user page */
920 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
921 Status
= MmCreateMemoryArea(Process
,
922 &Process
->AddressSpace
,
923 MEMORY_AREA_NO_ACCESS
,
930 BoundaryAddressMultiple
);
931 if (!NT_SUCCESS(Status
))
933 MmUnlockAddressSpace(&Process
->AddressSpace
);
934 DPRINT1("Failed to protect the memory above the shared user page\n");
935 ObDereferenceObject(Process
);
936 goto exitdereferenceobjects
;
939 /* Create the shared data page */
940 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
941 Status
= MmCreateMemoryArea(Process
,
942 &Process
->AddressSpace
,
943 MEMORY_AREA_SHARED_DATA
,
950 BoundaryAddressMultiple
);
951 MmUnlockAddressSpace(&Process
->AddressSpace
);
952 if (!NT_SUCCESS(Status
))
954 DPRINT1("Failed to create shared data page\n");
955 ObDereferenceObject(Process
);
956 goto exitdereferenceobjects
;
961 * FIXME - the handle should be created after all things are initialized, NOT HERE!
963 Status
= ObInsertObject ((PVOID
)Process
,
969 if (!NT_SUCCESS(Status
))
971 DPRINT1("Failed to create a handle for the process\n");
972 ObDereferenceObject(Process
);
973 goto exitdereferenceobjects
;
980 Status
= LdrpMapSystemDll(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
982 if (!NT_SUCCESS(Status
))
984 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
985 ObDereferenceObject(Process
);
986 goto exitdereferenceobjects
;
990 * Map the process image
992 if (SectionObject
!= NULL
)
995 DPRINT("Mapping process image\n");
996 Status
= MmMapViewOfSection(SectionObject
,
1006 ObDereferenceObject(SectionObject
);
1007 if (!NT_SUCCESS(Status
))
1009 DbgPrint("Failed to map the process section (Status %x)\n", Status
);
1010 ObDereferenceObject(Process
);
1011 goto exitdereferenceobjects
;
1015 if(pParentProcess
!= NULL
)
1018 * Duplicate the token
1020 Status
= SepInitializeNewProcess(Process
, pParentProcess
);
1021 if (!NT_SUCCESS(Status
))
1023 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
1024 ObDereferenceObject(Process
);
1025 goto exitdereferenceobjects
;
1034 * FIXME - Create PEB
1036 DPRINT("Creating PEB\n");
1037 Status
= PsCreatePeb(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
1040 if (!NT_SUCCESS(Status
))
1042 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
1043 ObDereferenceObject(Process
);
1044 goto exitdereferenceobjects
;
1048 * Maybe send a message to the creator process's debugger
1051 if (pParentProcess
->DebugPort
!= NULL
)
1053 LPC_DBG_MESSAGE Message
;
1056 ObCreateHandle(NULL
, // Debugger Process
1057 NULL
, // SectionHandle
1062 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
1063 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
1064 sizeof(LPC_MESSAGE
);
1065 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
1066 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
1067 Message
.Data
.CreateProcess
.Base
= ImageBase
;
1068 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
1070 Status
= LpcSendDebugMessagePort(pParentProcess
->DebugPort
,
1075 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
1078 * FIXME - the handle should be created not before this point!
1081 Status
= ObInsertObject ((PVOID
)Process
,
1088 if (NT_SUCCESS(Status
))
1092 *ProcessHandle
= hProcess
;
1096 Status
= _SEH_GetExceptionCode();
1102 * don't dereference the debug port, exception port and section object even
1103 * if ObInsertObject() failed, the process is alive! We just couldn't return
1104 * the handle to the caller!
1107 ObDereferenceObject(Process
);
1108 if(pParentProcess
!= NULL
)
1109 ObDereferenceObject(pParentProcess
);
1119 PsCreateSystemProcess(PHANDLE ProcessHandle
,
1120 ACCESS_MASK DesiredAccess
,
1121 POBJECT_ATTRIBUTES ObjectAttributes
)
1123 return PspCreateProcess(ProcessHandle
,
1126 NULL
, /* no parent process */
1138 NtCreateProcess(OUT PHANDLE ProcessHandle
,
1139 IN ACCESS_MASK DesiredAccess
,
1140 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1141 IN HANDLE ParentProcess
,
1142 IN BOOLEAN InheritObjectTable
,
1143 IN HANDLE SectionHandle OPTIONAL
,
1144 IN HANDLE DebugPort OPTIONAL
,
1145 IN HANDLE ExceptionPort OPTIONAL
)
1147 * FUNCTION: Creates a process.
1149 * ProcessHandle (OUT) = Caller supplied storage for the resulting
1151 * DesiredAccess = Specifies the allowed or desired access to the
1152 * process can be a combination of
1153 * STANDARD_RIGHTS_REQUIRED| ..
1154 * ObjectAttribute = Initialized attributes for the object, contains
1155 * the rootdirectory and the filename
1156 * ParentProcess = Handle to the parent process.
1157 * InheritObjectTable = Specifies to inherit the objects of the parent
1159 * SectionHandle = Handle to a section object to back the image file
1160 * DebugPort = Handle to a DebugPort if NULL the system default debug
1161 * port will be used.
1162 * ExceptionPort = Handle to a exception port.
1164 * This function maps to the win32 CreateProcess.
1168 KPROCESSOR_MODE PreviousMode
;
1169 NTSTATUS Status
= STATUS_SUCCESS
;
1173 PreviousMode
= ExGetPreviousMode();
1175 if(PreviousMode
!= KernelMode
)
1179 ProbeForWrite(ProcessHandle
,
1185 Status
= _SEH_GetExceptionCode();
1189 if(!NT_SUCCESS(Status
))
1195 if(ParentProcess
== NULL
)
1197 Status
= STATUS_INVALID_PARAMETER
;
1201 Status
= PspCreateProcess(ProcessHandle
,
1219 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1220 IN ACCESS_MASK DesiredAccess
,
1221 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1222 IN PCLIENT_ID ClientId
)
1224 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1225 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1226 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
1227 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
);
1264 PLIST_ENTRY current_entry
;
1268 ExAcquireFastMutex(&PspActiveProcessMutex
);
1269 current_entry
= PsActiveProcessHead
.Flink
;
1270 while (current_entry
!= &PsActiveProcessHead
)
1272 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
1274 if (current
->UniqueProcessId
== ClientId
->UniqueProcess
)
1276 if (current
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
1278 Status
= STATUS_PROCESS_IS_TERMINATING
;
1282 Status
= ObReferenceObjectByPointer(current
,
1287 ExReleaseFastMutex(&PspActiveProcessMutex
);
1288 if (NT_SUCCESS(Status
))
1290 Status
= ObCreateHandle(PsGetCurrentProcess(),
1295 ObDereferenceObject(current
);
1296 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
1297 DPRINT("NtOpenProcess() = %x\n", Status
);
1301 current_entry
= current_entry
->Flink
;
1303 ExReleaseFastMutex(&PspActiveProcessMutex
);
1304 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1305 return(STATUS_UNSUCCESSFUL
);
1307 return(STATUS_UNSUCCESSFUL
);
1315 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
1316 IN PROCESSINFOCLASS ProcessInformationClass
,
1317 OUT PVOID ProcessInformation
,
1318 IN ULONG ProcessInformationLength
,
1319 OUT PULONG ReturnLength OPTIONAL
)
1322 KPROCESSOR_MODE PreviousMode
;
1323 NTSTATUS Status
= STATUS_SUCCESS
;
1327 PreviousMode
= ExGetPreviousMode();
1329 DefaultQueryInfoBufferCheck(ProcessInformationClass
,
1332 ProcessInformationLength
,
1336 if(!NT_SUCCESS(Status
))
1338 DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status
);
1343 * TODO: Here we should probably check that ProcessInformationLength
1344 * bytes indeed are writable at address ProcessInformation.
1347 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1348 PROCESS_QUERY_INFORMATION
,
1353 if (!NT_SUCCESS(Status
))
1358 switch (ProcessInformationClass
)
1360 case ProcessBasicInformation
:
1362 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
=
1363 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
1367 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
1368 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
1369 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
1370 ProcessBasicInformationP
->UniqueProcessId
=
1371 Process
->UniqueProcessId
;
1372 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
1373 Process
->InheritedFromUniqueProcessId
;
1374 ProcessBasicInformationP
->BasePriority
=
1375 Process
->Pcb
.BasePriority
;
1379 *ReturnLength
= sizeof(PROCESS_BASIC_INFORMATION
);
1384 Status
= _SEH_GetExceptionCode();
1390 case ProcessQuotaLimits
:
1391 case ProcessIoCounters
:
1392 Status
= STATUS_NOT_IMPLEMENTED
;
1397 PKERNEL_USER_TIMES ProcessTimeP
= (PKERNEL_USER_TIMES
)ProcessInformation
;
1400 ProcessTimeP
->CreateTime
= Process
->CreateTime
;
1401 ProcessTimeP
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
* 100000LL;
1402 ProcessTimeP
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
* 100000LL;
1403 ProcessTimeP
->ExitTime
= Process
->ExitTime
;
1407 *ReturnLength
= sizeof(KERNEL_USER_TIMES
);
1412 Status
= _SEH_GetExceptionCode();
1418 case ProcessDebugPort
:
1422 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
!= NULL
? (HANDLE
)-1 : NULL
);
1425 *ReturnLength
= sizeof(HANDLE
);
1430 Status
= _SEH_GetExceptionCode();
1436 case ProcessLdtInformation
:
1437 case ProcessWorkingSetWatch
:
1438 case ProcessWx86Information
:
1439 Status
= STATUS_NOT_IMPLEMENTED
;
1442 case ProcessHandleCount
:
1444 ULONG HandleCount
= ObpGetHandleCountByHandleTable(&Process
->HandleTable
);
1448 *(PULONG
)ProcessInformation
= HandleCount
;
1451 *ReturnLength
= sizeof(ULONG
);
1456 Status
= _SEH_GetExceptionCode();
1462 case ProcessSessionInformation
:
1464 PPROCESS_SESSION_INFORMATION SessionInfo
= (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1468 SessionInfo
->SessionId
= Process
->SessionId
;
1471 *ReturnLength
= sizeof(PROCESS_SESSION_INFORMATION
);
1476 Status
= _SEH_GetExceptionCode();
1482 case ProcessWow64Information
:
1483 DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
1484 Status
= STATUS_NOT_IMPLEMENTED
;
1487 case ProcessVmCounters
:
1489 PVM_COUNTERS pOut
= (PVM_COUNTERS
)ProcessInformation
;
1493 pOut
->PeakVirtualSize
= Process
->PeakVirtualSize
;
1495 * Here we should probably use VirtualSize.LowPart, but due to
1496 * incompatibilities in current headers (no unnamed union),
1499 pOut
->VirtualSize
= (ULONG
)Process
->VirtualSize
.QuadPart
;
1500 pOut
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
1501 pOut
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
1502 pOut
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
1503 pOut
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[0]; // TODO: Verify!
1504 pOut
->QuotaPagedPoolUsage
= Process
->QuotaPoolUsage
[0]; // TODO: Verify!
1505 pOut
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[1]; // TODO: Verify!
1506 pOut
->QuotaNonPagedPoolUsage
= Process
->QuotaPoolUsage
[1]; // TODO: Verify!
1507 pOut
->PagefileUsage
= Process
->PagefileUsage
;
1508 pOut
->PeakPagefileUsage
= Process
->PeakPagefileUsage
;
1512 *ReturnLength
= sizeof(VM_COUNTERS
);
1517 Status
= _SEH_GetExceptionCode();
1523 case ProcessDefaultHardErrorMode
:
1525 PULONG HardErrMode
= (PULONG
)ProcessInformation
;
1528 *HardErrMode
= Process
->DefaultHardErrorProcessing
;
1531 *ReturnLength
= sizeof(ULONG
);
1536 Status
= _SEH_GetExceptionCode();
1542 case ProcessPriorityBoost
:
1544 PULONG BoostEnabled
= (PULONG
)ProcessInformation
;
1548 *BoostEnabled
= Process
->Pcb
.DisableBoost
? FALSE
: TRUE
;
1552 *ReturnLength
= sizeof(ULONG
);
1557 Status
= _SEH_GetExceptionCode();
1563 case ProcessDeviceMap
:
1565 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
1567 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
1571 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
1574 *ReturnLength
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
1579 Status
= _SEH_GetExceptionCode();
1585 case ProcessPriorityClass
:
1587 PUSHORT Priority
= (PUSHORT
)ProcessInformation
;
1591 *Priority
= Process
->PriorityClass
;
1595 *ReturnLength
= sizeof(USHORT
);
1600 Status
= _SEH_GetExceptionCode();
1606 case ProcessImageFileName
:
1609 * We DO NOT return the file name stored in the EPROCESS structure.
1610 * Propably if we can't find a PEB or ProcessParameters structure for the
1613 if(Process
->Peb
!= NULL
)
1615 PRTL_USER_PROCESS_PARAMETERS ProcParams
= NULL
;
1616 UNICODE_STRING LocalDest
;
1618 ULONG ImagePathLen
= 0;
1619 PUNICODE_STRING DstPath
= (PUNICODE_STRING
)ProcessInformation
;
1621 /* we need to attach to the process to make sure we're in the right context! */
1622 Attached
= Process
!= PsGetCurrentProcess();
1625 KeAttachProcess(&Process
->Pcb
);
1629 ProcParams
= Process
->Peb
->ProcessParameters
;
1630 ImagePathLen
= ProcParams
->ImagePathName
.Length
;
1634 Status
= _SEH_GetExceptionCode();
1638 if(NT_SUCCESS(Status
))
1640 if(ProcessInformationLength
< sizeof(UNICODE_STRING
) + ImagePathLen
+ sizeof(WCHAR
))
1642 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1646 PWSTR StrSource
= NULL
;
1648 /* create a DstPath structure on the stack */
1651 LocalDest
.Length
= ImagePathLen
;
1652 LocalDest
.MaximumLength
= ImagePathLen
+ sizeof(WCHAR
);
1653 LocalDest
.Buffer
= (PWSTR
)(DstPath
+ 1);
1655 /* save a copy of the pointer to the source buffer */
1656 StrSource
= ProcParams
->ImagePathName
.Buffer
;
1660 Status
= _SEH_GetExceptionCode();
1664 if(NT_SUCCESS(Status
))
1666 /* now, let's allocate some anonymous memory to copy the string to.
1667 we can't just copy it to the buffer the caller pointed as it might
1668 be user memory in another context */
1669 PWSTR PathCopy
= ExAllocatePool(PagedPool
, LocalDest
.Length
+ sizeof(WCHAR
));
1670 if(PathCopy
!= NULL
)
1672 /* make a copy of the buffer to the temporary buffer */
1675 RtlCopyMemory(PathCopy
, StrSource
, LocalDest
.Length
);
1676 PathCopy
[LocalDest
.Length
/ sizeof(WCHAR
)] = L
'\0';
1680 Status
= _SEH_GetExceptionCode();
1684 /* detach from the process */
1688 /* only copy the string back to the caller if we were able to
1689 copy it into the temporary buffer! */
1690 if(NT_SUCCESS(Status
))
1692 /* now let's copy the buffer back to the caller */
1695 *DstPath
= LocalDest
;
1696 RtlCopyMemory(LocalDest
.Buffer
, PathCopy
, LocalDest
.Length
+ sizeof(WCHAR
));
1699 *ReturnLength
= sizeof(UNICODE_STRING
) + LocalDest
.Length
+ sizeof(WCHAR
);
1704 Status
= _SEH_GetExceptionCode();
1709 /* we're done with the copy operation, free the temporary kernel buffer */
1710 ExFreePool(PathCopy
);
1712 /* we need to bail because we're already detached from the process */
1717 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1723 /* don't forget to detach from the process!!! */
1729 /* FIXME - what to do here? */
1730 Status
= STATUS_UNSUCCESSFUL
;
1736 * Note: The following 10 information classes are verified to not be
1737 * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
1739 case ProcessBasePriority
:
1740 case ProcessRaisePriority
:
1741 case ProcessExceptionPort
:
1742 case ProcessAccessToken
:
1743 case ProcessLdtSize
:
1744 case ProcessIoPortHandlers
:
1745 case ProcessUserModeIOPL
:
1746 case ProcessEnableAlignmentFaultFixup
:
1747 case ProcessAffinityMask
:
1748 case ProcessForegroundInformation
:
1750 Status
= STATUS_INVALID_INFO_CLASS
;
1753 ObDereferenceObject(Process
);
1759 PspAssignPrimaryToken(PEPROCESS Process
,
1762 PACCESS_TOKEN Token
;
1763 PACCESS_TOKEN OldToken
;
1766 Status
= ObReferenceObjectByHandle(TokenHandle
,
1772 if (!NT_SUCCESS(Status
))
1776 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
1777 if (NT_SUCCESS(Status
))
1779 ObDereferenceObject(OldToken
);
1781 ObDereferenceObject(Token
);
1789 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1790 IN PROCESSINFOCLASS ProcessInformationClass
,
1791 IN PVOID ProcessInformation
,
1792 IN ULONG ProcessInformationLength
)
1795 KPROCESSOR_MODE PreviousMode
;
1797 NTSTATUS Status
= STATUS_SUCCESS
;
1801 PreviousMode
= ExGetPreviousMode();
1803 DefaultSetInfoBufferCheck(ProcessInformationClass
,
1806 ProcessInformationLength
,
1809 if(!NT_SUCCESS(Status
))
1811 DPRINT1("NtSetInformationProcess() %d %x %x called\n", ProcessInformationClass
, ProcessInformation
, ProcessInformationLength
);
1812 DPRINT1("NtSetInformationProcess() %x failed, Status: 0x%x\n", Status
);
1816 switch(ProcessInformationClass
)
1818 case ProcessSessionInformation
:
1819 Access
= PROCESS_SET_INFORMATION
| PROCESS_SET_SESSIONID
;
1821 case ProcessExceptionPort
:
1822 case ProcessDebugPort
:
1823 Access
= PROCESS_SET_INFORMATION
| PROCESS_SET_PORT
;
1827 Access
= PROCESS_SET_INFORMATION
;
1831 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1837 if (!NT_SUCCESS(Status
))
1842 switch (ProcessInformationClass
)
1844 case ProcessQuotaLimits
:
1845 case ProcessBasePriority
:
1846 case ProcessRaisePriority
:
1847 Status
= STATUS_NOT_IMPLEMENTED
;
1850 case ProcessDebugPort
:
1852 HANDLE PortHandle
= NULL
;
1854 /* make a safe copy of the buffer on the stack */
1857 PortHandle
= *(PHANDLE
)ProcessInformation
;
1858 Status
= (PortHandle
!= NULL
? STATUS_SUCCESS
: STATUS_INVALID_PARAMETER
);
1862 Status
= _SEH_GetExceptionCode();
1866 if(NT_SUCCESS(Status
))
1870 /* in case we had success reading from the buffer, verify the provided
1873 Status
= ObReferenceObjectByHandle(PortHandle
,
1879 if(NT_SUCCESS(Status
))
1881 /* lock the process to be thread-safe! */
1883 Status
= PsLockProcess(Process
, FALSE
);
1884 if(NT_SUCCESS(Status
))
1887 * according to "NT Native API" documentation, setting the debug
1888 * port is only permitted once!
1890 if(Process
->DebugPort
== NULL
)
1892 /* keep the reference to the handle! */
1893 Process
->DebugPort
= DebugPort
;
1897 /* we're now debugging the process, so set the flag in the PEB
1898 structure. However, to access it we need to attach to the
1899 process so we're sure we're in the right context! */
1901 KeAttachProcess(&Process
->Pcb
);
1904 Process
->Peb
->BeingDebugged
= TRUE
;
1908 DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process
, _SEH_GetExceptionCode());
1913 Status
= STATUS_SUCCESS
;
1917 ObDereferenceObject(DebugPort
);
1918 Status
= STATUS_PORT_ALREADY_SET
;
1920 PsUnlockProcess(Process
);
1924 ObDereferenceObject(DebugPort
);
1931 case ProcessExceptionPort
:
1933 HANDLE PortHandle
= NULL
;
1935 /* make a safe copy of the buffer on the stack */
1938 PortHandle
= *(PHANDLE
)ProcessInformation
;
1939 Status
= STATUS_SUCCESS
;
1943 Status
= _SEH_GetExceptionCode();
1947 if(NT_SUCCESS(Status
))
1949 PEPORT ExceptionPort
;
1951 /* in case we had success reading from the buffer, verify the provided
1954 Status
= ObReferenceObjectByHandle(PortHandle
,
1958 (PVOID
)&ExceptionPort
,
1960 if(NT_SUCCESS(Status
))
1962 /* lock the process to be thread-safe! */
1964 Status
= PsLockProcess(Process
, FALSE
);
1965 if(NT_SUCCESS(Status
))
1968 * according to "NT Native API" documentation, setting the exception
1969 * port is only permitted once!
1971 if(Process
->ExceptionPort
== NULL
)
1973 /* keep the reference to the handle! */
1974 Process
->ExceptionPort
= ExceptionPort
;
1975 Status
= STATUS_SUCCESS
;
1979 ObDereferenceObject(ExceptionPort
);
1980 Status
= STATUS_PORT_ALREADY_SET
;
1982 PsUnlockProcess(Process
);
1986 ObDereferenceObject(ExceptionPort
);
1993 case ProcessAccessToken
:
1995 HANDLE TokenHandle
= NULL
;
1997 /* make a safe copy of the buffer on the stack */
2000 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->Token
;
2001 Status
= STATUS_SUCCESS
;
2005 Status
= _SEH_GetExceptionCode();
2009 if(NT_SUCCESS(Status
))
2011 /* in case we had success reading from the buffer, perform the actual task */
2012 Status
= PspAssignPrimaryToken(Process
, TokenHandle
);
2017 case ProcessDefaultHardErrorMode
:
2021 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
2022 *(PLONG
)ProcessInformation
);
2023 Status
= STATUS_SUCCESS
;
2027 Status
= _SEH_GetExceptionCode();
2033 case ProcessSessionInformation
:
2035 PROCESS_SESSION_INFORMATION SessionInfo
;
2036 Status
= STATUS_SUCCESS
;
2040 /* copy the structure to the stack */
2041 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
2045 Status
= _SEH_GetExceptionCode();
2049 if(NT_SUCCESS(Status
))
2051 /* we successfully copied the structure to the stack, continue processing */
2054 * setting the session id requires the SeTcbPrivilege!
2056 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
2059 DPRINT1("NtSetInformationProcess: Caller requires the SeTcbPrivilege privilege for setting ProcessSessionInformation!\n");
2060 /* can't set the session id, bail! */
2061 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2065 /* FIXME - update the session id for the process token */
2067 Status
= PsLockProcess(Process
, FALSE
);
2068 if(NT_SUCCESS(Status
))
2070 Process
->SessionId
= SessionInfo
.SessionId
;
2072 /* Update the session id in the PEB structure */
2073 if(Process
->Peb
!= NULL
)
2075 /* we need to attach to the process to make sure we're in the right
2076 context to access the PEB structure */
2077 KeAttachProcess(&Process
->Pcb
);
2081 /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
2083 Status
= STATUS_SUCCESS
;
2087 Status
= _SEH_GetExceptionCode();
2094 PsUnlockProcess(Process
);
2100 case ProcessPriorityClass
:
2102 PROCESS_PRIORITY_CLASS ppc
;
2106 ppc
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
2110 Status
= _SEH_GetExceptionCode();
2114 if(NT_SUCCESS(Status
))
2121 case ProcessLdtInformation
:
2122 case ProcessLdtSize
:
2123 case ProcessIoPortHandlers
:
2124 case ProcessWorkingSetWatch
:
2125 case ProcessUserModeIOPL
:
2126 case ProcessEnableAlignmentFaultFixup
:
2127 case ProcessAffinityMask
:
2128 Status
= STATUS_NOT_IMPLEMENTED
;
2131 case ProcessBasicInformation
:
2132 case ProcessIoCounters
:
2134 case ProcessPooledUsageAndLimits
:
2135 case ProcessWx86Information
:
2136 case ProcessHandleCount
:
2137 case ProcessWow64Information
:
2139 Status
= STATUS_INVALID_INFO_CLASS
;
2141 ObDereferenceObject(Process
);
2146 /**********************************************************************
2148 * PiQuerySystemProcessInformation
2151 * Compute the size of a process+thread snapshot as
2152 * expected by NtQuerySystemInformation.
2155 * 0 on error; otherwise the size, in bytes of the buffer
2156 * required to write a full snapshot.
2159 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
2162 PiQuerySystemProcessInformation(PVOID Buffer
,
2166 return STATUS_NOT_IMPLEMENTED
;
2169 PLIST_ENTRY CurrentEntryP
;
2171 PLIST_ENTRY CurrentEntryT
;
2174 ULONG RequiredSize
= 0L;
2175 BOOLEAN SizeOnly
= FALSE
;
2179 PSYSTEM_PROCESS_INFORMATION pInfoP
= (PSYSTEM_PROCESS_INFORMATION
) SnapshotBuffer
;
2180 PSYSTEM_PROCESS_INFORMATION pInfoPLast
= NULL
;
2181 PSYSTEM_THREAD_INFO pInfoT
= NULL
;
2184 /* Lock the process list. */
2185 ExAcquireFastMutex(&PspActiveProcessMutex
);
2188 * Scan the process list. Since the
2189 * list is circular, the guard is false
2190 * after the last process.
2192 for ( CurrentEntryP
= PsActiveProcessHead
.Flink
;
2193 (CurrentEntryP
!= & PsActiveProcessHead
);
2194 CurrentEntryP
= CurrentEntryP
->Flink
2198 * Compute how much space is
2199 * occupied in the snapshot
2200 * by adding this process info.
2201 * (at least one thread).
2203 SpiSizeCurrent
= sizeof (SYSTEM_PROCESS_INFORMATION
);
2204 RequiredSize
+= SpiSizeCurrent
;
2206 * Do not write process data in the
2207 * buffer if it is too small.
2209 if (TRUE
== SizeOnly
) continue;
2211 * Check if the buffer can contain
2212 * the full snapshot.
2214 if (Size
< RequiredSize
)
2220 * Get a reference to the
2221 * process descriptor we are
2224 CurrentP
= CONTAINING_RECORD(
2230 * Write process data in the buffer.
2232 RtlZeroMemory (pInfoP
, sizeof (SYSTEM_PROCESS_INFORMATION
));
2234 pInfoP
->ThreadCount
= 0L;
2235 pInfoP
->ProcessId
= CurrentP
->UniqueProcessId
;
2236 RtlInitUnicodeString (
2238 CurrentP
->ImageFileName
2241 for ( pInfoT
= & CurrentP
->ThreadSysInfo
[0],
2242 CurrentEntryT
= CurrentP
->ThreadListHead
.Flink
;
2244 (CurrentEntryT
!= & CurrentP
->ThreadListHead
);
2246 pInfoT
= & CurrentP
->ThreadSysInfo
[pInfoP
->ThreadCount
],
2247 CurrentEntryT
= CurrentEntryT
->Flink
2251 * Recalculate the size of the
2252 * information block.
2254 if (0 < pInfoP
->ThreadCount
)
2256 RequiredSize
+= sizeof (SYSTEM_THREAD_INFORMATION
);
2259 * Do not write thread data in the
2260 * buffer if it is too small.
2262 if (TRUE
== SizeOnly
) continue;
2264 * Check if the buffer can contain
2265 * the full snapshot.
2267 if (Size
< RequiredSize
)
2273 * Get a reference to the
2274 * thread descriptor we are
2277 CurrentT
= CONTAINING_RECORD(
2283 * Write thread data.
2287 sizeof (SYSTEM_THREAD_INFORMATION
)
2289 pInfoT
->KernelTime
= CurrentT
-> ; /* TIME */
2290 pInfoT
->UserTime
= CurrentT
-> ; /* TIME */
2291 pInfoT
->CreateTime
= CurrentT
-> ; /* TIME */
2292 pInfoT
->TickCount
= CurrentT
-> ; /* ULONG */
2293 pInfoT
->StartEIP
= CurrentT
-> ; /* ULONG */
2294 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2295 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2296 pInfoT
->DynamicPriority
= CurrentT
-> ; /* ULONG */
2297 pInfoT
->BasePriority
= CurrentT
-> ; /* ULONG */
2298 pInfoT
->nSwitches
= CurrentT
-> ; /* ULONG */
2299 pInfoT
->State
= CurrentT
-> ; /* DWORD */
2300 pInfoT
->WaitReason
= CurrentT
-> ; /* KWAIT_REASON */
2302 * Count the number of threads
2305 ++ pInfoP
->ThreadCount
;
2308 * Save the size of information
2309 * stored in the buffer for the
2312 pInfoP
->RelativeOffset
= SpiSize
;
2314 * Save a reference to the last
2315 * valid information block.
2317 pInfoPLast
= pInfoP
;
2319 * Compute the offset of the
2320 * SYSTEM_PROCESS_INFORMATION
2321 * descriptor in the snapshot
2322 * buffer for the next process.
2324 (ULONG
) pInfoP
+= SpiSize
;
2327 * Unlock the process list.
2329 ExReleaseFastMutex (
2330 & PspActiveProcessMutex
2333 * Return the proper error status code,
2334 * if the buffer was too small.
2336 if (TRUE
== SizeOnly
)
2338 if (NULL
!= RequiredSize
)
2340 *pRequiredSize
= RequiredSize
;
2342 return STATUS_INFO_LENGTH_MISMATCH
;
2345 * Mark the end of the snapshot.
2347 pInfoP
->RelativeOffset
= 0L;
2349 return STATUS_SUCCESS
;
2356 LARGE_INTEGER STDCALL
2357 PsGetProcessExitTime(VOID
)
2360 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
2369 PsGetProcessCreateTimeQuadPart(
2373 return Process
->CreateTime
.QuadPart
;
2381 PsGetProcessDebugPort(
2385 return Process
->DebugPort
;
2393 PsGetProcessExitProcessCalled(
2397 return Process
->ExitProcessCalled
;
2405 PsGetProcessExitStatus(
2409 return Process
->ExitStatus
;
2421 return (HANDLE
)Process
->UniqueProcessId
;
2429 PsGetProcessImageFileName(
2433 return (LPSTR
)Process
->ImageFileName
;
2441 PsGetProcessInheritedFromUniqueProcessId(
2445 return Process
->InheritedFromUniqueProcessId
;
2457 return Process
->Job
;
2469 return Process
->Peb
;
2477 PsGetProcessPriorityClass(
2481 return Process
->PriorityClass
;
2489 PsGetProcessSectionBaseAddress(
2493 return Process
->SectionBaseAddress
;
2501 PsGetProcessSecurityPort(
2505 return Process
->SecurityPort
;
2513 PsGetProcessSessionId(
2517 return (HANDLE
)Process
->SessionId
;
2525 PsGetProcessWin32Process(
2529 return Process
->Win32Process
;
2537 PsGetProcessWin32WindowStation(
2541 return Process
->Win32WindowStation
;
2549 PsIsProcessBeingDebugged(
2553 return FALSE
/*Process->IsProcessBeingDebugged*/;
2561 PsLookupProcessByProcessId(IN HANDLE ProcessId
,
2562 OUT PEPROCESS
*Process
)
2564 PLIST_ENTRY current_entry
;
2567 ExAcquireFastMutex(&PspActiveProcessMutex
);
2569 current_entry
= PsActiveProcessHead
.Flink
;
2570 while (current_entry
!= &PsActiveProcessHead
)
2572 current
= CONTAINING_RECORD(current_entry
,
2575 if (current
->UniqueProcessId
== ProcessId
)
2578 ObReferenceObject(current
);
2579 ExReleaseFastMutex(&PspActiveProcessMutex
);
2580 return(STATUS_SUCCESS
);
2582 current_entry
= current_entry
->Flink
;
2585 ExReleaseFastMutex(&PspActiveProcessMutex
);
2587 return(STATUS_INVALID_PARAMETER
);
2592 PspRunCreateProcessNotifyRoutines
2594 PEPROCESS CurrentProcess
,
2599 HANDLE ProcessId
= (HANDLE
)CurrentProcess
->UniqueProcessId
;
2600 HANDLE ParentId
= CurrentProcess
->InheritedFromUniqueProcessId
;
2602 for(i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2603 if(PiProcessNotifyRoutine
[i
])
2604 PiProcessNotifyRoutine
[i
](ParentId
, ProcessId
, Create
);
2611 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
2618 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2620 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
2622 PiProcessNotifyRoutine
[i
] = NULL
;
2627 return(STATUS_SUCCESS
);
2631 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2633 if (PiProcessNotifyRoutine
[i
] == NULL
)
2635 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
2640 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2642 return STATUS_INSUFFICIENT_RESOURCES
;
2645 return STATUS_SUCCESS
;
2649 PspRunLoadImageNotifyRoutines(
2650 PUNICODE_STRING FullImageName
,
2652 PIMAGE_INFO ImageInfo
)
2656 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2657 if (PiLoadImageNotifyRoutine
[i
])
2658 PiLoadImageNotifyRoutine
[i
](FullImageName
, ProcessId
, ImageInfo
);
2666 PsRemoveLoadImageNotifyRoutine(
2667 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
2671 return STATUS_NOT_IMPLEMENTED
;
2678 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
2682 for (i
= 0; i
< MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
; i
++)
2684 if (PiLoadImageNotifyRoutine
[i
] == NULL
)
2686 PiLoadImageNotifyRoutine
[i
] = NotifyRoutine
;
2691 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2693 return STATUS_INSUFFICIENT_RESOURCES
;
2696 return STATUS_SUCCESS
;
2704 PsSetProcessPriorityClass(
2709 Process
->PriorityClass
= PriorityClass
;
2717 PsSetProcessSecurityPort(
2722 Process
->SecurityPort
= SecurityPort
;
2730 PsSetProcessWin32Process(
2735 Process
->Win32Process
= Win32Process
;
2743 PsSetProcessWin32WindowStation(
2748 Process
->Win32WindowStation
= WindowStation
;
2758 IN PEPROCESS Process
,
2759 IN POOL_TYPE PoolType
,
2765 /* Charge the usage */
2766 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
2768 /* Raise Exception */
2769 if (!NT_SUCCESS(Status
)) {
2770 ExRaiseStatus(Status
);
2779 PsChargeProcessNonPagedPoolQuota (
2780 IN PEPROCESS Process
,
2784 /* Call the general function */
2785 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
2793 PsChargeProcessPagedPoolQuota (
2794 IN PEPROCESS Process
,
2798 /* Call the general function */
2799 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
2807 PsChargeProcessPoolQuota(
2808 IN PEPROCESS Process
,
2809 IN POOL_TYPE PoolType
,
2813 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
2817 /* Get current Quota Block */
2818 QuotaBlock
= Process
->QuotaBlock
;
2820 /* Quota Operations are not to be done on the SYSTEM Process */
2821 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
2823 /* New Size in use */
2824 NewUsageSize
= QuotaBlock
->QuotaEntry
[PoolType
].Usage
+ Amount
;
2826 /* Does this size respect the quota? */
2827 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Limit
) {
2829 /* It doesn't, so keep raising the Quota */
2830 while (MiRaisePoolQuota(PoolType
, QuotaBlock
->QuotaEntry
[PoolType
].Limit
, &NewMaxQuota
)) {
2831 /* Save new Maximum Quota */
2832 QuotaBlock
->QuotaEntry
[PoolType
].Limit
= NewMaxQuota
;
2834 /* See if the new Maximum Quota fulfills our need */
2835 if (NewUsageSize
<= NewMaxQuota
) goto QuotaChanged
;
2838 return STATUS_QUOTA_EXCEEDED
;
2842 /* Save new Usage */
2843 QuotaBlock
->QuotaEntry
[PoolType
].Usage
= NewUsageSize
;
2845 /* Is this a new peak? */
2846 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Peak
) {
2847 QuotaBlock
->QuotaEntry
[PoolType
].Peak
= NewUsageSize
;
2851 return STATUS_SUCCESS
;
2860 IN PEPROCESS Process
,
2861 IN POOL_TYPE PoolType
,
2873 PsReturnProcessNonPagedPoolQuota(
2874 IN PEPROCESS Process
,
2886 PsReturnProcessPagedPoolQuota(
2887 IN PEPROCESS Process
,
2895 PsLockProcess(PEPROCESS Process
, BOOL Timeout
)
2898 PKTHREAD PrevLockOwner
;
2899 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2900 PLARGE_INTEGER Delay
= (Timeout
? &PsLockTimeout
: NULL
);
2901 PKTHREAD CallingThread
= KeGetCurrentThread();
2905 KeEnterCriticalRegion();
2909 if(Process
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
2911 KeLeaveCriticalRegion();
2912 return STATUS_PROCESS_IS_TERMINATING
;
2915 PrevLockOwner
= (PKTHREAD
)InterlockedCompareExchangePointer(
2916 &Process
->LockOwner
, CallingThread
, NULL
);
2917 if(PrevLockOwner
== NULL
|| PrevLockOwner
== CallingThread
)
2919 /* we got the lock or already locked it */
2920 if(InterlockedIncrementUL(&Process
->LockCount
) == 1)
2922 KeClearEvent(&Process
->LockEvent
);
2925 return STATUS_SUCCESS
;
2931 Status
= KeWaitForSingleObject(&Process
->LockEvent
,
2936 if(!NT_SUCCESS(Status
) || Status
== STATUS_TIMEOUT
)
2939 if(Status
== STATUS_TIMEOUT
)
2941 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process
);
2944 KeLeaveCriticalRegion();
2951 KeDelayExecutionThread(KernelMode
, FALSE
, &ShortPsLockDelay
);
2960 PsUnlockProcess(PEPROCESS Process
)
2964 ASSERT(Process
->LockOwner
== KeGetCurrentThread());
2966 if(InterlockedDecrementUL(&Process
->LockCount
) == 0)
2968 InterlockedExchangePointer(&Process
->LockOwner
, NULL
);
2969 KeSetEvent(&Process
->LockEvent
, IO_NO_INCREMENT
, FALSE
);
2972 KeLeaveCriticalRegion();