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);
137 PACCESS_TOKEN STDCALL
138 PsReferencePrimaryToken(PEPROCESS Process)
140 ObReferenceObjectByPointer(Process->Token,
144 return(Process->Token);
149 PsOpenTokenOfProcess(HANDLE ProcessHandle,
150 PACCESS_TOKEN* Token)
155 Status = ObReferenceObjectByHandle(ProcessHandle,
156 PROCESS_QUERY_INFORMATION,
161 if (!NT_SUCCESS(Status))
165 *Token = PsReferencePrimaryToken(Process);
166 ObDereferenceObject(Process);
167 return(STATUS_SUCCESS);
172 PiKillMostProcesses(VOID)
175 PLIST_ENTRY current_entry;
178 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
180 current_entry = PsProcessListHead.Flink;
181 while (current_entry != &PsProcessListHead)
183 current = CONTAINING_RECORD(current_entry, EPROCESS,
185 current_entry = current_entry->Flink;
187 if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
188 current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
190 PiTerminateProcessThreads(current, STATUS_SUCCESS);
194 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
197 #endif /* LIBCAPTIVE */
200 PsInitProcessManagment(VOID)
207 * Register the process object type
210 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
212 PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
213 PsProcessType->TotalObjects = 0;
214 PsProcessType->TotalHandles = 0;
215 PsProcessType->MaxObjects = ULONG_MAX;
216 PsProcessType->MaxHandles = ULONG_MAX;
217 PsProcessType->PagedPoolCharge = 0;
218 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
219 PsProcessType->Mapping = &PiProcessMapping;
220 PsProcessType->Dump = NULL;
221 PsProcessType->Open = NULL;
222 PsProcessType->Close = NULL;
224 PsProcessType->Delete = PiDeleteProcess;
226 PsProcessType->Delete = NULL; /* never Delete PsInitialSystemProcess */
227 #endif /* LIBCAPTIVE */
228 PsProcessType->Parse = NULL;
229 PsProcessType->Security = NULL;
230 PsProcessType->QueryName = NULL;
231 PsProcessType->OkayToClose = NULL;
232 PsProcessType->Create = NULL;
233 PsProcessType->DuplicationNotify = NULL;
235 RtlInitUnicodeStringFromLiteral(&PsProcessType->TypeName, REACTOS_UCS2(L"Process"));
237 InitializeListHead(&PsProcessListHead);
238 KeInitializeSpinLock(&PsProcessListLock);
241 * Initialize the system process
243 Status = ObCreateObject(NULL,
247 (PVOID*)&PsInitialSystemProcess);
248 if (!NT_SUCCESS(Status))
253 /* System threads may run on any processor. */
254 PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
255 PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
257 KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
261 #endif /* LIBCAPTIVE */
262 KProcess = &PsInitialSystemProcess->Pcb;
265 MmInitializeAddressSpace(PsInitialSystemProcess,
266 &PsInitialSystemProcess->AddressSpace);
267 #endif /* LIBCAPTIVE */
268 ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess);
270 KProcess->DirectoryTableBase =
271 (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
272 #endif /* LIBCAPTIVE */
273 PsInitialSystemProcess->UniqueProcessId =
274 InterlockedIncrement(&PiNextProcessUniqueId);
275 PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
276 PsInitialSystemProcess->Win32Desktop = (HANDLE)0;
278 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
279 InsertHeadList(&PsProcessListHead,
280 &PsInitialSystemProcess->ProcessListEntry);
281 InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
282 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
284 strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM");
287 SepCreateSystemProcessToken(PsInitialSystemProcess);
288 #endif /* LIBCAPTIVE */
290 ObCreateHandle(PsInitialSystemProcess,
291 PsInitialSystemProcess,
294 &SystemProcessHandle);
300 PiDeleteProcess(PVOID ObjectBody)
306 DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody);
308 Process = (PEPROCESS)ObjectBody;
309 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
310 for (i = 0; i < PiProcessNotifyRoutineCount; i++)
312 PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
313 (HANDLE)Process->UniqueProcessId,
316 RemoveEntryList(&Process->ProcessListEntry);
317 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
320 KDB_DELETEPROCESS_HOOK(Process->Peb);
322 ObDereferenceObject(Process->Token);
324 (VOID)MmReleaseMmInfo(Process);
325 ObDeleteHandleTable(Process);
330 PsCreatePeb(HANDLE ProcessHandle,
340 memset(&Peb, 0, sizeof(Peb));
341 Peb.ImageBaseAddress = ImageBase;
343 PebBase = (PVOID)PEB_BASE;
345 Status = NtAllocateVirtualMemory(ProcessHandle,
349 MEM_RESERVE | MEM_COMMIT,
351 if (!NT_SUCCESS(Status))
356 NtWriteVirtualMemory(ProcessHandle,
362 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase);
366 return(STATUS_SUCCESS);
371 KeGetCurrentProcess(VOID)
373 * FUNCTION: Returns a pointer to the current process
376 return(&(PsGetCurrentProcess()->Pcb));
380 PsGetCurrentProcessId(VOID)
382 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
385 #endif /* LIBCAPTIVE */
388 * FUNCTION: Returns a pointer to the current process
391 PsGetCurrentProcess(VOID)
394 if (PsGetCurrentThread() == NULL ||
395 PsGetCurrentThread()->ThreadsProcess == NULL)
397 #endif /* LIBCAPTIVE */
398 return(PsInitialSystemProcess);
403 return(PsGetCurrentThread()->ThreadsProcess);
405 #endif /* LIBCAPTIVE */
411 IoGetCurrentProcess(VOID)
413 return(PsGetCurrentProcess());
417 PsCreateSystemProcess(PHANDLE ProcessHandle,
418 ACCESS_MASK DesiredAccess,
419 POBJECT_ATTRIBUTES ObjectAttributes)
421 return NtCreateProcess(ProcessHandle,
432 NtCreateProcess(OUT PHANDLE ProcessHandle,
433 IN ACCESS_MASK DesiredAccess,
434 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
435 IN HANDLE ParentProcessHandle,
436 IN BOOLEAN InheritObjectTable,
437 IN HANDLE SectionHandle OPTIONAL,
438 IN HANDLE DebugPortHandle OPTIONAL,
439 IN HANDLE ExceptionPortHandle OPTIONAL)
441 * FUNCTION: Creates a process.
443 * ProcessHandle (OUT) = Caller supplied storage for the resulting
445 * DesiredAccess = Specifies the allowed or desired access to the
446 * process can be a combination of
447 * STANDARD_RIGHTS_REQUIRED| ..
448 * ObjectAttribute = Initialized attributes for the object, contains
449 * the rootdirectory and the filename
450 * ParentProcess = Handle to the parent process.
451 * InheritObjectTable = Specifies to inherit the objects of the parent
453 * SectionHandle = Handle to a section object to back the image file
454 * DebugPort = Handle to a DebugPort if NULL the system default debug
456 * ExceptionPort = Handle to a exception port.
458 * This function maps to the win32 CreateProcess.
463 PEPROCESS ParentProcess;
467 PVOID LdrStartupAddr;
471 PEPORT ExceptionPort;
473 PMEMORY_AREA MemoryArea;
476 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
478 Status = ObReferenceObjectByHandle(ParentProcessHandle,
479 PROCESS_CREATE_PROCESS,
482 (PVOID*)&ParentProcess,
484 if (!NT_SUCCESS(Status))
486 DPRINT("NtCreateProcess() = %x\n",Status);
490 Status = ObCreateObject(ProcessHandle,
495 if (!NT_SUCCESS(Status))
497 ObDereferenceObject(ParentProcess);
498 DPRINT("ObCreateObject() = %x\n",Status);
502 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
506 KProcess = &Process->Pcb;
507 /* Inherit parent process's affinity. */
508 KProcess->Affinity = ParentProcess->Pcb.Affinity;
509 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
510 MmInitializeAddressSpace(Process,
511 &Process->AddressSpace);
512 Process->UniqueProcessId = InterlockedIncrement(&PiNextProcessUniqueId);
513 Process->InheritedFromUniqueProcessId =
514 (HANDLE)ParentProcess->UniqueProcessId;
515 ObCreateHandleTable(ParentProcess,
518 MmCopyMmInfo(ParentProcess, Process);
519 if (ParentProcess->Win32WindowStation != (HANDLE)0)
521 /* Always duplicate the process window station. */
522 Process->Win32WindowStation = 0;
523 Status = ObDuplicateObject(ParentProcess,
525 ParentProcess->Win32WindowStation,
526 &Process->Win32WindowStation,
529 DUPLICATE_SAME_ACCESS);
530 if (!NT_SUCCESS(Status))
537 Process->Win32WindowStation = (HANDLE)0;
539 if (ParentProcess->Win32Desktop != (HANDLE)0)
541 /* Always duplicate the process window station. */
542 Process->Win32Desktop = 0;
543 Status = ObDuplicateObject(ParentProcess,
545 ParentProcess->Win32Desktop,
546 &Process->Win32Desktop,
549 DUPLICATE_SAME_ACCESS);
550 if (!NT_SUCCESS(Status))
557 Process->Win32Desktop = (HANDLE)0;
560 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
561 for (i = 0; i < PiProcessNotifyRoutineCount; i++)
563 PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
564 (HANDLE)Process->UniqueProcessId,
567 InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
568 InitializeListHead(&Process->ThreadListHead);
569 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
571 Process->Pcb.State = PROCESS_STATE_ACTIVE;
576 if (DebugPortHandle != NULL)
578 Status = ObReferenceObjectByHandle(DebugPortHandle,
584 if (!NT_SUCCESS(Status))
586 ObDereferenceObject(Process);
587 ObDereferenceObject(ParentProcess);
588 ZwClose(*ProcessHandle);
589 *ProcessHandle = NULL;
592 Process->DebugPort = DebugPort;
596 * Add the exception port
598 if (ExceptionPortHandle != NULL)
600 Status = ObReferenceObjectByHandle(ExceptionPortHandle,
604 (PVOID*)&ExceptionPort,
606 if (!NT_SUCCESS(Status))
608 ObDereferenceObject(Process);
609 ObDereferenceObject(ParentProcess);
610 ZwClose(*ProcessHandle);
611 *ProcessHandle = NULL;
614 Process->ExceptionPort = ExceptionPort;
618 * Now we have created the process proper
622 * Create the shared data page
624 MmLockAddressSpace(&Process->AddressSpace);
625 BaseAddress = (PVOID)USER_SHARED_DATA;
626 Status = MmCreateMemoryArea(Process,
627 &Process->AddressSpace,
628 MEMORY_AREA_SHARED_DATA,
634 MmUnlockAddressSpace(&Process->AddressSpace);
635 if (!NT_SUCCESS(Status))
637 DPRINT1("Failed to create shared data page\n");
644 Status = LdrpMapSystemDll(*ProcessHandle,
646 if (!NT_SUCCESS(Status))
648 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
649 ObDereferenceObject(Process);
650 ObDereferenceObject(ParentProcess);
655 * Map the process image
657 if (SectionHandle != NULL)
659 DPRINT("Mapping process image\n");
660 Status = LdrpMapImage(*ProcessHandle,
663 if (!NT_SUCCESS(Status))
665 DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
666 ObDereferenceObject(Process);
667 ObDereferenceObject(ParentProcess);
677 * Duplicate the token
679 Status = SepInitializeNewProcess(Process, ParentProcess);
680 if (!NT_SUCCESS(Status))
682 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
683 ObDereferenceObject(Process);
684 ObDereferenceObject(ParentProcess);
691 DPRINT("Creating PEB\n");
692 Status = PsCreatePeb(*ProcessHandle,
695 if (!NT_SUCCESS(Status))
697 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
698 ObDereferenceObject(Process);
699 ObDereferenceObject(ParentProcess);
700 ZwClose(*ProcessHandle);
701 *ProcessHandle = NULL;
707 * Maybe send a message to the creator process's debugger
710 if (ParentProcess->DebugPort != NULL)
712 LPC_DBG_MESSAGE Message;
715 ObCreateHandle(NULL, // Debugger Process
716 NULL, // SectionHandle
721 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
722 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
724 Message.Type = DBG_EVENT_CREATE_PROCESS;
725 Message.Data.CreateProcess.FileHandle = FileHandle;
726 Message.Data.CreateProcess.Base = ImageBase;
727 Message.Data.CreateProcess.EntryPoint = NULL; //
729 Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
734 ObDereferenceObject(Process);
735 ObDereferenceObject(ParentProcess);
736 return(STATUS_SUCCESS);
741 NtOpenProcess(OUT PHANDLE ProcessHandle,
742 IN ACCESS_MASK DesiredAccess,
743 IN POBJECT_ATTRIBUTES ObjectAttributes,
744 IN PCLIENT_ID ClientId)
746 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
747 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
748 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
749 ClientId->UniqueProcess, ClientId->UniqueThread);
753 * Not sure of the exact semantics
755 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
756 ObjectAttributes->ObjectName->Buffer != NULL)
761 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
762 ObjectAttributes->Attributes,
769 if (Status != STATUS_SUCCESS)
774 Status = ObCreateHandle(PsGetCurrentProcess(),
779 ObDereferenceObject(Process);
786 PLIST_ENTRY current_entry;
790 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
791 current_entry = PsProcessListHead.Flink;
792 while (current_entry != &PsProcessListHead)
794 current = CONTAINING_RECORD(current_entry, EPROCESS,
796 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
798 ObReferenceObjectByPointer(current,
802 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
803 Status = ObCreateHandle(PsGetCurrentProcess(),
808 ObDereferenceObject(current);
809 DPRINT("*ProcessHandle %x\n", ProcessHandle);
810 DPRINT("NtOpenProcess() = %x\n", Status);
813 current_entry = current_entry->Flink;
815 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
816 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
817 return(STATUS_UNSUCCESSFUL);
819 return(STATUS_UNSUCCESSFUL);
824 NtQueryInformationProcess(IN HANDLE ProcessHandle,
825 IN CINT ProcessInformationClass,
826 OUT PVOID ProcessInformation,
827 IN ULONG ProcessInformationLength,
828 OUT PULONG ReturnLength)
832 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
834 Status = ObReferenceObjectByHandle(ProcessHandle,
835 PROCESS_SET_INFORMATION,
840 if (Status != STATUS_SUCCESS)
845 switch (ProcessInformationClass)
847 case ProcessBasicInformation:
848 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
850 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
851 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
852 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
853 ProcessBasicInformationP->UniqueProcessId =
854 Process->UniqueProcessId;
855 ProcessBasicInformationP->InheritedFromUniqueProcessId =
856 (ULONG)Process->InheritedFromUniqueProcessId;
857 Status = STATUS_SUCCESS;
860 case ProcessQuotaLimits:
861 case ProcessIoCounters:
862 case ProcessVmCounters:
864 case ProcessDebugPort:
865 case ProcessLdtInformation:
866 Status = STATUS_NOT_IMPLEMENTED;
869 case ProcessDefaultHardErrorMode:
870 *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
873 case ProcessWorkingSetWatch:
874 Status = STATUS_NOT_IMPLEMENTED;
877 case ProcessWx86Information:
878 case ProcessHandleCount:
879 case ProcessPriorityBoost:
880 case ProcessDeviceMap:
881 case ProcessSessionInformation:
882 case ProcessWow64Information:
883 Status = STATUS_NOT_IMPLEMENTED;
886 case ProcessBasePriority:
887 case ProcessRaisePriority:
888 case ProcessExceptionPort:
889 case ProcessAccessToken:
891 case ProcessIoPortHandlers:
892 case ProcessUserModeIOPL:
893 case ProcessEnableAlignmentFaultFixup:
894 case ProcessPriorityClass:
895 case ProcessAffinityMask:
896 case ProcessForegroundInformation:
898 Status = STATUS_INVALID_INFO_CLASS;
900 ObDereferenceObject(Process);
905 PspAssignPrimaryToken(PEPROCESS Process,
909 PACCESS_TOKEN OldToken;
912 Status = ObReferenceObjectByHandle(TokenHandle,
918 if (!NT_SUCCESS(Status))
922 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
923 if (NT_SUCCESS(Status))
925 ObDereferenceObject(OldToken);
927 ObDereferenceObject(Token);
932 NtSetInformationProcess(IN HANDLE ProcessHandle,
933 IN CINT ProcessInformationClass,
934 IN PVOID ProcessInformation,
935 IN ULONG ProcessInformationLength)
939 PHANDLE ProcessAccessTokenP;
941 Status = ObReferenceObjectByHandle(ProcessHandle,
942 PROCESS_SET_INFORMATION,
947 if (!NT_SUCCESS(Status))
952 switch (ProcessInformationClass)
954 case ProcessQuotaLimits:
955 case ProcessBasePriority:
956 case ProcessRaisePriority:
957 case ProcessDebugPort:
958 case ProcessExceptionPort:
959 Status = STATUS_NOT_IMPLEMENTED;
962 case ProcessAccessToken:
963 ProcessAccessTokenP = (PHANDLE)ProcessInformation;
964 Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
967 case ProcessImageFileName:
968 memcpy(Process->ImageFileName, ProcessInformation, 8);
969 Status = STATUS_SUCCESS;
972 case ProcessLdtInformation:
974 case ProcessDefaultHardErrorMode:
975 case ProcessIoPortHandlers:
976 case ProcessWorkingSetWatch:
977 case ProcessUserModeIOPL:
978 case ProcessEnableAlignmentFaultFixup:
979 case ProcessPriorityClass:
980 case ProcessAffinityMask:
981 Status = STATUS_NOT_IMPLEMENTED;
984 case ProcessBasicInformation:
985 case ProcessIoCounters:
986 case ProcessVmCounters:
988 case ProcessPooledUsageAndLimits:
989 case ProcessWx86Information:
990 case ProcessHandleCount:
991 case ProcessWow64Information:
993 Status = STATUS_INVALID_INFO_CLASS;
996 Process->Win32Desktop = *(PHANDLE)ProcessInformation;
997 Status = STATUS_SUCCESS;
1000 ObDereferenceObject(Process);
1005 /**********************************************************************
1007 * PiQuerySystemProcessInformation
1010 * Compute the size of a process+thread snapshot as
1011 * expected by NtQuerySystemInformation.
1014 * 0 on error; otherwise the size, in bytes of the buffer
1015 * required to write a full snapshot.
1018 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
1021 PiQuerySystemProcessInformation(PVOID Buffer,
1025 return STATUS_NOT_IMPLEMENTED;
1029 PLIST_ENTRY CurrentEntryP;
1031 PLIST_ENTRY CurrentEntryT;
1034 ULONG RequiredSize = 0L;
1035 BOOLEAN SizeOnly = FALSE;
1039 PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
1040 PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
1041 PSYSTEM_THREAD_INFO pInfoT = NULL;
1044 /* Lock the process list. */
1045 KeAcquireSpinLock(&PsProcessListLock,
1049 * Scan the process list. Since the
1050 * list is circular, the guard is false
1051 * after the last process.
1053 for ( CurrentEntryP = PsProcessListHead.Flink;
1054 (CurrentEntryP != & PsProcessListHead);
1055 CurrentEntryP = CurrentEntryP->Flink
1059 * Compute how much space is
1060 * occupied in the snapshot
1061 * by adding this process info.
1062 * (at least one thread).
1064 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
1065 RequiredSize += SpiSizeCurrent;
1067 * Do not write process data in the
1068 * buffer if it is too small.
1070 if (TRUE == SizeOnly) continue;
1072 * Check if the buffer can contain
1073 * the full snapshot.
1075 if (Size < RequiredSize)
1081 * Get a reference to the
1082 * process descriptor we are
1085 CurrentP = CONTAINING_RECORD(
1091 * Write process data in the buffer.
1093 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
1095 pInfoP->ThreadCount = 0L;
1096 pInfoP->ProcessId = CurrentP->UniqueProcessId;
1097 RtlInitUnicodeString (
1099 CurrentP->ImageFileName
1102 for ( pInfoT = & CurrentP->ThreadSysInfo [0],
1103 CurrentEntryT = CurrentP->ThreadListHead.Flink;
1105 (CurrentEntryT != & CurrentP->ThreadListHead);
1107 pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
1108 CurrentEntryT = CurrentEntryT->Flink
1112 * Recalculate the size of the
1113 * information block.
1115 if (0 < pInfoP->ThreadCount)
1117 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
1120 * Do not write thread data in the
1121 * buffer if it is too small.
1123 if (TRUE == SizeOnly) continue;
1125 * Check if the buffer can contain
1126 * the full snapshot.
1128 if (Size < RequiredSize)
1134 * Get a reference to the
1135 * thread descriptor we are
1138 CurrentT = CONTAINING_RECORD(
1144 * Write thread data.
1148 sizeof (SYSTEM_THREAD_INFORMATION)
1150 pInfoT->KernelTime = CurrentT-> ; /* TIME */
1151 pInfoT->UserTime = CurrentT-> ; /* TIME */
1152 pInfoT->CreateTime = CurrentT-> ; /* TIME */
1153 pInfoT->TickCount = CurrentT-> ; /* ULONG */
1154 pInfoT->StartEIP = CurrentT-> ; /* ULONG */
1155 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1156 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1157 pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
1158 pInfoT->BasePriority = CurrentT-> ; /* ULONG */
1159 pInfoT->nSwitches = CurrentT-> ; /* ULONG */
1160 pInfoT->State = CurrentT-> ; /* DWORD */
1161 pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
1163 * Count the number of threads
1166 ++ pInfoP->ThreadCount;
1169 * Save the size of information
1170 * stored in the buffer for the
1173 pInfoP->RelativeOffset = SpiSize;
1175 * Save a reference to the last
1176 * valid information block.
1178 pInfoPLast = pInfoP;
1180 * Compute the offset of the
1181 * SYSTEM_PROCESS_INFORMATION
1182 * descriptor in the snapshot
1183 * buffer for the next process.
1185 (ULONG) pInfoP += SpiSize;
1188 * Unlock the process list.
1191 & PsProcessListLock,
1195 * Return the proper error status code,
1196 * if the buffer was too small.
1198 if (TRUE == SizeOnly)
1200 if (NULL != RequiredSize)
1202 *pRequiredSize = RequiredSize;
1204 return STATUS_INFO_LENGTH_MISMATCH;
1207 * Mark the end of the snapshot.
1209 pInfoP->RelativeOffset = 0L;
1211 return STATUS_SUCCESS;
1215 LARGE_INTEGER STDCALL
1216 PsGetProcessExitTime(VOID)
1219 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1224 PsIsThreadTerminating(IN PETHREAD Thread)
1226 return(Thread->DeadThread);
1231 PsLookupProcessByProcessId(IN PVOID ProcessId,
1232 OUT PEPROCESS *Process)
1235 PLIST_ENTRY current_entry;
1238 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
1240 current_entry = PsProcessListHead.Flink;
1241 while (current_entry != &PsProcessListHead)
1243 current = CONTAINING_RECORD(current_entry,
1246 if (current->UniqueProcessId == (ULONG)ProcessId)
1249 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1250 return(STATUS_SUCCESS);
1252 current_entry = current_entry->Flink;
1255 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1257 return(STATUS_INVALID_PARAMETER);
1262 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
1265 if (PiProcessNotifyRoutineCount >= MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1266 return(STATUS_INSUFFICIENT_RESOURCES);
1268 PiProcessNotifyRoutine[PiProcessNotifyRoutineCount] = NotifyRoutine;
1269 PiProcessNotifyRoutineCount++;
1271 return(STATUS_SUCCESS);
1274 #endif /* LIBCAPTIVE */