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
;
23 POBJECT_TYPE EXPORTED PsProcessType
= NULL
;
25 LIST_ENTRY PsActiveProcessHead
;
26 FAST_MUTEX PspActiveProcessMutex
;
27 static LARGE_INTEGER ShortPsLockDelay
, PsLockTimeout
;
29 static GENERIC_MAPPING PiProcessMapping
= {STANDARD_RIGHTS_READ
| PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
30 STANDARD_RIGHTS_WRITE
| PROCESS_CREATE_PROCESS
| PROCESS_CREATE_THREAD
|
31 PROCESS_VM_OPERATION
| PROCESS_VM_WRITE
| PROCESS_DUP_HANDLE
|
32 PROCESS_TERMINATE
| PROCESS_SET_QUOTA
| PROCESS_SET_INFORMATION
| PROCESS_SET_PORT
,
33 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
36 static const INFORMATION_CLASS_INFO PsProcessInfoClass
[] =
38 ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessBasicInformation */
39 ICI_SQ_SAME( sizeof(QUOTA_LIMITS
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessQuotaLimits */
40 ICI_SQ_SAME( sizeof(IO_COUNTERS
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessIoCounters */
41 ICI_SQ_SAME( sizeof(VM_COUNTERS
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessVmCounters */
42 ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessTimes */
43 ICI_SQ_SAME( sizeof(KPRIORITY
), sizeof(ULONG
), ICIF_SET
), /* ProcessBasePriority */
44 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_SET
), /* ProcessRaisePriority */
45 ICI_SQ_SAME( sizeof(HANDLE
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessDebugPort */
46 ICI_SQ_SAME( sizeof(HANDLE
), sizeof(ULONG
), ICIF_SET
), /* ProcessExceptionPort */
47 ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN
), sizeof(ULONG
), ICIF_SET
), /* ProcessAccessToken */
48 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessLdtInformation */
49 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_SET
), /* ProcessLdtSize */
50 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessDefaultHardErrorMode */
51 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_SET
), /* ProcessIoPortHandlers */
52 ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessPooledUsageAndLimits */
53 ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessWorkingSetWatch */
54 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG
), ICIF_SET
), /* ProcessUserModeIOPL */
55 ICI_SQ_SAME( sizeof(BOOLEAN
), sizeof(ULONG
), ICIF_SET
), /* ProcessEnableAlignmentFaultFixup */
56 ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS
), sizeof(USHORT
), ICIF_QUERY
| ICIF_SET
), /* ProcessPriorityClass */
57 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessWx86Information */
58 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessHandleCount */
59 ICI_SQ_SAME( sizeof(KAFFINITY
), sizeof(ULONG
), ICIF_SET
), /* ProcessAffinityMask */
60 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessPriorityBoost */
62 ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION
)0x0)->Query
), /* ProcessDeviceMap */
63 /*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION
)0x0)->Set
),
66 ICIF_QUERY
| ICIF_SET
),
68 ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SET
), /* ProcessSessionInformation */
69 ICI_SQ_SAME( sizeof(BOOLEAN
), sizeof(ULONG
), ICIF_SET
), /* ProcessForegroundInformation */
70 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessWow64Information */
71 ICI_SQ_SAME( sizeof(UNICODE_STRING
), sizeof(ULONG
), ICIF_QUERY
| ICIF_SIZE_VARIABLE
), /* ProcessImageFileName */
74 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessLUIDDeviceMapsEnabled */
75 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessBreakOnTermination */
76 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessDebugObjectHandle */
77 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessDebugFlags */
78 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessHandleTracing */
79 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessUnknown33 */
80 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessUnknown34 */
81 ICI_SQ_SAME( 0, 0, 0 ), /* ProcessUnknown35 */
83 ICI_SQ_SAME( sizeof(ULONG
), sizeof(ULONG
), ICIF_QUERY
), /* ProcessCookie */
86 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
87 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
89 static PCREATE_PROCESS_NOTIFY_ROUTINE
90 PiProcessNotifyRoutine
[MAX_PROCESS_NOTIFY_ROUTINE_COUNT
];
91 static PLOAD_IMAGE_NOTIFY_ROUTINE
92 PiLoadImageNotifyRoutine
[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
];
97 WORK_QUEUE_ITEM WorkQueueItem
;
100 BOOLEAN IsWorkerQueue
;
101 } DEL_CONTEXT
, *PDEL_CONTEXT
;
103 /* FUNCTIONS *****************************************************************/
107 PsExitSpecialApc(PKAPC Apc
,
108 PKNORMAL_ROUTINE
*NormalRoutine
,
109 PVOID
*NormalContext
,
110 PVOID
*SystemArgument1
,
111 PVOID
*SystemArgument2
)
116 PsGetNextProcess(PEPROCESS OldProcess
)
118 PEPROCESS NextProcess
;
121 if (OldProcess
== NULL
)
123 Status
= ObReferenceObjectByPointer(PsInitialSystemProcess
,
127 if (!NT_SUCCESS(Status
))
129 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsInitialSystemProcess\n");
132 return PsInitialSystemProcess
;
135 ExAcquireFastMutex(&PspActiveProcessMutex
);
136 NextProcess
= OldProcess
;
139 if (NextProcess
->ProcessListEntry
.Blink
== &PsActiveProcessHead
)
141 NextProcess
= CONTAINING_RECORD(PsActiveProcessHead
.Blink
,
147 NextProcess
= CONTAINING_RECORD(NextProcess
->ProcessListEntry
.Blink
,
151 Status
= ObReferenceObjectByPointer(NextProcess
,
155 if (NT_SUCCESS(Status
))
159 else if (Status
== STATUS_PROCESS_IS_TERMINATING
)
163 else if (!NT_SUCCESS(Status
))
165 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
170 ExReleaseFastMutex(&PspActiveProcessMutex
);
171 ObDereferenceObject(OldProcess
);
181 NtOpenProcessToken(IN HANDLE ProcessHandle
,
182 IN ACCESS_MASK DesiredAccess
,
183 OUT PHANDLE TokenHandle
)
185 return NtOpenProcessTokenEx(ProcessHandle
,
197 NtOpenProcessTokenEx(
198 IN HANDLE ProcessHandle
,
199 IN ACCESS_MASK DesiredAccess
,
200 IN ULONG HandleAttributes
,
201 OUT PHANDLE TokenHandle
206 KPROCESSOR_MODE PreviousMode
;
207 NTSTATUS Status
= STATUS_SUCCESS
;
211 PreviousMode
= ExGetPreviousMode();
213 if(PreviousMode
== UserMode
)
217 ProbeForWrite(TokenHandle
,
223 Status
= _SEH_GetExceptionCode();
227 if(!NT_SUCCESS(Status
))
233 Status
= PsOpenTokenOfProcess(ProcessHandle
,
235 if(NT_SUCCESS(Status
))
237 Status
= ObCreateHandle(PsGetCurrentProcess(),
242 ObDereferenceObject(Token
);
246 *TokenHandle
= hToken
;
250 Status
= _SEH_GetExceptionCode();
262 PACCESS_TOKEN STDCALL
263 PsReferencePrimaryToken(PEPROCESS Process
)
265 ObReferenceObjectByPointer(Process
->Token
,
269 return(Process
->Token
);
274 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
275 PACCESS_TOKEN
* Token
)
280 Status
= ObReferenceObjectByHandle(ProcessHandle
,
281 PROCESS_QUERY_INFORMATION
,
286 if(NT_SUCCESS(Status
))
288 *Token
= PsReferencePrimaryToken(Process
);
289 ObDereferenceObject(Process
);
297 PiKillMostProcesses(VOID
)
299 PLIST_ENTRY current_entry
;
302 ExAcquireFastMutex(&PspActiveProcessMutex
);
304 current_entry
= PsActiveProcessHead
.Flink
;
305 while (current_entry
!= &PsActiveProcessHead
)
307 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
309 current_entry
= current_entry
->Flink
;
311 if (current
->UniqueProcessId
!= PsInitialSystemProcess
->UniqueProcessId
&&
312 current
->UniqueProcessId
!= PsGetCurrentProcessId())
314 PiTerminateProcessThreads(current
, STATUS_SUCCESS
);
318 ExReleaseFastMutex(&PspActiveProcessMutex
);
323 PsInitProcessManagment(VOID
)
328 ShortPsLockDelay
.QuadPart
= -100LL;
329 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
331 * Register the process object type
334 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
336 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
337 PsProcessType
->TotalObjects
= 0;
338 PsProcessType
->TotalHandles
= 0;
339 PsProcessType
->PeakObjects
= 0;
340 PsProcessType
->PeakHandles
= 0;
341 PsProcessType
->PagedPoolCharge
= 0;
342 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
343 PsProcessType
->Mapping
= &PiProcessMapping
;
344 PsProcessType
->Dump
= NULL
;
345 PsProcessType
->Open
= NULL
;
346 PsProcessType
->Close
= NULL
;
347 PsProcessType
->Delete
= PiDeleteProcess
;
348 PsProcessType
->Parse
= NULL
;
349 PsProcessType
->Security
= NULL
;
350 PsProcessType
->QueryName
= NULL
;
351 PsProcessType
->OkayToClose
= NULL
;
352 PsProcessType
->Create
= NULL
;
353 PsProcessType
->DuplicationNotify
= NULL
;
355 RtlInitUnicodeString(&PsProcessType
->TypeName
, L
"Process");
357 ObpCreateTypeObject(PsProcessType
);
359 InitializeListHead(&PsActiveProcessHead
);
360 ExInitializeFastMutex(&PspActiveProcessMutex
);
362 RtlZeroMemory(PiProcessNotifyRoutine
, sizeof(PiProcessNotifyRoutine
));
363 RtlZeroMemory(PiLoadImageNotifyRoutine
, sizeof(PiLoadImageNotifyRoutine
));
366 * Initialize the system process
368 Status
= ObCreateObject(KernelMode
,
376 (PVOID
*)&PsInitialSystemProcess
);
377 if (!NT_SUCCESS(Status
))
382 /* System threads may run on any processor. */
383 PsInitialSystemProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
384 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
385 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[0] = 0;
386 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[1] = 0;
387 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
388 PsInitialSystemProcess
->Pcb
.ThreadQuantum
= 6;
389 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
390 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
394 KProcess
= &PsInitialSystemProcess
->Pcb
;
396 MmInitializeAddressSpace(PsInitialSystemProcess
,
397 &PsInitialSystemProcess
->AddressSpace
);
399 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
400 PsInitialSystemProcess
->LockCount
= 0;
401 PsInitialSystemProcess
->LockOwner
= NULL
;
403 #if defined(__GNUC__)
404 KProcess
->DirectoryTableBase
=
405 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
409 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
410 KProcess
->DirectoryTableBase
= dummy
;
414 strcpy(PsInitialSystemProcess
->ImageFileName
, "System");
416 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
418 InsertHeadList(&PsActiveProcessHead
,
419 &PsInitialSystemProcess
->ProcessListEntry
);
420 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
422 SepCreateSystemProcessToken(PsInitialSystemProcess
);
426 PspPostInitSystemProcess(VOID
)
430 /* this routine is called directly after the exectuive handle tables were
431 initialized. We'll set up the Client ID handle table and assign the system
433 PsInitClientIDManagment();
435 ObCreateHandleTable(NULL
, FALSE
, PsInitialSystemProcess
);
437 Status
= PsCreateCidHandle(PsInitialSystemProcess
,
439 &PsInitialSystemProcess
->UniqueProcessId
);
440 if(!NT_SUCCESS(Status
))
442 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
448 PiDeleteProcessWorker(PVOID pContext
)
450 PDEL_CONTEXT Context
;
451 PEPROCESS CurrentProcess
;
454 Context
= (PDEL_CONTEXT
)pContext
;
455 Process
= Context
->Process
;
456 CurrentProcess
= PsGetCurrentProcess();
458 DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process
);
460 if (CurrentProcess
!= Process
)
462 KeAttachProcess(&Process
->Pcb
);
465 ExAcquireFastMutex(&PspActiveProcessMutex
);
466 RemoveEntryList(&Process
->ProcessListEntry
);
467 ExReleaseFastMutex(&PspActiveProcessMutex
);
470 KDB_DELETEPROCESS_HOOK(Process
);
472 ObDereferenceObject(Process
->Token
);
474 if (CurrentProcess
!= Process
)
479 MmReleaseMmInfo(Process
);
480 if (Context
->IsWorkerQueue
)
482 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
487 PiDeleteProcess(PVOID ObjectBody
)
491 Context
.Process
= (PEPROCESS
)ObjectBody
;
493 if (PsGetCurrentProcess() == Context
.Process
||
494 PsGetCurrentThread()->ThreadsProcess
== Context
.Process
)
499 if (PsGetCurrentThread()->ThreadsProcess
== PsGetCurrentProcess())
501 Context
.IsWorkerQueue
= FALSE
;
502 PiDeleteProcessWorker(&Context
);
506 Context
.IsWorkerQueue
= TRUE
;
507 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
508 ExInitializeWorkItem (&Context
.WorkQueueItem
, PiDeleteProcessWorker
, &Context
);
509 ExQueueWorkItem(&Context
.WorkQueueItem
, HyperCriticalWorkQueue
);
510 if (KeReadStateEvent(&Context
.Event
) == 0)
512 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
516 if(((PEPROCESS
)ObjectBody
)->Win32Process
!= NULL
)
518 /* delete the W32PROCESS structure if there's one associated */
519 ExFreePool (((PEPROCESS
)ObjectBody
)->Win32Process
);
524 PsCreatePeb(HANDLE ProcessHandle
,
531 LARGE_INTEGER SectionOffset
;
538 /* Allocate the Process Environment Block (PEB) */
539 Process
->TebBlock
= (PVOID
) MM_ROUND_DOWN(PEB_BASE
, MM_VIRTMEM_GRANULARITY
);
540 AllocSize
= MM_VIRTMEM_GRANULARITY
;
541 Status
= NtAllocateVirtualMemory(ProcessHandle
,
547 if (!NT_SUCCESS(Status
))
549 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
552 ASSERT((ULONG_PTR
) Process
->TebBlock
<= PEB_BASE
&&
553 PEB_BASE
+ PAGE_SIZE
<= (ULONG_PTR
) Process
->TebBlock
+ AllocSize
);
554 Peb
= (PPEB
)PEB_BASE
;
556 Status
= NtAllocateVirtualMemory(ProcessHandle
,
562 if (!NT_SUCCESS(Status
))
564 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
567 DPRINT("Peb %p PebSize %lu\n", Peb
, PebSize
);
568 ASSERT((PPEB
) PEB_BASE
== Peb
&& PAGE_SIZE
<= PebSize
);
569 Process
->TebLastAllocated
= (PVOID
) Peb
;
572 SectionOffset
.QuadPart
= (ULONGLONG
)0;
574 Status
= MmMapViewOfSection(NlsSectionObject
,
584 if (!NT_SUCCESS(Status
))
586 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
589 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
591 KeAttachProcess(&Process
->Pcb
);
593 /* Initialize the PEB */
594 RtlZeroMemory(Peb
, sizeof(PEB
));
595 Peb
->ImageBaseAddress
= ImageBase
;
597 Peb
->OSMajorVersion
= 4;
598 Peb
->OSMinorVersion
= 0;
599 Peb
->OSBuildNumber
= 1381;
600 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
601 Peb
->OSCSDVersion
= 6 << 8;
603 Peb
->AnsiCodePageData
= (char*)TableBase
+ NlsAnsiTableOffset
;
604 Peb
->OemCodePageData
= (char*)TableBase
+ NlsOemTableOffset
;
605 Peb
->UnicodeCaseTableData
= (char*)TableBase
+ NlsUnicodeTableOffset
;
610 DPRINT("PsCreatePeb: Peb created at %p\n", Peb
);
612 return(STATUS_SUCCESS
);
617 KeGetCurrentProcess(VOID
)
619 * FUNCTION: Returns a pointer to the current process
622 return(&(PsGetCurrentProcess()->Pcb
));
626 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
627 * ULONG ProcessId! (Skywing)
633 PsGetCurrentProcessId(VOID
)
635 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
643 PsGetCurrentProcessSessionId (
647 return PsGetCurrentProcess()->SessionId
;
651 * FUNCTION: Returns a pointer to the current process
656 IoGetCurrentProcess(VOID
)
658 if (PsGetCurrentThread() == NULL
||
659 PsGetCurrentThread()->Tcb
.ApcState
.Process
== NULL
)
661 return(PsInitialSystemProcess
);
665 return(PEPROCESS
)(PsGetCurrentThread()->Tcb
.ApcState
.Process
);
670 PspCreateProcess(OUT PHANDLE ProcessHandle
,
671 IN ACCESS_MASK DesiredAccess
,
672 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
673 IN HANDLE ParentProcess OPTIONAL
,
674 IN BOOLEAN InheritObjectTable
,
675 IN HANDLE SectionHandle OPTIONAL
,
676 IN HANDLE DebugPort OPTIONAL
,
677 IN HANDLE ExceptionPort OPTIONAL
)
681 PEPROCESS pParentProcess
;
683 PVOID LdrStartupAddr
;
685 PMEMORY_AREA MemoryArea
;
686 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
687 KPROCESSOR_MODE PreviousMode
;
688 PVOID ImageBase
= NULL
;
689 PEPORT pDebugPort
= NULL
;
690 PEPORT pExceptionPort
= NULL
;
691 PSECTION_OBJECT SectionObject
= NULL
;
692 NTSTATUS Status
= STATUS_SUCCESS
;
694 DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes
);
696 PreviousMode
= ExGetPreviousMode();
698 BoundaryAddressMultiple
.QuadPart
= 0;
700 if(ParentProcess
!= NULL
)
702 Status
= ObReferenceObjectByHandle(ParentProcess
,
703 PROCESS_CREATE_PROCESS
,
706 (PVOID
*)&pParentProcess
,
708 if (!NT_SUCCESS(Status
))
710 DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status
);
716 pParentProcess
= NULL
;
722 if (DebugPort
!= NULL
)
724 Status
= ObReferenceObjectByHandle(DebugPort
,
730 if (!NT_SUCCESS(Status
))
732 DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status
);
733 goto exitdereferenceobjects
;
738 * Add the exception port
740 if (ExceptionPort
!= NULL
)
742 Status
= ObReferenceObjectByHandle(ExceptionPort
,
746 (PVOID
*)&pExceptionPort
,
748 if (!NT_SUCCESS(Status
))
750 DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status
);
751 goto exitdereferenceobjects
;
755 if (SectionHandle
!= NULL
)
757 Status
= ObReferenceObjectByHandle(SectionHandle
,
761 (PVOID
*)&SectionObject
,
763 if (!NT_SUCCESS(Status
))
765 DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status
);
766 goto exitdereferenceobjects
;
770 Status
= ObCreateObject(PreviousMode
,
779 if (!NT_SUCCESS(Status
))
781 DPRINT1("Failed to create process object, Status: 0x%x\n", Status
);
783 exitdereferenceobjects
:
784 if(SectionObject
!= NULL
)
785 ObDereferenceObject(SectionObject
);
786 if(pExceptionPort
!= NULL
)
787 ObDereferenceObject(pExceptionPort
);
788 if(pDebugPort
!= NULL
)
789 ObDereferenceObject(pDebugPort
);
790 if(pParentProcess
!= NULL
)
791 ObDereferenceObject(pParentProcess
);
795 KProcess
= &Process
->Pcb
;
797 RtlZeroMemory(Process
, sizeof(EPROCESS
));
799 Status
= PsCreateCidHandle(Process
,
801 &Process
->UniqueProcessId
);
802 if(!NT_SUCCESS(Status
))
804 DPRINT1("Failed to create CID handle (unique process ID)! Status: 0x%x\n", Status
);
805 ObDereferenceObject(Process
);
806 goto exitdereferenceobjects
;
809 Process
->DebugPort
= pDebugPort
;
810 Process
->ExceptionPort
= pExceptionPort
;
812 if(SectionObject
!= NULL
)
814 UNICODE_STRING FileName
;
820 * Determine the image file name and save it to the EPROCESS structure
823 FileName
= SectionObject
->FileObject
->FileName
;
824 szSrc
= (PWCHAR
)(FileName
.Buffer
+ (FileName
.Length
/ sizeof(WCHAR
)) - 1);
825 while(szSrc
>= FileName
.Buffer
)
839 /* copy the image file name to the process and truncate it to 15 characters
841 szDest
= Process
->ImageFileName
;
842 lnFName
= min(lnFName
, sizeof(Process
->ImageFileName
) - 1);
845 *(szDest
++) = (UCHAR
)*(szSrc
++);
847 /* *szDest = '\0'; */
850 KeInitializeDispatcherHeader(&KProcess
->DispatcherHeader
,
855 /* Inherit parent process's affinity. */
856 if(pParentProcess
!= NULL
)
858 KProcess
->Affinity
= pParentProcess
->Pcb
.Affinity
;
859 Process
->InheritedFromUniqueProcessId
= pParentProcess
->UniqueProcessId
;
860 Process
->SessionId
= pParentProcess
->SessionId
;
864 KProcess
->Affinity
= KeActiveProcessors
;
867 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
868 KProcess
->IopmOffset
= 0xffff;
869 KProcess
->LdtDescriptor
[0] = 0;
870 KProcess
->LdtDescriptor
[1] = 0;
871 InitializeListHead(&KProcess
->ThreadListHead
);
872 KProcess
->ThreadQuantum
= 6;
873 KProcess
->AutoAlignment
= 0;
874 MmInitializeAddressSpace(Process
,
875 &Process
->AddressSpace
);
877 ObCreateHandleTable(pParentProcess
,
880 MmCopyMmInfo(pParentProcess
? pParentProcess
: PsInitialSystemProcess
, Process
);
882 KeInitializeEvent(&Process
->LockEvent
, SynchronizationEvent
, FALSE
);
883 Process
->LockCount
= 0;
884 Process
->LockOwner
= NULL
;
886 Process
->Win32WindowStation
= (HANDLE
)0;
888 ExAcquireFastMutex(&PspActiveProcessMutex
);
889 InsertHeadList(&PsActiveProcessHead
, &Process
->ProcessListEntry
);
890 InitializeListHead(&Process
->ThreadListHead
);
891 ExReleaseFastMutex(&PspActiveProcessMutex
);
893 ExInitializeFastMutex(&Process
->TebLock
);
894 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
897 * Now we have created the process proper
900 MmLockAddressSpace(&Process
->AddressSpace
);
902 /* Protect the highest 64KB of the process address space */
903 BaseAddress
= (PVOID
)MmUserProbeAddress
;
904 Status
= MmCreateMemoryArea(Process
,
905 &Process
->AddressSpace
,
906 MEMORY_AREA_NO_ACCESS
,
913 BoundaryAddressMultiple
);
914 if (!NT_SUCCESS(Status
))
916 MmUnlockAddressSpace(&Process
->AddressSpace
);
917 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
918 ObDereferenceObject(Process
);
919 goto exitdereferenceobjects
;
922 /* Protect the lowest 64KB of the process address space */
924 BaseAddress
= (PVOID
)0x00000000;
925 Status
= MmCreateMemoryArea(Process
,
926 &Process
->AddressSpace
,
927 MEMORY_AREA_NO_ACCESS
,
934 BoundaryAddressMultiple
);
935 if (!NT_SUCCESS(Status
))
937 MmUnlockAddressSpace(&Process
->AddressSpace
);
938 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
939 ObDereferenceObject(Process
);
940 goto exitdereferenceobjects
;
944 /* Protect the 60KB above the shared user page */
945 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
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 memory above the shared user page\n");
960 ObDereferenceObject(Process
);
961 goto exitdereferenceobjects
;
964 /* Create the shared data page */
965 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
966 Status
= MmCreateMemoryArea(Process
,
967 &Process
->AddressSpace
,
968 MEMORY_AREA_SHARED_DATA
,
975 BoundaryAddressMultiple
);
976 MmUnlockAddressSpace(&Process
->AddressSpace
);
977 if (!NT_SUCCESS(Status
))
979 DPRINT1("Failed to create shared data page\n");
980 ObDereferenceObject(Process
);
981 goto exitdereferenceobjects
;
986 * FIXME - the handle should be created after all things are initialized, NOT HERE!
988 Status
= ObInsertObject ((PVOID
)Process
,
994 if (!NT_SUCCESS(Status
))
996 DPRINT1("Failed to create a handle for the process\n");
997 ObDereferenceObject(Process
);
998 goto exitdereferenceobjects
;
1005 Status
= LdrpMapSystemDll(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
1007 if (!NT_SUCCESS(Status
))
1009 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
1010 ObDereferenceObject(Process
);
1011 goto exitdereferenceobjects
;
1015 * Map the process image
1017 if (SectionObject
!= NULL
)
1020 DPRINT("Mapping process image\n");
1021 Status
= MmMapViewOfSection(SectionObject
,
1031 ObDereferenceObject(SectionObject
);
1032 if (!NT_SUCCESS(Status
))
1034 DbgPrint("Failed to map the process section (Status %x)\n", Status
);
1035 ObDereferenceObject(Process
);
1036 goto exitdereferenceobjects
;
1040 if(pParentProcess
!= NULL
)
1043 * Duplicate the token
1045 Status
= SepInitializeNewProcess(Process
, pParentProcess
);
1046 if (!NT_SUCCESS(Status
))
1048 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
1049 ObDereferenceObject(Process
);
1050 goto exitdereferenceobjects
;
1059 * FIXME - Create PEB
1061 DPRINT("Creating PEB\n");
1062 Status
= PsCreatePeb(hProcess
, /* FIXME - hProcess shouldn't be available at this point! */
1065 if (!NT_SUCCESS(Status
))
1067 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
1068 ObDereferenceObject(Process
);
1069 goto exitdereferenceobjects
;
1073 * Maybe send a message to the creator process's debugger
1076 if (pParentProcess
->DebugPort
!= NULL
)
1078 LPC_DBG_MESSAGE Message
;
1081 ObCreateHandle(NULL
, // Debugger Process
1082 NULL
, // SectionHandle
1087 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
1088 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
1089 sizeof(LPC_MESSAGE
);
1090 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
1091 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
1092 Message
.Data
.CreateProcess
.Base
= ImageBase
;
1093 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
1095 Status
= LpcSendDebugMessagePort(pParentProcess
->DebugPort
,
1100 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
1103 * FIXME - the handle should be created not before this point!
1106 Status
= ObInsertObject ((PVOID
)Process
,
1113 if (NT_SUCCESS(Status
))
1117 *ProcessHandle
= hProcess
;
1121 Status
= _SEH_GetExceptionCode();
1127 * don't dereference the debug port, exception port and section object even
1128 * if ObInsertObject() failed, the process is alive! We just couldn't return
1129 * the handle to the caller!
1132 ObDereferenceObject(Process
);
1133 if(pParentProcess
!= NULL
)
1134 ObDereferenceObject(pParentProcess
);
1144 PsCreateSystemProcess(PHANDLE ProcessHandle
,
1145 ACCESS_MASK DesiredAccess
,
1146 POBJECT_ATTRIBUTES ObjectAttributes
)
1148 return PspCreateProcess(ProcessHandle
,
1151 NULL
, /* no parent process */
1163 NtCreateProcess(OUT PHANDLE ProcessHandle
,
1164 IN ACCESS_MASK DesiredAccess
,
1165 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
1166 IN HANDLE ParentProcess
,
1167 IN BOOLEAN InheritObjectTable
,
1168 IN HANDLE SectionHandle OPTIONAL
,
1169 IN HANDLE DebugPort OPTIONAL
,
1170 IN HANDLE ExceptionPort OPTIONAL
)
1172 * FUNCTION: Creates a process.
1174 * ProcessHandle (OUT) = Caller supplied storage for the resulting
1176 * DesiredAccess = Specifies the allowed or desired access to the
1177 * process can be a combination of
1178 * STANDARD_RIGHTS_REQUIRED| ..
1179 * ObjectAttribute = Initialized attributes for the object, contains
1180 * the rootdirectory and the filename
1181 * ParentProcess = Handle to the parent process.
1182 * InheritObjectTable = Specifies to inherit the objects of the parent
1184 * SectionHandle = Handle to a section object to back the image file
1185 * DebugPort = Handle to a DebugPort if NULL the system default debug
1186 * port will be used.
1187 * ExceptionPort = Handle to a exception port.
1189 * This function maps to the win32 CreateProcess.
1193 KPROCESSOR_MODE PreviousMode
;
1194 NTSTATUS Status
= STATUS_SUCCESS
;
1198 PreviousMode
= ExGetPreviousMode();
1200 if(PreviousMode
!= KernelMode
)
1204 ProbeForWrite(ProcessHandle
,
1210 Status
= _SEH_GetExceptionCode();
1214 if(!NT_SUCCESS(Status
))
1220 if(ParentProcess
== NULL
)
1222 Status
= STATUS_INVALID_PARAMETER
;
1226 Status
= PspCreateProcess(ProcessHandle
,
1244 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1245 IN ACCESS_MASK DesiredAccess
,
1246 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1247 IN PCLIENT_ID ClientId
)
1249 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1250 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1251 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
1252 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
1257 * Not sure of the exact semantics
1259 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
1260 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
1265 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
1266 ObjectAttributes
->Attributes
,
1273 if (Status
!= STATUS_SUCCESS
)
1278 Status
= ObCreateHandle(PsGetCurrentProcess(),
1283 ObDereferenceObject(Process
);
1289 PLIST_ENTRY current_entry
;
1293 ExAcquireFastMutex(&PspActiveProcessMutex
);
1294 current_entry
= PsActiveProcessHead
.Flink
;
1295 while (current_entry
!= &PsActiveProcessHead
)
1297 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
1299 if (current
->UniqueProcessId
== ClientId
->UniqueProcess
)
1301 if (current
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
1303 Status
= STATUS_PROCESS_IS_TERMINATING
;
1307 Status
= ObReferenceObjectByPointer(current
,
1312 ExReleaseFastMutex(&PspActiveProcessMutex
);
1313 if (NT_SUCCESS(Status
))
1315 Status
= ObCreateHandle(PsGetCurrentProcess(),
1320 ObDereferenceObject(current
);
1321 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
1322 DPRINT("NtOpenProcess() = %x\n", Status
);
1326 current_entry
= current_entry
->Flink
;
1328 ExReleaseFastMutex(&PspActiveProcessMutex
);
1329 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1330 return(STATUS_UNSUCCESSFUL
);
1332 return(STATUS_UNSUCCESSFUL
);
1340 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
1341 IN PROCESSINFOCLASS ProcessInformationClass
,
1342 OUT PVOID ProcessInformation
,
1343 IN ULONG ProcessInformationLength
,
1344 OUT PULONG ReturnLength OPTIONAL
)
1347 KPROCESSOR_MODE PreviousMode
;
1348 NTSTATUS Status
= STATUS_SUCCESS
;
1352 PreviousMode
= ExGetPreviousMode();
1354 DefaultQueryInfoBufferCheck(ProcessInformationClass
,
1357 ProcessInformationLength
,
1361 if(!NT_SUCCESS(Status
))
1363 DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status
);
1367 if(ProcessInformationClass
!= ProcessCookie
)
1369 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1370 PROCESS_QUERY_INFORMATION
,
1375 if (!NT_SUCCESS(Status
))
1380 else if(ProcessHandle
!= NtCurrentProcess())
1382 /* retreiving the process cookie is only allowed for the calling process
1383 itself! XP only allowes NtCurrentProcess() as process handles even if a
1384 real handle actually represents the current process. */
1385 return STATUS_INVALID_PARAMETER
;
1388 switch (ProcessInformationClass
)
1390 case ProcessBasicInformation
:
1392 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
=
1393 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
1397 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
1398 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
1399 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
1400 ProcessBasicInformationP
->UniqueProcessId
=
1401 Process
->UniqueProcessId
;
1402 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
1403 Process
->InheritedFromUniqueProcessId
;
1404 ProcessBasicInformationP
->BasePriority
=
1405 Process
->Pcb
.BasePriority
;
1409 *ReturnLength
= sizeof(PROCESS_BASIC_INFORMATION
);
1414 Status
= _SEH_GetExceptionCode();
1420 case ProcessQuotaLimits
:
1421 case ProcessIoCounters
:
1422 Status
= STATUS_NOT_IMPLEMENTED
;
1427 PKERNEL_USER_TIMES ProcessTimeP
= (PKERNEL_USER_TIMES
)ProcessInformation
;
1430 ProcessTimeP
->CreateTime
= Process
->CreateTime
;
1431 ProcessTimeP
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
* 100000LL;
1432 ProcessTimeP
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
* 100000LL;
1433 ProcessTimeP
->ExitTime
= Process
->ExitTime
;
1437 *ReturnLength
= sizeof(KERNEL_USER_TIMES
);
1442 Status
= _SEH_GetExceptionCode();
1448 case ProcessDebugPort
:
1452 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
!= NULL
? (HANDLE
)-1 : NULL
);
1455 *ReturnLength
= sizeof(HANDLE
);
1460 Status
= _SEH_GetExceptionCode();
1466 case ProcessLdtInformation
:
1467 case ProcessWorkingSetWatch
:
1468 case ProcessWx86Information
:
1469 Status
= STATUS_NOT_IMPLEMENTED
;
1472 case ProcessHandleCount
:
1474 ULONG HandleCount
= ObpGetHandleCountByHandleTable(Process
->ObjectTable
);
1478 *(PULONG
)ProcessInformation
= HandleCount
;
1481 *ReturnLength
= sizeof(ULONG
);
1486 Status
= _SEH_GetExceptionCode();
1492 case ProcessSessionInformation
:
1494 PPROCESS_SESSION_INFORMATION SessionInfo
= (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1498 SessionInfo
->SessionId
= Process
->SessionId
;
1501 *ReturnLength
= sizeof(PROCESS_SESSION_INFORMATION
);
1506 Status
= _SEH_GetExceptionCode();
1512 case ProcessWow64Information
:
1513 DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
1514 Status
= STATUS_NOT_IMPLEMENTED
;
1517 case ProcessVmCounters
:
1519 PVM_COUNTERS pOut
= (PVM_COUNTERS
)ProcessInformation
;
1523 pOut
->PeakVirtualSize
= Process
->PeakVirtualSize
;
1525 * Here we should probably use VirtualSize.LowPart, but due to
1526 * incompatibilities in current headers (no unnamed union),
1529 pOut
->VirtualSize
= (ULONG
)Process
->VirtualSize
.QuadPart
;
1530 pOut
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
1531 pOut
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
1532 pOut
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
1533 pOut
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[0]; // TODO: Verify!
1534 pOut
->QuotaPagedPoolUsage
= Process
->QuotaPoolUsage
[0]; // TODO: Verify!
1535 pOut
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[1]; // TODO: Verify!
1536 pOut
->QuotaNonPagedPoolUsage
= Process
->QuotaPoolUsage
[1]; // TODO: Verify!
1537 pOut
->PagefileUsage
= Process
->PagefileUsage
;
1538 pOut
->PeakPagefileUsage
= Process
->PeakPagefileUsage
;
1542 *ReturnLength
= sizeof(VM_COUNTERS
);
1547 Status
= _SEH_GetExceptionCode();
1553 case ProcessDefaultHardErrorMode
:
1555 PULONG HardErrMode
= (PULONG
)ProcessInformation
;
1558 *HardErrMode
= Process
->DefaultHardErrorProcessing
;
1561 *ReturnLength
= sizeof(ULONG
);
1566 Status
= _SEH_GetExceptionCode();
1572 case ProcessPriorityBoost
:
1574 PULONG BoostEnabled
= (PULONG
)ProcessInformation
;
1578 *BoostEnabled
= Process
->Pcb
.DisableBoost
? FALSE
: TRUE
;
1582 *ReturnLength
= sizeof(ULONG
);
1587 Status
= _SEH_GetExceptionCode();
1593 case ProcessDeviceMap
:
1595 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
1597 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
1601 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
1604 *ReturnLength
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
1609 Status
= _SEH_GetExceptionCode();
1615 case ProcessPriorityClass
:
1617 PUSHORT Priority
= (PUSHORT
)ProcessInformation
;
1621 *Priority
= Process
->PriorityClass
;
1625 *ReturnLength
= sizeof(USHORT
);
1630 Status
= _SEH_GetExceptionCode();
1636 case ProcessImageFileName
:
1639 * We DO NOT return the file name stored in the EPROCESS structure.
1640 * Propably if we can't find a PEB or ProcessParameters structure for the
1643 if(Process
->Peb
!= NULL
)
1645 PRTL_USER_PROCESS_PARAMETERS ProcParams
= NULL
;
1646 UNICODE_STRING LocalDest
;
1648 ULONG ImagePathLen
= 0;
1649 PUNICODE_STRING DstPath
= (PUNICODE_STRING
)ProcessInformation
;
1651 /* we need to attach to the process to make sure we're in the right context! */
1652 Attached
= Process
!= PsGetCurrentProcess();
1655 KeAttachProcess(&Process
->Pcb
);
1659 ProcParams
= Process
->Peb
->ProcessParameters
;
1660 ImagePathLen
= ProcParams
->ImagePathName
.Length
;
1664 Status
= _SEH_GetExceptionCode();
1668 if(NT_SUCCESS(Status
))
1670 if(ProcessInformationLength
< sizeof(UNICODE_STRING
) + ImagePathLen
+ sizeof(WCHAR
))
1672 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1676 PWSTR StrSource
= NULL
;
1678 /* create a DstPath structure on the stack */
1681 LocalDest
.Length
= ImagePathLen
;
1682 LocalDest
.MaximumLength
= ImagePathLen
+ sizeof(WCHAR
);
1683 LocalDest
.Buffer
= (PWSTR
)(DstPath
+ 1);
1685 /* save a copy of the pointer to the source buffer */
1686 StrSource
= ProcParams
->ImagePathName
.Buffer
;
1690 Status
= _SEH_GetExceptionCode();
1694 if(NT_SUCCESS(Status
))
1696 /* now, let's allocate some anonymous memory to copy the string to.
1697 we can't just copy it to the buffer the caller pointed as it might
1698 be user memory in another context */
1699 PWSTR PathCopy
= ExAllocatePool(PagedPool
, LocalDest
.Length
+ sizeof(WCHAR
));
1700 if(PathCopy
!= NULL
)
1702 /* make a copy of the buffer to the temporary buffer */
1705 RtlCopyMemory(PathCopy
, StrSource
, LocalDest
.Length
);
1706 PathCopy
[LocalDest
.Length
/ sizeof(WCHAR
)] = L
'\0';
1710 Status
= _SEH_GetExceptionCode();
1714 /* detach from the process */
1718 /* only copy the string back to the caller if we were able to
1719 copy it into the temporary buffer! */
1720 if(NT_SUCCESS(Status
))
1722 /* now let's copy the buffer back to the caller */
1725 *DstPath
= LocalDest
;
1726 RtlCopyMemory(LocalDest
.Buffer
, PathCopy
, LocalDest
.Length
+ sizeof(WCHAR
));
1729 *ReturnLength
= sizeof(UNICODE_STRING
) + LocalDest
.Length
+ sizeof(WCHAR
);
1734 Status
= _SEH_GetExceptionCode();
1739 /* we're done with the copy operation, free the temporary kernel buffer */
1740 ExFreePool(PathCopy
);
1742 /* we need to bail because we're already detached from the process */
1747 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1753 /* don't forget to detach from the process!!! */
1759 /* FIXME - what to do here? */
1760 Status
= STATUS_UNSUCCESSFUL
;
1769 /* receive the process cookie, this is only allowed for the current
1772 Process
= PsGetCurrentProcess();
1774 Cookie
= Process
->Cookie
;
1777 LARGE_INTEGER SystemTime
;
1781 /* generate a new cookie */
1783 KeQuerySystemTime(&SystemTime
);
1785 Prcb
= KeGetCurrentPrcb();
1787 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
1788 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
1790 /* try to set the new cookie, return the current one if another thread
1791 set it in the meanwhile */
1792 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
1797 /* successfully set the cookie */
1804 *(PULONG
)ProcessInformation
= Cookie
;
1807 *ReturnLength
= sizeof(ULONG
);
1812 Status
= _SEH_GetExceptionCode();
1820 * Note: The following 10 information classes are verified to not be
1821 * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
1823 case ProcessBasePriority
:
1824 case ProcessRaisePriority
:
1825 case ProcessExceptionPort
:
1826 case ProcessAccessToken
:
1827 case ProcessLdtSize
:
1828 case ProcessIoPortHandlers
:
1829 case ProcessUserModeIOPL
:
1830 case ProcessEnableAlignmentFaultFixup
:
1831 case ProcessAffinityMask
:
1832 case ProcessForegroundInformation
:
1834 Status
= STATUS_INVALID_INFO_CLASS
;
1837 if(ProcessInformationClass
!= ProcessCookie
)
1839 ObDereferenceObject(Process
);
1847 PspAssignPrimaryToken(PEPROCESS Process
,
1850 PACCESS_TOKEN Token
;
1851 PACCESS_TOKEN OldToken
;
1854 Status
= ObReferenceObjectByHandle(TokenHandle
,
1860 if (!NT_SUCCESS(Status
))
1864 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
1865 if (NT_SUCCESS(Status
))
1867 ObDereferenceObject(OldToken
);
1869 ObDereferenceObject(Token
);
1877 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1878 IN PROCESSINFOCLASS ProcessInformationClass
,
1879 IN PVOID ProcessInformation
,
1880 IN ULONG ProcessInformationLength
)
1883 KPROCESSOR_MODE PreviousMode
;
1885 NTSTATUS Status
= STATUS_SUCCESS
;
1889 PreviousMode
= ExGetPreviousMode();
1891 DefaultSetInfoBufferCheck(ProcessInformationClass
,
1894 ProcessInformationLength
,
1897 if(!NT_SUCCESS(Status
))
1899 DPRINT1("NtSetInformationProcess() %d %x %x called\n", ProcessInformationClass
, ProcessInformation
, ProcessInformationLength
);
1900 DPRINT1("NtSetInformationProcess() %x failed, Status: 0x%x\n", Status
);
1904 switch(ProcessInformationClass
)
1906 case ProcessSessionInformation
:
1907 Access
= PROCESS_SET_INFORMATION
| PROCESS_SET_SESSIONID
;
1909 case ProcessExceptionPort
:
1910 case ProcessDebugPort
:
1911 Access
= PROCESS_SET_INFORMATION
| PROCESS_SET_PORT
;
1915 Access
= PROCESS_SET_INFORMATION
;
1919 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1925 if (!NT_SUCCESS(Status
))
1930 switch (ProcessInformationClass
)
1932 case ProcessQuotaLimits
:
1933 case ProcessBasePriority
:
1934 case ProcessRaisePriority
:
1935 Status
= STATUS_NOT_IMPLEMENTED
;
1938 case ProcessDebugPort
:
1940 HANDLE PortHandle
= NULL
;
1942 /* make a safe copy of the buffer on the stack */
1945 PortHandle
= *(PHANDLE
)ProcessInformation
;
1946 Status
= (PortHandle
!= NULL
? STATUS_SUCCESS
: STATUS_INVALID_PARAMETER
);
1950 Status
= _SEH_GetExceptionCode();
1954 if(NT_SUCCESS(Status
))
1958 /* in case we had success reading from the buffer, verify the provided
1961 Status
= ObReferenceObjectByHandle(PortHandle
,
1967 if(NT_SUCCESS(Status
))
1969 /* lock the process to be thread-safe! */
1971 Status
= PsLockProcess(Process
, FALSE
);
1972 if(NT_SUCCESS(Status
))
1975 * according to "NT Native API" documentation, setting the debug
1976 * port is only permitted once!
1978 if(Process
->DebugPort
== NULL
)
1980 /* keep the reference to the handle! */
1981 Process
->DebugPort
= DebugPort
;
1985 /* we're now debugging the process, so set the flag in the PEB
1986 structure. However, to access it we need to attach to the
1987 process so we're sure we're in the right context! */
1989 KeAttachProcess(&Process
->Pcb
);
1992 Process
->Peb
->BeingDebugged
= TRUE
;
1996 DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process
, _SEH_GetExceptionCode());
2001 Status
= STATUS_SUCCESS
;
2005 ObDereferenceObject(DebugPort
);
2006 Status
= STATUS_PORT_ALREADY_SET
;
2008 PsUnlockProcess(Process
);
2012 ObDereferenceObject(DebugPort
);
2019 case ProcessExceptionPort
:
2021 HANDLE PortHandle
= NULL
;
2023 /* make a safe copy of the buffer on the stack */
2026 PortHandle
= *(PHANDLE
)ProcessInformation
;
2027 Status
= STATUS_SUCCESS
;
2031 Status
= _SEH_GetExceptionCode();
2035 if(NT_SUCCESS(Status
))
2037 PEPORT ExceptionPort
;
2039 /* in case we had success reading from the buffer, verify the provided
2042 Status
= ObReferenceObjectByHandle(PortHandle
,
2046 (PVOID
)&ExceptionPort
,
2048 if(NT_SUCCESS(Status
))
2050 /* lock the process to be thread-safe! */
2052 Status
= PsLockProcess(Process
, FALSE
);
2053 if(NT_SUCCESS(Status
))
2056 * according to "NT Native API" documentation, setting the exception
2057 * port is only permitted once!
2059 if(Process
->ExceptionPort
== NULL
)
2061 /* keep the reference to the handle! */
2062 Process
->ExceptionPort
= ExceptionPort
;
2063 Status
= STATUS_SUCCESS
;
2067 ObDereferenceObject(ExceptionPort
);
2068 Status
= STATUS_PORT_ALREADY_SET
;
2070 PsUnlockProcess(Process
);
2074 ObDereferenceObject(ExceptionPort
);
2081 case ProcessAccessToken
:
2083 HANDLE TokenHandle
= NULL
;
2085 /* make a safe copy of the buffer on the stack */
2088 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->Token
;
2089 Status
= STATUS_SUCCESS
;
2093 Status
= _SEH_GetExceptionCode();
2097 if(NT_SUCCESS(Status
))
2099 /* in case we had success reading from the buffer, perform the actual task */
2100 Status
= PspAssignPrimaryToken(Process
, TokenHandle
);
2105 case ProcessDefaultHardErrorMode
:
2109 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
2110 *(PLONG
)ProcessInformation
);
2111 Status
= STATUS_SUCCESS
;
2115 Status
= _SEH_GetExceptionCode();
2121 case ProcessSessionInformation
:
2123 PROCESS_SESSION_INFORMATION SessionInfo
;
2124 Status
= STATUS_SUCCESS
;
2128 /* copy the structure to the stack */
2129 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
2133 Status
= _SEH_GetExceptionCode();
2137 if(NT_SUCCESS(Status
))
2139 /* we successfully copied the structure to the stack, continue processing */
2142 * setting the session id requires the SeTcbPrivilege!
2144 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
2147 DPRINT1("NtSetInformationProcess: Caller requires the SeTcbPrivilege privilege for setting ProcessSessionInformation!\n");
2148 /* can't set the session id, bail! */
2149 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2153 /* FIXME - update the session id for the process token */
2155 Status
= PsLockProcess(Process
, FALSE
);
2156 if(NT_SUCCESS(Status
))
2158 Process
->SessionId
= SessionInfo
.SessionId
;
2160 /* Update the session id in the PEB structure */
2161 if(Process
->Peb
!= NULL
)
2163 /* we need to attach to the process to make sure we're in the right
2164 context to access the PEB structure */
2165 KeAttachProcess(&Process
->Pcb
);
2169 /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
2171 Status
= STATUS_SUCCESS
;
2175 Status
= _SEH_GetExceptionCode();
2182 PsUnlockProcess(Process
);
2188 case ProcessPriorityClass
:
2190 PROCESS_PRIORITY_CLASS ppc
;
2194 ppc
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
2198 Status
= _SEH_GetExceptionCode();
2202 if(NT_SUCCESS(Status
))
2209 case ProcessLdtInformation
:
2210 case ProcessLdtSize
:
2211 case ProcessIoPortHandlers
:
2212 case ProcessWorkingSetWatch
:
2213 case ProcessUserModeIOPL
:
2214 case ProcessEnableAlignmentFaultFixup
:
2215 case ProcessAffinityMask
:
2216 Status
= STATUS_NOT_IMPLEMENTED
;
2219 case ProcessBasicInformation
:
2220 case ProcessIoCounters
:
2222 case ProcessPooledUsageAndLimits
:
2223 case ProcessWx86Information
:
2224 case ProcessHandleCount
:
2225 case ProcessWow64Information
:
2227 Status
= STATUS_INVALID_INFO_CLASS
;
2229 ObDereferenceObject(Process
);
2234 /**********************************************************************
2236 * PiQuerySystemProcessInformation
2239 * Compute the size of a process+thread snapshot as
2240 * expected by NtQuerySystemInformation.
2243 * 0 on error; otherwise the size, in bytes of the buffer
2244 * required to write a full snapshot.
2247 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
2250 PiQuerySystemProcessInformation(PVOID Buffer
,
2254 return STATUS_NOT_IMPLEMENTED
;
2257 PLIST_ENTRY CurrentEntryP
;
2259 PLIST_ENTRY CurrentEntryT
;
2262 ULONG RequiredSize
= 0L;
2263 BOOLEAN SizeOnly
= FALSE
;
2267 PSYSTEM_PROCESS_INFORMATION pInfoP
= (PSYSTEM_PROCESS_INFORMATION
) SnapshotBuffer
;
2268 PSYSTEM_PROCESS_INFORMATION pInfoPLast
= NULL
;
2269 PSYSTEM_THREAD_INFO pInfoT
= NULL
;
2272 /* Lock the process list. */
2273 ExAcquireFastMutex(&PspActiveProcessMutex
);
2276 * Scan the process list. Since the
2277 * list is circular, the guard is false
2278 * after the last process.
2280 for ( CurrentEntryP
= PsActiveProcessHead
.Flink
;
2281 (CurrentEntryP
!= & PsActiveProcessHead
);
2282 CurrentEntryP
= CurrentEntryP
->Flink
2286 * Compute how much space is
2287 * occupied in the snapshot
2288 * by adding this process info.
2289 * (at least one thread).
2291 SpiSizeCurrent
= sizeof (SYSTEM_PROCESS_INFORMATION
);
2292 RequiredSize
+= SpiSizeCurrent
;
2294 * Do not write process data in the
2295 * buffer if it is too small.
2297 if (TRUE
== SizeOnly
) continue;
2299 * Check if the buffer can contain
2300 * the full snapshot.
2302 if (Size
< RequiredSize
)
2308 * Get a reference to the
2309 * process descriptor we are
2312 CurrentP
= CONTAINING_RECORD(
2318 * Write process data in the buffer.
2320 RtlZeroMemory (pInfoP
, sizeof (SYSTEM_PROCESS_INFORMATION
));
2322 pInfoP
->ThreadCount
= 0L;
2323 pInfoP
->ProcessId
= CurrentP
->UniqueProcessId
;
2324 RtlInitUnicodeString (
2326 CurrentP
->ImageFileName
2329 for ( pInfoT
= & CurrentP
->ThreadSysInfo
[0],
2330 CurrentEntryT
= CurrentP
->ThreadListHead
.Flink
;
2332 (CurrentEntryT
!= & CurrentP
->ThreadListHead
);
2334 pInfoT
= & CurrentP
->ThreadSysInfo
[pInfoP
->ThreadCount
],
2335 CurrentEntryT
= CurrentEntryT
->Flink
2339 * Recalculate the size of the
2340 * information block.
2342 if (0 < pInfoP
->ThreadCount
)
2344 RequiredSize
+= sizeof (SYSTEM_THREAD_INFORMATION
);
2347 * Do not write thread data in the
2348 * buffer if it is too small.
2350 if (TRUE
== SizeOnly
) continue;
2352 * Check if the buffer can contain
2353 * the full snapshot.
2355 if (Size
< RequiredSize
)
2361 * Get a reference to the
2362 * thread descriptor we are
2365 CurrentT
= CONTAINING_RECORD(
2371 * Write thread data.
2375 sizeof (SYSTEM_THREAD_INFORMATION
)
2377 pInfoT
->KernelTime
= CurrentT
-> ; /* TIME */
2378 pInfoT
->UserTime
= CurrentT
-> ; /* TIME */
2379 pInfoT
->CreateTime
= CurrentT
-> ; /* TIME */
2380 pInfoT
->TickCount
= CurrentT
-> ; /* ULONG */
2381 pInfoT
->StartEIP
= CurrentT
-> ; /* ULONG */
2382 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2383 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2384 pInfoT
->DynamicPriority
= CurrentT
-> ; /* ULONG */
2385 pInfoT
->BasePriority
= CurrentT
-> ; /* ULONG */
2386 pInfoT
->nSwitches
= CurrentT
-> ; /* ULONG */
2387 pInfoT
->State
= CurrentT
-> ; /* DWORD */
2388 pInfoT
->WaitReason
= CurrentT
-> ; /* KWAIT_REASON */
2390 * Count the number of threads
2393 ++ pInfoP
->ThreadCount
;
2396 * Save the size of information
2397 * stored in the buffer for the
2400 pInfoP
->RelativeOffset
= SpiSize
;
2402 * Save a reference to the last
2403 * valid information block.
2405 pInfoPLast
= pInfoP
;
2407 * Compute the offset of the
2408 * SYSTEM_PROCESS_INFORMATION
2409 * descriptor in the snapshot
2410 * buffer for the next process.
2412 (ULONG
) pInfoP
+= SpiSize
;
2415 * Unlock the process list.
2417 ExReleaseFastMutex (
2418 & PspActiveProcessMutex
2421 * Return the proper error status code,
2422 * if the buffer was too small.
2424 if (TRUE
== SizeOnly
)
2426 if (NULL
!= RequiredSize
)
2428 *pRequiredSize
= RequiredSize
;
2430 return STATUS_INFO_LENGTH_MISMATCH
;
2433 * Mark the end of the snapshot.
2435 pInfoP
->RelativeOffset
= 0L;
2437 return STATUS_SUCCESS
;
2444 LARGE_INTEGER STDCALL
2445 PsGetProcessExitTime(VOID
)
2448 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
2457 PsGetProcessCreateTimeQuadPart(
2461 return Process
->CreateTime
.QuadPart
;
2469 PsGetProcessDebugPort(
2473 return Process
->DebugPort
;
2481 PsGetProcessExitProcessCalled(
2485 return Process
->ExitProcessCalled
;
2493 PsGetProcessExitStatus(
2497 return Process
->ExitStatus
;
2509 return (HANDLE
)Process
->UniqueProcessId
;
2517 PsGetProcessImageFileName(
2521 return (LPSTR
)Process
->ImageFileName
;
2529 PsGetProcessInheritedFromUniqueProcessId(
2533 return Process
->InheritedFromUniqueProcessId
;
2545 return Process
->Job
;
2557 return Process
->Peb
;
2565 PsGetProcessPriorityClass(
2569 return Process
->PriorityClass
;
2577 PsGetProcessSectionBaseAddress(
2581 return Process
->SectionBaseAddress
;
2589 PsGetProcessSecurityPort(
2593 return Process
->SecurityPort
;
2601 PsGetProcessSessionId(
2605 return (HANDLE
)Process
->SessionId
;
2613 PsGetProcessWin32Process(
2617 return Process
->Win32Process
;
2625 PsGetProcessWin32WindowStation(
2629 return Process
->Win32WindowStation
;
2637 PsIsProcessBeingDebugged(
2641 return FALSE
/*Process->IsProcessBeingDebugged*/;
2649 PsLookupProcessByProcessId(IN HANDLE ProcessId
,
2650 OUT PEPROCESS
*Process
)
2652 PHANDLE_TABLE_ENTRY CidEntry
;
2653 PEPROCESS FoundProcess
;
2659 CidEntry
= PsLookupCidHandle(ProcessId
, PsProcessType
, (PVOID
*)&FoundProcess
);
2660 if(CidEntry
!= NULL
)
2662 ObReferenceObject(FoundProcess
);
2664 PsUnlockCidHandle(CidEntry
);
2666 *Process
= FoundProcess
;
2667 return STATUS_SUCCESS
;
2670 return STATUS_INVALID_PARAMETER
;
2675 PspRunCreateProcessNotifyRoutines
2677 PEPROCESS CurrentProcess
,
2682 HANDLE ProcessId
= (HANDLE
)CurrentProcess
->UniqueProcessId
;
2683 HANDLE ParentId
= CurrentProcess
->InheritedFromUniqueProcessId
;
2685 for(i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2686 if(PiProcessNotifyRoutine
[i
])
2687 PiProcessNotifyRoutine
[i
](ParentId
, ProcessId
, Create
);
2694 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
2701 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2703 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
2705 PiProcessNotifyRoutine
[i
] = NULL
;
2710 return(STATUS_SUCCESS
);
2714 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2716 if (PiProcessNotifyRoutine
[i
] == NULL
)
2718 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
2723 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2725 return STATUS_INSUFFICIENT_RESOURCES
;
2728 return STATUS_SUCCESS
;
2732 PspRunLoadImageNotifyRoutines(
2733 PUNICODE_STRING FullImageName
,
2735 PIMAGE_INFO ImageInfo
)
2739 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2740 if (PiLoadImageNotifyRoutine
[i
])
2741 PiLoadImageNotifyRoutine
[i
](FullImageName
, ProcessId
, ImageInfo
);
2749 PsRemoveLoadImageNotifyRoutine(
2750 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
2754 return STATUS_NOT_IMPLEMENTED
;
2761 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
2765 for (i
= 0; i
< MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
; i
++)
2767 if (PiLoadImageNotifyRoutine
[i
] == NULL
)
2769 PiLoadImageNotifyRoutine
[i
] = NotifyRoutine
;
2774 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2776 return STATUS_INSUFFICIENT_RESOURCES
;
2779 return STATUS_SUCCESS
;
2787 PsSetProcessPriorityClass(
2792 Process
->PriorityClass
= PriorityClass
;
2800 PsSetProcessSecurityPort(
2805 Process
->SecurityPort
= SecurityPort
;
2813 PsSetProcessWin32Process(
2818 Process
->Win32Process
= Win32Process
;
2826 PsSetProcessWin32WindowStation(
2831 Process
->Win32WindowStation
= WindowStation
;
2841 IN PEPROCESS Process
,
2842 IN POOL_TYPE PoolType
,
2848 /* Charge the usage */
2849 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
2851 /* Raise Exception */
2852 if (!NT_SUCCESS(Status
)) {
2853 ExRaiseStatus(Status
);
2862 PsChargeProcessNonPagedPoolQuota (
2863 IN PEPROCESS Process
,
2867 /* Call the general function */
2868 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
2876 PsChargeProcessPagedPoolQuota (
2877 IN PEPROCESS Process
,
2881 /* Call the general function */
2882 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
2890 PsChargeProcessPoolQuota(
2891 IN PEPROCESS Process
,
2892 IN POOL_TYPE PoolType
,
2896 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
2900 /* Get current Quota Block */
2901 QuotaBlock
= Process
->QuotaBlock
;
2903 /* Quota Operations are not to be done on the SYSTEM Process */
2904 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
2906 /* New Size in use */
2907 NewUsageSize
= QuotaBlock
->QuotaEntry
[PoolType
].Usage
+ Amount
;
2909 /* Does this size respect the quota? */
2910 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Limit
) {
2912 /* It doesn't, so keep raising the Quota */
2913 while (MiRaisePoolQuota(PoolType
, QuotaBlock
->QuotaEntry
[PoolType
].Limit
, &NewMaxQuota
)) {
2914 /* Save new Maximum Quota */
2915 QuotaBlock
->QuotaEntry
[PoolType
].Limit
= NewMaxQuota
;
2917 /* See if the new Maximum Quota fulfills our need */
2918 if (NewUsageSize
<= NewMaxQuota
) goto QuotaChanged
;
2921 return STATUS_QUOTA_EXCEEDED
;
2925 /* Save new Usage */
2926 QuotaBlock
->QuotaEntry
[PoolType
].Usage
= NewUsageSize
;
2928 /* Is this a new peak? */
2929 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Peak
) {
2930 QuotaBlock
->QuotaEntry
[PoolType
].Peak
= NewUsageSize
;
2934 return STATUS_SUCCESS
;
2943 IN PEPROCESS Process
,
2944 IN POOL_TYPE PoolType
,
2956 PsReturnProcessNonPagedPoolQuota(
2957 IN PEPROCESS Process
,
2969 PsReturnProcessPagedPoolQuota(
2970 IN PEPROCESS Process
,
2978 PsLockProcess(PEPROCESS Process
, BOOL Timeout
)
2981 PKTHREAD PrevLockOwner
;
2982 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2983 PLARGE_INTEGER Delay
= (Timeout
? &PsLockTimeout
: NULL
);
2984 PKTHREAD CallingThread
= KeGetCurrentThread();
2988 KeEnterCriticalRegion();
2992 if(Process
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
2994 KeLeaveCriticalRegion();
2995 return STATUS_PROCESS_IS_TERMINATING
;
2998 PrevLockOwner
= (PKTHREAD
)InterlockedCompareExchangePointer(
2999 &Process
->LockOwner
, CallingThread
, NULL
);
3000 if(PrevLockOwner
== NULL
|| PrevLockOwner
== CallingThread
)
3002 /* we got the lock or already locked it */
3003 if(InterlockedIncrementUL(&Process
->LockCount
) == 1)
3005 KeClearEvent(&Process
->LockEvent
);
3008 return STATUS_SUCCESS
;
3014 Status
= KeWaitForSingleObject(&Process
->LockEvent
,
3019 if(!NT_SUCCESS(Status
) || Status
== STATUS_TIMEOUT
)
3022 if(Status
== STATUS_TIMEOUT
)
3024 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process
);
3027 KeLeaveCriticalRegion();
3034 KeDelayExecutionThread(KernelMode
, FALSE
, &ShortPsLockDelay
);
3043 PsUnlockProcess(PEPROCESS Process
)
3047 ASSERT(Process
->LockOwner
== KeGetCurrentThread());
3049 if(InterlockedDecrementUL(&Process
->LockCount
) == 0)
3051 InterlockedExchangePointer(&Process
->LockOwner
, NULL
);
3052 KeSetEvent(&Process
->LockEvent
, IO_NO_INCREMENT
, FALSE
);
3055 KeLeaveCriticalRegion();