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 #define NTOS_MODE_KERNEL
17 #include <internal/ob.h>
18 #include <internal/mm.h>
19 #include <internal/ke.h>
20 #include <internal/ps.h>
21 #include <internal/se.h>
22 #include <internal/id.h>
24 #include <internal/ldr.h>
25 #include <internal/port.h>
27 #include <internal/dbg.h>
28 #include <internal/pool.h>
30 #include <internal/se.h>
31 #include <internal/kd.h>
32 #include <internal/nls.h>
35 #include <internal/debug.h>
38 /* GLOBALS ******************************************************************/
40 PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
41 HANDLE SystemProcessHandle = NULL;
43 POBJECT_TYPE EXPORTED PsProcessType = NULL;
45 LIST_ENTRY PsProcessListHead;
46 static KSPIN_LOCK PsProcessListLock;
47 static ULONG PiNextProcessUniqueId = 0;
49 static GENERIC_MAPPING PiProcessMapping = {PROCESS_READ,
54 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
56 static PCREATE_PROCESS_NOTIFY_ROUTINE
57 PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
61 WORK_QUEUE_ITEM WorkQueueItem;
64 BOOLEAN IsWorkerQueue;
65 } DEL_CONTEXT, *PDEL_CONTEXT;
67 /* FUNCTIONS *****************************************************************/
70 PsGetNextProcess(PEPROCESS OldProcess)
73 PEPROCESS NextProcess;
76 if (OldProcess == NULL)
78 return(PsInitialSystemProcess);
81 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
82 if (OldProcess->ProcessListEntry.Flink == &PsProcessListHead)
84 NextProcess = CONTAINING_RECORD(PsProcessListHead.Flink,
90 NextProcess = CONTAINING_RECORD(OldProcess->ProcessListEntry.Flink,
94 Status = ObReferenceObjectByPointer(NextProcess,
98 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
99 if (!NT_SUCCESS(Status))
101 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
104 ObDereferenceObject(OldProcess);
111 _NtOpenProcessToken(IN HANDLE ProcessHandle,
112 IN ACCESS_MASK DesiredAccess,
113 OUT PHANDLE TokenHandle)
118 Status = PsOpenTokenOfProcess(ProcessHandle,
120 if (!NT_SUCCESS(Status))
124 Status = ObCreateHandle(PsGetCurrentProcess(),
129 ObDereferenceObject(Token);
138 NtOpenProcessToken(IN HANDLE ProcessHandle,
139 IN ACCESS_MASK DesiredAccess,
140 OUT PHANDLE TokenHandle)
142 return _NtOpenProcessToken(ProcessHandle, DesiredAccess, TokenHandle);
149 PACCESS_TOKEN STDCALL
150 PsReferencePrimaryToken(PEPROCESS Process)
152 ObReferenceObjectByPointer(Process->Token,
156 return(Process->Token);
161 PsOpenTokenOfProcess(HANDLE ProcessHandle,
162 PACCESS_TOKEN* Token)
167 Status = ObReferenceObjectByHandle(ProcessHandle,
168 PROCESS_QUERY_INFORMATION,
173 if (!NT_SUCCESS(Status))
177 *Token = PsReferencePrimaryToken(Process);
178 ObDereferenceObject(Process);
179 return(STATUS_SUCCESS);
184 PiKillMostProcesses(VOID)
187 PLIST_ENTRY current_entry;
190 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
192 current_entry = PsProcessListHead.Flink;
193 while (current_entry != &PsProcessListHead)
195 current = CONTAINING_RECORD(current_entry, EPROCESS,
197 current_entry = current_entry->Flink;
199 if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
200 current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
202 PiTerminateProcessThreads(current, STATUS_SUCCESS);
206 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
211 PsInitProcessManagment(VOID)
218 * Register the process object type
221 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
223 PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
224 PsProcessType->TotalObjects = 0;
225 PsProcessType->TotalHandles = 0;
226 PsProcessType->MaxObjects = ULONG_MAX;
227 PsProcessType->MaxHandles = ULONG_MAX;
228 PsProcessType->PagedPoolCharge = 0;
229 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
230 PsProcessType->Mapping = &PiProcessMapping;
231 PsProcessType->Dump = NULL;
232 PsProcessType->Open = NULL;
233 PsProcessType->Close = NULL;
234 PsProcessType->Delete = PiDeleteProcess;
235 PsProcessType->Parse = NULL;
236 PsProcessType->Security = NULL;
237 PsProcessType->QueryName = NULL;
238 PsProcessType->OkayToClose = NULL;
239 PsProcessType->Create = NULL;
240 PsProcessType->DuplicationNotify = NULL;
242 RtlInitUnicodeStringFromLiteral(&PsProcessType->TypeName, L"Process");
244 InitializeListHead(&PsProcessListHead);
245 KeInitializeSpinLock(&PsProcessListLock);
248 * Initialize the system process
250 Status = ObRosCreateObject(NULL,
254 (PVOID*)&PsInitialSystemProcess);
255 if (!NT_SUCCESS(Status))
260 /* System threads may run on any processor. */
261 PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
262 PsInitialSystemProcess->Pcb.IopmOffset = 0xffff;
263 PsInitialSystemProcess->Pcb.LdtDescriptor[0] = 0;
264 PsInitialSystemProcess->Pcb.LdtDescriptor[1] = 0;
265 PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
266 KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
270 KProcess = &PsInitialSystemProcess->Pcb;
272 MmInitializeAddressSpace(PsInitialSystemProcess,
273 &PsInitialSystemProcess->AddressSpace);
274 ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess);
275 KProcess->DirectoryTableBase =
276 (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
277 PsInitialSystemProcess->UniqueProcessId =
278 InterlockedIncrement((LONG *)&PiNextProcessUniqueId);
279 PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
280 PsInitialSystemProcess->Win32Desktop = (HANDLE)0;
282 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
283 InsertHeadList(&PsProcessListHead,
284 &PsInitialSystemProcess->ProcessListEntry);
285 InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
286 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
288 strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM");
290 SepCreateSystemProcessToken(PsInitialSystemProcess);
292 ObCreateHandle(PsInitialSystemProcess,
293 PsInitialSystemProcess,
296 &SystemProcessHandle);
300 PiDeleteProcessWorker(PVOID pContext)
304 PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
305 ULONG NotifyRoutineCount;
306 PDEL_CONTEXT Context;
307 PEPROCESS CurrentProcess;
310 Context = (PDEL_CONTEXT)pContext;
311 Process = Context->Process;
312 CurrentProcess = PsGetCurrentProcess();
314 DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process);
316 if (CurrentProcess != Process)
318 KeAttachProcess(Process);
321 /* Terminate Win32 Process */
322 PsTerminateWin32Process (Process);
324 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
325 NotifyRoutineCount = 0;
326 for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; i++)
328 if (PiProcessNotifyRoutine[i])
330 NotifyRoutine[NotifyRoutineCount++] = PiProcessNotifyRoutine[i];
333 RemoveEntryList(&Process->ProcessListEntry);
334 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
336 for (i = 0;i < NotifyRoutineCount; i++)
338 /* must be called below DISPATCH_LVL */
339 NotifyRoutine[i](Process->InheritedFromUniqueProcessId,
340 (HANDLE)Process->UniqueProcessId,
345 KDB_DELETEPROCESS_HOOK(Process);
347 ObDereferenceObject(Process->Token);
348 ObDeleteHandleTable(Process);
350 if (CurrentProcess != Process)
355 MmReleaseMmInfo(Process);
356 if (Context->IsWorkerQueue)
358 KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
363 PiDeleteProcess(PVOID ObjectBody)
367 Context.Process = (PEPROCESS)ObjectBody;
369 if (PsGetCurrentProcess() == Context.Process || PsGetCurrentThread()->OldProcess == NULL)
371 Context.IsWorkerQueue = FALSE;
372 PiDeleteProcessWorker(&Context);
376 Context.IsWorkerQueue = TRUE;
377 KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
378 ExInitializeWorkItem (&Context.WorkQueueItem, PiDeleteProcessWorker, &Context);
379 ExQueueWorkItem(&Context.WorkQueueItem, HyperCriticalWorkQueue);
380 if (KeReadStateEvent(&Context.Event) == 0)
382 KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL);
388 PsCreatePeb(HANDLE ProcessHandle,
394 LARGE_INTEGER SectionOffset;
399 /* Allocate the Process Environment Block (PEB) */
400 Peb = (PPEB)PEB_BASE;
402 Status = NtAllocateVirtualMemory(ProcessHandle,
406 MEM_RESERVE | MEM_COMMIT,
408 if (!NT_SUCCESS(Status))
410 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
413 DPRINT("Peb %p PebSize %lu\n", Peb, PebSize);
416 SectionOffset.QuadPart = 0LL;
418 Status = MmMapViewOfSection(NlsSectionObject,
428 if (!NT_SUCCESS(Status))
430 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
433 DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
435 KeAttachProcess(Process);
437 /* Initialize the PEB */
438 RtlZeroMemory(Peb, sizeof(PEB));
439 Peb->ImageBaseAddress = ImageBase;
441 Peb->OSMajorVersion = 4;
442 Peb->OSMinorVersion = 0;
443 Peb->OSBuildNumber = 0;
444 Peb->OSPlatformId = 2; //VER_PLATFORM_WIN32_NT;
446 Peb->AnsiCodePageData = TableBase + NlsAnsiTableOffset;
447 Peb->OemCodePageData = TableBase + NlsOemTableOffset;
448 Peb->UnicodeCaseTableData = TableBase + NlsUnicodeTableOffset;
453 DPRINT("PsCreatePeb: Peb created at %p\n", Peb);
455 return(STATUS_SUCCESS);
460 KeGetCurrentProcess(VOID)
462 * FUNCTION: Returns a pointer to the current process
465 return(&(PsGetCurrentProcess()->Pcb));
472 PsGetCurrentProcessId(VOID)
474 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
478 * FUNCTION: Returns a pointer to the current process
483 IoGetCurrentProcess(VOID)
485 if (PsGetCurrentThread() == NULL ||
486 PsGetCurrentThread()->ThreadsProcess == NULL)
488 return(PsInitialSystemProcess);
492 return(PsGetCurrentThread()->ThreadsProcess);
500 PsCreateSystemProcess(PHANDLE ProcessHandle,
501 ACCESS_MASK DesiredAccess,
502 POBJECT_ATTRIBUTES ObjectAttributes)
504 return NtCreateProcess(ProcessHandle,
515 NtCreateProcess(OUT PHANDLE ProcessHandle,
516 IN ACCESS_MASK DesiredAccess,
517 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
518 IN HANDLE ParentProcessHandle,
519 IN BOOLEAN InheritObjectTable,
520 IN HANDLE SectionHandle OPTIONAL,
521 IN HANDLE DebugPortHandle OPTIONAL,
522 IN HANDLE ExceptionPortHandle OPTIONAL)
524 * FUNCTION: Creates a process.
526 * ProcessHandle (OUT) = Caller supplied storage for the resulting
528 * DesiredAccess = Specifies the allowed or desired access to the
529 * process can be a combination of
530 * STANDARD_RIGHTS_REQUIRED| ..
531 * ObjectAttribute = Initialized attributes for the object, contains
532 * the rootdirectory and the filename
533 * ParentProcess = Handle to the parent process.
534 * InheritObjectTable = Specifies to inherit the objects of the parent
536 * SectionHandle = Handle to a section object to back the image file
537 * DebugPort = Handle to a DebugPort if NULL the system default debug
539 * ExceptionPort = Handle to a exception port.
541 * This function maps to the win32 CreateProcess.
546 PEPROCESS ParentProcess;
550 PVOID LdrStartupAddr;
553 PEPORT ExceptionPort;
555 PMEMORY_AREA MemoryArea;
557 PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
558 ULONG NotifyRoutineCount;
560 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
562 Status = ObReferenceObjectByHandle(ParentProcessHandle,
563 PROCESS_CREATE_PROCESS,
566 (PVOID*)&ParentProcess,
568 if (!NT_SUCCESS(Status))
570 DPRINT("NtCreateProcess() = %x\n",Status);
574 Status = ObRosCreateObject(ProcessHandle,
579 if (!NT_SUCCESS(Status))
581 ObDereferenceObject(ParentProcess);
582 DPRINT("ObRosCreateObject() = %x\n",Status);
586 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
590 KProcess = &Process->Pcb;
591 /* Inherit parent process's affinity. */
592 KProcess->Affinity = ParentProcess->Pcb.Affinity;
593 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
594 KProcess->IopmOffset = 0xffff;
595 KProcess->LdtDescriptor[0] = 0;
596 KProcess->LdtDescriptor[1] = 0;
597 MmInitializeAddressSpace(Process,
598 &Process->AddressSpace);
599 Process->UniqueProcessId = InterlockedIncrement((LONG *)&PiNextProcessUniqueId);
600 Process->InheritedFromUniqueProcessId =
601 (HANDLE)ParentProcess->UniqueProcessId;
602 ObCreateHandleTable(ParentProcess,
605 MmCopyMmInfo(ParentProcess, Process);
606 if (ParentProcess->Win32WindowStation != (HANDLE)0)
608 /* Always duplicate the process window station. */
609 Process->Win32WindowStation = 0;
610 Status = ObDuplicateObject(ParentProcess,
612 ParentProcess->Win32WindowStation,
613 &Process->Win32WindowStation,
616 DUPLICATE_SAME_ACCESS);
617 if (!NT_SUCCESS(Status))
624 Process->Win32WindowStation = (HANDLE)0;
626 if (ParentProcess->Win32Desktop != (HANDLE)0)
628 /* Always duplicate the process window station. */
629 Process->Win32Desktop = 0;
630 Status = ObDuplicateObject(ParentProcess,
632 ParentProcess->Win32Desktop,
633 &Process->Win32Desktop,
636 DUPLICATE_SAME_ACCESS);
637 if (!NT_SUCCESS(Status))
644 Process->Win32Desktop = (HANDLE)0;
647 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
648 NotifyRoutineCount = 0;
649 for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; i++)
651 if (PiProcessNotifyRoutine[i])
653 NotifyRoutine[NotifyRoutineCount++] = PiProcessNotifyRoutine[i];
656 InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
657 InitializeListHead(&Process->ThreadListHead);
658 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
660 for (i = 0;i < NotifyRoutineCount; i++)
662 //must be called below DISPATCH_LVL
663 NotifyRoutine[i](Process->InheritedFromUniqueProcessId,
664 (HANDLE)Process->UniqueProcessId,
668 Process->Pcb.State = PROCESS_STATE_ACTIVE;
673 if (DebugPortHandle != NULL)
675 Status = ObReferenceObjectByHandle(DebugPortHandle,
681 if (!NT_SUCCESS(Status))
683 ObDereferenceObject(Process);
684 ObDereferenceObject(ParentProcess);
685 ZwClose(*ProcessHandle);
686 *ProcessHandle = NULL;
689 Process->DebugPort = DebugPort;
693 * Add the exception port
695 if (ExceptionPortHandle != NULL)
697 Status = ObReferenceObjectByHandle(ExceptionPortHandle,
701 (PVOID*)&ExceptionPort,
703 if (!NT_SUCCESS(Status))
705 ObDereferenceObject(Process);
706 ObDereferenceObject(ParentProcess);
707 ZwClose(*ProcessHandle);
708 *ProcessHandle = NULL;
711 Process->ExceptionPort = ExceptionPort;
715 * Now we have created the process proper
718 MmLockAddressSpace(&Process->AddressSpace);
720 /* Protect the highest 64KB of the process address space */
721 BaseAddress = MmUserProbeAddress;
722 Status = MmCreateMemoryArea(Process,
723 &Process->AddressSpace,
724 MEMORY_AREA_NO_ACCESS,
731 if (!NT_SUCCESS(Status))
733 MmUnlockAddressSpace(&Process->AddressSpace);
734 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
738 /* Protect the lowest 64KB of the process address space */
740 BaseAddress = (PVOID)0x00000000;
741 Status = MmCreateMemoryArea(Process,
742 &Process->AddressSpace,
743 MEMORY_AREA_NO_ACCESS,
750 if (!NT_SUCCESS(Status))
752 MmUnlockAddressSpace(&Process->AddressSpace);
753 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
758 /* Protect the 60KB above the shared user page */
759 BaseAddress = (PVOID)USER_SHARED_DATA + PAGE_SIZE;
760 Status = MmCreateMemoryArea(Process,
761 &Process->AddressSpace,
762 MEMORY_AREA_NO_ACCESS,
769 if (!NT_SUCCESS(Status))
771 MmUnlockAddressSpace(&Process->AddressSpace);
772 DPRINT1("Failed to protect the memory above the shared user page\n");
776 /* Create the shared data page */
777 BaseAddress = (PVOID)USER_SHARED_DATA;
778 Status = MmCreateMemoryArea(Process,
779 &Process->AddressSpace,
780 MEMORY_AREA_SHARED_DATA,
787 MmUnlockAddressSpace(&Process->AddressSpace);
788 if (!NT_SUCCESS(Status))
790 DPRINT1("Failed to create shared data page\n");
797 Status = LdrpMapSystemDll(*ProcessHandle,
799 if (!NT_SUCCESS(Status))
801 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
802 ObDereferenceObject(Process);
803 ObDereferenceObject(ParentProcess);
808 * Map the process image
810 if (SectionHandle != NULL)
812 DPRINT("Mapping process image\n");
813 Status = LdrpMapImage(*ProcessHandle,
816 if (!NT_SUCCESS(Status))
818 DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
819 ObDereferenceObject(Process);
820 ObDereferenceObject(ParentProcess);
830 * Duplicate the token
832 Status = SepInitializeNewProcess(Process, ParentProcess);
833 if (!NT_SUCCESS(Status))
835 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
836 ObDereferenceObject(Process);
837 ObDereferenceObject(ParentProcess);
844 DPRINT("Creating PEB\n");
845 Status = PsCreatePeb(*ProcessHandle,
848 if (!NT_SUCCESS(Status))
850 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
851 ObDereferenceObject(Process);
852 ObDereferenceObject(ParentProcess);
853 ZwClose(*ProcessHandle);
854 *ProcessHandle = NULL;
859 * Maybe send a message to the creator process's debugger
862 if (ParentProcess->DebugPort != NULL)
864 LPC_DBG_MESSAGE Message;
867 ObCreateHandle(NULL, // Debugger Process
868 NULL, // SectionHandle
873 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
874 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
876 Message.Type = DBG_EVENT_CREATE_PROCESS;
877 Message.Data.CreateProcess.FileHandle = FileHandle;
878 Message.Data.CreateProcess.Base = ImageBase;
879 Message.Data.CreateProcess.EntryPoint = NULL; //
881 Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
886 ObDereferenceObject(Process);
887 ObDereferenceObject(ParentProcess);
888 return(STATUS_SUCCESS);
896 NtOpenProcess(OUT PHANDLE ProcessHandle,
897 IN ACCESS_MASK DesiredAccess,
898 IN POBJECT_ATTRIBUTES ObjectAttributes,
899 IN PCLIENT_ID ClientId)
901 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
902 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
903 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
904 ClientId->UniqueProcess, ClientId->UniqueThread);
908 * Not sure of the exact semantics
910 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
911 ObjectAttributes->ObjectName->Buffer != NULL)
916 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
917 ObjectAttributes->Attributes,
924 if (Status != STATUS_SUCCESS)
929 Status = ObCreateHandle(PsGetCurrentProcess(),
934 ObDereferenceObject(Process);
941 PLIST_ENTRY current_entry;
945 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
946 current_entry = PsProcessListHead.Flink;
947 while (current_entry != &PsProcessListHead)
949 current = CONTAINING_RECORD(current_entry, EPROCESS,
951 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
953 ObReferenceObjectByPointer(current,
957 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
958 Status = ObCreateHandle(PsGetCurrentProcess(),
963 ObDereferenceObject(current);
964 DPRINT("*ProcessHandle %x\n", ProcessHandle);
965 DPRINT("NtOpenProcess() = %x\n", Status);
968 current_entry = current_entry->Flink;
970 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
971 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
972 return(STATUS_UNSUCCESSFUL);
974 return(STATUS_UNSUCCESSFUL);
982 NtQueryInformationProcess(IN HANDLE ProcessHandle,
983 IN CINT ProcessInformationClass,
984 OUT PVOID ProcessInformation,
985 IN ULONG ProcessInformationLength,
986 OUT PULONG ReturnLength OPTIONAL)
992 * TODO: Here we should probably check that ProcessInformationLength
993 * bytes indeed are writable at address ProcessInformation.
996 Status = ObReferenceObjectByHandle(ProcessHandle,
997 PROCESS_SET_INFORMATION,
1002 if (Status != STATUS_SUCCESS)
1007 switch (ProcessInformationClass)
1009 case ProcessBasicInformation:
1010 if (ProcessInformationLength != sizeof(PROCESS_BASIC_INFORMATION))
1012 Status = STATUS_INFO_LENGTH_MISMATCH;
1016 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP =
1017 (PPROCESS_BASIC_INFORMATION)ProcessInformation;
1018 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
1019 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
1020 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
1021 ProcessBasicInformationP->UniqueProcessId =
1022 Process->UniqueProcessId;
1023 ProcessBasicInformationP->InheritedFromUniqueProcessId =
1024 (ULONG)Process->InheritedFromUniqueProcessId;
1028 *ReturnLength = sizeof(PROCESS_BASIC_INFORMATION);
1033 case ProcessQuotaLimits:
1034 case ProcessIoCounters:
1036 case ProcessDebugPort:
1037 case ProcessLdtInformation:
1038 case ProcessWorkingSetWatch:
1039 case ProcessWx86Information:
1040 case ProcessHandleCount:
1041 case ProcessSessionInformation:
1042 case ProcessWow64Information:
1043 Status = STATUS_NOT_IMPLEMENTED;
1046 case ProcessVmCounters:
1047 if (ProcessInformationLength != sizeof(VM_COUNTERS))
1049 Status = STATUS_INFO_LENGTH_MISMATCH;
1053 PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation;
1054 pOut->PeakVirtualSize = Process->PeakVirtualSize;
1056 * Here we should probably use VirtualSize.LowPart, but due to
1057 * incompatibilities in current headers (no unnamed union),
1060 pOut->VirtualSize = (ULONG)Process->VirtualSize.QuadPart;
1061 pOut->PageFaultCount = Process->Vm.PageFaultCount;
1062 pOut->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
1063 pOut->WorkingSetSize = Process->Vm.WorkingSetSize;
1064 pOut->QuotaPeakPagedPoolUsage = Process->QuotaPeakPoolUsage[0]; // TODO: Verify!
1065 pOut->QuotaPagedPoolUsage = Process->QuotaPoolUsage[0]; // TODO: Verify!
1066 pOut->QuotaPeakNonPagedPoolUsage = Process->QuotaPeakPoolUsage[1]; // TODO: Verify!
1067 pOut->QuotaNonPagedPoolUsage = Process->QuotaPoolUsage[1]; // TODO: Verify!
1068 pOut->PagefileUsage = Process->PagefileUsage;
1069 pOut->PeakPagefileUsage = Process->PeakPagefileUsage;
1073 *ReturnLength = sizeof(VM_COUNTERS);
1078 case ProcessDefaultHardErrorMode:
1079 if (ProcessInformationLength != sizeof(ULONG))
1081 Status = STATUS_INFO_LENGTH_MISMATCH;
1085 PULONG HardErrMode = (PULONG)ProcessInformation;
1086 *HardErrMode = Process->DefaultHardErrorProcessing;
1090 *ReturnLength = sizeof(ULONG);
1095 case ProcessPriorityBoost:
1096 if (ProcessInformationLength != sizeof(ULONG))
1098 Status = STATUS_INFO_LENGTH_MISMATCH;
1102 PULONG BoostEnabled = (PULONG)ProcessInformation;
1103 *BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE;
1107 *ReturnLength = sizeof(ULONG);
1112 case ProcessDeviceMap:
1113 Status = STATUS_NOT_IMPLEMENTED;
1116 case ProcessPriorityClass:
1117 if (ProcessInformationLength != sizeof(USHORT))
1119 Status = STATUS_INFO_LENGTH_MISMATCH;
1123 PUSHORT Priority = (PUSHORT)ProcessInformation;
1124 *Priority = Process->PriorityClass;
1128 *ReturnLength = sizeof(USHORT);
1134 * Note: The following 10 information classes are verified to not be
1135 * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
1137 case ProcessBasePriority:
1138 case ProcessRaisePriority:
1139 case ProcessExceptionPort:
1140 case ProcessAccessToken:
1141 case ProcessLdtSize:
1142 case ProcessIoPortHandlers:
1143 case ProcessUserModeIOPL:
1144 case ProcessEnableAlignmentFaultFixup:
1145 case ProcessAffinityMask:
1146 case ProcessForegroundInformation:
1148 Status = STATUS_INVALID_INFO_CLASS;
1150 ObDereferenceObject(Process);
1156 PspAssignPrimaryToken(PEPROCESS Process,
1159 PACCESS_TOKEN Token;
1160 PACCESS_TOKEN OldToken;
1163 Status = ObReferenceObjectByHandle(TokenHandle,
1169 if (!NT_SUCCESS(Status))
1173 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
1174 if (NT_SUCCESS(Status))
1176 ObDereferenceObject(OldToken);
1178 ObDereferenceObject(Token);
1186 NtSetInformationProcess(IN HANDLE ProcessHandle,
1187 IN CINT ProcessInformationClass,
1188 IN PVOID ProcessInformation,
1189 IN ULONG ProcessInformationLength)
1193 PHANDLE ProcessAccessTokenP;
1195 Status = ObReferenceObjectByHandle(ProcessHandle,
1196 PROCESS_SET_INFORMATION,
1201 if (!NT_SUCCESS(Status))
1206 switch (ProcessInformationClass)
1208 case ProcessQuotaLimits:
1209 case ProcessBasePriority:
1210 case ProcessRaisePriority:
1211 case ProcessDebugPort:
1212 case ProcessExceptionPort:
1213 Status = STATUS_NOT_IMPLEMENTED;
1216 case ProcessAccessToken:
1217 ProcessAccessTokenP = (PHANDLE)ProcessInformation;
1218 Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
1221 case ProcessImageFileName:
1222 memcpy(Process->ImageFileName, ProcessInformation, 8);
1223 Status = STATUS_SUCCESS;
1226 case ProcessLdtInformation:
1227 case ProcessLdtSize:
1228 case ProcessDefaultHardErrorMode:
1229 case ProcessIoPortHandlers:
1230 case ProcessWorkingSetWatch:
1231 case ProcessUserModeIOPL:
1232 case ProcessEnableAlignmentFaultFixup:
1233 case ProcessPriorityClass:
1234 case ProcessAffinityMask:
1235 Status = STATUS_NOT_IMPLEMENTED;
1238 case ProcessBasicInformation:
1239 case ProcessIoCounters:
1241 case ProcessPooledUsageAndLimits:
1242 case ProcessWx86Information:
1243 case ProcessHandleCount:
1244 case ProcessWow64Information:
1246 Status = STATUS_INVALID_INFO_CLASS;
1248 case ProcessDesktop:
1249 Process->Win32Desktop = *(PHANDLE)ProcessInformation;
1250 Status = STATUS_SUCCESS;
1253 ObDereferenceObject(Process);
1258 /**********************************************************************
1260 * PiQuerySystemProcessInformation
1263 * Compute the size of a process+thread snapshot as
1264 * expected by NtQuerySystemInformation.
1267 * 0 on error; otherwise the size, in bytes of the buffer
1268 * required to write a full snapshot.
1271 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
1274 PiQuerySystemProcessInformation(PVOID Buffer,
1278 return STATUS_NOT_IMPLEMENTED;
1282 PLIST_ENTRY CurrentEntryP;
1284 PLIST_ENTRY CurrentEntryT;
1287 ULONG RequiredSize = 0L;
1288 BOOLEAN SizeOnly = FALSE;
1292 PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
1293 PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
1294 PSYSTEM_THREAD_INFO pInfoT = NULL;
1297 /* Lock the process list. */
1298 KeAcquireSpinLock(&PsProcessListLock,
1302 * Scan the process list. Since the
1303 * list is circular, the guard is false
1304 * after the last process.
1306 for ( CurrentEntryP = PsProcessListHead.Flink;
1307 (CurrentEntryP != & PsProcessListHead);
1308 CurrentEntryP = CurrentEntryP->Flink
1312 * Compute how much space is
1313 * occupied in the snapshot
1314 * by adding this process info.
1315 * (at least one thread).
1317 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
1318 RequiredSize += SpiSizeCurrent;
1320 * Do not write process data in the
1321 * buffer if it is too small.
1323 if (TRUE == SizeOnly) continue;
1325 * Check if the buffer can contain
1326 * the full snapshot.
1328 if (Size < RequiredSize)
1334 * Get a reference to the
1335 * process descriptor we are
1338 CurrentP = CONTAINING_RECORD(
1344 * Write process data in the buffer.
1346 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
1348 pInfoP->ThreadCount = 0L;
1349 pInfoP->ProcessId = CurrentP->UniqueProcessId;
1350 RtlInitUnicodeString (
1352 CurrentP->ImageFileName
1355 for ( pInfoT = & CurrentP->ThreadSysInfo [0],
1356 CurrentEntryT = CurrentP->ThreadListHead.Flink;
1358 (CurrentEntryT != & CurrentP->ThreadListHead);
1360 pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
1361 CurrentEntryT = CurrentEntryT->Flink
1365 * Recalculate the size of the
1366 * information block.
1368 if (0 < pInfoP->ThreadCount)
1370 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
1373 * Do not write thread data in the
1374 * buffer if it is too small.
1376 if (TRUE == SizeOnly) continue;
1378 * Check if the buffer can contain
1379 * the full snapshot.
1381 if (Size < RequiredSize)
1387 * Get a reference to the
1388 * thread descriptor we are
1391 CurrentT = CONTAINING_RECORD(
1397 * Write thread data.
1401 sizeof (SYSTEM_THREAD_INFORMATION)
1403 pInfoT->KernelTime = CurrentT-> ; /* TIME */
1404 pInfoT->UserTime = CurrentT-> ; /* TIME */
1405 pInfoT->CreateTime = CurrentT-> ; /* TIME */
1406 pInfoT->TickCount = CurrentT-> ; /* ULONG */
1407 pInfoT->StartEIP = CurrentT-> ; /* ULONG */
1408 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1409 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1410 pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
1411 pInfoT->BasePriority = CurrentT-> ; /* ULONG */
1412 pInfoT->nSwitches = CurrentT-> ; /* ULONG */
1413 pInfoT->State = CurrentT-> ; /* DWORD */
1414 pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
1416 * Count the number of threads
1419 ++ pInfoP->ThreadCount;
1422 * Save the size of information
1423 * stored in the buffer for the
1426 pInfoP->RelativeOffset = SpiSize;
1428 * Save a reference to the last
1429 * valid information block.
1431 pInfoPLast = pInfoP;
1433 * Compute the offset of the
1434 * SYSTEM_PROCESS_INFORMATION
1435 * descriptor in the snapshot
1436 * buffer for the next process.
1438 (ULONG) pInfoP += SpiSize;
1441 * Unlock the process list.
1444 & PsProcessListLock,
1448 * Return the proper error status code,
1449 * if the buffer was too small.
1451 if (TRUE == SizeOnly)
1453 if (NULL != RequiredSize)
1455 *pRequiredSize = RequiredSize;
1457 return STATUS_INFO_LENGTH_MISMATCH;
1460 * Mark the end of the snapshot.
1462 pInfoP->RelativeOffset = 0L;
1464 return STATUS_SUCCESS;
1471 LARGE_INTEGER STDCALL
1472 PsGetProcessExitTime(VOID)
1475 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1483 PsIsThreadTerminating(IN PETHREAD Thread)
1485 return(Thread->DeadThread);
1493 PsLookupProcessByProcessId(IN PVOID ProcessId,
1494 OUT PEPROCESS *Process)
1497 PLIST_ENTRY current_entry;
1500 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
1502 current_entry = PsProcessListHead.Flink;
1503 while (current_entry != &PsProcessListHead)
1505 current = CONTAINING_RECORD(current_entry,
1508 if (current->UniqueProcessId == (ULONG)ProcessId)
1511 ObReferenceObject(current);
1512 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1513 return(STATUS_SUCCESS);
1515 current_entry = current_entry->Flink;
1518 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1520 return(STATUS_INVALID_PARAMETER);
1528 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
1534 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
1538 for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
1540 if ((PVOID)PiProcessNotifyRoutine[i] == (PVOID)NotifyRoutine)
1542 PiProcessNotifyRoutine[i] = NULL;
1547 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1548 return(STATUS_SUCCESS);
1552 for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
1554 if (PiProcessNotifyRoutine[i] == NULL)
1556 PiProcessNotifyRoutine[i] = NotifyRoutine;
1561 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1563 if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1565 return STATUS_INSUFFICIENT_RESOURCES;
1568 return STATUS_SUCCESS;