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(&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->Peb);
304 ObDereferenceObject(Process->Token);
306 (VOID)MmReleaseMmInfo(Process);
307 ObDeleteHandleTable(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 PsGetCurrentProcess(VOID)
373 if (PsGetCurrentThread() == NULL ||
374 PsGetCurrentThread()->ThreadsProcess == NULL)
376 return(PsInitialSystemProcess);
380 return(PsGetCurrentThread()->ThreadsProcess);
385 IoGetCurrentProcess(VOID)
387 return(PsGetCurrentProcess());
391 PsCreateSystemProcess(PHANDLE ProcessHandle,
392 ACCESS_MASK DesiredAccess,
393 POBJECT_ATTRIBUTES ObjectAttributes)
395 return NtCreateProcess(ProcessHandle,
406 NtCreateProcess(OUT PHANDLE ProcessHandle,
407 IN ACCESS_MASK DesiredAccess,
408 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
409 IN HANDLE ParentProcessHandle,
410 IN BOOLEAN InheritObjectTable,
411 IN HANDLE SectionHandle OPTIONAL,
412 IN HANDLE DebugPortHandle OPTIONAL,
413 IN HANDLE ExceptionPortHandle OPTIONAL)
415 * FUNCTION: Creates a process.
417 * ProcessHandle (OUT) = Caller supplied storage for the resulting
419 * DesiredAccess = Specifies the allowed or desired access to the
420 * process can be a combination of
421 * STANDARD_RIGHTS_REQUIRED| ..
422 * ObjectAttribute = Initialized attributes for the object, contains
423 * the rootdirectory and the filename
424 * ParentProcess = Handle to the parent process.
425 * InheritObjectTable = Specifies to inherit the objects of the parent
427 * SectionHandle = Handle to a section object to back the image file
428 * DebugPort = Handle to a DebugPort if NULL the system default debug
430 * ExceptionPort = Handle to a exception port.
432 * This function maps to the win32 CreateProcess.
437 PEPROCESS ParentProcess;
441 PVOID LdrStartupAddr;
445 PEPORT ExceptionPort;
447 PMEMORY_AREA MemoryArea;
450 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
452 Status = ObReferenceObjectByHandle(ParentProcessHandle,
453 PROCESS_CREATE_PROCESS,
456 (PVOID*)&ParentProcess,
458 if (!NT_SUCCESS(Status))
460 DPRINT("NtCreateProcess() = %x\n",Status);
464 Status = ObCreateObject(ProcessHandle,
469 if (!NT_SUCCESS(Status))
471 ObDereferenceObject(ParentProcess);
472 DPRINT("ObCreateObject() = %x\n",Status);
476 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
480 KProcess = &Process->Pcb;
481 /* Inherit parent process's affinity. */
482 KProcess->Affinity = ParentProcess->Pcb.Affinity;
483 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
484 MmInitializeAddressSpace(Process,
485 &Process->AddressSpace);
486 Process->UniqueProcessId = InterlockedIncrement(&PiNextProcessUniqueId);
487 Process->InheritedFromUniqueProcessId =
488 (HANDLE)ParentProcess->UniqueProcessId;
489 ObCreateHandleTable(ParentProcess,
492 MmCopyMmInfo(ParentProcess, Process);
493 if (ParentProcess->Win32WindowStation != (HANDLE)0)
495 /* Always duplicate the process window station. */
496 Process->Win32WindowStation = 0;
497 Status = ObDuplicateObject(ParentProcess,
499 ParentProcess->Win32WindowStation,
500 &Process->Win32WindowStation,
503 DUPLICATE_SAME_ACCESS);
504 if (!NT_SUCCESS(Status))
511 Process->Win32WindowStation = (HANDLE)0;
513 if (ParentProcess->Win32Desktop != (HANDLE)0)
515 /* Always duplicate the process window station. */
516 Process->Win32Desktop = 0;
517 Status = ObDuplicateObject(ParentProcess,
519 ParentProcess->Win32Desktop,
520 &Process->Win32Desktop,
523 DUPLICATE_SAME_ACCESS);
524 if (!NT_SUCCESS(Status))
531 Process->Win32Desktop = (HANDLE)0;
534 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
535 for (i = 0; i < PiProcessNotifyRoutineCount; i++)
537 PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
538 (HANDLE)Process->UniqueProcessId,
541 InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
542 InitializeListHead(&Process->ThreadListHead);
543 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
545 Process->Pcb.State = PROCESS_STATE_ACTIVE;
550 if (DebugPortHandle != NULL)
552 Status = ObReferenceObjectByHandle(DebugPortHandle,
558 if (!NT_SUCCESS(Status))
560 ObDereferenceObject(Process);
561 ObDereferenceObject(ParentProcess);
562 ZwClose(*ProcessHandle);
563 *ProcessHandle = NULL;
566 Process->DebugPort = DebugPort;
570 * Add the exception port
572 if (ExceptionPortHandle != NULL)
574 Status = ObReferenceObjectByHandle(ExceptionPortHandle,
578 (PVOID*)&ExceptionPort,
580 if (!NT_SUCCESS(Status))
582 ObDereferenceObject(Process);
583 ObDereferenceObject(ParentProcess);
584 ZwClose(*ProcessHandle);
585 *ProcessHandle = NULL;
588 Process->ExceptionPort = ExceptionPort;
592 * Now we have created the process proper
596 * Create the shared data page
598 MmLockAddressSpace(&Process->AddressSpace);
599 BaseAddress = (PVOID)USER_SHARED_DATA;
600 Status = MmCreateMemoryArea(Process,
601 &Process->AddressSpace,
602 MEMORY_AREA_SHARED_DATA,
608 MmUnlockAddressSpace(&Process->AddressSpace);
609 if (!NT_SUCCESS(Status))
611 DPRINT1("Failed to create shared data page\n");
618 Status = LdrpMapSystemDll(*ProcessHandle,
620 if (!NT_SUCCESS(Status))
622 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
623 ObDereferenceObject(Process);
624 ObDereferenceObject(ParentProcess);
629 * Map the process image
631 if (SectionHandle != NULL)
633 DPRINT("Mapping process image\n");
634 Status = LdrpMapImage(*ProcessHandle,
637 if (!NT_SUCCESS(Status))
639 DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
640 ObDereferenceObject(Process);
641 ObDereferenceObject(ParentProcess);
651 * Duplicate the token
653 Status = SepInitializeNewProcess(Process, ParentProcess);
654 if (!NT_SUCCESS(Status))
656 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
657 ObDereferenceObject(Process);
658 ObDereferenceObject(ParentProcess);
665 DPRINT("Creating PEB\n");
666 Status = PsCreatePeb(*ProcessHandle,
669 if (!NT_SUCCESS(Status))
671 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
672 ObDereferenceObject(Process);
673 ObDereferenceObject(ParentProcess);
674 ZwClose(*ProcessHandle);
675 *ProcessHandle = NULL;
681 * Maybe send a message to the creator process's debugger
684 if (ParentProcess->DebugPort != NULL)
686 LPC_DBG_MESSAGE Message;
689 ObCreateHandle(NULL, // Debugger Process
690 NULL, // SectionHandle
695 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
696 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
697 sizeof(LPC_MESSAGE_HEADER);
698 Message.Type = DBG_EVENT_CREATE_PROCESS;
699 Message.Data.CreateProcess.FileHandle = FileHandle;
700 Message.Data.CreateProcess.Base = ImageBase;
701 Message.Data.CreateProcess.EntryPoint = NULL; //
703 Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
708 ObDereferenceObject(Process);
709 ObDereferenceObject(ParentProcess);
710 return(STATUS_SUCCESS);
715 NtOpenProcess(OUT PHANDLE ProcessHandle,
716 IN ACCESS_MASK DesiredAccess,
717 IN POBJECT_ATTRIBUTES ObjectAttributes,
718 IN PCLIENT_ID ClientId)
720 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
721 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
722 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
723 ClientId->UniqueProcess, ClientId->UniqueThread);
727 * Not sure of the exact semantics
729 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
730 ObjectAttributes->ObjectName->Buffer != NULL)
735 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
736 ObjectAttributes->Attributes,
743 if (Status != STATUS_SUCCESS)
748 Status = ObCreateHandle(PsGetCurrentProcess(),
753 ObDereferenceObject(Process);
760 PLIST_ENTRY current_entry;
764 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
765 current_entry = PsProcessListHead.Flink;
766 while (current_entry != &PsProcessListHead)
768 current = CONTAINING_RECORD(current_entry, EPROCESS,
770 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
772 ObReferenceObjectByPointer(current,
776 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
777 Status = ObCreateHandle(PsGetCurrentProcess(),
782 ObDereferenceObject(current);
783 DPRINT("*ProcessHandle %x\n", ProcessHandle);
784 DPRINT("NtOpenProcess() = %x\n", Status);
787 current_entry = current_entry->Flink;
789 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
790 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
791 return(STATUS_UNSUCCESSFUL);
793 return(STATUS_UNSUCCESSFUL);
798 NtQueryInformationProcess(IN HANDLE ProcessHandle,
799 IN CINT ProcessInformationClass,
800 OUT PVOID ProcessInformation,
801 IN ULONG ProcessInformationLength,
802 OUT PULONG ReturnLength)
806 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
808 Status = ObReferenceObjectByHandle(ProcessHandle,
809 PROCESS_SET_INFORMATION,
814 if (Status != STATUS_SUCCESS)
819 switch (ProcessInformationClass)
821 case ProcessBasicInformation:
822 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
824 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
825 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
826 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
827 ProcessBasicInformationP->UniqueProcessId =
828 Process->UniqueProcessId;
829 ProcessBasicInformationP->InheritedFromUniqueProcessId =
830 (ULONG)Process->InheritedFromUniqueProcessId;
831 Status = STATUS_SUCCESS;
834 case ProcessQuotaLimits:
835 case ProcessIoCounters:
836 case ProcessVmCounters:
838 case ProcessDebugPort:
839 case ProcessLdtInformation:
840 Status = STATUS_NOT_IMPLEMENTED;
843 case ProcessDefaultHardErrorMode:
844 *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
847 case ProcessWorkingSetWatch:
848 Status = STATUS_NOT_IMPLEMENTED;
851 case ProcessWx86Information:
852 case ProcessHandleCount:
853 case ProcessPriorityBoost:
854 case ProcessDeviceMap:
855 case ProcessSessionInformation:
856 case ProcessWow64Information:
857 Status = STATUS_NOT_IMPLEMENTED;
860 case ProcessBasePriority:
861 case ProcessRaisePriority:
862 case ProcessExceptionPort:
863 case ProcessAccessToken:
865 case ProcessIoPortHandlers:
866 case ProcessUserModeIOPL:
867 case ProcessEnableAlignmentFaultFixup:
868 case ProcessPriorityClass:
869 case ProcessAffinityMask:
870 case ProcessForegroundInformation:
872 Status = STATUS_INVALID_INFO_CLASS;
874 ObDereferenceObject(Process);
879 PspAssignPrimaryToken(PEPROCESS Process,
883 PACCESS_TOKEN OldToken;
886 Status = ObReferenceObjectByHandle(TokenHandle,
892 if (!NT_SUCCESS(Status))
896 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
897 if (NT_SUCCESS(Status))
899 ObDereferenceObject(OldToken);
901 ObDereferenceObject(Token);
906 NtSetInformationProcess(IN HANDLE ProcessHandle,
907 IN CINT ProcessInformationClass,
908 IN PVOID ProcessInformation,
909 IN ULONG ProcessInformationLength)
913 PHANDLE ProcessAccessTokenP;
915 Status = ObReferenceObjectByHandle(ProcessHandle,
916 PROCESS_SET_INFORMATION,
921 if (!NT_SUCCESS(Status))
926 switch (ProcessInformationClass)
928 case ProcessQuotaLimits:
929 case ProcessBasePriority:
930 case ProcessRaisePriority:
931 case ProcessDebugPort:
932 case ProcessExceptionPort:
933 Status = STATUS_NOT_IMPLEMENTED;
936 case ProcessAccessToken:
937 ProcessAccessTokenP = (PHANDLE)ProcessInformation;
938 Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
941 case ProcessImageFileName:
942 memcpy(Process->ImageFileName, ProcessInformation, 8);
943 Status = STATUS_SUCCESS;
946 case ProcessLdtInformation:
948 case ProcessDefaultHardErrorMode:
949 case ProcessIoPortHandlers:
950 case ProcessWorkingSetWatch:
951 case ProcessUserModeIOPL:
952 case ProcessEnableAlignmentFaultFixup:
953 case ProcessPriorityClass:
954 case ProcessAffinityMask:
955 Status = STATUS_NOT_IMPLEMENTED;
958 case ProcessBasicInformation:
959 case ProcessIoCounters:
960 case ProcessVmCounters:
962 case ProcessPooledUsageAndLimits:
963 case ProcessWx86Information:
964 case ProcessHandleCount:
965 case ProcessWow64Information:
967 Status = STATUS_INVALID_INFO_CLASS;
970 Process->Win32Desktop = *(PHANDLE)ProcessInformation;
971 Status = STATUS_SUCCESS;
974 ObDereferenceObject(Process);
979 /**********************************************************************
981 * PiQuerySystemProcessInformation
984 * Compute the size of a process+thread snapshot as
985 * expected by NtQuerySystemInformation.
988 * 0 on error; otherwise the size, in bytes of the buffer
989 * required to write a full snapshot.
992 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
995 PiQuerySystemProcessInformation(PVOID Buffer,
999 return STATUS_NOT_IMPLEMENTED;
1003 PLIST_ENTRY CurrentEntryP;
1005 PLIST_ENTRY CurrentEntryT;
1008 ULONG RequiredSize = 0L;
1009 BOOLEAN SizeOnly = FALSE;
1013 PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
1014 PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
1015 PSYSTEM_THREAD_INFO pInfoT = NULL;
1018 /* Lock the process list. */
1019 KeAcquireSpinLock(&PsProcessListLock,
1023 * Scan the process list. Since the
1024 * list is circular, the guard is false
1025 * after the last process.
1027 for ( CurrentEntryP = PsProcessListHead.Flink;
1028 (CurrentEntryP != & PsProcessListHead);
1029 CurrentEntryP = CurrentEntryP->Flink
1033 * Compute how much space is
1034 * occupied in the snapshot
1035 * by adding this process info.
1036 * (at least one thread).
1038 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
1039 RequiredSize += SpiSizeCurrent;
1041 * Do not write process data in the
1042 * buffer if it is too small.
1044 if (TRUE == SizeOnly) continue;
1046 * Check if the buffer can contain
1047 * the full snapshot.
1049 if (Size < RequiredSize)
1055 * Get a reference to the
1056 * process descriptor we are
1059 CurrentP = CONTAINING_RECORD(
1065 * Write process data in the buffer.
1067 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
1069 pInfoP->ThreadCount = 0L;
1070 pInfoP->ProcessId = CurrentP->UniqueProcessId;
1071 RtlInitUnicodeString (
1073 CurrentP->ImageFileName
1076 for ( pInfoT = & CurrentP->ThreadSysInfo [0],
1077 CurrentEntryT = CurrentP->ThreadListHead.Flink;
1079 (CurrentEntryT != & CurrentP->ThreadListHead);
1081 pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
1082 CurrentEntryT = CurrentEntryT->Flink
1086 * Recalculate the size of the
1087 * information block.
1089 if (0 < pInfoP->ThreadCount)
1091 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
1094 * Do not write thread data in the
1095 * buffer if it is too small.
1097 if (TRUE == SizeOnly) continue;
1099 * Check if the buffer can contain
1100 * the full snapshot.
1102 if (Size < RequiredSize)
1108 * Get a reference to the
1109 * thread descriptor we are
1112 CurrentT = CONTAINING_RECORD(
1118 * Write thread data.
1122 sizeof (SYSTEM_THREAD_INFORMATION)
1124 pInfoT->KernelTime = CurrentT-> ; /* TIME */
1125 pInfoT->UserTime = CurrentT-> ; /* TIME */
1126 pInfoT->CreateTime = CurrentT-> ; /* TIME */
1127 pInfoT->TickCount = CurrentT-> ; /* ULONG */
1128 pInfoT->StartEIP = CurrentT-> ; /* ULONG */
1129 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1130 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1131 pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
1132 pInfoT->BasePriority = CurrentT-> ; /* ULONG */
1133 pInfoT->nSwitches = CurrentT-> ; /* ULONG */
1134 pInfoT->State = CurrentT-> ; /* DWORD */
1135 pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
1137 * Count the number of threads
1140 ++ pInfoP->ThreadCount;
1143 * Save the size of information
1144 * stored in the buffer for the
1147 pInfoP->RelativeOffset = SpiSize;
1149 * Save a reference to the last
1150 * valid information block.
1152 pInfoPLast = pInfoP;
1154 * Compute the offset of the
1155 * SYSTEM_PROCESS_INFORMATION
1156 * descriptor in the snapshot
1157 * buffer for the next process.
1159 (ULONG) pInfoP += SpiSize;
1162 * Unlock the process list.
1165 & PsProcessListLock,
1169 * Return the proper error status code,
1170 * if the buffer was too small.
1172 if (TRUE == SizeOnly)
1174 if (NULL != RequiredSize)
1176 *pRequiredSize = RequiredSize;
1178 return STATUS_INFO_LENGTH_MISMATCH;
1181 * Mark the end of the snapshot.
1183 pInfoP->RelativeOffset = 0L;
1185 return STATUS_SUCCESS;
1189 LARGE_INTEGER STDCALL
1190 PsGetProcessExitTime(VOID)
1193 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1198 PsIsThreadTerminating(IN PETHREAD Thread)
1200 return(Thread->DeadThread);
1205 PsLookupProcessByProcessId(IN PVOID ProcessId,
1206 OUT PEPROCESS *Process)
1209 PLIST_ENTRY current_entry;
1212 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
1214 current_entry = PsProcessListHead.Flink;
1215 while (current_entry != &PsProcessListHead)
1217 current = CONTAINING_RECORD(current_entry,
1220 if (current->UniqueProcessId == (ULONG)ProcessId)
1223 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1224 return(STATUS_SUCCESS);
1226 current_entry = current_entry->Flink;
1229 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1231 return(STATUS_INVALID_PARAMETER);
1236 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
1239 if (PiProcessNotifyRoutineCount >= MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1240 return(STATUS_INSUFFICIENT_RESOURCES);
1242 PiProcessNotifyRoutine[PiProcessNotifyRoutineCount] = NotifyRoutine;
1243 PiProcessNotifyRoutineCount++;
1245 return(STATUS_SUCCESS);