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 VOID INIT_FUNCTION
PsInitClientIDManagment(VOID
);
21 PEPROCESS EXPORTED PsInitialSystemProcess
= NULL
;
22 PEPROCESS PsIdleProcess
= NULL
;
24 POBJECT_TYPE EXPORTED PsProcessType
= NULL
;
26 LIST_ENTRY PsActiveProcessHead
;
27 FAST_MUTEX PspActiveProcessMutex
;
28 static LARGE_INTEGER ShortPsLockDelay
, PsLockTimeout
;
30 static GENERIC_MAPPING PiProcessMapping
= {STANDARD_RIGHTS_READ
| PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
31 STANDARD_RIGHTS_WRITE
| PROCESS_CREATE_PROCESS
| PROCESS_CREATE_THREAD
|
32 PROCESS_VM_OPERATION
| PROCESS_VM_WRITE
| PROCESS_DUP_HANDLE
|
33 PROCESS_TERMINATE
| PROCESS_SET_QUOTA
| PROCESS_SET_INFORMATION
| PROCESS_SET_PORT
,
34 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
37 static const INFORMATION_CLASS_INFO PsProcessInfoClass
[] =
39 ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessBasicInformation */
40 ICI_SQ_SAME( sizeof(QUOTA_LIMITS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessQuotaLimits */
41 ICI_SQ_SAME( sizeof(IO_COUNTERS
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessIoCounters */
42 ICI_SQ_SAME( sizeof(VM_COUNTERS
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessVmCounters */
43 ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessTimes */
44 ICI_SQ_SAME( sizeof(KPRIORITY
), sizeof(ULONG
), ICIF_SET
), /* ProcessBasePriority */
45 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_SET
), /* ProcessRaisePriority */
46 ICI_SQ_SAME( sizeof(HANDLE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessDebugPort */
47 ICI_SQ_SAME( sizeof(HANDLE
), sizeof(ULONG
), ICIF_SET
), /* ProcessExceptionPort */
48 ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN
), sizeof(ULONG
), ICIF_SET
), /* ProcessAccessToken */
49 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessLdtInformation */
50 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_SET
), /* ProcessLdtSize */
51 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessDefaultHardErrorMode */
52 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_SET
), /* ProcessIoPortHandlers */
53 ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessPooledUsageAndLimits */
54 ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessWorkingSetWatch */
55 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_SET
), /* ProcessUserModeIOPL */
56 ICI_SQ_SAME( sizeof(BOOLEAN
), sizeof(ULONG
), ICIF_SET
), /* ProcessEnableAlignmentFaultFixup */
57 ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS
), sizeof(USHORT
), ICIF_QUERY
| ICIF_SET
), /* ProcessPriorityClass */
58 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessWx86Information */
59 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessHandleCount */
60 ICI_SQ_SAME( sizeof(KAFFINITY
), sizeof(ULONG
), ICIF_SET
), /* ProcessAffinityMask */
61 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessPriorityBoost */
63 ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION
)0x0)->Query
), /* ProcessDeviceMap */
64 /*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION
)0x0)->Set
),
67 ICIF_QUERY
| ICIF_SET
),
69 ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessSessionInformation */
70 ICI_SQ_SAME( sizeof(BOOLEAN
), sizeof(ULONG
), ICIF_SET
), /* ProcessForegroundInformation */
71 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessWow64Information */
72 ICI_SQ_SAME( sizeof(UNICODE_STRING
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SIZE_VARIABLE
), /* ProcessImageFileName */
75 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessLUIDDeviceMapsEnabled */
76 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessBreakOnTermination */
77 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessDebugObjectHandle */
78 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessDebugFlags */
79 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessHandleTracing */
80 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessUnknown33 */
81 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessUnknown34 */
82 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessUnknown35 */
84 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessCookie */
87 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
88 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
90 static PCREATE_PROCESS_NOTIFY_ROUTINE
91 PiProcessNotifyRoutine
[MAX_PROCESS_NOTIFY_ROUTINE_COUNT
];
92 static PLOAD_IMAGE_NOTIFY_ROUTINE
93 PiLoadImageNotifyRoutine
[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
];
98 WORK_QUEUE_ITEM WorkQueueItem
;
101 BOOLEAN IsWorkerQueue
;
102 } DEL_CONTEXT
, *PDEL_CONTEXT
;
104 /* FUNCTIONS *****************************************************************/
108 PsExitSpecialApc(PKAPC Apc
,
109 PKNORMAL_ROUTINE
*NormalRoutine
,
110 PVOID
*NormalContext
,
111 PVOID
*SystemArgument1
,
112 PVOID
*SystemArgument2
)
117 PsGetNextProcess(PEPROCESS OldProcess
)
119 PEPROCESS NextProcess
;
122 if (OldProcess
== NULL
)
124 Status
= ObReferenceObjectByPointer(PsIdleProcess
,
128 if (!NT_SUCCESS(Status
))
130 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsIdleProcess\n");
133 return PsIdleProcess
;
136 ExAcquireFastMutex(&PspActiveProcessMutex
);
137 NextProcess
= OldProcess
;
140 PLIST_ENTRY Flink
= (NextProcess
== PsIdleProcess
? PsActiveProcessHead
.Flink
:
141 NextProcess
->ProcessListEntry
.Flink
);
142 if (Flink
!= &PsActiveProcessHead
)
144 NextProcess
= CONTAINING_RECORD(Flink
,
154 Status
= ObReferenceObjectByPointer(NextProcess
,
158 if (NT_SUCCESS(Status
))
162 else if (Status
== STATUS_PROCESS_IS_TERMINATING
)
166 else if (!NT_SUCCESS(Status
))
172 ExReleaseFastMutex(&PspActiveProcessMutex
);
173 ObDereferenceObject(OldProcess
);
183 NtOpenProcessToken(IN HANDLE ProcessHandle
,
184 IN ACCESS_MASK DesiredAccess
,
185 OUT PHANDLE TokenHandle
)
187 return NtOpenProcessTokenEx(ProcessHandle
,
199 NtOpenProcessTokenEx(
200 IN HANDLE ProcessHandle
,
201 IN ACCESS_MASK DesiredAccess
,
202 IN ULONG HandleAttributes
,
203 OUT PHANDLE TokenHandle
208 KPROCESSOR_MODE PreviousMode
;
209 NTSTATUS Status
= STATUS_SUCCESS
;
213 PreviousMode
= ExGetPreviousMode();
215 if(PreviousMode
== UserMode
)
219 ProbeForWrite(TokenHandle
,
225 Status
= _SEH_GetExceptionCode();
229 if(!NT_SUCCESS(Status
))
235 Status
= PsOpenTokenOfProcess(ProcessHandle
,
237 if(NT_SUCCESS(Status
))
239 Status
= ObCreateHandle(PsGetCurrentProcess(),
244 ObDereferenceObject(Token
);
248 *TokenHandle
= hToken
;
252 Status
= _SEH_GetExceptionCode();
264 PACCESS_TOKEN STDCALL
265 PsReferencePrimaryToken(PEPROCESS Process
)
267 ObReferenceObjectByPointer(Process
->Token
,
271 return(Process
->Token
);
276 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
277 PACCESS_TOKEN
* Token
)
282 Status
= ObReferenceObjectByHandle(ProcessHandle
,
283 PROCESS_QUERY_INFORMATION
,
288 if(NT_SUCCESS(Status
))
290 *Token
= PsReferencePrimaryToken(Process
);
291 ObDereferenceObject(Process
);
299 PiKillMostProcesses(VOID
)
301 PLIST_ENTRY current_entry
;
304 ExAcquireFastMutex(&PspActiveProcessMutex
);
306 current_entry
= PsActiveProcessHead
.Flink
;
307 while (current_entry
!= &PsActiveProcessHead
)
309 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
311 current_entry
= current_entry
->Flink
;
313 if (current
->UniqueProcessId
!= PsInitialSystemProcess
->UniqueProcessId
&&
314 current
->UniqueProcessId
!= PsGetCurrentProcessId())
316 PiTerminateProcessThreads(current
, STATUS_SUCCESS
);
320 ExReleaseFastMutex(&PspActiveProcessMutex
);
325 PsInitProcessManagment(VOID
)
330 ShortPsLockDelay
.QuadPart
= -100LL;
331 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
333 * Register the process object type
336 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
338 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
339 PsProcessType
->TotalObjects
= 0;
340 PsProcessType
->TotalHandles
= 0;
341 PsProcessType
->PeakObjects
= 0;
342 PsProcessType
->PeakHandles
= 0;
343 PsProcessType
->PagedPoolCharge
= 0;
344 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
345 PsProcessType
->Mapping
= &PiProcessMapping
;
346 PsProcessType
->Dump
= NULL
;
347 PsProcessType
->Open
= NULL
;
348 PsProcessType
->Close
= NULL
;
349 PsProcessType
->Delete
= PiDeleteProcess
;
350 PsProcessType
->Parse
= NULL
;
351 PsProcessType
->Security
= NULL
;
352 PsProcessType
->QueryName
= NULL
;
353 PsProcessType
->OkayToClose
= NULL
;
354 PsProcessType
->Create
= NULL
;
355 PsProcessType
->DuplicationNotify
= NULL
;
357 RtlInitUnicodeString(&PsProcessType
->TypeName
, L
"Process");
359 ObpCreateTypeObject(PsProcessType
);
361 InitializeListHead(&PsActiveProcessHead
);
362 ExInitializeFastMutex(&PspActiveProcessMutex
);
364 RtlZeroMemory(PiProcessNotifyRoutine
, sizeof(PiProcessNotifyRoutine
));
365 RtlZeroMemory(PiLoadImageNotifyRoutine
, sizeof(PiLoadImageNotifyRoutine
));
368 * Initialize the idle process
370 Status
= ObCreateObject(KernelMode
,
378 (PVOID
*)&PsIdleProcess
);
379 if (!NT_SUCCESS(Status
))
381 DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status
);
386 RtlZeroMemory(PsIdleProcess
, sizeof(EPROCESS
));
388 PsIdleProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
389 PsIdleProcess
->Pcb
.IopmOffset
= 0xffff;
390 PsIdleProcess
->Pcb
.LdtDescriptor
[0] = 0;
391 PsIdleProcess
->Pcb
.LdtDescriptor
[1] = 0;
392 PsIdleProcess
->Pcb
.BasePriority
= PROCESS_PRIO_IDLE
;
393 PsIdleProcess
->Pcb
.ThreadQuantum
= 6;
394 InitializeListHead(&PsIdleProcess
->Pcb
.ThreadListHead
);
395 InitializeListHead(&PsIdleProcess
->ThreadListHead
);
396 InitializeListHead(&PsIdleProcess
->ProcessListEntry
);
397 KeInitializeDispatcherHeader(&PsIdleProcess
->Pcb
.DispatcherHeader
,
401 PsIdleProcess
->Pcb
.DirectoryTableBase
=
402 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
403 strcpy(PsInitialSystemProcess
->ImageFileName
, "Idle");
406 * Initialize the system process
408 Status
= ObCreateObject(KernelMode
,
416 (PVOID
*)&PsInitialSystemProcess
);
417 if (!NT_SUCCESS(Status
))
419 DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status
);
424 /* System threads may run on any processor. */
425 PsInitialSystemProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
426 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
427 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[0] = 0;
428 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[1] = 0;
429 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
430 PsInitialSystemProcess
->Pcb
.ThreadQuantum
= 6;
431 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
432 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
436 KProcess
= &PsInitialSystemProcess
->Pcb
;
438 MmInitializeAddressSpace(PsInitialSystemProcess
,
439 &PsInitialSystemProcess
->AddressSpace
);
441 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
442 PsInitialSystemProcess
->LockCount
= 0;
443 PsInitialSystemProcess
->LockOwner
= NULL
;
445 #if defined(__GNUC__)
446 KProcess
->DirectoryTableBase
=
447 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
451 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
452 KProcess
->DirectoryTableBase
= dummy
;
456 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
458 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
460 InsertHeadList(&PsActiveProcessHead
,
461 &PsInitialSystemProcess
->ProcessListEntry
);
462 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
464 SepCreateSystemProcessToken(PsInitialSystemProcess
);
468 PspPostInitSystemProcess(VOID
)
472 /* this routine is called directly after the exectuive handle tables were
473 initialized. We'll set up the Client ID handle table and assign the system
475 PsInitClientIDManagment();
477 ObCreateHandleTable(NULL
, FALSE
, PsInitialSystemProcess
);
479 Status
= PsCreateCidHandle(PsInitialSystemProcess
,
481 &PsInitialSystemProcess
->UniqueProcessId
);
482 if(!NT_SUCCESS(Status
))
484 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
490 PiDeleteProcessWorker(PVOID pContext
)
492 PDEL_CONTEXT Context
;
493 PEPROCESS CurrentProcess
;
496 Context
= (PDEL_CONTEXT
)pContext
;
497 Process
= Context
->Process
;
498 CurrentProcess
= PsGetCurrentProcess();
500 DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process
);
502 if (CurrentProcess
!= Process
)
504 KeAttachProcess(&Process
->Pcb
);
507 ExAcquireFastMutex(&PspActiveProcessMutex
);
508 RemoveEntryList(&Process
->ProcessListEntry
);
509 ExReleaseFastMutex(&PspActiveProcessMutex
);
512 KDB_DELETEPROCESS_HOOK(Process
);
514 ObDereferenceObject(Process
->Token
);
516 if (CurrentProcess
!= Process
)
521 MmReleaseMmInfo(Process
);
522 if (Context
->IsWorkerQueue
)
524 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
529 PiDeleteProcess(PVOID ObjectBody
)
533 Context
.Process
= (PEPROCESS
)ObjectBody
;
535 if (PsGetCurrentProcess() == Context
.Process
||
536 PsGetCurrentThread()->ThreadsProcess
== Context
.Process
)
541 if (PsGetCurrentThread()->ThreadsProcess
== PsGetCurrentProcess())
543 Context
.IsWorkerQueue
= FALSE
;
544 PiDeleteProcessWorker(&Context
);
548 Context
.IsWorkerQueue
= TRUE
;
549 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
550 ExInitializeWorkItem (&Context
.WorkQueueItem
, PiDeleteProcessWorker
, &Context
);
551 ExQueueWorkItem(&Context
.WorkQueueItem
, HyperCriticalWorkQueue
);
552 if (KeReadStateEvent(&Context
.Event
) == 0)
554 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
558 if(((PEPROCESS
)ObjectBody
)->Win32Process
!= NULL
)
560 /* delete the W32PROCESS structure if there's one associated */
561 ExFreePool (((PEPROCESS
)ObjectBody
)->Win32Process
);
566 PsCreatePeb(HANDLE ProcessHandle
,
573 LARGE_INTEGER SectionOffset
;
580 /* Allocate the Process Environment Block (PEB) */
581 Process
->TebBlock
= (PVOID
) MM_ROUND_DOWN(PEB_BASE
, MM_VIRTMEM_GRANULARITY
);
582 AllocSize
= MM_VIRTMEM_GRANULARITY
;
583 Status
= NtAllocateVirtualMemory(ProcessHandle
,
589 if (!NT_SUCCESS(Status
))
591 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
594 ASSERT((ULONG_PTR
) Process
->TebBlock
<= PEB_BASE
&&
595 PEB_BASE
+ PAGE_SIZE
<= (ULONG_PTR
) Process
->TebBlock
+ AllocSize
);
596 Peb
= (PPEB
)PEB_BASE
;
598 Status
= NtAllocateVirtualMemory(ProcessHandle
,
604 if (!NT_SUCCESS(Status
))
606 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
609 DPRINT("Peb %p PebSize %lu\n", Peb
, PebSize
);
610 ASSERT((PPEB
) PEB_BASE
== Peb
&& PAGE_SIZE
<= PebSize
);
611 Process
->TebLastAllocated
= (PVOID
) Peb
;
614 SectionOffset
.QuadPart
= (ULONGLONG
)0;
616 Status
= MmMapViewOfSection(NlsSectionObject
,
626 if (!NT_SUCCESS(Status
))
628 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
631 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
633 KeAttachProcess(&Process
->Pcb
);
635 /* Initialize the PEB */
636 RtlZeroMemory(Peb
, sizeof(PEB
));
637 Peb
->ImageBaseAddress
= ImageBase
;
639 Peb
->OSMajorVersion
= 4;
640 Peb
->OSMinorVersion
= 0;
641 Peb
->OSBuildNumber
= 1381;
642 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
643 Peb
->OSCSDVersion
= 6 << 8;
645 Peb
->AnsiCodePageData
= (char*)TableBase
+ NlsAnsiTableOffset
;
646 Peb
->OemCodePageData
= (char*)TableBase
+ NlsOemTableOffset
;
647 Peb
->UnicodeCaseTableData
= (char*)TableBase
+ NlsUnicodeTableOffset
;
652 DPRINT("PsCreatePeb: Peb created at %p\n", Peb
);
654 return(STATUS_SUCCESS
);
659 KeGetCurrentProcess(VOID
)
661 * FUNCTION: Returns a pointer to the current process
664 return(&(PsGetCurrentProcess()->Pcb
));
668 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
669 * ULONG ProcessId! (Skywing)
675 PsGetCurrentProcessId(VOID
)
677 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
685 PsGetCurrentProcessSessionId (
689 return PsGetCurrentProcess()->SessionId
;
693 * FUNCTION: Returns a pointer to the current process
698 IoGetCurrentProcess(VOID
)
700 if (PsGetCurrentThread() == NULL
||
701 PsGetCurrentThread()->Tcb
.ApcState
.Process
== NULL
)
703 return(PsInitialSystemProcess
);
707 return(PEPROCESS
)(PsGetCurrentThread()->Tcb
.ApcState
.Process
);
712 PspCreateProcess(OUT PHANDLE ProcessHandle
,
713 IN ACCESS_MASK DesiredAccess
,
714 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
715 IN HANDLE ParentProcess OPTIONAL
,
716 IN BOOLEAN InheritObjectTable
,
717 IN HANDLE SectionHandle OPTIONAL
,
718 IN HANDLE DebugPort OPTIONAL
,
719 IN HANDLE ExceptionPort OPTIONAL
)
723 PEPROCESS pParentProcess
;
725 PVOID LdrStartupAddr
;
727 PMEMORY_AREA MemoryArea
;
728 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
729 KPROCESSOR_MODE PreviousMode
;
730 PVOID ImageBase
= NULL
;
731 PEPORT pDebugPort
= NULL
;
732 PEPORT pExceptionPort
= NULL
;
733 PSECTION_OBJECT SectionObject
= NULL
;
734 NTSTATUS Status
= STATUS_SUCCESS
;
736 DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes
);
738 PreviousMode
= ExGetPreviousMode();
740 BoundaryAddressMultiple
.QuadPart
= 0;
742 if(ParentProcess
!= NULL
)
744 Status
= ObReferenceObjectByHandle(ParentProcess
,
745 PROCESS_CREATE_PROCESS
,
748 (PVOID
*)&pParentProcess
,
750 if (!NT_SUCCESS(Status
))
752 DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status
);
758 pParentProcess
= NULL
;
764 if (DebugPort
!= NULL
)
766 Status
= ObReferenceObjectByHandle(DebugPort
,
772 if (!NT_SUCCESS(Status
))
774 DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status
);
775 goto exitdereferenceobjects
;
780 * Add the exception port
782 if (ExceptionPort
!= NULL
)
784 Status
= ObReferenceObjectByHandle(ExceptionPort
,
788 (PVOID
*)&pExceptionPort
,
790 if (!NT_SUCCESS(Status
))
792 DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status
);
793 goto exitdereferenceobjects
;
797 if (SectionHandle
!= NULL
)
799 Status
= ObReferenceObjectByHandle(SectionHandle
,
803 (PVOID
*)&SectionObject
,
805 if (!NT_SUCCESS(Status
))
807 DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status
);
808 goto exitdereferenceobjects
;
812 Status
= ObCreateObject(PreviousMode
,
821 if (!NT_SUCCESS(Status
))
823 DPRINT1("Failed to create process object, Status: 0x%x\n", Status
);
825 exitdereferenceobjects
:
826 if(SectionObject
!= NULL
)
827 ObDereferenceObject(SectionObject
);
828 if(pExceptionPort
!= NULL
)
829 ObDereferenceObject(pExceptionPort
);
830 if(pDebugPort
!= NULL
)
831 ObDereferenceObject(pDebugPort
);
832 if(pParentProcess
!= NULL
)
833 ObDereferenceObject(pParentProcess
);
837 KProcess
= &Process
->Pcb
;
839 RtlZeroMemory(Process
, sizeof(EPROCESS
));
841 Status
= PsCreateCidHandle(Process
,
843 &Process
->UniqueProcessId
);
844 if(!NT_SUCCESS(Status
))
846 DPRINT1("Failed to create CID handle (unique process ID)! Status: 0x%x\n", Status
);
847 ObDereferenceObject(Process
);
848 goto exitdereferenceobjects
;
851 Process
->DebugPort
= pDebugPort
;
852 Process
->ExceptionPort
= pExceptionPort
;
854 if(SectionObject
!= NULL
)
856 UNICODE_STRING FileName
;
862 * Determine the image file name and save it to the EPROCESS structure
865 FileName
= SectionObject
->FileObject
->FileName
;
866 szSrc
= (PWCHAR
)(FileName
.Buffer
+ (FileName
.Length
/ sizeof(WCHAR
)) - 1);
867 while(szSrc
>= FileName
.Buffer
)
881 /* copy the image file name to the process and truncate it to 15 characters
883 szDest
= Process
->ImageFileName
;
884 lnFName
= min(lnFName
, sizeof(Process
->ImageFileName
) - 1);
887 *(szDest
++) = (UCHAR
)*(szSrc
++);
889 /* *szDest = '\0'; */
892 KeInitializeDispatcherHeader(&KProcess
->DispatcherHeader
,
897 /* Inherit parent process's affinity. */
898 if(pParentProcess
!= NULL
)
900 KProcess
->Affinity
= pParentProcess
->Pcb
.Affinity
;
901 Process
->InheritedFromUniqueProcessId
= pParentProcess
->UniqueProcessId
;
902 Process
->SessionId
= pParentProcess
->SessionId
;
906 KProcess
->Affinity
= KeActiveProcessors
;
909 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
910 KProcess
->IopmOffset
= 0xffff;
911 KProcess
->LdtDescriptor
[0] = 0;
912 KProcess
->LdtDescriptor
[1] = 0;
913 InitializeListHead(&KProcess
->ThreadListHead
);
914 KProcess
->ThreadQuantum
= 6;
915 KProcess
->AutoAlignment
= 0;
916 MmInitializeAddressSpace(Process
,
917 &Process
->AddressSpace
);
919 ObCreateHandleTable(pParentProcess
,
922 MmCopyMmInfo(pParentProcess
? pParentProcess
: PsInitialSystemProcess
, Process
);
924 KeInitializeEvent(&Process
->LockEvent
, SynchronizationEvent
, FALSE
);
925 Process
->LockCount
= 0;
926 Process
->LockOwner
= NULL
;
928 Process
->Win32WindowStation
= (HANDLE
)0;
930 ExAcquireFastMutex(&PspActiveProcessMutex
);
931 InsertTailList(&PsActiveProcessHead
, &Process
->ProcessListEntry
);
932 InitializeListHead(&Process
->ThreadListHead
);
933 ExReleaseFastMutex(&PspActiveProcessMutex
);
935 ExInitializeFastMutex(&Process
->TebLock
);
936 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
939 * Now we have created the process proper
942 MmLockAddressSpace(&Process
->AddressSpace
);
944 /* Protect the highest 64KB of the process address space */
945 BaseAddress
= (PVOID
)MmUserProbeAddress
;
946 Status
= MmCreateMemoryArea(Process
,
947 &Process
->AddressSpace
,
948 MEMORY_AREA_NO_ACCESS
,
955 BoundaryAddressMultiple
);
956 if (!NT_SUCCESS(Status
))
958 MmUnlockAddressSpace(&Process
->AddressSpace
);
959 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
960 ObDereferenceObject(Process
);
961 goto exitdereferenceobjects
;
964 /* Protect the lowest 64KB of the process address space */
966 BaseAddress
= (PVOID
)0x00000000;
967 Status
= MmCreateMemoryArea(Process
,
968 &Process
->AddressSpace
,
969 MEMORY_AREA_NO_ACCESS
,
976 BoundaryAddressMultiple
);
977 if (!NT_SUCCESS(Status
))
979 MmUnlockAddressSpace(&Process
->AddressSpace
);
980 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
981 ObDereferenceObject(Process
);
982 goto exitdereferenceobjects
;
986 /* Protect the 60KB above the shared user page */
987 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
988 Status
= MmCreateMemoryArea(Process
,
989 &Process
->AddressSpace
,
990 MEMORY_AREA_NO_ACCESS
,
997 BoundaryAddressMultiple
);
998 if (!NT_SUCCESS(Status
))
1000 MmUnlockAddressSpace(&Process
->AddressSpace
);
1001 DPRINT1("Failed to protect the memory above the shared user page\n");
1002 ObDereferenceObject(Process
);
1003 goto exitdereferenceobjects
;
1006 /* Create the shared data page */
1007 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
1008 Status
= MmCreateMemoryArea(Process
,
1009 &Process
->AddressSpace
,
1010 MEMORY_AREA_SHARED_DATA
,
1017 BoundaryAddressMultiple
);
1018 MmUnlockAddressSpace(&Process
->AddressSpace
);
1019 if (!NT_SUCCESS(Status
))
1021 DPRINT1("Failed to create shared data page\n");
1022 ObDereferenceObject(Process
);
1023 goto exitdereferenceobjects
;
1028 * FIXME - the handle should be created after all things are initialized, NOT HERE!
1030 Status
= ObInsertObject ((PVOID
)Process
,
1036 if (!NT_SUCCESS(Status
))
1038 DPRINT1("Failed to create a handle for the process\n");
1039 ObDereferenceObject(Process
);
1040 goto exitdereferenceobjects
;
1047 Status
= LdrpMapSystemDll(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
1049 if (!NT_SUCCESS(Status
))
1051 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
1052 ObDereferenceObject(Process
);
1053 goto exitdereferenceobjects
;
1057 * Map the process image
1059 if (SectionObject
!= NULL
)
1062 DPRINT("Mapping process image\n");
1063 Status
= MmMapViewOfSection(SectionObject
,
1073 ObDereferenceObject(SectionObject
);
1074 if (!NT_SUCCESS(Status
))
1076 DbgPrint("Failed to map the process section (Status %x)\n", Status
);
1077 ObDereferenceObject(Process
);
1078 goto exitdereferenceobjects
;
1082 if(pParentProcess
!= NULL
)
1085 * Duplicate the token
1087 Status
= SepInitializeNewProcess(Process
, pParentProcess
);
1088 if (!NT_SUCCESS(Status
))
1090 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
1091 ObDereferenceObject(Process
);
1092 goto exitdereferenceobjects
;
1101 * FIXME - Create PEB
1103 DPRINT("Creating PEB\n");
1104 Status
= PsCreatePeb(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
1107 if (!NT_SUCCESS(Status
))
1109 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
1110 ObDereferenceObject(Process
);
1111 goto exitdereferenceobjects
;
1115 * Maybe send a message to the creator process's debugger
1118 if (pParentProcess
->DebugPort
!= NULL
)
1120 LPC_DBG_MESSAGE Message
;
1123 ObCreateHandle(NULL
, // Debugger Process
1124 NULL
, // SectionHandle
1129 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
1130 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
1131 sizeof(LPC_MESSAGE
);
1132 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
1133 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
1134 Message
.Data
.CreateProcess
.Base
= ImageBase
;
1135 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
1137 Status
= LpcSendDebugMessagePort(pParentProcess
->DebugPort
,
1142 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
1145 * FIXME - the handle should be created not before this point!
1148 Status
= ObInsertObject ((PVOID
)Process
,
1155 if (NT_SUCCESS(Status
))
1159 *ProcessHandle
= hProcess
;
1163 Status
= _SEH_GetExceptionCode();
1169 * don't dereference the debug port, exception port and section object even
1170 * if ObInsertObject() failed, the process is alive! We just couldn't return
1171 * the handle to the caller!
1174 ObDereferenceObject(Process
);
1175 if(pParentProcess
!= NULL
)
1176 ObDereferenceObject(pParentProcess
);
1186 PsCreateSystemProcess(PHANDLE ProcessHandle
,
1187 ACCESS_MASK DesiredAccess
,
1188 POBJECT_ATTRIBUTES ObjectAttributes
)
1190 return PspCreateProcess(ProcessHandle
,
1193 NULL
, /* no parent process */
1205 NtCreateProcess(OUT PHANDLE ProcessHandle
,
1206 IN ACCESS_MASK DesiredAccess
,
1207 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1208 IN HANDLE ParentProcess
,
1209 IN BOOLEAN InheritObjectTable
,
1210 IN HANDLE SectionHandle OPTIONAL
,
1211 IN HANDLE DebugPort OPTIONAL
,
1212 IN HANDLE ExceptionPort OPTIONAL
)
1214 * FUNCTION: Creates a process.
1216 * ProcessHandle (OUT) = Caller supplied storage for the resulting
1218 * DesiredAccess = Specifies the allowed or desired access to the
1219 * process can be a combination of
1220 * STANDARD_RIGHTS_REQUIRED| ..
1221 * ObjectAttribute = Initialized attributes for the object, contains
1222 * the rootdirectory and the filename
1223 * ParentProcess = Handle to the parent process.
1224 * InheritObjectTable = Specifies to inherit the objects of the parent
1226 * SectionHandle = Handle to a section object to back the image file
1227 * DebugPort = Handle to a DebugPort if NULL the system default debug
1228 * port will be used.
1229 * ExceptionPort = Handle to a exception port.
1231 * This function maps to the win32 CreateProcess.
1235 KPROCESSOR_MODE PreviousMode
;
1236 NTSTATUS Status
= STATUS_SUCCESS
;
1240 PreviousMode
= ExGetPreviousMode();
1242 if(PreviousMode
!= KernelMode
)
1246 ProbeForWrite(ProcessHandle
,
1252 Status
= _SEH_GetExceptionCode();
1256 if(!NT_SUCCESS(Status
))
1262 if(ParentProcess
== NULL
)
1264 Status
= STATUS_INVALID_PARAMETER
;
1268 Status
= PspCreateProcess(ProcessHandle
,
1286 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1287 IN ACCESS_MASK DesiredAccess
,
1288 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1289 IN PCLIENT_ID ClientId
)
1291 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1292 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1293 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
1294 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
1299 * Not sure of the exact semantics
1301 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
1302 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
1307 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
1308 ObjectAttributes
->Attributes
,
1315 if (Status
!= STATUS_SUCCESS
)
1320 Status
= ObCreateHandle(PsGetCurrentProcess(),
1325 ObDereferenceObject(Process
);
1331 PLIST_ENTRY current_entry
;
1335 ExAcquireFastMutex(&PspActiveProcessMutex
);
1336 current_entry
= PsActiveProcessHead
.Flink
;
1337 while (current_entry
!= &PsActiveProcessHead
)
1339 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
1341 if (current
->UniqueProcessId
== ClientId
->UniqueProcess
)
1343 if (current
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
1345 Status
= STATUS_PROCESS_IS_TERMINATING
;
1349 Status
= ObReferenceObjectByPointer(current
,
1354 ExReleaseFastMutex(&PspActiveProcessMutex
);
1355 if (NT_SUCCESS(Status
))
1357 Status
= ObCreateHandle(PsGetCurrentProcess(),
1362 ObDereferenceObject(current
);
1363 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
1364 DPRINT("NtOpenProcess() = %x\n", Status
);
1368 current_entry
= current_entry
->Flink
;
1370 ExReleaseFastMutex(&PspActiveProcessMutex
);
1371 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1372 return(STATUS_UNSUCCESSFUL
);
1374 return(STATUS_UNSUCCESSFUL
);
1382 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
1383 IN PROCESSINFOCLASS ProcessInformationClass
,
1384 OUT PVOID ProcessInformation
,
1385 IN ULONG ProcessInformationLength
,
1386 OUT PULONG ReturnLength OPTIONAL
)
1389 KPROCESSOR_MODE PreviousMode
;
1390 NTSTATUS Status
= STATUS_SUCCESS
;
1394 PreviousMode
= ExGetPreviousMode();
1396 DefaultQueryInfoBufferCheck(ProcessInformationClass
,
1399 ProcessInformationLength
,
1403 if(!NT_SUCCESS(Status
))
1405 DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status
);
1409 if(ProcessInformationClass
!= ProcessCookie
)
1411 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1412 PROCESS_QUERY_INFORMATION
,
1417 if (!NT_SUCCESS(Status
))
1422 else if(ProcessHandle
!= NtCurrentProcess())
1424 /* retreiving the process cookie is only allowed for the calling process
1425 itself! XP only allowes NtCurrentProcess() as process handles even if a
1426 real handle actually represents the current process. */
1427 return STATUS_INVALID_PARAMETER
;
1430 switch (ProcessInformationClass
)
1432 case ProcessBasicInformation
:
1434 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
=
1435 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
1439 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
1440 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
1441 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
1442 ProcessBasicInformationP
->UniqueProcessId
=
1443 Process
->UniqueProcessId
;
1444 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
1445 Process
->InheritedFromUniqueProcessId
;
1446 ProcessBasicInformationP
->BasePriority
=
1447 Process
->Pcb
.BasePriority
;
1451 *ReturnLength
= sizeof(PROCESS_BASIC_INFORMATION
);
1456 Status
= _SEH_GetExceptionCode();
1462 case ProcessQuotaLimits
:
1463 case ProcessIoCounters
:
1464 Status
= STATUS_NOT_IMPLEMENTED
;
1469 PKERNEL_USER_TIMES ProcessTimeP
= (PKERNEL_USER_TIMES
)ProcessInformation
;
1472 ProcessTimeP
->CreateTime
= Process
->CreateTime
;
1473 ProcessTimeP
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
* 100000LL;
1474 ProcessTimeP
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
* 100000LL;
1475 ProcessTimeP
->ExitTime
= Process
->ExitTime
;
1479 *ReturnLength
= sizeof(KERNEL_USER_TIMES
);
1484 Status
= _SEH_GetExceptionCode();
1490 case ProcessDebugPort
:
1494 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
!= NULL
? (HANDLE
)-1 : NULL
);
1497 *ReturnLength
= sizeof(HANDLE
);
1502 Status
= _SEH_GetExceptionCode();
1508 case ProcessLdtInformation
:
1509 case ProcessWorkingSetWatch
:
1510 case ProcessWx86Information
:
1511 Status
= STATUS_NOT_IMPLEMENTED
;
1514 case ProcessHandleCount
:
1516 ULONG HandleCount
= ObpGetHandleCountByHandleTable(Process
->ObjectTable
);
1520 *(PULONG
)ProcessInformation
= HandleCount
;
1523 *ReturnLength
= sizeof(ULONG
);
1528 Status
= _SEH_GetExceptionCode();
1534 case ProcessSessionInformation
:
1536 PPROCESS_SESSION_INFORMATION SessionInfo
= (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1540 SessionInfo
->SessionId
= Process
->SessionId
;
1543 *ReturnLength
= sizeof(PROCESS_SESSION_INFORMATION
);
1548 Status
= _SEH_GetExceptionCode();
1554 case ProcessWow64Information
:
1555 DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
1556 Status
= STATUS_NOT_IMPLEMENTED
;
1559 case ProcessVmCounters
:
1561 PVM_COUNTERS pOut
= (PVM_COUNTERS
)ProcessInformation
;
1565 pOut
->PeakVirtualSize
= Process
->PeakVirtualSize
;
1567 * Here we should probably use VirtualSize.LowPart, but due to
1568 * incompatibilities in current headers (no unnamed union),
1571 pOut
->VirtualSize
= (ULONG
)Process
->VirtualSize
.QuadPart
;
1572 pOut
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
1573 pOut
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
1574 pOut
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
1575 pOut
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[0]; // TODO: Verify!
1576 pOut
->QuotaPagedPoolUsage
= Process
->QuotaPoolUsage
[0]; // TODO: Verify!
1577 pOut
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[1]; // TODO: Verify!
1578 pOut
->QuotaNonPagedPoolUsage
= Process
->QuotaPoolUsage
[1]; // TODO: Verify!
1579 pOut
->PagefileUsage
= Process
->PagefileUsage
;
1580 pOut
->PeakPagefileUsage
= Process
->PeakPagefileUsage
;
1584 *ReturnLength
= sizeof(VM_COUNTERS
);
1589 Status
= _SEH_GetExceptionCode();
1595 case ProcessDefaultHardErrorMode
:
1597 PULONG HardErrMode
= (PULONG
)ProcessInformation
;
1600 *HardErrMode
= Process
->DefaultHardErrorProcessing
;
1603 *ReturnLength
= sizeof(ULONG
);
1608 Status
= _SEH_GetExceptionCode();
1614 case ProcessPriorityBoost
:
1616 PULONG BoostEnabled
= (PULONG
)ProcessInformation
;
1620 *BoostEnabled
= Process
->Pcb
.DisableBoost
? FALSE
: TRUE
;
1624 *ReturnLength
= sizeof(ULONG
);
1629 Status
= _SEH_GetExceptionCode();
1635 case ProcessDeviceMap
:
1637 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
1639 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
1643 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
1646 *ReturnLength
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
1651 Status
= _SEH_GetExceptionCode();
1657 case ProcessPriorityClass
:
1659 PUSHORT Priority
= (PUSHORT
)ProcessInformation
;
1663 *Priority
= Process
->PriorityClass
;
1667 *ReturnLength
= sizeof(USHORT
);
1672 Status
= _SEH_GetExceptionCode();
1678 case ProcessImageFileName
:
1681 * We DO NOT return the file name stored in the EPROCESS structure.
1682 * Propably if we can't find a PEB or ProcessParameters structure for the
1685 if(Process
->Peb
!= NULL
)
1687 PRTL_USER_PROCESS_PARAMETERS ProcParams
= NULL
;
1688 UNICODE_STRING LocalDest
;
1690 ULONG ImagePathLen
= 0;
1691 PUNICODE_STRING DstPath
= (PUNICODE_STRING
)ProcessInformation
;
1693 /* we need to attach to the process to make sure we're in the right context! */
1694 Attached
= Process
!= PsGetCurrentProcess();
1697 KeAttachProcess(&Process
->Pcb
);
1701 ProcParams
= Process
->Peb
->ProcessParameters
;
1702 ImagePathLen
= ProcParams
->ImagePathName
.Length
;
1706 Status
= _SEH_GetExceptionCode();
1710 if(NT_SUCCESS(Status
))
1712 if(ProcessInformationLength
< sizeof(UNICODE_STRING
) + ImagePathLen
+ sizeof(WCHAR
))
1714 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1718 PWSTR StrSource
= NULL
;
1720 /* create a DstPath structure on the stack */
1723 LocalDest
.Length
= ImagePathLen
;
1724 LocalDest
.MaximumLength
= ImagePathLen
+ sizeof(WCHAR
);
1725 LocalDest
.Buffer
= (PWSTR
)(DstPath
+ 1);
1727 /* save a copy of the pointer to the source buffer */
1728 StrSource
= ProcParams
->ImagePathName
.Buffer
;
1732 Status
= _SEH_GetExceptionCode();
1736 if(NT_SUCCESS(Status
))
1738 /* now, let's allocate some anonymous memory to copy the string to.
1739 we can't just copy it to the buffer the caller pointed as it might
1740 be user memory in another context */
1741 PWSTR PathCopy
= ExAllocatePool(PagedPool
, LocalDest
.Length
+ sizeof(WCHAR
));
1742 if(PathCopy
!= NULL
)
1744 /* make a copy of the buffer to the temporary buffer */
1747 RtlCopyMemory(PathCopy
, StrSource
, LocalDest
.Length
);
1748 PathCopy
[LocalDest
.Length
/ sizeof(WCHAR
)] = L
'\0';
1752 Status
= _SEH_GetExceptionCode();
1756 /* detach from the process */
1760 /* only copy the string back to the caller if we were able to
1761 copy it into the temporary buffer! */
1762 if(NT_SUCCESS(Status
))
1764 /* now let's copy the buffer back to the caller */
1767 *DstPath
= LocalDest
;
1768 RtlCopyMemory(LocalDest
.Buffer
, PathCopy
, LocalDest
.Length
+ sizeof(WCHAR
));
1771 *ReturnLength
= sizeof(UNICODE_STRING
) + LocalDest
.Length
+ sizeof(WCHAR
);
1776 Status
= _SEH_GetExceptionCode();
1781 /* we're done with the copy operation, free the temporary kernel buffer */
1782 ExFreePool(PathCopy
);
1784 /* we need to bail because we're already detached from the process */
1789 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1795 /* don't forget to detach from the process!!! */
1801 /* FIXME - what to do here? */
1802 Status
= STATUS_UNSUCCESSFUL
;
1811 /* receive the process cookie, this is only allowed for the current
1814 Process
= PsGetCurrentProcess();
1816 Cookie
= Process
->Cookie
;
1819 LARGE_INTEGER SystemTime
;
1823 /* generate a new cookie */
1825 KeQuerySystemTime(&SystemTime
);
1827 Prcb
= KeGetCurrentPrcb();
1829 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
1830 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
1832 /* try to set the new cookie, return the current one if another thread
1833 set it in the meanwhile */
1834 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
1839 /* successfully set the cookie */
1846 *(PULONG
)ProcessInformation
= Cookie
;
1849 *ReturnLength
= sizeof(ULONG
);
1854 Status
= _SEH_GetExceptionCode();
1862 * Note: The following 10 information classes are verified to not be
1863 * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
1865 case ProcessBasePriority
:
1866 case ProcessRaisePriority
:
1867 case ProcessExceptionPort
:
1868 case ProcessAccessToken
:
1869 case ProcessLdtSize
:
1870 case ProcessIoPortHandlers
:
1871 case ProcessUserModeIOPL
:
1872 case ProcessEnableAlignmentFaultFixup
:
1873 case ProcessAffinityMask
:
1874 case ProcessForegroundInformation
:
1876 Status
= STATUS_INVALID_INFO_CLASS
;
1879 if(ProcessInformationClass
!= ProcessCookie
)
1881 ObDereferenceObject(Process
);
1889 PspAssignPrimaryToken(PEPROCESS Process
,
1892 PACCESS_TOKEN Token
;
1893 PACCESS_TOKEN OldToken
;
1896 Status
= ObReferenceObjectByHandle(TokenHandle
,
1902 if (!NT_SUCCESS(Status
))
1906 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
1907 if (NT_SUCCESS(Status
))
1909 ObDereferenceObject(OldToken
);
1911 ObDereferenceObject(Token
);
1919 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1920 IN PROCESSINFOCLASS ProcessInformationClass
,
1921 IN PVOID ProcessInformation
,
1922 IN ULONG ProcessInformationLength
)
1925 KPROCESSOR_MODE PreviousMode
;
1927 NTSTATUS Status
= STATUS_SUCCESS
;
1931 PreviousMode
= ExGetPreviousMode();
1933 DefaultSetInfoBufferCheck(ProcessInformationClass
,
1936 ProcessInformationLength
,
1939 if(!NT_SUCCESS(Status
))
1941 DPRINT1("NtSetInformationProcess() %d %x %x called\n", ProcessInformationClass
, ProcessInformation
, ProcessInformationLength
);
1942 DPRINT1("NtSetInformationProcess() %x failed, Status: 0x%x\n", Status
);
1946 switch(ProcessInformationClass
)
1948 case ProcessSessionInformation
:
1949 Access
= PROCESS_SET_INFORMATION
| PROCESS_SET_SESSIONID
;
1951 case ProcessExceptionPort
:
1952 case ProcessDebugPort
:
1953 Access
= PROCESS_SET_INFORMATION
| PROCESS_SET_PORT
;
1957 Access
= PROCESS_SET_INFORMATION
;
1961 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1967 if (!NT_SUCCESS(Status
))
1972 switch (ProcessInformationClass
)
1974 case ProcessQuotaLimits
:
1975 case ProcessBasePriority
:
1976 case ProcessRaisePriority
:
1977 Status
= STATUS_NOT_IMPLEMENTED
;
1980 case ProcessDebugPort
:
1982 HANDLE PortHandle
= NULL
;
1984 /* make a safe copy of the buffer on the stack */
1987 PortHandle
= *(PHANDLE
)ProcessInformation
;
1988 Status
= (PortHandle
!= NULL
? STATUS_SUCCESS
: STATUS_INVALID_PARAMETER
);
1992 Status
= _SEH_GetExceptionCode();
1996 if(NT_SUCCESS(Status
))
2000 /* in case we had success reading from the buffer, verify the provided
2003 Status
= ObReferenceObjectByHandle(PortHandle
,
2009 if(NT_SUCCESS(Status
))
2011 /* lock the process to be thread-safe! */
2013 Status
= PsLockProcess(Process
, FALSE
);
2014 if(NT_SUCCESS(Status
))
2017 * according to "NT Native API" documentation, setting the debug
2018 * port is only permitted once!
2020 if(Process
->DebugPort
== NULL
)
2022 /* keep the reference to the handle! */
2023 Process
->DebugPort
= DebugPort
;
2027 /* we're now debugging the process, so set the flag in the PEB
2028 structure. However, to access it we need to attach to the
2029 process so we're sure we're in the right context! */
2031 KeAttachProcess(&Process
->Pcb
);
2034 Process
->Peb
->BeingDebugged
= TRUE
;
2038 DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process
, _SEH_GetExceptionCode());
2043 Status
= STATUS_SUCCESS
;
2047 ObDereferenceObject(DebugPort
);
2048 Status
= STATUS_PORT_ALREADY_SET
;
2050 PsUnlockProcess(Process
);
2054 ObDereferenceObject(DebugPort
);
2061 case ProcessExceptionPort
:
2063 HANDLE PortHandle
= NULL
;
2065 /* make a safe copy of the buffer on the stack */
2068 PortHandle
= *(PHANDLE
)ProcessInformation
;
2069 Status
= STATUS_SUCCESS
;
2073 Status
= _SEH_GetExceptionCode();
2077 if(NT_SUCCESS(Status
))
2079 PEPORT ExceptionPort
;
2081 /* in case we had success reading from the buffer, verify the provided
2084 Status
= ObReferenceObjectByHandle(PortHandle
,
2088 (PVOID
)&ExceptionPort
,
2090 if(NT_SUCCESS(Status
))
2092 /* lock the process to be thread-safe! */
2094 Status
= PsLockProcess(Process
, FALSE
);
2095 if(NT_SUCCESS(Status
))
2098 * according to "NT Native API" documentation, setting the exception
2099 * port is only permitted once!
2101 if(Process
->ExceptionPort
== NULL
)
2103 /* keep the reference to the handle! */
2104 Process
->ExceptionPort
= ExceptionPort
;
2105 Status
= STATUS_SUCCESS
;
2109 ObDereferenceObject(ExceptionPort
);
2110 Status
= STATUS_PORT_ALREADY_SET
;
2112 PsUnlockProcess(Process
);
2116 ObDereferenceObject(ExceptionPort
);
2123 case ProcessAccessToken
:
2125 HANDLE TokenHandle
= NULL
;
2127 /* make a safe copy of the buffer on the stack */
2130 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->Token
;
2131 Status
= STATUS_SUCCESS
;
2135 Status
= _SEH_GetExceptionCode();
2139 if(NT_SUCCESS(Status
))
2141 /* in case we had success reading from the buffer, perform the actual task */
2142 Status
= PspAssignPrimaryToken(Process
, TokenHandle
);
2147 case ProcessDefaultHardErrorMode
:
2151 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
2152 *(PLONG
)ProcessInformation
);
2153 Status
= STATUS_SUCCESS
;
2157 Status
= _SEH_GetExceptionCode();
2163 case ProcessSessionInformation
:
2165 PROCESS_SESSION_INFORMATION SessionInfo
;
2166 Status
= STATUS_SUCCESS
;
2170 /* copy the structure to the stack */
2171 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
2175 Status
= _SEH_GetExceptionCode();
2179 if(NT_SUCCESS(Status
))
2181 /* we successfully copied the structure to the stack, continue processing */
2184 * setting the session id requires the SeTcbPrivilege!
2186 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
2189 DPRINT1("NtSetInformationProcess: Caller requires the SeTcbPrivilege privilege for setting ProcessSessionInformation!\n");
2190 /* can't set the session id, bail! */
2191 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2195 /* FIXME - update the session id for the process token */
2197 Status
= PsLockProcess(Process
, FALSE
);
2198 if(NT_SUCCESS(Status
))
2200 Process
->SessionId
= SessionInfo
.SessionId
;
2202 /* Update the session id in the PEB structure */
2203 if(Process
->Peb
!= NULL
)
2205 /* we need to attach to the process to make sure we're in the right
2206 context to access the PEB structure */
2207 KeAttachProcess(&Process
->Pcb
);
2211 /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
2213 Status
= STATUS_SUCCESS
;
2217 Status
= _SEH_GetExceptionCode();
2224 PsUnlockProcess(Process
);
2230 case ProcessPriorityClass
:
2232 PROCESS_PRIORITY_CLASS ppc
;
2236 ppc
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
2240 Status
= _SEH_GetExceptionCode();
2244 if(NT_SUCCESS(Status
))
2251 case ProcessLdtInformation
:
2252 case ProcessLdtSize
:
2253 case ProcessIoPortHandlers
:
2254 case ProcessWorkingSetWatch
:
2255 case ProcessUserModeIOPL
:
2256 case ProcessEnableAlignmentFaultFixup
:
2257 case ProcessAffinityMask
:
2258 Status
= STATUS_NOT_IMPLEMENTED
;
2261 case ProcessBasicInformation
:
2262 case ProcessIoCounters
:
2264 case ProcessPooledUsageAndLimits
:
2265 case ProcessWx86Information
:
2266 case ProcessHandleCount
:
2267 case ProcessWow64Information
:
2269 Status
= STATUS_INVALID_INFO_CLASS
;
2271 ObDereferenceObject(Process
);
2276 /**********************************************************************
2278 * PiQuerySystemProcessInformation
2281 * Compute the size of a process+thread snapshot as
2282 * expected by NtQuerySystemInformation.
2285 * 0 on error; otherwise the size, in bytes of the buffer
2286 * required to write a full snapshot.
2289 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
2292 PiQuerySystemProcessInformation(PVOID Buffer
,
2296 return STATUS_NOT_IMPLEMENTED
;
2299 PLIST_ENTRY CurrentEntryP
;
2301 PLIST_ENTRY CurrentEntryT
;
2304 ULONG RequiredSize
= 0L;
2305 BOOLEAN SizeOnly
= FALSE
;
2309 PSYSTEM_PROCESS_INFORMATION pInfoP
= (PSYSTEM_PROCESS_INFORMATION
) SnapshotBuffer
;
2310 PSYSTEM_PROCESS_INFORMATION pInfoPLast
= NULL
;
2311 PSYSTEM_THREAD_INFO pInfoT
= NULL
;
2314 /* Lock the process list. */
2315 ExAcquireFastMutex(&PspActiveProcessMutex
);
2318 * Scan the process list. Since the
2319 * list is circular, the guard is false
2320 * after the last process.
2322 for ( CurrentEntryP
= PsActiveProcessHead
.Flink
;
2323 (CurrentEntryP
!= & PsActiveProcessHead
);
2324 CurrentEntryP
= CurrentEntryP
->Flink
2328 * Compute how much space is
2329 * occupied in the snapshot
2330 * by adding this process info.
2331 * (at least one thread).
2333 SpiSizeCurrent
= sizeof (SYSTEM_PROCESS_INFORMATION
);
2334 RequiredSize
+= SpiSizeCurrent
;
2336 * Do not write process data in the
2337 * buffer if it is too small.
2339 if (TRUE
== SizeOnly
) continue;
2341 * Check if the buffer can contain
2342 * the full snapshot.
2344 if (Size
< RequiredSize
)
2350 * Get a reference to the
2351 * process descriptor we are
2354 CurrentP
= CONTAINING_RECORD(
2360 * Write process data in the buffer.
2362 RtlZeroMemory (pInfoP
, sizeof (SYSTEM_PROCESS_INFORMATION
));
2364 pInfoP
->ThreadCount
= 0L;
2365 pInfoP
->ProcessId
= CurrentP
->UniqueProcessId
;
2366 RtlInitUnicodeString (
2368 CurrentP
->ImageFileName
2371 for ( pInfoT
= & CurrentP
->ThreadSysInfo
[0],
2372 CurrentEntryT
= CurrentP
->ThreadListHead
.Flink
;
2374 (CurrentEntryT
!= & CurrentP
->ThreadListHead
);
2376 pInfoT
= & CurrentP
->ThreadSysInfo
[pInfoP
->ThreadCount
],
2377 CurrentEntryT
= CurrentEntryT
->Flink
2381 * Recalculate the size of the
2382 * information block.
2384 if (0 < pInfoP
->ThreadCount
)
2386 RequiredSize
+= sizeof (SYSTEM_THREAD_INFORMATION
);
2389 * Do not write thread data in the
2390 * buffer if it is too small.
2392 if (TRUE
== SizeOnly
) continue;
2394 * Check if the buffer can contain
2395 * the full snapshot.
2397 if (Size
< RequiredSize
)
2403 * Get a reference to the
2404 * thread descriptor we are
2407 CurrentT
= CONTAINING_RECORD(
2413 * Write thread data.
2417 sizeof (SYSTEM_THREAD_INFORMATION
)
2419 pInfoT
->KernelTime
= CurrentT
-> ; /* TIME */
2420 pInfoT
->UserTime
= CurrentT
-> ; /* TIME */
2421 pInfoT
->CreateTime
= CurrentT
-> ; /* TIME */
2422 pInfoT
->TickCount
= CurrentT
-> ; /* ULONG */
2423 pInfoT
->StartEIP
= CurrentT
-> ; /* ULONG */
2424 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2425 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2426 pInfoT
->DynamicPriority
= CurrentT
-> ; /* ULONG */
2427 pInfoT
->BasePriority
= CurrentT
-> ; /* ULONG */
2428 pInfoT
->nSwitches
= CurrentT
-> ; /* ULONG */
2429 pInfoT
->State
= CurrentT
-> ; /* DWORD */
2430 pInfoT
->WaitReason
= CurrentT
-> ; /* KWAIT_REASON */
2432 * Count the number of threads
2435 ++ pInfoP
->ThreadCount
;
2438 * Save the size of information
2439 * stored in the buffer for the
2442 pInfoP
->RelativeOffset
= SpiSize
;
2444 * Save a reference to the last
2445 * valid information block.
2447 pInfoPLast
= pInfoP
;
2449 * Compute the offset of the
2450 * SYSTEM_PROCESS_INFORMATION
2451 * descriptor in the snapshot
2452 * buffer for the next process.
2454 (ULONG
) pInfoP
+= SpiSize
;
2457 * Unlock the process list.
2459 ExReleaseFastMutex (
2460 & PspActiveProcessMutex
2463 * Return the proper error status code,
2464 * if the buffer was too small.
2466 if (TRUE
== SizeOnly
)
2468 if (NULL
!= RequiredSize
)
2470 *pRequiredSize
= RequiredSize
;
2472 return STATUS_INFO_LENGTH_MISMATCH
;
2475 * Mark the end of the snapshot.
2477 pInfoP
->RelativeOffset
= 0L;
2479 return STATUS_SUCCESS
;
2486 LARGE_INTEGER STDCALL
2487 PsGetProcessExitTime(VOID
)
2490 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
2499 PsGetProcessCreateTimeQuadPart(
2503 return Process
->CreateTime
.QuadPart
;
2511 PsGetProcessDebugPort(
2515 return Process
->DebugPort
;
2523 PsGetProcessExitProcessCalled(
2527 return Process
->ExitProcessCalled
;
2535 PsGetProcessExitStatus(
2539 return Process
->ExitStatus
;
2551 return (HANDLE
)Process
->UniqueProcessId
;
2559 PsGetProcessImageFileName(
2563 return (LPSTR
)Process
->ImageFileName
;
2571 PsGetProcessInheritedFromUniqueProcessId(
2575 return Process
->InheritedFromUniqueProcessId
;
2587 return Process
->Job
;
2599 return Process
->Peb
;
2607 PsGetProcessPriorityClass(
2611 return Process
->PriorityClass
;
2619 PsGetProcessSectionBaseAddress(
2623 return Process
->SectionBaseAddress
;
2631 PsGetProcessSecurityPort(
2635 return Process
->SecurityPort
;
2643 PsGetProcessSessionId(
2647 return (HANDLE
)Process
->SessionId
;
2655 PsGetProcessWin32Process(
2659 return Process
->Win32Process
;
2667 PsGetProcessWin32WindowStation(
2671 return Process
->Win32WindowStation
;
2679 PsIsProcessBeingDebugged(
2683 return FALSE
/*Process->IsProcessBeingDebugged*/;
2691 PsLookupProcessByProcessId(IN HANDLE ProcessId
,
2692 OUT PEPROCESS
*Process
)
2694 PHANDLE_TABLE_ENTRY CidEntry
;
2695 PEPROCESS FoundProcess
;
2701 CidEntry
= PsLookupCidHandle(ProcessId
, PsProcessType
, (PVOID
*)&FoundProcess
);
2702 if(CidEntry
!= NULL
)
2704 ObReferenceObject(FoundProcess
);
2706 PsUnlockCidHandle(CidEntry
);
2708 *Process
= FoundProcess
;
2709 return STATUS_SUCCESS
;
2712 return STATUS_INVALID_PARAMETER
;
2717 PspRunCreateProcessNotifyRoutines
2719 PEPROCESS CurrentProcess
,
2724 HANDLE ProcessId
= (HANDLE
)CurrentProcess
->UniqueProcessId
;
2725 HANDLE ParentId
= CurrentProcess
->InheritedFromUniqueProcessId
;
2727 for(i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2728 if(PiProcessNotifyRoutine
[i
])
2729 PiProcessNotifyRoutine
[i
](ParentId
, ProcessId
, Create
);
2736 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
2743 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2745 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
2747 PiProcessNotifyRoutine
[i
] = NULL
;
2752 return(STATUS_SUCCESS
);
2756 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2758 if (PiProcessNotifyRoutine
[i
] == NULL
)
2760 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
2765 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2767 return STATUS_INSUFFICIENT_RESOURCES
;
2770 return STATUS_SUCCESS
;
2774 PspRunLoadImageNotifyRoutines(
2775 PUNICODE_STRING FullImageName
,
2777 PIMAGE_INFO ImageInfo
)
2781 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2782 if (PiLoadImageNotifyRoutine
[i
])
2783 PiLoadImageNotifyRoutine
[i
](FullImageName
, ProcessId
, ImageInfo
);
2791 PsRemoveLoadImageNotifyRoutine(
2792 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
2796 return STATUS_NOT_IMPLEMENTED
;
2803 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
2807 for (i
= 0; i
< MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
; i
++)
2809 if (PiLoadImageNotifyRoutine
[i
] == NULL
)
2811 PiLoadImageNotifyRoutine
[i
] = NotifyRoutine
;
2816 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2818 return STATUS_INSUFFICIENT_RESOURCES
;
2821 return STATUS_SUCCESS
;
2829 PsSetProcessPriorityClass(
2834 Process
->PriorityClass
= PriorityClass
;
2842 PsSetProcessSecurityPort(
2847 Process
->SecurityPort
= SecurityPort
;
2855 PsSetProcessWin32Process(
2860 Process
->Win32Process
= Win32Process
;
2868 PsSetProcessWin32WindowStation(
2873 Process
->Win32WindowStation
= WindowStation
;
2883 IN PEPROCESS Process
,
2884 IN POOL_TYPE PoolType
,
2890 /* Charge the usage */
2891 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
2893 /* Raise Exception */
2894 if (!NT_SUCCESS(Status
)) {
2895 ExRaiseStatus(Status
);
2904 PsChargeProcessNonPagedPoolQuota (
2905 IN PEPROCESS Process
,
2909 /* Call the general function */
2910 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
2918 PsChargeProcessPagedPoolQuota (
2919 IN PEPROCESS Process
,
2923 /* Call the general function */
2924 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
2932 PsChargeProcessPoolQuota(
2933 IN PEPROCESS Process
,
2934 IN POOL_TYPE PoolType
,
2938 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
2942 /* Get current Quota Block */
2943 QuotaBlock
= Process
->QuotaBlock
;
2945 /* Quota Operations are not to be done on the SYSTEM Process */
2946 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
2948 /* New Size in use */
2949 NewUsageSize
= QuotaBlock
->QuotaEntry
[PoolType
].Usage
+ Amount
;
2951 /* Does this size respect the quota? */
2952 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Limit
) {
2954 /* It doesn't, so keep raising the Quota */
2955 while (MiRaisePoolQuota(PoolType
, QuotaBlock
->QuotaEntry
[PoolType
].Limit
, &NewMaxQuota
)) {
2956 /* Save new Maximum Quota */
2957 QuotaBlock
->QuotaEntry
[PoolType
].Limit
= NewMaxQuota
;
2959 /* See if the new Maximum Quota fulfills our need */
2960 if (NewUsageSize
<= NewMaxQuota
) goto QuotaChanged
;
2963 return STATUS_QUOTA_EXCEEDED
;
2967 /* Save new Usage */
2968 QuotaBlock
->QuotaEntry
[PoolType
].Usage
= NewUsageSize
;
2970 /* Is this a new peak? */
2971 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Peak
) {
2972 QuotaBlock
->QuotaEntry
[PoolType
].Peak
= NewUsageSize
;
2976 return STATUS_SUCCESS
;
2985 IN PEPROCESS Process
,
2986 IN POOL_TYPE PoolType
,
2998 PsReturnProcessNonPagedPoolQuota(
2999 IN PEPROCESS Process
,
3011 PsReturnProcessPagedPoolQuota(
3012 IN PEPROCESS Process
,
3020 PsLockProcess(PEPROCESS Process
, BOOL Timeout
)
3023 PKTHREAD PrevLockOwner
;
3024 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
3025 PLARGE_INTEGER Delay
= (Timeout
? &PsLockTimeout
: NULL
);
3026 PKTHREAD CallingThread
= KeGetCurrentThread();
3030 KeEnterCriticalRegion();
3034 if(Process
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
3036 KeLeaveCriticalRegion();
3037 return STATUS_PROCESS_IS_TERMINATING
;
3040 PrevLockOwner
= (PKTHREAD
)InterlockedCompareExchangePointer(
3041 &Process
->LockOwner
, CallingThread
, NULL
);
3042 if(PrevLockOwner
== NULL
|| PrevLockOwner
== CallingThread
)
3044 /* we got the lock or already locked it */
3045 if(InterlockedIncrementUL(&Process
->LockCount
) == 1)
3047 KeClearEvent(&Process
->LockEvent
);
3050 return STATUS_SUCCESS
;
3056 Status
= KeWaitForSingleObject(&Process
->LockEvent
,
3061 if(!NT_SUCCESS(Status
) || Status
== STATUS_TIMEOUT
)
3064 if(Status
== STATUS_TIMEOUT
)
3066 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process
);
3069 KeLeaveCriticalRegion();
3076 KeDelayExecutionThread(KernelMode
, FALSE
, &ShortPsLockDelay
);
3085 PsUnlockProcess(PEPROCESS Process
)
3089 ASSERT(Process
->LockOwner
== KeGetCurrentThread());
3091 if(InterlockedDecrementUL(&Process
->LockCount
) == 0)
3093 InterlockedExchangePointer(&Process
->LockOwner
, NULL
);
3094 KeSetEvent(&Process
->LockEvent
, IO_NO_INCREMENT
, FALSE
);
3097 KeLeaveCriticalRegion();