1 /* $Id: process.c,v 1.139 2004/08/15 16:39:10 chorns Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/process.c
6 * PURPOSE: Process managment
7 * PROGRAMMER: David Welch (welch@cwcom.net)
12 /* INCLUDES ******************************************************************/
16 #include <internal/debug.h>
19 /* GLOBALS ******************************************************************/
21 PEPROCESS EXPORTED PsInitialSystemProcess
= NULL
;
22 HANDLE SystemProcessHandle
= NULL
;
24 POBJECT_TYPE EXPORTED PsProcessType
= NULL
;
26 LIST_ENTRY PsProcessListHead
;
27 static KSPIN_LOCK PsProcessListLock
;
28 static ULONG PiNextProcessUniqueId
= 0;
30 static GENERIC_MAPPING PiProcessMapping
= {PROCESS_READ
,
35 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
36 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
38 static PCREATE_PROCESS_NOTIFY_ROUTINE
39 PiProcessNotifyRoutine
[MAX_PROCESS_NOTIFY_ROUTINE_COUNT
];
40 static PLOAD_IMAGE_NOTIFY_ROUTINE
41 PiLoadImageNotifyRoutine
[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
];
46 WORK_QUEUE_ITEM WorkQueueItem
;
49 BOOLEAN IsWorkerQueue
;
50 } DEL_CONTEXT
, *PDEL_CONTEXT
;
52 /* FUNCTIONS *****************************************************************/
55 PsGetNextProcess(PEPROCESS OldProcess
)
58 PEPROCESS NextProcess
;
61 if (OldProcess
== NULL
)
63 Status
= ObReferenceObjectByPointer(PsInitialSystemProcess
,
67 if (!NT_SUCCESS(Status
))
69 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsInitialSystemProcess\n");
72 return PsInitialSystemProcess
;
75 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
76 NextProcess
= OldProcess
;
79 if (NextProcess
->ProcessListEntry
.Blink
== &PsProcessListHead
)
81 NextProcess
= CONTAINING_RECORD(PsProcessListHead
.Blink
,
87 NextProcess
= CONTAINING_RECORD(NextProcess
->ProcessListEntry
.Blink
,
91 Status
= ObReferenceObjectByPointer(NextProcess
,
95 if (NT_SUCCESS(Status
))
99 else if (Status
== STATUS_PROCESS_IS_TERMINATING
)
103 else if (!NT_SUCCESS(Status
))
105 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
110 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
111 ObDereferenceObject(OldProcess
);
118 _NtOpenProcessToken(IN HANDLE ProcessHandle
,
119 IN ACCESS_MASK DesiredAccess
,
120 OUT PHANDLE TokenHandle
)
125 Status
= PsOpenTokenOfProcess(ProcessHandle
,
127 if (!NT_SUCCESS(Status
))
131 Status
= ObCreateHandle(PsGetCurrentProcess(),
136 ObDereferenceObject(Token
);
145 NtOpenProcessToken(IN HANDLE ProcessHandle
,
146 IN ACCESS_MASK DesiredAccess
,
147 OUT PHANDLE TokenHandle
)
149 return _NtOpenProcessToken(ProcessHandle
, DesiredAccess
, TokenHandle
);
157 NtOpenProcessTokenEx(
158 IN HANDLE ProcessHandle
,
159 IN ACCESS_MASK DesiredAccess
,
160 IN ULONG HandleAttributes
,
161 OUT PHANDLE TokenHandle
165 return STATUS_NOT_IMPLEMENTED
;
173 PACCESS_TOKEN STDCALL
174 PsReferencePrimaryToken(PEPROCESS Process
)
176 ObReferenceObjectByPointer(Process
->Token
,
180 return(Process
->Token
);
185 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
186 PACCESS_TOKEN
* Token
)
191 Status
= ObReferenceObjectByHandle(ProcessHandle
,
192 PROCESS_QUERY_INFORMATION
,
197 if (!NT_SUCCESS(Status
))
201 *Token
= PsReferencePrimaryToken(Process
);
202 ObDereferenceObject(Process
);
203 return(STATUS_SUCCESS
);
208 PiKillMostProcesses(VOID
)
211 PLIST_ENTRY current_entry
;
214 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
216 current_entry
= PsProcessListHead
.Flink
;
217 while (current_entry
!= &PsProcessListHead
)
219 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
221 current_entry
= current_entry
->Flink
;
223 if (current
->UniqueProcessId
!= PsInitialSystemProcess
->UniqueProcessId
&&
224 current
->UniqueProcessId
!= (ULONG
)PsGetCurrentProcessId())
226 PiTerminateProcessThreads(current
, STATUS_SUCCESS
);
230 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
235 PsInitProcessManagment(VOID
)
242 * Register the process object type
245 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
247 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
248 PsProcessType
->TotalObjects
= 0;
249 PsProcessType
->TotalHandles
= 0;
250 PsProcessType
->MaxObjects
= ULONG_MAX
;
251 PsProcessType
->MaxHandles
= ULONG_MAX
;
252 PsProcessType
->PagedPoolCharge
= 0;
253 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
254 PsProcessType
->Mapping
= &PiProcessMapping
;
255 PsProcessType
->Dump
= NULL
;
256 PsProcessType
->Open
= NULL
;
257 PsProcessType
->Close
= NULL
;
258 PsProcessType
->Delete
= PiDeleteProcess
;
259 PsProcessType
->Parse
= NULL
;
260 PsProcessType
->Security
= NULL
;
261 PsProcessType
->QueryName
= NULL
;
262 PsProcessType
->OkayToClose
= NULL
;
263 PsProcessType
->Create
= NULL
;
264 PsProcessType
->DuplicationNotify
= NULL
;
266 RtlRosInitUnicodeStringFromLiteral(&PsProcessType
->TypeName
, L
"Process");
268 ObpCreateTypeObject(PsProcessType
);
270 InitializeListHead(&PsProcessListHead
);
271 KeInitializeSpinLock(&PsProcessListLock
);
273 RtlZeroMemory(PiProcessNotifyRoutine
, sizeof(PiProcessNotifyRoutine
));
274 RtlZeroMemory(PiLoadImageNotifyRoutine
, sizeof(PiLoadImageNotifyRoutine
));
277 * Initialize the system process
279 Status
= ObCreateObject(KernelMode
,
287 (PVOID
*)&PsInitialSystemProcess
);
288 if (!NT_SUCCESS(Status
))
293 /* System threads may run on any processor. */
294 PsInitialSystemProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
295 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
296 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[0] = 0;
297 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[1] = 0;
298 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
299 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
303 KProcess
= &PsInitialSystemProcess
->Pcb
;
305 MmInitializeAddressSpace(PsInitialSystemProcess
,
306 &PsInitialSystemProcess
->AddressSpace
);
307 ObCreateHandleTable(NULL
,FALSE
,PsInitialSystemProcess
);
309 #if defined(__GNUC__)
310 KProcess
->DirectoryTableBase
=
311 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
315 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
316 KProcess
->DirectoryTableBase
= dummy
;
320 PsInitialSystemProcess
->UniqueProcessId
=
321 InterlockedIncrement((LONG
*)&PiNextProcessUniqueId
);
322 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
323 PsInitialSystemProcess
->Win32Desktop
= (HANDLE
)0;
325 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
326 InsertHeadList(&PsProcessListHead
,
327 &PsInitialSystemProcess
->ProcessListEntry
);
328 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
329 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
331 strcpy(PsInitialSystemProcess
->ImageFileName
, "SYSTEM");
333 SepCreateSystemProcessToken(PsInitialSystemProcess
);
335 ObCreateHandle(PsInitialSystemProcess
,
336 PsInitialSystemProcess
,
339 &SystemProcessHandle
);
343 PiDeleteProcessWorker(PVOID pContext
)
346 PDEL_CONTEXT Context
;
347 PEPROCESS CurrentProcess
;
350 Context
= (PDEL_CONTEXT
)pContext
;
351 Process
= Context
->Process
;
352 CurrentProcess
= PsGetCurrentProcess();
354 DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process
);
356 if (CurrentProcess
!= Process
)
358 KeAttachProcess(Process
);
361 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
362 RemoveEntryList(&Process
->ProcessListEntry
);
363 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
366 KDB_DELETEPROCESS_HOOK(Process
);
368 ObDereferenceObject(Process
->Token
);
369 ObDeleteHandleTable(Process
);
371 if (CurrentProcess
!= Process
)
376 MmReleaseMmInfo(Process
);
377 if (Context
->IsWorkerQueue
)
379 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
384 PiDeleteProcess(PVOID ObjectBody
)
388 Context
.Process
= (PEPROCESS
)ObjectBody
;
390 if (PsGetCurrentProcess() == Context
.Process
|| PsGetCurrentThread()->OldProcess
== NULL
)
392 Context
.IsWorkerQueue
= FALSE
;
393 PiDeleteProcessWorker(&Context
);
397 Context
.IsWorkerQueue
= TRUE
;
398 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
399 ExInitializeWorkItem (&Context
.WorkQueueItem
, PiDeleteProcessWorker
, &Context
);
400 ExQueueWorkItem(&Context
.WorkQueueItem
, HyperCriticalWorkQueue
);
401 if (KeReadStateEvent(&Context
.Event
) == 0)
403 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
409 PsCreatePeb(HANDLE ProcessHandle
,
415 LARGE_INTEGER SectionOffset
;
420 /* Allocate the Process Environment Block (PEB) */
421 Peb
= (PPEB
)PEB_BASE
;
423 Status
= NtAllocateVirtualMemory(ProcessHandle
,
427 MEM_RESERVE
| MEM_COMMIT
,
429 if (!NT_SUCCESS(Status
))
431 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
434 DPRINT("Peb %p PebSize %lu\n", Peb
, PebSize
);
437 #if defined(__GNUC__)
438 SectionOffset
.QuadPart
= 0LL;
440 SectionOffset
.QuadPart
= 0;
443 Status
= MmMapViewOfSection(NlsSectionObject
,
453 if (!NT_SUCCESS(Status
))
455 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
458 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
460 KeAttachProcess(Process
);
462 /* Initialize the PEB */
463 RtlZeroMemory(Peb
, sizeof(PEB
));
464 Peb
->ImageBaseAddress
= ImageBase
;
466 Peb
->OSMajorVersion
= 4;
467 Peb
->OSMinorVersion
= 0;
468 Peb
->OSBuildNumber
= 0;
469 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
470 Peb
->SPMajorVersion
= 6;
472 Peb
->AnsiCodePageData
= (char*)TableBase
+ NlsAnsiTableOffset
;
473 Peb
->OemCodePageData
= (char*)TableBase
+ NlsOemTableOffset
;
474 Peb
->UnicodeCaseTableData
= (char*)TableBase
+ NlsUnicodeTableOffset
;
479 DPRINT("PsCreatePeb: Peb created at %p\n", Peb
);
481 return(STATUS_SUCCESS
);
486 KeGetCurrentProcess(VOID
)
488 * FUNCTION: Returns a pointer to the current process
491 return(&(PsGetCurrentProcess()->Pcb
));
495 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
496 * ULONG ProcessId! (Skywing)
502 PsGetCurrentProcessId(VOID
)
504 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
512 PsGetCurrentProcessSessionId (
516 return PsGetCurrentProcess()->SessionId
;
520 * FUNCTION: Returns a pointer to the current process
525 IoGetCurrentProcess(VOID
)
527 if (PsGetCurrentThread() == NULL
||
528 PsGetCurrentThread()->ThreadsProcess
== NULL
)
530 return(PsInitialSystemProcess
);
534 return(PsGetCurrentThread()->ThreadsProcess
);
542 PsCreateSystemProcess(PHANDLE ProcessHandle
,
543 ACCESS_MASK DesiredAccess
,
544 POBJECT_ATTRIBUTES ObjectAttributes
)
546 return NtCreateProcess(ProcessHandle
,
557 NtCreateProcess(OUT PHANDLE ProcessHandle
,
558 IN ACCESS_MASK DesiredAccess
,
559 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
560 IN HANDLE ParentProcessHandle
,
561 IN BOOLEAN InheritObjectTable
,
562 IN HANDLE SectionHandle OPTIONAL
,
563 IN HANDLE DebugPortHandle OPTIONAL
,
564 IN HANDLE ExceptionPortHandle OPTIONAL
)
566 * FUNCTION: Creates a process.
568 * ProcessHandle (OUT) = Caller supplied storage for the resulting
570 * DesiredAccess = Specifies the allowed or desired access to the
571 * process can be a combination of
572 * STANDARD_RIGHTS_REQUIRED| ..
573 * ObjectAttribute = Initialized attributes for the object, contains
574 * the rootdirectory and the filename
575 * ParentProcess = Handle to the parent process.
576 * InheritObjectTable = Specifies to inherit the objects of the parent
578 * SectionHandle = Handle to a section object to back the image file
579 * DebugPort = Handle to a DebugPort if NULL the system default debug
581 * ExceptionPort = Handle to a exception port.
583 * This function maps to the win32 CreateProcess.
588 PEPROCESS ParentProcess
;
592 PVOID LdrStartupAddr
;
595 PEPORT ExceptionPort
;
597 PMEMORY_AREA MemoryArea
;
598 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
600 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes
);
602 BoundaryAddressMultiple
.QuadPart
= 0;
604 Status
= ObReferenceObjectByHandle(ParentProcessHandle
,
605 PROCESS_CREATE_PROCESS
,
608 (PVOID
*)&ParentProcess
,
610 if (!NT_SUCCESS(Status
))
612 DPRINT("NtCreateProcess() = %x\n",Status
);
616 Status
= ObCreateObject(ExGetPreviousMode(),
625 if (!NT_SUCCESS(Status
))
627 ObDereferenceObject(ParentProcess
);
628 DPRINT("ObCreateObject() = %x\n",Status
);
632 Status
= ObInsertObject ((PVOID
)Process
,
638 if (!NT_SUCCESS(Status
))
640 ObDereferenceObject (Process
);
641 ObDereferenceObject (ParentProcess
);
642 DPRINT("ObInsertObject() = %x\n",Status
);
646 KeInitializeDispatcherHeader(&Process
->Pcb
.DispatcherHeader
,
650 KProcess
= &Process
->Pcb
;
651 /* Inherit parent process's affinity. */
652 KProcess
->Affinity
= ParentProcess
->Pcb
.Affinity
;
653 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
654 KProcess
->IopmOffset
= 0xffff;
655 KProcess
->LdtDescriptor
[0] = 0;
656 KProcess
->LdtDescriptor
[1] = 0;
657 MmInitializeAddressSpace(Process
,
658 &Process
->AddressSpace
);
659 Process
->UniqueProcessId
= InterlockedIncrement((LONG
*)&PiNextProcessUniqueId
);
660 Process
->InheritedFromUniqueProcessId
=
661 (HANDLE
)ParentProcess
->UniqueProcessId
;
662 ObCreateHandleTable(ParentProcess
,
665 MmCopyMmInfo(ParentProcess
, Process
);
666 if (ParentProcess
->Win32WindowStation
!= (HANDLE
)0)
668 /* Always duplicate the process window station. */
669 Process
->Win32WindowStation
= 0;
670 Status
= ObDuplicateObject(ParentProcess
,
672 ParentProcess
->Win32WindowStation
,
673 &Process
->Win32WindowStation
,
676 DUPLICATE_SAME_ACCESS
);
677 if (!NT_SUCCESS(Status
))
684 Process
->Win32WindowStation
= (HANDLE
)0;
686 if (ParentProcess
->Win32Desktop
!= (HANDLE
)0)
688 /* Always duplicate the process window station. */
689 Process
->Win32Desktop
= 0;
690 Status
= ObDuplicateObject(ParentProcess
,
692 ParentProcess
->Win32Desktop
,
693 &Process
->Win32Desktop
,
696 DUPLICATE_SAME_ACCESS
);
697 if (!NT_SUCCESS(Status
))
704 Process
->Win32Desktop
= (HANDLE
)0;
707 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
708 InsertHeadList(&PsProcessListHead
, &Process
->ProcessListEntry
);
709 InitializeListHead(&Process
->ThreadListHead
);
710 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
712 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
717 if (DebugPortHandle
!= NULL
)
719 Status
= ObReferenceObjectByHandle(DebugPortHandle
,
725 if (!NT_SUCCESS(Status
))
727 ObDereferenceObject(Process
);
728 ObDereferenceObject(ParentProcess
);
729 ZwClose(*ProcessHandle
);
730 *ProcessHandle
= NULL
;
733 Process
->DebugPort
= DebugPort
;
737 * Add the exception port
739 if (ExceptionPortHandle
!= NULL
)
741 Status
= ObReferenceObjectByHandle(ExceptionPortHandle
,
745 (PVOID
*)&ExceptionPort
,
747 if (!NT_SUCCESS(Status
))
749 ObDereferenceObject(Process
);
750 ObDereferenceObject(ParentProcess
);
751 ZwClose(*ProcessHandle
);
752 *ProcessHandle
= NULL
;
755 Process
->ExceptionPort
= ExceptionPort
;
759 * Now we have created the process proper
762 MmLockAddressSpace(&Process
->AddressSpace
);
764 /* Protect the highest 64KB of the process address space */
765 BaseAddress
= MmUserProbeAddress
;
766 Status
= MmCreateMemoryArea(Process
,
767 &Process
->AddressSpace
,
768 MEMORY_AREA_NO_ACCESS
,
775 BoundaryAddressMultiple
);
776 if (!NT_SUCCESS(Status
))
778 MmUnlockAddressSpace(&Process
->AddressSpace
);
779 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
783 /* Protect the lowest 64KB of the process address space */
785 BaseAddress
= (PVOID
)0x00000000;
786 Status
= MmCreateMemoryArea(Process
,
787 &Process
->AddressSpace
,
788 MEMORY_AREA_NO_ACCESS
,
795 BoundaryAddressMultiple
);
796 if (!NT_SUCCESS(Status
))
798 MmUnlockAddressSpace(&Process
->AddressSpace
);
799 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
804 /* Protect the 60KB above the shared user page */
805 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
806 Status
= MmCreateMemoryArea(Process
,
807 &Process
->AddressSpace
,
808 MEMORY_AREA_NO_ACCESS
,
815 BoundaryAddressMultiple
);
816 if (!NT_SUCCESS(Status
))
818 MmUnlockAddressSpace(&Process
->AddressSpace
);
819 DPRINT1("Failed to protect the memory above the shared user page\n");
823 /* Create the shared data page */
824 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
825 Status
= MmCreateMemoryArea(Process
,
826 &Process
->AddressSpace
,
827 MEMORY_AREA_SHARED_DATA
,
834 BoundaryAddressMultiple
);
835 MmUnlockAddressSpace(&Process
->AddressSpace
);
836 if (!NT_SUCCESS(Status
))
838 DPRINT1("Failed to create shared data page\n");
845 Status
= LdrpMapSystemDll(*ProcessHandle
,
847 if (!NT_SUCCESS(Status
))
849 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
850 ObDereferenceObject(Process
);
851 ObDereferenceObject(ParentProcess
);
856 * Map the process image
858 if (SectionHandle
!= NULL
)
860 DPRINT("Mapping process image\n");
861 Status
= LdrpMapImage(*ProcessHandle
,
864 if (!NT_SUCCESS(Status
))
866 DbgPrint("LdrpMapImage failed (Status %x)\n", Status
);
867 ObDereferenceObject(Process
);
868 ObDereferenceObject(ParentProcess
);
878 * Duplicate the token
880 Status
= SepInitializeNewProcess(Process
, ParentProcess
);
881 if (!NT_SUCCESS(Status
))
883 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
884 ObDereferenceObject(Process
);
885 ObDereferenceObject(ParentProcess
);
892 DPRINT("Creating PEB\n");
893 Status
= PsCreatePeb(*ProcessHandle
,
896 if (!NT_SUCCESS(Status
))
898 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
899 ObDereferenceObject(Process
);
900 ObDereferenceObject(ParentProcess
);
901 ZwClose(*ProcessHandle
);
902 *ProcessHandle
= NULL
;
907 * Maybe send a message to the creator process's debugger
910 if (ParentProcess
->DebugPort
!= NULL
)
912 LPC_DBG_MESSAGE Message
;
915 ObCreateHandle(NULL
, // Debugger Process
916 NULL
, // SectionHandle
921 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
922 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
924 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
925 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
926 Message
.Data
.CreateProcess
.Base
= ImageBase
;
927 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
929 Status
= LpcSendDebugMessagePort(ParentProcess
->DebugPort
,
934 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
936 ObDereferenceObject(Process
);
937 ObDereferenceObject(ParentProcess
);
938 return(STATUS_SUCCESS
);
946 NtOpenProcess(OUT PHANDLE ProcessHandle
,
947 IN ACCESS_MASK DesiredAccess
,
948 IN POBJECT_ATTRIBUTES ObjectAttributes
,
949 IN PCLIENT_ID ClientId
)
951 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
952 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
953 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
954 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
958 * Not sure of the exact semantics
960 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
961 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
966 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
967 ObjectAttributes
->Attributes
,
974 if (Status
!= STATUS_SUCCESS
)
979 Status
= ObCreateHandle(PsGetCurrentProcess(),
984 ObDereferenceObject(Process
);
991 PLIST_ENTRY current_entry
;
995 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
996 current_entry
= PsProcessListHead
.Flink
;
997 while (current_entry
!= &PsProcessListHead
)
999 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
1001 if (current
->UniqueProcessId
== (ULONG
)ClientId
->UniqueProcess
)
1003 if (current
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
1005 Status
= STATUS_PROCESS_IS_TERMINATING
;
1009 Status
= ObReferenceObjectByPointer(current
,
1014 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1015 if (NT_SUCCESS(Status
))
1017 Status
= ObCreateHandle(PsGetCurrentProcess(),
1022 ObDereferenceObject(current
);
1023 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
1024 DPRINT("NtOpenProcess() = %x\n", Status
);
1028 current_entry
= current_entry
->Flink
;
1030 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1031 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1032 return(STATUS_UNSUCCESSFUL
);
1034 return(STATUS_UNSUCCESSFUL
);
1042 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
1043 IN CINT ProcessInformationClass
,
1044 OUT PVOID ProcessInformation
,
1045 IN ULONG ProcessInformationLength
,
1046 OUT PULONG ReturnLength OPTIONAL
)
1052 * TODO: Here we should probably check that ProcessInformationLength
1053 * bytes indeed are writable at address ProcessInformation.
1056 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1057 PROCESS_SET_INFORMATION
,
1062 if (Status
!= STATUS_SUCCESS
)
1067 switch (ProcessInformationClass
)
1069 case ProcessBasicInformation
:
1070 if (ProcessInformationLength
!= sizeof(PROCESS_BASIC_INFORMATION
))
1072 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1076 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
=
1077 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
1078 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
1079 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
1080 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
1081 ProcessBasicInformationP
->UniqueProcessId
=
1082 Process
->UniqueProcessId
;
1083 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
1084 (ULONG
)Process
->InheritedFromUniqueProcessId
;
1085 ProcessBasicInformationP
->BasePriority
=
1086 Process
->Pcb
.BasePriority
;
1090 *ReturnLength
= sizeof(PROCESS_BASIC_INFORMATION
);
1095 case ProcessQuotaLimits
:
1096 case ProcessIoCounters
:
1097 Status
= STATUS_NOT_IMPLEMENTED
;
1101 if (ProcessInformationLength
!= sizeof(KERNEL_USER_TIMES
))
1103 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1107 PKERNEL_USER_TIMES ProcessTimeP
=
1108 (PKERNEL_USER_TIMES
)ProcessInformation
;
1110 ProcessTimeP
->CreateTime
= (TIME
) Process
->CreateTime
;
1111 ProcessTimeP
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
* 100000LL;
1112 ProcessTimeP
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
* 100000LL;
1113 ProcessTimeP
->ExitTime
= (TIME
) Process
->ExitTime
;
1117 *ReturnLength
= sizeof(KERNEL_USER_TIMES
);
1122 case ProcessDebugPort
:
1123 case ProcessLdtInformation
:
1124 case ProcessWorkingSetWatch
:
1125 case ProcessWx86Information
:
1126 Status
= STATUS_NOT_IMPLEMENTED
;
1129 case ProcessHandleCount
:
1130 if (ProcessInformationLength
!= sizeof(ULONG
))
1132 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1136 PULONG HandleCount
= (PULONG
)ProcessInformation
;
1137 *HandleCount
= ObpGetHandleCountByHandleTable(&Process
->HandleTable
);
1140 *ReturnLength
= sizeof(ULONG
);
1145 case ProcessSessionInformation
:
1146 case ProcessWow64Information
:
1147 Status
= STATUS_NOT_IMPLEMENTED
;
1150 case ProcessVmCounters
:
1151 if (ProcessInformationLength
!= sizeof(VM_COUNTERS
))
1153 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1157 PVM_COUNTERS pOut
= (PVM_COUNTERS
)ProcessInformation
;
1158 pOut
->PeakVirtualSize
= Process
->PeakVirtualSize
;
1160 * Here we should probably use VirtualSize.LowPart, but due to
1161 * incompatibilities in current headers (no unnamed union),
1164 pOut
->VirtualSize
= (ULONG
)Process
->VirtualSize
.QuadPart
;
1165 pOut
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
1166 pOut
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
1167 pOut
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
1168 pOut
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[0]; // TODO: Verify!
1169 pOut
->QuotaPagedPoolUsage
= Process
->QuotaPoolUsage
[0]; // TODO: Verify!
1170 pOut
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[1]; // TODO: Verify!
1171 pOut
->QuotaNonPagedPoolUsage
= Process
->QuotaPoolUsage
[1]; // TODO: Verify!
1172 pOut
->PagefileUsage
= Process
->PagefileUsage
;
1173 pOut
->PeakPagefileUsage
= Process
->PeakPagefileUsage
;
1177 *ReturnLength
= sizeof(VM_COUNTERS
);
1182 case ProcessDefaultHardErrorMode
:
1183 if (ProcessInformationLength
!= sizeof(ULONG
))
1185 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1189 PULONG HardErrMode
= (PULONG
)ProcessInformation
;
1190 *HardErrMode
= Process
->DefaultHardErrorProcessing
;
1194 *ReturnLength
= sizeof(ULONG
);
1199 case ProcessPriorityBoost
:
1200 if (ProcessInformationLength
!= sizeof(ULONG
))
1202 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1206 PULONG BoostEnabled
= (PULONG
)ProcessInformation
;
1207 *BoostEnabled
= Process
->Pcb
.DisableBoost
? FALSE
: TRUE
;
1211 *ReturnLength
= sizeof(ULONG
);
1216 case ProcessDeviceMap
:
1217 Status
= STATUS_NOT_IMPLEMENTED
;
1220 case ProcessPriorityClass
:
1221 if (ProcessInformationLength
!= sizeof(USHORT
))
1223 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1227 PUSHORT Priority
= (PUSHORT
)ProcessInformation
;
1228 *Priority
= Process
->PriorityClass
;
1232 *ReturnLength
= sizeof(USHORT
);
1238 * Note: The following 10 information classes are verified to not be
1239 * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
1241 case ProcessBasePriority
:
1242 case ProcessRaisePriority
:
1243 case ProcessExceptionPort
:
1244 case ProcessAccessToken
:
1245 case ProcessLdtSize
:
1246 case ProcessIoPortHandlers
:
1247 case ProcessUserModeIOPL
:
1248 case ProcessEnableAlignmentFaultFixup
:
1249 case ProcessAffinityMask
:
1250 case ProcessForegroundInformation
:
1252 Status
= STATUS_INVALID_INFO_CLASS
;
1254 ObDereferenceObject(Process
);
1260 PspAssignPrimaryToken(PEPROCESS Process
,
1263 PACCESS_TOKEN Token
;
1264 PACCESS_TOKEN OldToken
;
1267 Status
= ObReferenceObjectByHandle(TokenHandle
,
1273 if (!NT_SUCCESS(Status
))
1277 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
1278 if (NT_SUCCESS(Status
))
1280 ObDereferenceObject(OldToken
);
1282 ObDereferenceObject(Token
);
1290 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1291 IN CINT ProcessInformationClass
,
1292 IN PVOID ProcessInformation
,
1293 IN ULONG ProcessInformationLength
)
1297 PHANDLE ProcessAccessTokenP
;
1299 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1300 PROCESS_SET_INFORMATION
,
1305 if (!NT_SUCCESS(Status
))
1310 switch (ProcessInformationClass
)
1312 case ProcessQuotaLimits
:
1313 case ProcessBasePriority
:
1314 case ProcessRaisePriority
:
1315 case ProcessDebugPort
:
1316 case ProcessExceptionPort
:
1317 Status
= STATUS_NOT_IMPLEMENTED
;
1320 case ProcessAccessToken
:
1321 ProcessAccessTokenP
= (PHANDLE
)ProcessInformation
;
1322 Status
= PspAssignPrimaryToken(Process
, *ProcessAccessTokenP
);
1325 case ProcessImageFileName
:
1326 memcpy(Process
->ImageFileName
, ProcessInformation
, 8);
1327 Status
= STATUS_SUCCESS
;
1330 case ProcessLdtInformation
:
1331 case ProcessLdtSize
:
1332 case ProcessDefaultHardErrorMode
:
1333 case ProcessIoPortHandlers
:
1334 case ProcessWorkingSetWatch
:
1335 case ProcessUserModeIOPL
:
1336 case ProcessEnableAlignmentFaultFixup
:
1337 case ProcessPriorityClass
:
1338 case ProcessAffinityMask
:
1339 Status
= STATUS_NOT_IMPLEMENTED
;
1342 case ProcessBasicInformation
:
1343 case ProcessIoCounters
:
1345 case ProcessPooledUsageAndLimits
:
1346 case ProcessWx86Information
:
1347 case ProcessHandleCount
:
1348 case ProcessWow64Information
:
1350 Status
= STATUS_INVALID_INFO_CLASS
;
1352 case ProcessDesktop
:
1353 Process
->Win32Desktop
= *(PHANDLE
)ProcessInformation
;
1354 Status
= STATUS_SUCCESS
;
1357 ObDereferenceObject(Process
);
1362 /**********************************************************************
1364 * PiQuerySystemProcessInformation
1367 * Compute the size of a process+thread snapshot as
1368 * expected by NtQuerySystemInformation.
1371 * 0 on error; otherwise the size, in bytes of the buffer
1372 * required to write a full snapshot.
1375 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
1378 PiQuerySystemProcessInformation(PVOID Buffer
,
1382 return STATUS_NOT_IMPLEMENTED
;
1386 PLIST_ENTRY CurrentEntryP
;
1388 PLIST_ENTRY CurrentEntryT
;
1391 ULONG RequiredSize
= 0L;
1392 BOOLEAN SizeOnly
= FALSE
;
1396 PSYSTEM_PROCESS_INFORMATION pInfoP
= (PSYSTEM_PROCESS_INFORMATION
) SnapshotBuffer
;
1397 PSYSTEM_PROCESS_INFORMATION pInfoPLast
= NULL
;
1398 PSYSTEM_THREAD_INFO pInfoT
= NULL
;
1401 /* Lock the process list. */
1402 KeAcquireSpinLock(&PsProcessListLock
,
1406 * Scan the process list. Since the
1407 * list is circular, the guard is false
1408 * after the last process.
1410 for ( CurrentEntryP
= PsProcessListHead
.Flink
;
1411 (CurrentEntryP
!= & PsProcessListHead
);
1412 CurrentEntryP
= CurrentEntryP
->Flink
1416 * Compute how much space is
1417 * occupied in the snapshot
1418 * by adding this process info.
1419 * (at least one thread).
1421 SpiSizeCurrent
= sizeof (SYSTEM_PROCESS_INFORMATION
);
1422 RequiredSize
+= SpiSizeCurrent
;
1424 * Do not write process data in the
1425 * buffer if it is too small.
1427 if (TRUE
== SizeOnly
) continue;
1429 * Check if the buffer can contain
1430 * the full snapshot.
1432 if (Size
< RequiredSize
)
1438 * Get a reference to the
1439 * process descriptor we are
1442 CurrentP
= CONTAINING_RECORD(
1448 * Write process data in the buffer.
1450 RtlZeroMemory (pInfoP
, sizeof (SYSTEM_PROCESS_INFORMATION
));
1452 pInfoP
->ThreadCount
= 0L;
1453 pInfoP
->ProcessId
= CurrentP
->UniqueProcessId
;
1454 RtlInitUnicodeString (
1456 CurrentP
->ImageFileName
1459 for ( pInfoT
= & CurrentP
->ThreadSysInfo
[0],
1460 CurrentEntryT
= CurrentP
->ThreadListHead
.Flink
;
1462 (CurrentEntryT
!= & CurrentP
->ThreadListHead
);
1464 pInfoT
= & CurrentP
->ThreadSysInfo
[pInfoP
->ThreadCount
],
1465 CurrentEntryT
= CurrentEntryT
->Flink
1469 * Recalculate the size of the
1470 * information block.
1472 if (0 < pInfoP
->ThreadCount
)
1474 RequiredSize
+= sizeof (SYSTEM_THREAD_INFORMATION
);
1477 * Do not write thread data in the
1478 * buffer if it is too small.
1480 if (TRUE
== SizeOnly
) continue;
1482 * Check if the buffer can contain
1483 * the full snapshot.
1485 if (Size
< RequiredSize
)
1491 * Get a reference to the
1492 * thread descriptor we are
1495 CurrentT
= CONTAINING_RECORD(
1501 * Write thread data.
1505 sizeof (SYSTEM_THREAD_INFORMATION
)
1507 pInfoT
->KernelTime
= CurrentT
-> ; /* TIME */
1508 pInfoT
->UserTime
= CurrentT
-> ; /* TIME */
1509 pInfoT
->CreateTime
= CurrentT
-> ; /* TIME */
1510 pInfoT
->TickCount
= CurrentT
-> ; /* ULONG */
1511 pInfoT
->StartEIP
= CurrentT
-> ; /* ULONG */
1512 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
1513 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
1514 pInfoT
->DynamicPriority
= CurrentT
-> ; /* ULONG */
1515 pInfoT
->BasePriority
= CurrentT
-> ; /* ULONG */
1516 pInfoT
->nSwitches
= CurrentT
-> ; /* ULONG */
1517 pInfoT
->State
= CurrentT
-> ; /* DWORD */
1518 pInfoT
->WaitReason
= CurrentT
-> ; /* KWAIT_REASON */
1520 * Count the number of threads
1523 ++ pInfoP
->ThreadCount
;
1526 * Save the size of information
1527 * stored in the buffer for the
1530 pInfoP
->RelativeOffset
= SpiSize
;
1532 * Save a reference to the last
1533 * valid information block.
1535 pInfoPLast
= pInfoP
;
1537 * Compute the offset of the
1538 * SYSTEM_PROCESS_INFORMATION
1539 * descriptor in the snapshot
1540 * buffer for the next process.
1542 (ULONG
) pInfoP
+= SpiSize
;
1545 * Unlock the process list.
1548 & PsProcessListLock
,
1552 * Return the proper error status code,
1553 * if the buffer was too small.
1555 if (TRUE
== SizeOnly
)
1557 if (NULL
!= RequiredSize
)
1559 *pRequiredSize
= RequiredSize
;
1561 return STATUS_INFO_LENGTH_MISMATCH
;
1564 * Mark the end of the snapshot.
1566 pInfoP
->RelativeOffset
= 0L;
1568 return STATUS_SUCCESS
;
1575 LARGE_INTEGER STDCALL
1576 PsGetProcessExitTime(VOID
)
1579 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
1588 PsGetProcessCreateTimeQuadPart(
1592 return Process
->CreateTime
.QuadPart
;
1600 PsGetProcessDebugPort(
1604 return Process
->DebugPort
;
1612 PsGetProcessExitProcessCalled(
1616 return Process
->ExitProcessCalled
;
1624 PsGetProcessExitStatus(
1628 return Process
->ExitStatus
;
1640 return (HANDLE
)Process
->UniqueProcessId
;
1648 PsGetProcessImageFileName(
1652 return (LPSTR
)Process
->ImageFileName
;
1660 PsGetProcessInheritedFromUniqueProcessId(
1664 return Process
->InheritedFromUniqueProcessId
;
1689 return Process
->Peb
;
1697 PsGetProcessPriorityClass(
1701 return Process
->PriorityClass
;
1709 PsGetProcessSectionBaseAddress(
1713 return Process
->SectionBaseAddress
;
1721 PsGetProcessSecurityPort(
1725 return Process
->SecurityPort
;
1733 PsGetProcessSessionId(
1737 return (HANDLE
)Process
->SessionId
;
1745 PsGetProcessWin32Process(
1749 return Process
->Win32Process
;
1757 PsGetProcessWin32WindowStation(
1761 return Process
->Win32WindowStation
;
1769 PsIsProcessBeingDebugged(
1773 return FALSE
/*Process->IsProcessBeingDebugged*/;
1781 PsLookupProcessByProcessId(IN PVOID ProcessId
,
1782 OUT PEPROCESS
*Process
)
1785 PLIST_ENTRY current_entry
;
1788 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
1790 current_entry
= PsProcessListHead
.Flink
;
1791 while (current_entry
!= &PsProcessListHead
)
1793 current
= CONTAINING_RECORD(current_entry
,
1796 if (current
->UniqueProcessId
== (ULONG
)ProcessId
)
1799 ObReferenceObject(current
);
1800 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1801 return(STATUS_SUCCESS
);
1803 current_entry
= current_entry
->Flink
;
1806 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1808 return(STATUS_INVALID_PARAMETER
);
1813 PspRunCreateProcessNotifyRoutines
1815 PEPROCESS CurrentProcess
,
1820 HANDLE ProcessId
= (HANDLE
)CurrentProcess
->UniqueProcessId
;
1821 HANDLE ParentId
= CurrentProcess
->InheritedFromUniqueProcessId
;
1823 for(i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
1824 if(PiProcessNotifyRoutine
[i
])
1825 PiProcessNotifyRoutine
[i
](ParentId
, ProcessId
, Create
);
1832 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
1839 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
1841 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
1843 PiProcessNotifyRoutine
[i
] = NULL
;
1848 return(STATUS_SUCCESS
);
1852 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
1854 if (PiProcessNotifyRoutine
[i
] == NULL
)
1856 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
1861 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
1863 return STATUS_INSUFFICIENT_RESOURCES
;
1866 return STATUS_SUCCESS
;
1870 PspRunLoadImageNotifyRoutines(
1871 PUNICODE_STRING FullImageName
,
1873 PIMAGE_INFO ImageInfo
)
1877 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
1878 if (PiLoadImageNotifyRoutine
[i
])
1879 PiLoadImageNotifyRoutine
[i
](FullImageName
, ProcessId
, ImageInfo
);
1887 PsRemoveLoadImageNotifyRoutine(
1888 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
1892 return STATUS_NOT_IMPLEMENTED
;
1899 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
1903 for (i
= 0; i
< MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
; i
++)
1905 if (PiLoadImageNotifyRoutine
[i
] == NULL
)
1907 PiLoadImageNotifyRoutine
[i
] = NotifyRoutine
;
1912 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
1914 return STATUS_INSUFFICIENT_RESOURCES
;
1917 return STATUS_SUCCESS
;
1925 PsSetProcessPriorityClass(
1930 Process
->PriorityClass
= PriorityClass
;
1938 PsSetProcessSecurityPort(
1943 Process
->SecurityPort
= SecurityPort
;
1951 PsSetProcessWin32Process(
1956 Process
->Win32Process
= Win32Process
;
1964 PsSetProcessWin32WindowStation(
1969 Process
->Win32WindowStation
= WindowStation
;
1979 IN PEPROCESS Process
,
1980 IN POOL_TYPE PoolType
,
1986 /* Charge the usage */
1987 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
1989 /* Raise Exception */
1990 if (!NT_SUCCESS(Status
)) {
1991 ExRaiseStatus(Status
);
2000 PsChargeProcessNonPagedPoolQuota (
2001 IN PEPROCESS Process
,
2005 /* Call the general function */
2006 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
2014 PsChargeProcessPagedPoolQuota (
2015 IN PEPROCESS Process
,
2019 /* Call the general function */
2020 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
2028 PsChargeProcessPoolQuota(
2029 IN PEPROCESS Process
,
2030 IN POOL_TYPE PoolType
,
2034 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
2039 /* Get current Quota Block */
2040 QuotaBlock
= Process
->QuotaBlock
;
2042 /* Quota Operations are not to be done on the SYSTEM Process */
2043 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
2045 /* Acquire Spinlock */
2046 KeAcquireSpinLock(&QuotaBlock
->QuotaLock
, &OldValue
);
2048 /* New Size in use */
2049 NewUsageSize
= QuotaBlock
->QuotaPoolUsage
[PoolType
] + Amount
;
2051 /* Does this size respect the quota? */
2052 if (NewUsageSize
> QuotaBlock
->QuotaPoolLimit
[PoolType
]) {
2054 /* It doesn't, so keep raising the Quota */
2055 while (MiRaisePoolQuota(PoolType
, QuotaBlock
->QuotaPoolLimit
[PoolType
], &NewMaxQuota
)) {
2056 /* Save new Maximum Quota */
2057 QuotaBlock
->QuotaPoolLimit
[PoolType
] = NewMaxQuota
;
2059 /* See if the new Maximum Quota fulfills our need */
2060 if (NewUsageSize
<= NewMaxQuota
) goto QuotaChanged
;
2063 KeReleaseSpinLock(&QuotaBlock
->QuotaLock
, OldValue
);
2064 return STATUS_QUOTA_EXCEEDED
;
2068 /* Save new Usage */
2069 QuotaBlock
->QuotaPoolUsage
[PoolType
] = NewUsageSize
;
2071 /* Is this a new peak? */
2072 if (NewUsageSize
> QuotaBlock
->QuotaPeakPoolUsage
[PoolType
]) {
2073 QuotaBlock
->QuotaPeakPoolUsage
[PoolType
] = NewUsageSize
;
2076 /* Release spinlock */
2077 KeReleaseSpinLock(&QuotaBlock
->QuotaLock
, OldValue
);
2080 return STATUS_SUCCESS
;
2089 IN PEPROCESS Process
,
2090 IN POOL_TYPE PoolType
,
2102 PsReturnProcessNonPagedPoolQuota(
2103 IN PEPROCESS Process
,
2115 PsReturnProcessPagedPoolQuota(
2116 IN PEPROCESS Process
,