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
54 static ULONG PiProcessNotifyRoutineCount = 0;
55 static PCREATE_PROCESS_NOTIFY_ROUTINE
56 PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
57 #endif /* LIBCAPTIVE */
59 /* FUNCTIONS *****************************************************************/
64 PsGetNextProcess(PEPROCESS OldProcess)
67 PEPROCESS NextProcess;
70 if (OldProcess == NULL)
72 return(PsInitialSystemProcess);
75 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
76 if (OldProcess->ProcessListEntry.Flink == &PsProcessListHead)
78 NextProcess = CONTAINING_RECORD(PsProcessListHead.Flink,
84 NextProcess = CONTAINING_RECORD(OldProcess->ProcessListEntry.Flink,
88 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
89 Status = ObReferenceObjectByPointer(NextProcess,
93 if (!NT_SUCCESS(Status))
95 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
98 ObDereferenceObject(OldProcess);
105 _NtOpenProcessToken(IN HANDLE ProcessHandle,
106 IN ACCESS_MASK DesiredAccess,
107 OUT PHANDLE TokenHandle)
112 Status = PsOpenTokenOfProcess(ProcessHandle,
114 if (!NT_SUCCESS(Status))
118 Status = ObCreateHandle(PsGetCurrentProcess(),
123 ObDereferenceObject(Token);
129 NtOpenProcessToken(IN HANDLE ProcessHandle,
130 IN ACCESS_MASK DesiredAccess,
131 OUT PHANDLE TokenHandle)
133 return _NtOpenProcessToken(ProcessHandle, DesiredAccess, TokenHandle);
136 #endif /* LIBCAPTIVE */
138 PACCESS_TOKEN STDCALL
139 PsReferencePrimaryToken(PEPROCESS Process)
141 ObReferenceObjectByPointer(Process->Token,
145 return(Process->Token);
151 PsOpenTokenOfProcess(HANDLE ProcessHandle,
152 PACCESS_TOKEN* Token)
157 Status = ObReferenceObjectByHandle(ProcessHandle,
158 PROCESS_QUERY_INFORMATION,
163 if (!NT_SUCCESS(Status))
167 *Token = PsReferencePrimaryToken(Process);
168 ObDereferenceObject(Process);
169 return(STATUS_SUCCESS);
174 PiKillMostProcesses(VOID)
177 PLIST_ENTRY current_entry;
180 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
182 current_entry = PsProcessListHead.Flink;
183 while (current_entry != &PsProcessListHead)
185 current = CONTAINING_RECORD(current_entry, EPROCESS,
187 current_entry = current_entry->Flink;
189 if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
190 current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
192 PiTerminateProcessThreads(current, STATUS_SUCCESS);
196 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
199 #endif /* LIBCAPTIVE */
202 PsInitProcessManagment(VOID)
209 * Register the process object type
212 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
214 PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
215 PsProcessType->TotalObjects = 0;
216 PsProcessType->TotalHandles = 0;
217 PsProcessType->MaxObjects = ULONG_MAX;
218 PsProcessType->MaxHandles = ULONG_MAX;
219 PsProcessType->PagedPoolCharge = 0;
220 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS)
222 /* Need to present 0-terminated string "System"
223 * from KPROCESS up to PAGE_SIZE offset
224 * for ext2fsd.sys V0.10A debug.c/Ext2GetProcessNameOffset()
226 +strlen("System")+1/* 0-terminator */;
227 #endif /* LIBCAPTIVE */
229 PsProcessType->Mapping = &PiProcessMapping;
230 PsProcessType->Dump = NULL;
231 PsProcessType->Open = NULL;
232 PsProcessType->Close = NULL;
234 PsProcessType->Delete = PiDeleteProcess;
236 PsProcessType->Delete = NULL; /* never Delete PsInitialSystemProcess */
237 #endif /* LIBCAPTIVE */
238 PsProcessType->Parse = NULL;
239 PsProcessType->Security = NULL;
240 PsProcessType->QueryName = NULL;
241 PsProcessType->OkayToClose = NULL;
242 PsProcessType->Create = NULL;
243 PsProcessType->DuplicationNotify = NULL;
245 RtlInitUnicodeStringFromLiteral(&PsProcessType->TypeName, REACTOS_UCS2(L"Process"));
247 InitializeListHead(&PsProcessListHead);
248 KeInitializeSpinLock(&PsProcessListLock);
251 * Initialize the system process
253 Status = ObCreateObject(NULL,
257 (PVOID*)&PsInitialSystemProcess);
258 if (!NT_SUCCESS(Status))
264 /* Need to present 0-terminated string "System"
265 * from KPROCESS up to PAGE_SIZE offset
266 * for ext2fsd.sys V0.10A debug.c/Ext2GetProcessNameOffset()
268 strcpy(((char *)PsInitialSystemProcess) +strlen("System")+1/* 0-terminator */,"System");
269 #endif /* LIBCAPTIVE */
271 /* System threads may run on any processor. */
272 PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
273 PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
275 KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
279 #endif /* LIBCAPTIVE */
280 KProcess = &PsInitialSystemProcess->Pcb;
283 MmInitializeAddressSpace(PsInitialSystemProcess,
284 &PsInitialSystemProcess->AddressSpace);
285 #endif /* LIBCAPTIVE */
286 ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess);
288 KProcess->DirectoryTableBase =
289 (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
290 #endif /* LIBCAPTIVE */
291 PsInitialSystemProcess->UniqueProcessId =
292 InterlockedIncrement(&PiNextProcessUniqueId);
293 PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
294 PsInitialSystemProcess->Win32Desktop = (HANDLE)0;
296 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
297 InsertHeadList(&PsProcessListHead,
298 &PsInitialSystemProcess->ProcessListEntry);
299 InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
300 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
302 strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM");
304 SepCreateSystemProcessToken(PsInitialSystemProcess);
306 ObCreateHandle(PsInitialSystemProcess,
307 PsInitialSystemProcess,
310 &SystemProcessHandle);
316 PiDeleteProcess(PVOID ObjectBody)
322 DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody);
324 Process = (PEPROCESS)ObjectBody;
325 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
326 for (i = 0; i < PiProcessNotifyRoutineCount; i++)
328 PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
329 (HANDLE)Process->UniqueProcessId,
332 RemoveEntryList(&Process->ProcessListEntry);
333 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
336 KDB_DELETEPROCESS_HOOK(Process);
338 ObDereferenceObject(Process->Token);
339 ObDeleteHandleTable(Process);
341 (VOID)MmReleaseMmInfo(Process);
346 PsCreatePeb(HANDLE ProcessHandle,
356 memset(&Peb, 0, sizeof(Peb));
357 Peb.ImageBaseAddress = ImageBase;
359 PebBase = (PVOID)PEB_BASE;
361 Status = NtAllocateVirtualMemory(ProcessHandle,
365 MEM_RESERVE | MEM_COMMIT,
367 if (!NT_SUCCESS(Status))
372 NtWriteVirtualMemory(ProcessHandle,
378 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase);
382 return(STATUS_SUCCESS);
387 KeGetCurrentProcess(VOID)
389 * FUNCTION: Returns a pointer to the current process
392 return(&(PsGetCurrentProcess()->Pcb));
396 PsGetCurrentProcessId(VOID)
398 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
401 #endif /* LIBCAPTIVE */
404 * FUNCTION: Returns a pointer to the current process
407 PsGetCurrentProcess(VOID)
410 if (PsGetCurrentThread() == NULL ||
411 PsGetCurrentThread()->ThreadsProcess == NULL)
413 #endif /* LIBCAPTIVE */
414 return(PsInitialSystemProcess);
419 return(PsGetCurrentThread()->ThreadsProcess);
421 #endif /* LIBCAPTIVE */
425 IoGetCurrentProcess(VOID)
427 return(PsGetCurrentProcess());
433 PsCreateSystemProcess(PHANDLE ProcessHandle,
434 ACCESS_MASK DesiredAccess,
435 POBJECT_ATTRIBUTES ObjectAttributes)
437 return NtCreateProcess(ProcessHandle,
448 NtCreateProcess(OUT PHANDLE ProcessHandle,
449 IN ACCESS_MASK DesiredAccess,
450 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
451 IN HANDLE ParentProcessHandle,
452 IN BOOLEAN InheritObjectTable,
453 IN HANDLE SectionHandle OPTIONAL,
454 IN HANDLE DebugPortHandle OPTIONAL,
455 IN HANDLE ExceptionPortHandle OPTIONAL)
457 * FUNCTION: Creates a process.
459 * ProcessHandle (OUT) = Caller supplied storage for the resulting
461 * DesiredAccess = Specifies the allowed or desired access to the
462 * process can be a combination of
463 * STANDARD_RIGHTS_REQUIRED| ..
464 * ObjectAttribute = Initialized attributes for the object, contains
465 * the rootdirectory and the filename
466 * ParentProcess = Handle to the parent process.
467 * InheritObjectTable = Specifies to inherit the objects of the parent
469 * SectionHandle = Handle to a section object to back the image file
470 * DebugPort = Handle to a DebugPort if NULL the system default debug
472 * ExceptionPort = Handle to a exception port.
474 * This function maps to the win32 CreateProcess.
479 PEPROCESS ParentProcess;
483 PVOID LdrStartupAddr;
487 PEPORT ExceptionPort;
489 PMEMORY_AREA MemoryArea;
492 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
494 Status = ObReferenceObjectByHandle(ParentProcessHandle,
495 PROCESS_CREATE_PROCESS,
498 (PVOID*)&ParentProcess,
500 if (!NT_SUCCESS(Status))
502 DPRINT("NtCreateProcess() = %x\n",Status);
506 Status = ObCreateObject(ProcessHandle,
511 if (!NT_SUCCESS(Status))
513 ObDereferenceObject(ParentProcess);
514 DPRINT("ObCreateObject() = %x\n",Status);
518 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
522 KProcess = &Process->Pcb;
523 /* Inherit parent process's affinity. */
524 KProcess->Affinity = ParentProcess->Pcb.Affinity;
525 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
526 MmInitializeAddressSpace(Process,
527 &Process->AddressSpace);
528 Process->UniqueProcessId = InterlockedIncrement(&PiNextProcessUniqueId);
529 Process->InheritedFromUniqueProcessId =
530 (HANDLE)ParentProcess->UniqueProcessId;
531 ObCreateHandleTable(ParentProcess,
534 MmCopyMmInfo(ParentProcess, Process);
535 if (ParentProcess->Win32WindowStation != (HANDLE)0)
537 /* Always duplicate the process window station. */
538 Process->Win32WindowStation = 0;
539 Status = ObDuplicateObject(ParentProcess,
541 ParentProcess->Win32WindowStation,
542 &Process->Win32WindowStation,
545 DUPLICATE_SAME_ACCESS);
546 if (!NT_SUCCESS(Status))
553 Process->Win32WindowStation = (HANDLE)0;
555 if (ParentProcess->Win32Desktop != (HANDLE)0)
557 /* Always duplicate the process window station. */
558 Process->Win32Desktop = 0;
559 Status = ObDuplicateObject(ParentProcess,
561 ParentProcess->Win32Desktop,
562 &Process->Win32Desktop,
565 DUPLICATE_SAME_ACCESS);
566 if (!NT_SUCCESS(Status))
573 Process->Win32Desktop = (HANDLE)0;
576 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
577 for (i = 0; i < PiProcessNotifyRoutineCount; i++)
579 PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
580 (HANDLE)Process->UniqueProcessId,
583 InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
584 InitializeListHead(&Process->ThreadListHead);
585 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
587 Process->Pcb.State = PROCESS_STATE_ACTIVE;
592 if (DebugPortHandle != NULL)
594 Status = ObReferenceObjectByHandle(DebugPortHandle,
600 if (!NT_SUCCESS(Status))
602 ObDereferenceObject(Process);
603 ObDereferenceObject(ParentProcess);
604 ZwClose(*ProcessHandle);
605 *ProcessHandle = NULL;
608 Process->DebugPort = DebugPort;
612 * Add the exception port
614 if (ExceptionPortHandle != NULL)
616 Status = ObReferenceObjectByHandle(ExceptionPortHandle,
620 (PVOID*)&ExceptionPort,
622 if (!NT_SUCCESS(Status))
624 ObDereferenceObject(Process);
625 ObDereferenceObject(ParentProcess);
626 ZwClose(*ProcessHandle);
627 *ProcessHandle = NULL;
630 Process->ExceptionPort = ExceptionPort;
634 * Now we have created the process proper
638 * Create the shared data page
640 MmLockAddressSpace(&Process->AddressSpace);
641 BaseAddress = (PVOID)USER_SHARED_DATA;
642 Status = MmCreateMemoryArea(Process,
643 &Process->AddressSpace,
644 MEMORY_AREA_SHARED_DATA,
650 MmUnlockAddressSpace(&Process->AddressSpace);
651 if (!NT_SUCCESS(Status))
653 DPRINT1("Failed to create shared data page\n");
660 Status = LdrpMapSystemDll(*ProcessHandle,
662 if (!NT_SUCCESS(Status))
664 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
665 ObDereferenceObject(Process);
666 ObDereferenceObject(ParentProcess);
671 * Map the process image
673 if (SectionHandle != NULL)
675 DPRINT("Mapping process image\n");
676 Status = LdrpMapImage(*ProcessHandle,
679 if (!NT_SUCCESS(Status))
681 DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
682 ObDereferenceObject(Process);
683 ObDereferenceObject(ParentProcess);
693 * Duplicate the token
695 Status = SepInitializeNewProcess(Process, ParentProcess);
696 if (!NT_SUCCESS(Status))
698 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
699 ObDereferenceObject(Process);
700 ObDereferenceObject(ParentProcess);
707 DPRINT("Creating PEB\n");
708 Status = PsCreatePeb(*ProcessHandle,
711 if (!NT_SUCCESS(Status))
713 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
714 ObDereferenceObject(Process);
715 ObDereferenceObject(ParentProcess);
716 ZwClose(*ProcessHandle);
717 *ProcessHandle = NULL;
723 * Maybe send a message to the creator process's debugger
726 if (ParentProcess->DebugPort != NULL)
728 LPC_DBG_MESSAGE Message;
731 ObCreateHandle(NULL, // Debugger Process
732 NULL, // SectionHandle
737 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
738 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
740 Message.Type = DBG_EVENT_CREATE_PROCESS;
741 Message.Data.CreateProcess.FileHandle = FileHandle;
742 Message.Data.CreateProcess.Base = ImageBase;
743 Message.Data.CreateProcess.EntryPoint = NULL; //
745 Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
750 ObDereferenceObject(Process);
751 ObDereferenceObject(ParentProcess);
752 return(STATUS_SUCCESS);
757 NtOpenProcess(OUT PHANDLE ProcessHandle,
758 IN ACCESS_MASK DesiredAccess,
759 IN POBJECT_ATTRIBUTES ObjectAttributes,
760 IN PCLIENT_ID ClientId)
762 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
763 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
764 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
765 ClientId->UniqueProcess, ClientId->UniqueThread);
769 * Not sure of the exact semantics
771 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
772 ObjectAttributes->ObjectName->Buffer != NULL)
777 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
778 ObjectAttributes->Attributes,
785 if (Status != STATUS_SUCCESS)
790 Status = ObCreateHandle(PsGetCurrentProcess(),
795 ObDereferenceObject(Process);
802 PLIST_ENTRY current_entry;
806 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
807 current_entry = PsProcessListHead.Flink;
808 while (current_entry != &PsProcessListHead)
810 current = CONTAINING_RECORD(current_entry, EPROCESS,
812 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
814 ObReferenceObjectByPointer(current,
818 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
819 Status = ObCreateHandle(PsGetCurrentProcess(),
824 ObDereferenceObject(current);
825 DPRINT("*ProcessHandle %x\n", ProcessHandle);
826 DPRINT("NtOpenProcess() = %x\n", Status);
829 current_entry = current_entry->Flink;
831 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
832 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
833 return(STATUS_UNSUCCESSFUL);
835 return(STATUS_UNSUCCESSFUL);
840 NtQueryInformationProcess(IN HANDLE ProcessHandle,
841 IN CINT ProcessInformationClass,
842 OUT PVOID ProcessInformation,
843 IN ULONG ProcessInformationLength,
844 OUT PULONG ReturnLength)
848 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
850 Status = ObReferenceObjectByHandle(ProcessHandle,
851 PROCESS_SET_INFORMATION,
856 if (Status != STATUS_SUCCESS)
861 switch (ProcessInformationClass)
863 case ProcessBasicInformation:
864 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
866 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
867 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
868 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
869 ProcessBasicInformationP->UniqueProcessId =
870 Process->UniqueProcessId;
871 ProcessBasicInformationP->InheritedFromUniqueProcessId =
872 (ULONG)Process->InheritedFromUniqueProcessId;
873 Status = STATUS_SUCCESS;
876 case ProcessQuotaLimits:
877 case ProcessIoCounters:
878 case ProcessVmCounters:
880 case ProcessDebugPort:
881 case ProcessLdtInformation:
882 Status = STATUS_NOT_IMPLEMENTED;
885 case ProcessDefaultHardErrorMode:
886 *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
889 case ProcessWorkingSetWatch:
890 Status = STATUS_NOT_IMPLEMENTED;
893 case ProcessWx86Information:
894 case ProcessHandleCount:
895 case ProcessPriorityBoost:
896 case ProcessDeviceMap:
897 case ProcessSessionInformation:
898 case ProcessWow64Information:
899 Status = STATUS_NOT_IMPLEMENTED;
902 case ProcessBasePriority:
903 case ProcessRaisePriority:
904 case ProcessExceptionPort:
905 case ProcessAccessToken:
907 case ProcessIoPortHandlers:
908 case ProcessUserModeIOPL:
909 case ProcessEnableAlignmentFaultFixup:
910 case ProcessPriorityClass:
911 case ProcessAffinityMask:
912 case ProcessForegroundInformation:
914 Status = STATUS_INVALID_INFO_CLASS;
916 ObDereferenceObject(Process);
921 PspAssignPrimaryToken(PEPROCESS Process,
925 PACCESS_TOKEN OldToken;
928 Status = ObReferenceObjectByHandle(TokenHandle,
934 if (!NT_SUCCESS(Status))
938 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
939 if (NT_SUCCESS(Status))
941 ObDereferenceObject(OldToken);
943 ObDereferenceObject(Token);
948 NtSetInformationProcess(IN HANDLE ProcessHandle,
949 IN CINT ProcessInformationClass,
950 IN PVOID ProcessInformation,
951 IN ULONG ProcessInformationLength)
955 PHANDLE ProcessAccessTokenP;
957 Status = ObReferenceObjectByHandle(ProcessHandle,
958 PROCESS_SET_INFORMATION,
963 if (!NT_SUCCESS(Status))
968 switch (ProcessInformationClass)
970 case ProcessQuotaLimits:
971 case ProcessBasePriority:
972 case ProcessRaisePriority:
973 case ProcessDebugPort:
974 case ProcessExceptionPort:
975 Status = STATUS_NOT_IMPLEMENTED;
978 case ProcessAccessToken:
979 ProcessAccessTokenP = (PHANDLE)ProcessInformation;
980 Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
983 case ProcessImageFileName:
984 memcpy(Process->ImageFileName, ProcessInformation, 8);
985 Status = STATUS_SUCCESS;
988 case ProcessLdtInformation:
990 case ProcessDefaultHardErrorMode:
991 case ProcessIoPortHandlers:
992 case ProcessWorkingSetWatch:
993 case ProcessUserModeIOPL:
994 case ProcessEnableAlignmentFaultFixup:
995 case ProcessPriorityClass:
996 case ProcessAffinityMask:
997 Status = STATUS_NOT_IMPLEMENTED;
1000 case ProcessBasicInformation:
1001 case ProcessIoCounters:
1002 case ProcessVmCounters:
1004 case ProcessPooledUsageAndLimits:
1005 case ProcessWx86Information:
1006 case ProcessHandleCount:
1007 case ProcessWow64Information:
1009 Status = STATUS_INVALID_INFO_CLASS;
1011 case ProcessDesktop:
1012 Process->Win32Desktop = *(PHANDLE)ProcessInformation;
1013 Status = STATUS_SUCCESS;
1016 ObDereferenceObject(Process);
1021 /**********************************************************************
1023 * PiQuerySystemProcessInformation
1026 * Compute the size of a process+thread snapshot as
1027 * expected by NtQuerySystemInformation.
1030 * 0 on error; otherwise the size, in bytes of the buffer
1031 * required to write a full snapshot.
1034 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
1037 PiQuerySystemProcessInformation(PVOID Buffer,
1041 return STATUS_NOT_IMPLEMENTED;
1045 PLIST_ENTRY CurrentEntryP;
1047 PLIST_ENTRY CurrentEntryT;
1050 ULONG RequiredSize = 0L;
1051 BOOLEAN SizeOnly = FALSE;
1055 PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
1056 PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
1057 PSYSTEM_THREAD_INFO pInfoT = NULL;
1060 /* Lock the process list. */
1061 KeAcquireSpinLock(&PsProcessListLock,
1065 * Scan the process list. Since the
1066 * list is circular, the guard is false
1067 * after the last process.
1069 for ( CurrentEntryP = PsProcessListHead.Flink;
1070 (CurrentEntryP != & PsProcessListHead);
1071 CurrentEntryP = CurrentEntryP->Flink
1075 * Compute how much space is
1076 * occupied in the snapshot
1077 * by adding this process info.
1078 * (at least one thread).
1080 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
1081 RequiredSize += SpiSizeCurrent;
1083 * Do not write process data in the
1084 * buffer if it is too small.
1086 if (TRUE == SizeOnly) continue;
1088 * Check if the buffer can contain
1089 * the full snapshot.
1091 if (Size < RequiredSize)
1097 * Get a reference to the
1098 * process descriptor we are
1101 CurrentP = CONTAINING_RECORD(
1107 * Write process data in the buffer.
1109 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
1111 pInfoP->ThreadCount = 0L;
1112 pInfoP->ProcessId = CurrentP->UniqueProcessId;
1113 RtlInitUnicodeString (
1115 CurrentP->ImageFileName
1118 for ( pInfoT = & CurrentP->ThreadSysInfo [0],
1119 CurrentEntryT = CurrentP->ThreadListHead.Flink;
1121 (CurrentEntryT != & CurrentP->ThreadListHead);
1123 pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
1124 CurrentEntryT = CurrentEntryT->Flink
1128 * Recalculate the size of the
1129 * information block.
1131 if (0 < pInfoP->ThreadCount)
1133 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
1136 * Do not write thread data in the
1137 * buffer if it is too small.
1139 if (TRUE == SizeOnly) continue;
1141 * Check if the buffer can contain
1142 * the full snapshot.
1144 if (Size < RequiredSize)
1150 * Get a reference to the
1151 * thread descriptor we are
1154 CurrentT = CONTAINING_RECORD(
1160 * Write thread data.
1164 sizeof (SYSTEM_THREAD_INFORMATION)
1166 pInfoT->KernelTime = CurrentT-> ; /* TIME */
1167 pInfoT->UserTime = CurrentT-> ; /* TIME */
1168 pInfoT->CreateTime = CurrentT-> ; /* TIME */
1169 pInfoT->TickCount = CurrentT-> ; /* ULONG */
1170 pInfoT->StartEIP = CurrentT-> ; /* ULONG */
1171 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1172 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1173 pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
1174 pInfoT->BasePriority = CurrentT-> ; /* ULONG */
1175 pInfoT->nSwitches = CurrentT-> ; /* ULONG */
1176 pInfoT->State = CurrentT-> ; /* DWORD */
1177 pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
1179 * Count the number of threads
1182 ++ pInfoP->ThreadCount;
1185 * Save the size of information
1186 * stored in the buffer for the
1189 pInfoP->RelativeOffset = SpiSize;
1191 * Save a reference to the last
1192 * valid information block.
1194 pInfoPLast = pInfoP;
1196 * Compute the offset of the
1197 * SYSTEM_PROCESS_INFORMATION
1198 * descriptor in the snapshot
1199 * buffer for the next process.
1201 (ULONG) pInfoP += SpiSize;
1204 * Unlock the process list.
1207 & PsProcessListLock,
1211 * Return the proper error status code,
1212 * if the buffer was too small.
1214 if (TRUE == SizeOnly)
1216 if (NULL != RequiredSize)
1218 *pRequiredSize = RequiredSize;
1220 return STATUS_INFO_LENGTH_MISMATCH;
1223 * Mark the end of the snapshot.
1225 pInfoP->RelativeOffset = 0L;
1227 return STATUS_SUCCESS;
1231 LARGE_INTEGER STDCALL
1232 PsGetProcessExitTime(VOID)
1235 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1240 PsIsThreadTerminating(IN PETHREAD Thread)
1242 return(Thread->DeadThread);
1247 PsLookupProcessByProcessId(IN PVOID ProcessId,
1248 OUT PEPROCESS *Process)
1251 PLIST_ENTRY current_entry;
1254 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
1256 current_entry = PsProcessListHead.Flink;
1257 while (current_entry != &PsProcessListHead)
1259 current = CONTAINING_RECORD(current_entry,
1262 if (current->UniqueProcessId == (ULONG)ProcessId)
1265 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1266 return(STATUS_SUCCESS);
1268 current_entry = current_entry->Flink;
1271 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1273 return(STATUS_INVALID_PARAMETER);
1278 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
1281 if (PiProcessNotifyRoutineCount >= MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1282 return(STATUS_INSUFFICIENT_RESOURCES);
1284 PiProcessNotifyRoutine[PiProcessNotifyRoutineCount] = NotifyRoutine;
1285 PiProcessNotifyRoutineCount++;
1287 return(STATUS_SUCCESS);
1290 #endif /* LIBCAPTIVE */