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((LONG *)&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 IoGetCurrentProcess(VOID)
410 if (PsGetCurrentThread() == NULL ||
411 PsGetCurrentThread()->ThreadsProcess == NULL)
413 #endif /* LIBCAPTIVE */
414 return(PsInitialSystemProcess);
419 return(PsGetCurrentThread()->ThreadsProcess);
421 #endif /* LIBCAPTIVE */
427 PsCreateSystemProcess(PHANDLE ProcessHandle,
428 ACCESS_MASK DesiredAccess,
429 POBJECT_ATTRIBUTES ObjectAttributes)
431 return NtCreateProcess(ProcessHandle,
442 NtCreateProcess(OUT PHANDLE ProcessHandle,
443 IN ACCESS_MASK DesiredAccess,
444 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
445 IN HANDLE ParentProcessHandle,
446 IN BOOLEAN InheritObjectTable,
447 IN HANDLE SectionHandle OPTIONAL,
448 IN HANDLE DebugPortHandle OPTIONAL,
449 IN HANDLE ExceptionPortHandle OPTIONAL)
451 * FUNCTION: Creates a process.
453 * ProcessHandle (OUT) = Caller supplied storage for the resulting
455 * DesiredAccess = Specifies the allowed or desired access to the
456 * process can be a combination of
457 * STANDARD_RIGHTS_REQUIRED| ..
458 * ObjectAttribute = Initialized attributes for the object, contains
459 * the rootdirectory and the filename
460 * ParentProcess = Handle to the parent process.
461 * InheritObjectTable = Specifies to inherit the objects of the parent
463 * SectionHandle = Handle to a section object to back the image file
464 * DebugPort = Handle to a DebugPort if NULL the system default debug
466 * ExceptionPort = Handle to a exception port.
468 * This function maps to the win32 CreateProcess.
473 PEPROCESS ParentProcess;
477 PVOID LdrStartupAddr;
481 PEPORT ExceptionPort;
483 PMEMORY_AREA MemoryArea;
486 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
488 Status = ObReferenceObjectByHandle(ParentProcessHandle,
489 PROCESS_CREATE_PROCESS,
492 (PVOID*)&ParentProcess,
494 if (!NT_SUCCESS(Status))
496 DPRINT("NtCreateProcess() = %x\n",Status);
500 Status = ObCreateObject(ProcessHandle,
505 if (!NT_SUCCESS(Status))
507 ObDereferenceObject(ParentProcess);
508 DPRINT("ObCreateObject() = %x\n",Status);
512 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
516 KProcess = &Process->Pcb;
517 /* Inherit parent process's affinity. */
518 KProcess->Affinity = ParentProcess->Pcb.Affinity;
519 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
520 MmInitializeAddressSpace(Process,
521 &Process->AddressSpace);
522 Process->UniqueProcessId = InterlockedIncrement((LONG *)&PiNextProcessUniqueId);
523 Process->InheritedFromUniqueProcessId =
524 (HANDLE)ParentProcess->UniqueProcessId;
525 ObCreateHandleTable(ParentProcess,
528 MmCopyMmInfo(ParentProcess, Process);
529 if (ParentProcess->Win32WindowStation != (HANDLE)0)
531 /* Always duplicate the process window station. */
532 Process->Win32WindowStation = 0;
533 Status = ObDuplicateObject(ParentProcess,
535 ParentProcess->Win32WindowStation,
536 &Process->Win32WindowStation,
539 DUPLICATE_SAME_ACCESS);
540 if (!NT_SUCCESS(Status))
547 Process->Win32WindowStation = (HANDLE)0;
549 if (ParentProcess->Win32Desktop != (HANDLE)0)
551 /* Always duplicate the process window station. */
552 Process->Win32Desktop = 0;
553 Status = ObDuplicateObject(ParentProcess,
555 ParentProcess->Win32Desktop,
556 &Process->Win32Desktop,
559 DUPLICATE_SAME_ACCESS);
560 if (!NT_SUCCESS(Status))
567 Process->Win32Desktop = (HANDLE)0;
570 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
571 for (i = 0; i < PiProcessNotifyRoutineCount; i++)
573 PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
574 (HANDLE)Process->UniqueProcessId,
577 InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
578 InitializeListHead(&Process->ThreadListHead);
579 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
581 Process->Pcb.State = PROCESS_STATE_ACTIVE;
586 if (DebugPortHandle != NULL)
588 Status = ObReferenceObjectByHandle(DebugPortHandle,
594 if (!NT_SUCCESS(Status))
596 ObDereferenceObject(Process);
597 ObDereferenceObject(ParentProcess);
598 ZwClose(*ProcessHandle);
599 *ProcessHandle = NULL;
602 Process->DebugPort = DebugPort;
606 * Add the exception port
608 if (ExceptionPortHandle != NULL)
610 Status = ObReferenceObjectByHandle(ExceptionPortHandle,
614 (PVOID*)&ExceptionPort,
616 if (!NT_SUCCESS(Status))
618 ObDereferenceObject(Process);
619 ObDereferenceObject(ParentProcess);
620 ZwClose(*ProcessHandle);
621 *ProcessHandle = NULL;
624 Process->ExceptionPort = ExceptionPort;
628 * Now we have created the process proper
632 * Create the shared data page
634 MmLockAddressSpace(&Process->AddressSpace);
635 BaseAddress = (PVOID)USER_SHARED_DATA;
636 Status = MmCreateMemoryArea(Process,
637 &Process->AddressSpace,
638 MEMORY_AREA_SHARED_DATA,
644 MmUnlockAddressSpace(&Process->AddressSpace);
645 if (!NT_SUCCESS(Status))
647 DPRINT1("Failed to create shared data page\n");
654 Status = LdrpMapSystemDll(*ProcessHandle,
656 if (!NT_SUCCESS(Status))
658 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
659 ObDereferenceObject(Process);
660 ObDereferenceObject(ParentProcess);
665 * Map the process image
667 if (SectionHandle != NULL)
669 DPRINT("Mapping process image\n");
670 Status = LdrpMapImage(*ProcessHandle,
673 if (!NT_SUCCESS(Status))
675 DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
676 ObDereferenceObject(Process);
677 ObDereferenceObject(ParentProcess);
687 * Duplicate the token
689 Status = SepInitializeNewProcess(Process, ParentProcess);
690 if (!NT_SUCCESS(Status))
692 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
693 ObDereferenceObject(Process);
694 ObDereferenceObject(ParentProcess);
701 DPRINT("Creating PEB\n");
702 Status = PsCreatePeb(*ProcessHandle,
705 if (!NT_SUCCESS(Status))
707 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
708 ObDereferenceObject(Process);
709 ObDereferenceObject(ParentProcess);
710 ZwClose(*ProcessHandle);
711 *ProcessHandle = NULL;
717 * Maybe send a message to the creator process's debugger
720 if (ParentProcess->DebugPort != NULL)
722 LPC_DBG_MESSAGE Message;
725 ObCreateHandle(NULL, // Debugger Process
726 NULL, // SectionHandle
731 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
732 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
734 Message.Type = DBG_EVENT_CREATE_PROCESS;
735 Message.Data.CreateProcess.FileHandle = FileHandle;
736 Message.Data.CreateProcess.Base = ImageBase;
737 Message.Data.CreateProcess.EntryPoint = NULL; //
739 Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
744 ObDereferenceObject(Process);
745 ObDereferenceObject(ParentProcess);
746 return(STATUS_SUCCESS);
751 NtOpenProcess(OUT PHANDLE ProcessHandle,
752 IN ACCESS_MASK DesiredAccess,
753 IN POBJECT_ATTRIBUTES ObjectAttributes,
754 IN PCLIENT_ID ClientId)
756 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
757 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
758 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
759 ClientId->UniqueProcess, ClientId->UniqueThread);
763 * Not sure of the exact semantics
765 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
766 ObjectAttributes->ObjectName->Buffer != NULL)
771 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
772 ObjectAttributes->Attributes,
779 if (Status != STATUS_SUCCESS)
784 Status = ObCreateHandle(PsGetCurrentProcess(),
789 ObDereferenceObject(Process);
796 PLIST_ENTRY current_entry;
800 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
801 current_entry = PsProcessListHead.Flink;
802 while (current_entry != &PsProcessListHead)
804 current = CONTAINING_RECORD(current_entry, EPROCESS,
806 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
808 ObReferenceObjectByPointer(current,
812 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
813 Status = ObCreateHandle(PsGetCurrentProcess(),
818 ObDereferenceObject(current);
819 DPRINT("*ProcessHandle %x\n", ProcessHandle);
820 DPRINT("NtOpenProcess() = %x\n", Status);
823 current_entry = current_entry->Flink;
825 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
826 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
827 return(STATUS_UNSUCCESSFUL);
829 return(STATUS_UNSUCCESSFUL);
834 NtQueryInformationProcess(IN HANDLE ProcessHandle,
835 IN CINT ProcessInformationClass,
836 OUT PVOID ProcessInformation,
837 IN ULONG ProcessInformationLength,
838 OUT PULONG ReturnLength)
842 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
844 Status = ObReferenceObjectByHandle(ProcessHandle,
845 PROCESS_SET_INFORMATION,
850 if (Status != STATUS_SUCCESS)
855 switch (ProcessInformationClass)
857 case ProcessBasicInformation:
858 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
860 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
861 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
862 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
863 ProcessBasicInformationP->UniqueProcessId =
864 Process->UniqueProcessId;
865 ProcessBasicInformationP->InheritedFromUniqueProcessId =
866 (ULONG)Process->InheritedFromUniqueProcessId;
867 Status = STATUS_SUCCESS;
870 case ProcessQuotaLimits:
871 case ProcessIoCounters:
872 case ProcessVmCounters:
874 case ProcessDebugPort:
875 case ProcessLdtInformation:
876 Status = STATUS_NOT_IMPLEMENTED;
879 case ProcessDefaultHardErrorMode:
880 *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
883 case ProcessWorkingSetWatch:
884 Status = STATUS_NOT_IMPLEMENTED;
887 case ProcessWx86Information:
888 case ProcessHandleCount:
889 case ProcessPriorityBoost:
890 case ProcessDeviceMap:
891 case ProcessSessionInformation:
892 case ProcessWow64Information:
893 Status = STATUS_NOT_IMPLEMENTED;
896 case ProcessBasePriority:
897 case ProcessRaisePriority:
898 case ProcessExceptionPort:
899 case ProcessAccessToken:
901 case ProcessIoPortHandlers:
902 case ProcessUserModeIOPL:
903 case ProcessEnableAlignmentFaultFixup:
904 case ProcessPriorityClass:
905 case ProcessAffinityMask:
906 case ProcessForegroundInformation:
908 Status = STATUS_INVALID_INFO_CLASS;
910 ObDereferenceObject(Process);
915 PspAssignPrimaryToken(PEPROCESS Process,
919 PACCESS_TOKEN OldToken;
922 Status = ObReferenceObjectByHandle(TokenHandle,
928 if (!NT_SUCCESS(Status))
932 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
933 if (NT_SUCCESS(Status))
935 ObDereferenceObject(OldToken);
937 ObDereferenceObject(Token);
942 NtSetInformationProcess(IN HANDLE ProcessHandle,
943 IN CINT ProcessInformationClass,
944 IN PVOID ProcessInformation,
945 IN ULONG ProcessInformationLength)
949 PHANDLE ProcessAccessTokenP;
951 Status = ObReferenceObjectByHandle(ProcessHandle,
952 PROCESS_SET_INFORMATION,
957 if (!NT_SUCCESS(Status))
962 switch (ProcessInformationClass)
964 case ProcessQuotaLimits:
965 case ProcessBasePriority:
966 case ProcessRaisePriority:
967 case ProcessDebugPort:
968 case ProcessExceptionPort:
969 Status = STATUS_NOT_IMPLEMENTED;
972 case ProcessAccessToken:
973 ProcessAccessTokenP = (PHANDLE)ProcessInformation;
974 Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
977 case ProcessImageFileName:
978 memcpy(Process->ImageFileName, ProcessInformation, 8);
979 Status = STATUS_SUCCESS;
982 case ProcessLdtInformation:
984 case ProcessDefaultHardErrorMode:
985 case ProcessIoPortHandlers:
986 case ProcessWorkingSetWatch:
987 case ProcessUserModeIOPL:
988 case ProcessEnableAlignmentFaultFixup:
989 case ProcessPriorityClass:
990 case ProcessAffinityMask:
991 Status = STATUS_NOT_IMPLEMENTED;
994 case ProcessBasicInformation:
995 case ProcessIoCounters:
996 case ProcessVmCounters:
998 case ProcessPooledUsageAndLimits:
999 case ProcessWx86Information:
1000 case ProcessHandleCount:
1001 case ProcessWow64Information:
1003 Status = STATUS_INVALID_INFO_CLASS;
1005 case ProcessDesktop:
1006 Process->Win32Desktop = *(PHANDLE)ProcessInformation;
1007 Status = STATUS_SUCCESS;
1010 ObDereferenceObject(Process);
1015 /**********************************************************************
1017 * PiQuerySystemProcessInformation
1020 * Compute the size of a process+thread snapshot as
1021 * expected by NtQuerySystemInformation.
1024 * 0 on error; otherwise the size, in bytes of the buffer
1025 * required to write a full snapshot.
1028 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
1031 PiQuerySystemProcessInformation(PVOID Buffer,
1035 return STATUS_NOT_IMPLEMENTED;
1039 PLIST_ENTRY CurrentEntryP;
1041 PLIST_ENTRY CurrentEntryT;
1044 ULONG RequiredSize = 0L;
1045 BOOLEAN SizeOnly = FALSE;
1049 PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
1050 PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
1051 PSYSTEM_THREAD_INFO pInfoT = NULL;
1054 /* Lock the process list. */
1055 KeAcquireSpinLock(&PsProcessListLock,
1059 * Scan the process list. Since the
1060 * list is circular, the guard is false
1061 * after the last process.
1063 for ( CurrentEntryP = PsProcessListHead.Flink;
1064 (CurrentEntryP != & PsProcessListHead);
1065 CurrentEntryP = CurrentEntryP->Flink
1069 * Compute how much space is
1070 * occupied in the snapshot
1071 * by adding this process info.
1072 * (at least one thread).
1074 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
1075 RequiredSize += SpiSizeCurrent;
1077 * Do not write process data in the
1078 * buffer if it is too small.
1080 if (TRUE == SizeOnly) continue;
1082 * Check if the buffer can contain
1083 * the full snapshot.
1085 if (Size < RequiredSize)
1091 * Get a reference to the
1092 * process descriptor we are
1095 CurrentP = CONTAINING_RECORD(
1101 * Write process data in the buffer.
1103 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
1105 pInfoP->ThreadCount = 0L;
1106 pInfoP->ProcessId = CurrentP->UniqueProcessId;
1107 RtlInitUnicodeString (
1109 CurrentP->ImageFileName
1112 for ( pInfoT = & CurrentP->ThreadSysInfo [0],
1113 CurrentEntryT = CurrentP->ThreadListHead.Flink;
1115 (CurrentEntryT != & CurrentP->ThreadListHead);
1117 pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
1118 CurrentEntryT = CurrentEntryT->Flink
1122 * Recalculate the size of the
1123 * information block.
1125 if (0 < pInfoP->ThreadCount)
1127 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
1130 * Do not write thread data in the
1131 * buffer if it is too small.
1133 if (TRUE == SizeOnly) continue;
1135 * Check if the buffer can contain
1136 * the full snapshot.
1138 if (Size < RequiredSize)
1144 * Get a reference to the
1145 * thread descriptor we are
1148 CurrentT = CONTAINING_RECORD(
1154 * Write thread data.
1158 sizeof (SYSTEM_THREAD_INFORMATION)
1160 pInfoT->KernelTime = CurrentT-> ; /* TIME */
1161 pInfoT->UserTime = CurrentT-> ; /* TIME */
1162 pInfoT->CreateTime = CurrentT-> ; /* TIME */
1163 pInfoT->TickCount = CurrentT-> ; /* ULONG */
1164 pInfoT->StartEIP = CurrentT-> ; /* ULONG */
1165 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1166 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1167 pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
1168 pInfoT->BasePriority = CurrentT-> ; /* ULONG */
1169 pInfoT->nSwitches = CurrentT-> ; /* ULONG */
1170 pInfoT->State = CurrentT-> ; /* DWORD */
1171 pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
1173 * Count the number of threads
1176 ++ pInfoP->ThreadCount;
1179 * Save the size of information
1180 * stored in the buffer for the
1183 pInfoP->RelativeOffset = SpiSize;
1185 * Save a reference to the last
1186 * valid information block.
1188 pInfoPLast = pInfoP;
1190 * Compute the offset of the
1191 * SYSTEM_PROCESS_INFORMATION
1192 * descriptor in the snapshot
1193 * buffer for the next process.
1195 (ULONG) pInfoP += SpiSize;
1198 * Unlock the process list.
1201 & PsProcessListLock,
1205 * Return the proper error status code,
1206 * if the buffer was too small.
1208 if (TRUE == SizeOnly)
1210 if (NULL != RequiredSize)
1212 *pRequiredSize = RequiredSize;
1214 return STATUS_INFO_LENGTH_MISMATCH;
1217 * Mark the end of the snapshot.
1219 pInfoP->RelativeOffset = 0L;
1221 return STATUS_SUCCESS;
1225 LARGE_INTEGER STDCALL
1226 PsGetProcessExitTime(VOID)
1229 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1234 PsIsThreadTerminating(IN PETHREAD Thread)
1236 return(Thread->DeadThread);
1241 PsLookupProcessByProcessId(IN PVOID ProcessId,
1242 OUT PEPROCESS *Process)
1245 PLIST_ENTRY current_entry;
1248 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
1250 current_entry = PsProcessListHead.Flink;
1251 while (current_entry != &PsProcessListHead)
1253 current = CONTAINING_RECORD(current_entry,
1256 if (current->UniqueProcessId == (ULONG)ProcessId)
1259 ObReferenceObject(current);
1260 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1261 return(STATUS_SUCCESS);
1263 current_entry = current_entry->Flink;
1266 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1268 return(STATUS_INVALID_PARAMETER);
1273 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
1276 if (PiProcessNotifyRoutineCount >= MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1277 return(STATUS_INSUFFICIENT_RESOURCES);
1279 PiProcessNotifyRoutine[PiProcessNotifyRoutineCount] = NotifyRoutine;
1280 PiProcessNotifyRoutineCount++;
1282 return(STATUS_SUCCESS);
1285 #endif /* LIBCAPTIVE */