3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/process.c
6 * PURPOSE: Process managment
7 * PROGRAMMER: David Welch (welch@cwcom.net)
12 /* INCLUDES ******************************************************************/
15 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
17 #include <internal/mm.h>
18 #include <internal/ke.h>
19 #include <internal/ps.h>
20 #include <internal/se.h>
21 #include <internal/id.h>
23 #include <internal/ldr.h>
24 #include <internal/port.h>
26 #include <internal/dbg.h>
27 #include <internal/pool.h>
29 #include <internal/se.h>
30 #include <internal/kd.h>
33 #include <internal/debug.h>
35 /* GLOBALS ******************************************************************/
37 PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
38 HANDLE SystemProcessHandle = NULL;
40 POBJECT_TYPE EXPORTED PsProcessType = NULL;
42 LIST_ENTRY PsProcessListHead;
43 static KSPIN_LOCK PsProcessListLock;
44 static ULONG PiNextProcessUniqueId = 0;
46 static GENERIC_MAPPING PiProcessMapping = {PROCESS_READ,
51 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
53 static ULONG PiProcessNotifyRoutineCount = 0;
54 static PCREATE_PROCESS_NOTIFY_ROUTINE
55 PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
57 /* FUNCTIONS *****************************************************************/
61 PsGetNextProcess(PEPROCESS OldProcess)
64 PEPROCESS NextProcess;
67 if (OldProcess == NULL)
69 return(PsInitialSystemProcess);
72 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
73 if (OldProcess->ProcessListEntry.Flink == &PsProcessListHead)
75 NextProcess = CONTAINING_RECORD(PsProcessListHead.Flink,
81 NextProcess = CONTAINING_RECORD(OldProcess->ProcessListEntry.Flink,
85 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
86 Status = ObReferenceObjectByPointer(NextProcess,
90 if (!NT_SUCCESS(Status))
92 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
95 ObDereferenceObject(OldProcess);
102 _NtOpenProcessToken(IN HANDLE ProcessHandle,
103 IN ACCESS_MASK DesiredAccess,
104 OUT PHANDLE TokenHandle)
109 Status = PsOpenTokenOfProcess(ProcessHandle,
111 if (!NT_SUCCESS(Status))
115 Status = ObCreateHandle(PsGetCurrentProcess(),
120 ObDereferenceObject(Token);
126 NtOpenProcessToken(IN HANDLE ProcessHandle,
127 IN ACCESS_MASK DesiredAccess,
128 OUT PHANDLE TokenHandle)
130 return _NtOpenProcessToken(ProcessHandle, DesiredAccess, TokenHandle);
134 PACCESS_TOKEN STDCALL
135 PsReferencePrimaryToken(PEPROCESS Process)
137 ObReferenceObjectByPointer(Process->Token,
141 return(Process->Token);
146 PsOpenTokenOfProcess(HANDLE ProcessHandle,
147 PACCESS_TOKEN* Token)
152 Status = ObReferenceObjectByHandle(ProcessHandle,
153 PROCESS_QUERY_INFORMATION,
158 if (!NT_SUCCESS(Status))
162 *Token = PsReferencePrimaryToken(Process);
163 ObDereferenceObject(Process);
164 return(STATUS_SUCCESS);
169 PiKillMostProcesses(VOID)
172 PLIST_ENTRY current_entry;
175 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
177 current_entry = PsProcessListHead.Flink;
178 while (current_entry != &PsProcessListHead)
180 current = CONTAINING_RECORD(current_entry, EPROCESS,
182 current_entry = current_entry->Flink;
184 if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
185 current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
187 PiTerminateProcessThreads(current, STATUS_SUCCESS);
191 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
196 PsInitProcessManagment(VOID)
203 * Register the process object type
206 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
208 PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
209 PsProcessType->TotalObjects = 0;
210 PsProcessType->TotalHandles = 0;
211 PsProcessType->MaxObjects = ULONG_MAX;
212 PsProcessType->MaxHandles = ULONG_MAX;
213 PsProcessType->PagedPoolCharge = 0;
214 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
215 PsProcessType->Mapping = &PiProcessMapping;
216 PsProcessType->Dump = NULL;
217 PsProcessType->Open = NULL;
218 PsProcessType->Close = NULL;
219 PsProcessType->Delete = PiDeleteProcess;
220 PsProcessType->Parse = NULL;
221 PsProcessType->Security = NULL;
222 PsProcessType->QueryName = NULL;
223 PsProcessType->OkayToClose = NULL;
224 PsProcessType->Create = NULL;
225 PsProcessType->DuplicationNotify = NULL;
227 RtlInitUnicodeStringFromLiteral(&PsProcessType->TypeName, L"Process");
229 InitializeListHead(&PsProcessListHead);
230 KeInitializeSpinLock(&PsProcessListLock);
233 * Initialize the system process
235 Status = ObCreateObject(NULL,
239 (PVOID*)&PsInitialSystemProcess);
240 if (!NT_SUCCESS(Status))
245 /* System threads may run on any processor. */
246 PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
247 PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
248 KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
252 KProcess = &PsInitialSystemProcess->Pcb;
254 MmInitializeAddressSpace(PsInitialSystemProcess,
255 &PsInitialSystemProcess->AddressSpace);
256 ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess);
257 KProcess->DirectoryTableBase =
258 (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
259 PsInitialSystemProcess->UniqueProcessId =
260 InterlockedIncrement((LONG *)&PiNextProcessUniqueId);
261 PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
262 PsInitialSystemProcess->Win32Desktop = (HANDLE)0;
264 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
265 InsertHeadList(&PsProcessListHead,
266 &PsInitialSystemProcess->ProcessListEntry);
267 InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
268 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
270 strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM");
272 SepCreateSystemProcessToken(PsInitialSystemProcess);
274 ObCreateHandle(PsInitialSystemProcess,
275 PsInitialSystemProcess,
278 &SystemProcessHandle);
282 PiDeleteProcess(PVOID ObjectBody)
288 DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody);
290 Process = (PEPROCESS)ObjectBody;
291 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
292 for (i = 0; i < PiProcessNotifyRoutineCount; i++)
294 PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
295 (HANDLE)Process->UniqueProcessId,
298 RemoveEntryList(&Process->ProcessListEntry);
299 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
302 KDB_DELETEPROCESS_HOOK(Process);
304 ObDereferenceObject(Process->Token);
305 ObDeleteHandleTable(Process);
307 (VOID)MmReleaseMmInfo(Process);
312 PsCreatePeb(HANDLE ProcessHandle,
322 memset(&Peb, 0, sizeof(Peb));
323 Peb.ImageBaseAddress = ImageBase;
325 PebBase = (PVOID)PEB_BASE;
327 Status = NtAllocateVirtualMemory(ProcessHandle,
331 MEM_RESERVE | MEM_COMMIT,
333 if (!NT_SUCCESS(Status))
338 NtWriteVirtualMemory(ProcessHandle,
344 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase);
348 return(STATUS_SUCCESS);
353 KeGetCurrentProcess(VOID)
355 * FUNCTION: Returns a pointer to the current process
358 return(&(PsGetCurrentProcess()->Pcb));
362 PsGetCurrentProcessId(VOID)
364 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
368 * FUNCTION: Returns a pointer to the current process
371 IoGetCurrentProcess(VOID)
373 if (PsGetCurrentThread() == NULL ||
374 PsGetCurrentThread()->ThreadsProcess == NULL)
376 return(PsInitialSystemProcess);
380 return(PsGetCurrentThread()->ThreadsProcess);
385 PsCreateSystemProcess(PHANDLE ProcessHandle,
386 ACCESS_MASK DesiredAccess,
387 POBJECT_ATTRIBUTES ObjectAttributes)
389 return NtCreateProcess(ProcessHandle,
400 NtCreateProcess(OUT PHANDLE ProcessHandle,
401 IN ACCESS_MASK DesiredAccess,
402 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
403 IN HANDLE ParentProcessHandle,
404 IN BOOLEAN InheritObjectTable,
405 IN HANDLE SectionHandle OPTIONAL,
406 IN HANDLE DebugPortHandle OPTIONAL,
407 IN HANDLE ExceptionPortHandle OPTIONAL)
409 * FUNCTION: Creates a process.
411 * ProcessHandle (OUT) = Caller supplied storage for the resulting
413 * DesiredAccess = Specifies the allowed or desired access to the
414 * process can be a combination of
415 * STANDARD_RIGHTS_REQUIRED| ..
416 * ObjectAttribute = Initialized attributes for the object, contains
417 * the rootdirectory and the filename
418 * ParentProcess = Handle to the parent process.
419 * InheritObjectTable = Specifies to inherit the objects of the parent
421 * SectionHandle = Handle to a section object to back the image file
422 * DebugPort = Handle to a DebugPort if NULL the system default debug
424 * ExceptionPort = Handle to a exception port.
426 * This function maps to the win32 CreateProcess.
431 PEPROCESS ParentProcess;
435 PVOID LdrStartupAddr;
439 PEPORT ExceptionPort;
441 PMEMORY_AREA MemoryArea;
444 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
446 Status = ObReferenceObjectByHandle(ParentProcessHandle,
447 PROCESS_CREATE_PROCESS,
450 (PVOID*)&ParentProcess,
452 if (!NT_SUCCESS(Status))
454 DPRINT("NtCreateProcess() = %x\n",Status);
458 Status = ObCreateObject(ProcessHandle,
463 if (!NT_SUCCESS(Status))
465 ObDereferenceObject(ParentProcess);
466 DPRINT("ObCreateObject() = %x\n",Status);
470 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
474 KProcess = &Process->Pcb;
475 /* Inherit parent process's affinity. */
476 KProcess->Affinity = ParentProcess->Pcb.Affinity;
477 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
478 MmInitializeAddressSpace(Process,
479 &Process->AddressSpace);
480 Process->UniqueProcessId = InterlockedIncrement((LONG *)&PiNextProcessUniqueId);
481 Process->InheritedFromUniqueProcessId =
482 (HANDLE)ParentProcess->UniqueProcessId;
483 ObCreateHandleTable(ParentProcess,
486 MmCopyMmInfo(ParentProcess, Process);
487 if (ParentProcess->Win32WindowStation != (HANDLE)0)
489 /* Always duplicate the process window station. */
490 Process->Win32WindowStation = 0;
491 Status = ObDuplicateObject(ParentProcess,
493 ParentProcess->Win32WindowStation,
494 &Process->Win32WindowStation,
497 DUPLICATE_SAME_ACCESS);
498 if (!NT_SUCCESS(Status))
505 Process->Win32WindowStation = (HANDLE)0;
507 if (ParentProcess->Win32Desktop != (HANDLE)0)
509 /* Always duplicate the process window station. */
510 Process->Win32Desktop = 0;
511 Status = ObDuplicateObject(ParentProcess,
513 ParentProcess->Win32Desktop,
514 &Process->Win32Desktop,
517 DUPLICATE_SAME_ACCESS);
518 if (!NT_SUCCESS(Status))
525 Process->Win32Desktop = (HANDLE)0;
528 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
529 for (i = 0; i < PiProcessNotifyRoutineCount; i++)
531 PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
532 (HANDLE)Process->UniqueProcessId,
535 InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
536 InitializeListHead(&Process->ThreadListHead);
537 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
539 Process->Pcb.State = PROCESS_STATE_ACTIVE;
544 if (DebugPortHandle != NULL)
546 Status = ObReferenceObjectByHandle(DebugPortHandle,
552 if (!NT_SUCCESS(Status))
554 ObDereferenceObject(Process);
555 ObDereferenceObject(ParentProcess);
556 ZwClose(*ProcessHandle);
557 *ProcessHandle = NULL;
560 Process->DebugPort = DebugPort;
564 * Add the exception port
566 if (ExceptionPortHandle != NULL)
568 Status = ObReferenceObjectByHandle(ExceptionPortHandle,
572 (PVOID*)&ExceptionPort,
574 if (!NT_SUCCESS(Status))
576 ObDereferenceObject(Process);
577 ObDereferenceObject(ParentProcess);
578 ZwClose(*ProcessHandle);
579 *ProcessHandle = NULL;
582 Process->ExceptionPort = ExceptionPort;
586 * Now we have created the process proper
590 * Create the shared data page
592 MmLockAddressSpace(&Process->AddressSpace);
593 BaseAddress = (PVOID)USER_SHARED_DATA;
594 Status = MmCreateMemoryArea(Process,
595 &Process->AddressSpace,
596 MEMORY_AREA_SHARED_DATA,
602 MmUnlockAddressSpace(&Process->AddressSpace);
603 if (!NT_SUCCESS(Status))
605 DPRINT1("Failed to create shared data page\n");
612 Status = LdrpMapSystemDll(*ProcessHandle,
614 if (!NT_SUCCESS(Status))
616 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
617 ObDereferenceObject(Process);
618 ObDereferenceObject(ParentProcess);
623 * Map the process image
625 if (SectionHandle != NULL)
627 DPRINT("Mapping process image\n");
628 Status = LdrpMapImage(*ProcessHandle,
631 if (!NT_SUCCESS(Status))
633 DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
634 ObDereferenceObject(Process);
635 ObDereferenceObject(ParentProcess);
645 * Duplicate the token
647 Status = SepInitializeNewProcess(Process, ParentProcess);
648 if (!NT_SUCCESS(Status))
650 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
651 ObDereferenceObject(Process);
652 ObDereferenceObject(ParentProcess);
659 DPRINT("Creating PEB\n");
660 Status = PsCreatePeb(*ProcessHandle,
663 if (!NT_SUCCESS(Status))
665 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
666 ObDereferenceObject(Process);
667 ObDereferenceObject(ParentProcess);
668 ZwClose(*ProcessHandle);
669 *ProcessHandle = NULL;
675 * Maybe send a message to the creator process's debugger
678 if (ParentProcess->DebugPort != NULL)
680 LPC_DBG_MESSAGE Message;
683 ObCreateHandle(NULL, // Debugger Process
684 NULL, // SectionHandle
689 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
690 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
692 Message.Type = DBG_EVENT_CREATE_PROCESS;
693 Message.Data.CreateProcess.FileHandle = FileHandle;
694 Message.Data.CreateProcess.Base = ImageBase;
695 Message.Data.CreateProcess.EntryPoint = NULL; //
697 Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
702 ObDereferenceObject(Process);
703 ObDereferenceObject(ParentProcess);
704 return(STATUS_SUCCESS);
709 NtOpenProcess(OUT PHANDLE ProcessHandle,
710 IN ACCESS_MASK DesiredAccess,
711 IN POBJECT_ATTRIBUTES ObjectAttributes,
712 IN PCLIENT_ID ClientId)
714 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
715 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
716 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
717 ClientId->UniqueProcess, ClientId->UniqueThread);
721 * Not sure of the exact semantics
723 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
724 ObjectAttributes->ObjectName->Buffer != NULL)
729 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
730 ObjectAttributes->Attributes,
737 if (Status != STATUS_SUCCESS)
742 Status = ObCreateHandle(PsGetCurrentProcess(),
747 ObDereferenceObject(Process);
754 PLIST_ENTRY current_entry;
758 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
759 current_entry = PsProcessListHead.Flink;
760 while (current_entry != &PsProcessListHead)
762 current = CONTAINING_RECORD(current_entry, EPROCESS,
764 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
766 ObReferenceObjectByPointer(current,
770 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
771 Status = ObCreateHandle(PsGetCurrentProcess(),
776 ObDereferenceObject(current);
777 DPRINT("*ProcessHandle %x\n", ProcessHandle);
778 DPRINT("NtOpenProcess() = %x\n", Status);
781 current_entry = current_entry->Flink;
783 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
784 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
785 return(STATUS_UNSUCCESSFUL);
787 return(STATUS_UNSUCCESSFUL);
792 NtQueryInformationProcess(IN HANDLE ProcessHandle,
793 IN CINT ProcessInformationClass,
794 OUT PVOID ProcessInformation,
795 IN ULONG ProcessInformationLength,
796 OUT PULONG ReturnLength)
800 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
802 Status = ObReferenceObjectByHandle(ProcessHandle,
803 PROCESS_SET_INFORMATION,
808 if (Status != STATUS_SUCCESS)
813 switch (ProcessInformationClass)
815 case ProcessBasicInformation:
816 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
818 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
819 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
820 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
821 ProcessBasicInformationP->UniqueProcessId =
822 Process->UniqueProcessId;
823 ProcessBasicInformationP->InheritedFromUniqueProcessId =
824 (ULONG)Process->InheritedFromUniqueProcessId;
825 Status = STATUS_SUCCESS;
828 case ProcessQuotaLimits:
829 case ProcessIoCounters:
830 case ProcessVmCounters:
832 case ProcessDebugPort:
833 case ProcessLdtInformation:
834 Status = STATUS_NOT_IMPLEMENTED;
837 case ProcessDefaultHardErrorMode:
838 *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
841 case ProcessWorkingSetWatch:
842 Status = STATUS_NOT_IMPLEMENTED;
845 case ProcessWx86Information:
846 case ProcessHandleCount:
847 case ProcessPriorityBoost:
848 case ProcessDeviceMap:
849 case ProcessSessionInformation:
850 case ProcessWow64Information:
851 Status = STATUS_NOT_IMPLEMENTED;
854 case ProcessBasePriority:
855 case ProcessRaisePriority:
856 case ProcessExceptionPort:
857 case ProcessAccessToken:
859 case ProcessIoPortHandlers:
860 case ProcessUserModeIOPL:
861 case ProcessEnableAlignmentFaultFixup:
862 case ProcessPriorityClass:
863 case ProcessAffinityMask:
864 case ProcessForegroundInformation:
866 Status = STATUS_INVALID_INFO_CLASS;
868 ObDereferenceObject(Process);
873 PspAssignPrimaryToken(PEPROCESS Process,
877 PACCESS_TOKEN OldToken;
880 Status = ObReferenceObjectByHandle(TokenHandle,
886 if (!NT_SUCCESS(Status))
890 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
891 if (NT_SUCCESS(Status))
893 ObDereferenceObject(OldToken);
895 ObDereferenceObject(Token);
900 NtSetInformationProcess(IN HANDLE ProcessHandle,
901 IN CINT ProcessInformationClass,
902 IN PVOID ProcessInformation,
903 IN ULONG ProcessInformationLength)
907 PHANDLE ProcessAccessTokenP;
909 Status = ObReferenceObjectByHandle(ProcessHandle,
910 PROCESS_SET_INFORMATION,
915 if (!NT_SUCCESS(Status))
920 switch (ProcessInformationClass)
922 case ProcessQuotaLimits:
923 case ProcessBasePriority:
924 case ProcessRaisePriority:
925 case ProcessDebugPort:
926 case ProcessExceptionPort:
927 Status = STATUS_NOT_IMPLEMENTED;
930 case ProcessAccessToken:
931 ProcessAccessTokenP = (PHANDLE)ProcessInformation;
932 Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
935 case ProcessImageFileName:
936 memcpy(Process->ImageFileName, ProcessInformation, 8);
937 Status = STATUS_SUCCESS;
940 case ProcessLdtInformation:
942 case ProcessDefaultHardErrorMode:
943 case ProcessIoPortHandlers:
944 case ProcessWorkingSetWatch:
945 case ProcessUserModeIOPL:
946 case ProcessEnableAlignmentFaultFixup:
947 case ProcessPriorityClass:
948 case ProcessAffinityMask:
949 Status = STATUS_NOT_IMPLEMENTED;
952 case ProcessBasicInformation:
953 case ProcessIoCounters:
954 case ProcessVmCounters:
956 case ProcessPooledUsageAndLimits:
957 case ProcessWx86Information:
958 case ProcessHandleCount:
959 case ProcessWow64Information:
961 Status = STATUS_INVALID_INFO_CLASS;
964 Process->Win32Desktop = *(PHANDLE)ProcessInformation;
965 Status = STATUS_SUCCESS;
968 ObDereferenceObject(Process);
973 /**********************************************************************
975 * PiQuerySystemProcessInformation
978 * Compute the size of a process+thread snapshot as
979 * expected by NtQuerySystemInformation.
982 * 0 on error; otherwise the size, in bytes of the buffer
983 * required to write a full snapshot.
986 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
989 PiQuerySystemProcessInformation(PVOID Buffer,
993 return STATUS_NOT_IMPLEMENTED;
997 PLIST_ENTRY CurrentEntryP;
999 PLIST_ENTRY CurrentEntryT;
1002 ULONG RequiredSize = 0L;
1003 BOOLEAN SizeOnly = FALSE;
1007 PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
1008 PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
1009 PSYSTEM_THREAD_INFO pInfoT = NULL;
1012 /* Lock the process list. */
1013 KeAcquireSpinLock(&PsProcessListLock,
1017 * Scan the process list. Since the
1018 * list is circular, the guard is false
1019 * after the last process.
1021 for ( CurrentEntryP = PsProcessListHead.Flink;
1022 (CurrentEntryP != & PsProcessListHead);
1023 CurrentEntryP = CurrentEntryP->Flink
1027 * Compute how much space is
1028 * occupied in the snapshot
1029 * by adding this process info.
1030 * (at least one thread).
1032 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
1033 RequiredSize += SpiSizeCurrent;
1035 * Do not write process data in the
1036 * buffer if it is too small.
1038 if (TRUE == SizeOnly) continue;
1040 * Check if the buffer can contain
1041 * the full snapshot.
1043 if (Size < RequiredSize)
1049 * Get a reference to the
1050 * process descriptor we are
1053 CurrentP = CONTAINING_RECORD(
1059 * Write process data in the buffer.
1061 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
1063 pInfoP->ThreadCount = 0L;
1064 pInfoP->ProcessId = CurrentP->UniqueProcessId;
1065 RtlInitUnicodeString (
1067 CurrentP->ImageFileName
1070 for ( pInfoT = & CurrentP->ThreadSysInfo [0],
1071 CurrentEntryT = CurrentP->ThreadListHead.Flink;
1073 (CurrentEntryT != & CurrentP->ThreadListHead);
1075 pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
1076 CurrentEntryT = CurrentEntryT->Flink
1080 * Recalculate the size of the
1081 * information block.
1083 if (0 < pInfoP->ThreadCount)
1085 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
1088 * Do not write thread data in the
1089 * buffer if it is too small.
1091 if (TRUE == SizeOnly) continue;
1093 * Check if the buffer can contain
1094 * the full snapshot.
1096 if (Size < RequiredSize)
1102 * Get a reference to the
1103 * thread descriptor we are
1106 CurrentT = CONTAINING_RECORD(
1112 * Write thread data.
1116 sizeof (SYSTEM_THREAD_INFORMATION)
1118 pInfoT->KernelTime = CurrentT-> ; /* TIME */
1119 pInfoT->UserTime = CurrentT-> ; /* TIME */
1120 pInfoT->CreateTime = CurrentT-> ; /* TIME */
1121 pInfoT->TickCount = CurrentT-> ; /* ULONG */
1122 pInfoT->StartEIP = CurrentT-> ; /* ULONG */
1123 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1124 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1125 pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
1126 pInfoT->BasePriority = CurrentT-> ; /* ULONG */
1127 pInfoT->nSwitches = CurrentT-> ; /* ULONG */
1128 pInfoT->State = CurrentT-> ; /* DWORD */
1129 pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
1131 * Count the number of threads
1134 ++ pInfoP->ThreadCount;
1137 * Save the size of information
1138 * stored in the buffer for the
1141 pInfoP->RelativeOffset = SpiSize;
1143 * Save a reference to the last
1144 * valid information block.
1146 pInfoPLast = pInfoP;
1148 * Compute the offset of the
1149 * SYSTEM_PROCESS_INFORMATION
1150 * descriptor in the snapshot
1151 * buffer for the next process.
1153 (ULONG) pInfoP += SpiSize;
1156 * Unlock the process list.
1159 & PsProcessListLock,
1163 * Return the proper error status code,
1164 * if the buffer was too small.
1166 if (TRUE == SizeOnly)
1168 if (NULL != RequiredSize)
1170 *pRequiredSize = RequiredSize;
1172 return STATUS_INFO_LENGTH_MISMATCH;
1175 * Mark the end of the snapshot.
1177 pInfoP->RelativeOffset = 0L;
1179 return STATUS_SUCCESS;
1183 LARGE_INTEGER STDCALL
1184 PsGetProcessExitTime(VOID)
1187 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1192 PsIsThreadTerminating(IN PETHREAD Thread)
1194 return(Thread->DeadThread);
1199 PsLookupProcessByProcessId(IN PVOID ProcessId,
1200 OUT PEPROCESS *Process)
1203 PLIST_ENTRY current_entry;
1206 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
1208 current_entry = PsProcessListHead.Flink;
1209 while (current_entry != &PsProcessListHead)
1211 current = CONTAINING_RECORD(current_entry,
1214 if (current->UniqueProcessId == (ULONG)ProcessId)
1217 ObReferenceObject(current);
1218 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1219 return(STATUS_SUCCESS);
1221 current_entry = current_entry->Flink;
1224 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1226 return(STATUS_INVALID_PARAMETER);
1231 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
1234 if (PiProcessNotifyRoutineCount >= MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1235 return(STATUS_INSUFFICIENT_RESOURCES);
1237 PiProcessNotifyRoutine[PiProcessNotifyRoutineCount] = NotifyRoutine;
1238 PiProcessNotifyRoutineCount++;
1240 return(STATUS_SUCCESS);