1 /* $Id: process.c,v 1.87 2002/07/17 22:56:11 dwelch Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/process.c
6 * PURPOSE: Process managment
7 * PROGRAMMER: David Welch (welch@cwcom.net)
12 /* INCLUDES ******************************************************************/
15 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
17 #include <internal/mm.h>
18 #include <internal/ke.h>
19 #include <internal/ps.h>
20 #include <internal/se.h>
21 #include <internal/id.h>
23 #include <internal/ldr.h>
24 #include <internal/port.h>
26 #include <internal/dbg.h>
27 #include <internal/pool.h>
29 #include <internal/se.h>
30 #include <internal/kd.h>
33 #include <internal/debug.h>
35 /* GLOBALS ******************************************************************/
37 PEPROCESS EXPORTED PsInitialSystemProcess
= NULL
;
38 HANDLE SystemProcessHandle
= NULL
;
40 POBJECT_TYPE EXPORTED PsProcessType
= NULL
;
42 LIST_ENTRY PsProcessListHead
;
43 static KSPIN_LOCK PsProcessListLock
;
44 static ULONG PiNextProcessUniqueId
= 0;
46 static GENERIC_MAPPING PiProcessMapping
= {PROCESS_READ
,
51 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
53 static ULONG PiProcessNotifyRoutineCount
= 0;
54 static PCREATE_PROCESS_NOTIFY_ROUTINE
55 PiProcessNotifyRoutine
[MAX_PROCESS_NOTIFY_ROUTINE_COUNT
];
57 /* FUNCTIONS *****************************************************************/
61 PsGetNextProcess(PEPROCESS OldProcess
)
64 PEPROCESS NextProcess
;
67 if (OldProcess
== NULL
)
69 return(PsInitialSystemProcess
);
72 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
73 if (OldProcess
->ProcessListEntry
.Flink
== &PsProcessListHead
)
75 NextProcess
= CONTAINING_RECORD(PsProcessListHead
.Flink
,
81 NextProcess
= CONTAINING_RECORD(OldProcess
->ProcessListEntry
.Flink
,
85 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
86 Status
= ObReferenceObjectByPointer(NextProcess
,
90 if (!NT_SUCCESS(Status
))
92 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
95 ObDereferenceObject(OldProcess
);
102 _NtOpenProcessToken(IN HANDLE ProcessHandle
,
103 IN ACCESS_MASK DesiredAccess
,
104 OUT PHANDLE TokenHandle
)
109 Status
= PsOpenTokenOfProcess(ProcessHandle
,
111 if (!NT_SUCCESS(Status
))
115 Status
= ObCreateHandle(PsGetCurrentProcess(),
120 ObDereferenceObject(Token
);
126 NtOpenProcessToken(IN HANDLE ProcessHandle
,
127 IN ACCESS_MASK DesiredAccess
,
128 OUT PHANDLE TokenHandle
)
130 return _NtOpenProcessToken(ProcessHandle
, DesiredAccess
, TokenHandle
);
134 PACCESS_TOKEN STDCALL
135 PsReferencePrimaryToken(PEPROCESS Process
)
137 ObReferenceObjectByPointer(Process
->Token
,
141 return(Process
->Token
);
146 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
147 PACCESS_TOKEN
* Token
)
152 Status
= ObReferenceObjectByHandle(ProcessHandle
,
153 PROCESS_QUERY_INFORMATION
,
158 if (!NT_SUCCESS(Status
))
162 *Token
= PsReferencePrimaryToken(Process
);
163 ObDereferenceObject(Process
);
164 return(STATUS_SUCCESS
);
169 PiKillMostProcesses(VOID
)
172 PLIST_ENTRY current_entry
;
175 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
177 current_entry
= PsProcessListHead
.Flink
;
178 while (current_entry
!= &PsProcessListHead
)
180 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
182 current_entry
= current_entry
->Flink
;
184 if (current
->UniqueProcessId
!= PsInitialSystemProcess
->UniqueProcessId
&&
185 current
->UniqueProcessId
!= (ULONG
)PsGetCurrentProcessId())
187 PiTerminateProcessThreads(current
, STATUS_SUCCESS
);
191 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
196 PsInitProcessManagment(VOID
)
203 * Register the process object type
206 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
208 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
209 PsProcessType
->TotalObjects
= 0;
210 PsProcessType
->TotalHandles
= 0;
211 PsProcessType
->MaxObjects
= ULONG_MAX
;
212 PsProcessType
->MaxHandles
= ULONG_MAX
;
213 PsProcessType
->PagedPoolCharge
= 0;
214 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
215 PsProcessType
->Mapping
= &PiProcessMapping
;
216 PsProcessType
->Dump
= NULL
;
217 PsProcessType
->Open
= NULL
;
218 PsProcessType
->Close
= NULL
;
219 PsProcessType
->Delete
= PiDeleteProcess
;
220 PsProcessType
->Parse
= NULL
;
221 PsProcessType
->Security
= NULL
;
222 PsProcessType
->QueryName
= NULL
;
223 PsProcessType
->OkayToClose
= NULL
;
224 PsProcessType
->Create
= NULL
;
225 PsProcessType
->DuplicationNotify
= NULL
;
227 RtlInitUnicodeString(&PsProcessType
->TypeName
, L
"Process");
229 InitializeListHead(&PsProcessListHead
);
230 KeInitializeSpinLock(&PsProcessListLock
);
233 * Initialize the system process
235 Status
= ObCreateObject(NULL
,
239 (PVOID
*)&PsInitialSystemProcess
);
240 if (!NT_SUCCESS(Status
))
245 /* System threads may run on any processor. */
246 PsInitialSystemProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
247 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
248 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
252 KProcess
= &PsInitialSystemProcess
->Pcb
;
254 MmInitializeAddressSpace(PsInitialSystemProcess
,
255 &PsInitialSystemProcess
->AddressSpace
);
256 ObCreateHandleTable(NULL
,FALSE
,PsInitialSystemProcess
);
257 KProcess
->DirectoryTableBase
=
258 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
259 PsInitialSystemProcess
->UniqueProcessId
=
260 InterlockedIncrement(&PiNextProcessUniqueId
);
261 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
262 PsInitialSystemProcess
->Win32Desktop
= (HANDLE
)0;
264 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
265 InsertHeadList(&PsProcessListHead
,
266 &PsInitialSystemProcess
->ProcessListEntry
);
267 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
268 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
270 strcpy(PsInitialSystemProcess
->ImageFileName
, "SYSTEM");
272 SepCreateSystemProcessToken(PsInitialSystemProcess
);
274 ObCreateHandle(PsInitialSystemProcess
,
275 PsInitialSystemProcess
,
278 &SystemProcessHandle
);
282 PiDeleteProcess(PVOID ObjectBody
)
288 DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody
);
290 Process
= (PEPROCESS
)ObjectBody
;
291 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
292 for (i
= 0; i
< PiProcessNotifyRoutineCount
; i
++)
294 PiProcessNotifyRoutine
[i
](Process
->InheritedFromUniqueProcessId
,
295 (HANDLE
)Process
->UniqueProcessId
,
298 RemoveEntryList(&Process
->ProcessListEntry
);
299 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
302 KDB_DELETEPROCESS_HOOK(Process
);
304 ObDereferenceObject(Process
->Token
);
306 (VOID
)MmReleaseMmInfo(Process
);
307 ObDeleteHandleTable(Process
);
312 PsCreatePeb(HANDLE ProcessHandle
,
322 memset(&Peb
, 0, sizeof(Peb
));
323 Peb
.ImageBaseAddress
= ImageBase
;
325 PebBase
= (PVOID
)PEB_BASE
;
327 Status
= NtAllocateVirtualMemory(ProcessHandle
,
331 MEM_RESERVE
| MEM_COMMIT
,
333 if (!NT_SUCCESS(Status
))
338 NtWriteVirtualMemory(ProcessHandle
,
344 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase
);
348 return(STATUS_SUCCESS
);
353 KeGetCurrentProcess(VOID
)
355 * FUNCTION: Returns a pointer to the current process
358 return(&(PsGetCurrentProcess()->Pcb
));
362 PsGetCurrentProcessId(VOID
)
364 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
368 * FUNCTION: Returns a pointer to the current process
371 PsGetCurrentProcess(VOID
)
373 if (PsGetCurrentThread() == NULL
||
374 PsGetCurrentThread()->ThreadsProcess
== NULL
)
376 return(PsInitialSystemProcess
);
380 return(PsGetCurrentThread()->ThreadsProcess
);
385 IoGetCurrentProcess(VOID
)
387 return(PsGetCurrentProcess());
391 PsCreateSystemProcess(PHANDLE ProcessHandle
,
392 ACCESS_MASK DesiredAccess
,
393 POBJECT_ATTRIBUTES ObjectAttributes
)
395 return NtCreateProcess(ProcessHandle
,
406 NtCreateProcess(OUT PHANDLE ProcessHandle
,
407 IN ACCESS_MASK DesiredAccess
,
408 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
409 IN HANDLE ParentProcessHandle
,
410 IN BOOLEAN InheritObjectTable
,
411 IN HANDLE SectionHandle OPTIONAL
,
412 IN HANDLE DebugPortHandle OPTIONAL
,
413 IN HANDLE ExceptionPortHandle OPTIONAL
)
415 * FUNCTION: Creates a process.
417 * ProcessHandle (OUT) = Caller supplied storage for the resulting
419 * DesiredAccess = Specifies the allowed or desired access to the
420 * process can be a combination of
421 * STANDARD_RIGHTS_REQUIRED| ..
422 * ObjectAttribute = Initialized attributes for the object, contains
423 * the rootdirectory and the filename
424 * ParentProcess = Handle to the parent process.
425 * InheritObjectTable = Specifies to inherit the objects of the parent
427 * SectionHandle = Handle to a section object to back the image file
428 * DebugPort = Handle to a DebugPort if NULL the system default debug
430 * ExceptionPort = Handle to a exception port.
432 * This function maps to the win32 CreateProcess.
437 PEPROCESS ParentProcess
;
441 PVOID LdrStartupAddr
;
445 PEPORT ExceptionPort
;
447 PMEMORY_AREA MemoryArea
;
450 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes
);
452 Status
= ObReferenceObjectByHandle(ParentProcessHandle
,
453 PROCESS_CREATE_PROCESS
,
456 (PVOID
*)&ParentProcess
,
458 if (!NT_SUCCESS(Status
))
460 DPRINT("NtCreateProcess() = %x\n",Status
);
464 Status
= ObCreateObject(ProcessHandle
,
469 if (!NT_SUCCESS(Status
))
471 ObDereferenceObject(ParentProcess
);
472 DPRINT("ObCreateObject() = %x\n",Status
);
476 KeInitializeDispatcherHeader(&Process
->Pcb
.DispatcherHeader
,
480 KProcess
= &Process
->Pcb
;
481 /* Inherit parent process's affinity. */
482 KProcess
->Affinity
= ParentProcess
->Pcb
.Affinity
;
483 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
484 MmInitializeAddressSpace(Process
,
485 &Process
->AddressSpace
);
486 Process
->UniqueProcessId
= InterlockedIncrement(&PiNextProcessUniqueId
);
487 Process
->InheritedFromUniqueProcessId
=
488 (HANDLE
)ParentProcess
->UniqueProcessId
;
489 ObCreateHandleTable(ParentProcess
,
492 MmCopyMmInfo(ParentProcess
, Process
);
493 if (ParentProcess
->Win32WindowStation
!= (HANDLE
)0)
495 /* Always duplicate the process window station. */
496 Process
->Win32WindowStation
= 0;
497 Status
= ObDuplicateObject(ParentProcess
,
499 ParentProcess
->Win32WindowStation
,
500 &Process
->Win32WindowStation
,
503 DUPLICATE_SAME_ACCESS
);
504 if (!NT_SUCCESS(Status
))
511 Process
->Win32WindowStation
= (HANDLE
)0;
513 if (ParentProcess
->Win32Desktop
!= (HANDLE
)0)
515 /* Always duplicate the process window station. */
516 Process
->Win32Desktop
= 0;
517 Status
= ObDuplicateObject(ParentProcess
,
519 ParentProcess
->Win32Desktop
,
520 &Process
->Win32Desktop
,
523 DUPLICATE_SAME_ACCESS
);
524 if (!NT_SUCCESS(Status
))
531 Process
->Win32Desktop
= (HANDLE
)0;
534 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
535 for (i
= 0; i
< PiProcessNotifyRoutineCount
; i
++)
537 PiProcessNotifyRoutine
[i
](Process
->InheritedFromUniqueProcessId
,
538 (HANDLE
)Process
->UniqueProcessId
,
541 InsertHeadList(&PsProcessListHead
, &Process
->ProcessListEntry
);
542 InitializeListHead(&Process
->ThreadListHead
);
543 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
545 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
550 if (DebugPortHandle
!= NULL
)
552 Status
= ObReferenceObjectByHandle(DebugPortHandle
,
558 if (!NT_SUCCESS(Status
))
560 ObDereferenceObject(Process
);
561 ObDereferenceObject(ParentProcess
);
562 ZwClose(*ProcessHandle
);
563 *ProcessHandle
= NULL
;
566 Process
->DebugPort
= DebugPort
;
570 * Add the exception port
572 if (ExceptionPortHandle
!= NULL
)
574 Status
= ObReferenceObjectByHandle(ExceptionPortHandle
,
578 (PVOID
*)&ExceptionPort
,
580 if (!NT_SUCCESS(Status
))
582 ObDereferenceObject(Process
);
583 ObDereferenceObject(ParentProcess
);
584 ZwClose(*ProcessHandle
);
585 *ProcessHandle
= NULL
;
588 Process
->ExceptionPort
= ExceptionPort
;
592 * Now we have created the process proper
596 * Create the shared data page
598 MmLockAddressSpace(&Process
->AddressSpace
);
599 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
600 Status
= MmCreateMemoryArea(Process
,
601 &Process
->AddressSpace
,
602 MEMORY_AREA_SHARED_DATA
,
608 MmUnlockAddressSpace(&Process
->AddressSpace
);
609 if (!NT_SUCCESS(Status
))
611 DPRINT1("Failed to create shared data page\n");
618 Status
= LdrpMapSystemDll(*ProcessHandle
,
620 if (!NT_SUCCESS(Status
))
622 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
623 ObDereferenceObject(Process
);
624 ObDereferenceObject(ParentProcess
);
629 * Map the process image
631 if (SectionHandle
!= NULL
)
633 DPRINT("Mapping process image\n");
634 Status
= LdrpMapImage(*ProcessHandle
,
637 if (!NT_SUCCESS(Status
))
639 DbgPrint("LdrpMapImage failed (Status %x)\n", Status
);
640 ObDereferenceObject(Process
);
641 ObDereferenceObject(ParentProcess
);
651 * Duplicate the token
653 Status
= SepInitializeNewProcess(Process
, ParentProcess
);
654 if (!NT_SUCCESS(Status
))
656 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
657 ObDereferenceObject(Process
);
658 ObDereferenceObject(ParentProcess
);
665 DPRINT("Creating PEB\n");
666 Status
= PsCreatePeb(*ProcessHandle
,
669 if (!NT_SUCCESS(Status
))
671 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
672 ObDereferenceObject(Process
);
673 ObDereferenceObject(ParentProcess
);
674 ZwClose(*ProcessHandle
);
675 *ProcessHandle
= NULL
;
681 * Maybe send a message to the creator process's debugger
684 if (ParentProcess
->DebugPort
!= NULL
)
686 LPC_DBG_MESSAGE Message
;
689 ObCreateHandle(NULL
, // Debugger Process
690 NULL
, // SectionHandle
695 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
696 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
697 sizeof(LPC_MESSAGE_HEADER
);
698 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
699 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
700 Message
.Data
.CreateProcess
.Base
= ImageBase
;
701 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
703 Status
= LpcSendDebugMessagePort(ParentProcess
->DebugPort
,
708 ObDereferenceObject(Process
);
709 ObDereferenceObject(ParentProcess
);
710 return(STATUS_SUCCESS
);
715 NtOpenProcess(OUT PHANDLE ProcessHandle
,
716 IN ACCESS_MASK DesiredAccess
,
717 IN POBJECT_ATTRIBUTES ObjectAttributes
,
718 IN PCLIENT_ID ClientId
)
720 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
721 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
722 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
723 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
727 * Not sure of the exact semantics
729 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
730 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
735 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
736 ObjectAttributes
->Attributes
,
743 if (Status
!= STATUS_SUCCESS
)
748 Status
= ObCreateHandle(PsGetCurrentProcess(),
753 ObDereferenceObject(Process
);
760 PLIST_ENTRY current_entry
;
764 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
765 current_entry
= PsProcessListHead
.Flink
;
766 while (current_entry
!= &PsProcessListHead
)
768 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
770 if (current
->UniqueProcessId
== (ULONG
)ClientId
->UniqueProcess
)
772 ObReferenceObjectByPointer(current
,
776 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
777 Status
= ObCreateHandle(PsGetCurrentProcess(),
782 ObDereferenceObject(current
);
783 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
784 DPRINT("NtOpenProcess() = %x\n", Status
);
787 current_entry
= current_entry
->Flink
;
789 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
790 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
791 return(STATUS_UNSUCCESSFUL
);
793 return(STATUS_UNSUCCESSFUL
);
798 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
799 IN CINT ProcessInformationClass
,
800 OUT PVOID ProcessInformation
,
801 IN ULONG ProcessInformationLength
,
802 OUT PULONG ReturnLength
)
806 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
;
808 Status
= ObReferenceObjectByHandle(ProcessHandle
,
809 PROCESS_SET_INFORMATION
,
814 if (Status
!= STATUS_SUCCESS
)
819 switch (ProcessInformationClass
)
821 case ProcessBasicInformation
:
822 ProcessBasicInformationP
= (PPROCESS_BASIC_INFORMATION
)
824 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
825 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
826 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
827 ProcessBasicInformationP
->UniqueProcessId
=
828 Process
->UniqueProcessId
;
829 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
830 (ULONG
)Process
->InheritedFromUniqueProcessId
;
831 Status
= STATUS_SUCCESS
;
834 case ProcessQuotaLimits
:
835 case ProcessIoCounters
:
836 case ProcessVmCounters
:
838 case ProcessDebugPort
:
839 case ProcessLdtInformation
:
840 Status
= STATUS_NOT_IMPLEMENTED
;
843 case ProcessDefaultHardErrorMode
:
844 *((PULONG
)ProcessInformation
) = Process
->DefaultHardErrorProcessing
;
847 case ProcessWorkingSetWatch
:
848 Status
= STATUS_NOT_IMPLEMENTED
;
851 case ProcessWx86Information
:
852 case ProcessHandleCount
:
853 case ProcessPriorityBoost
:
854 case ProcessDeviceMap
:
855 case ProcessSessionInformation
:
856 case ProcessWow64Information
:
857 Status
= STATUS_NOT_IMPLEMENTED
;
860 case ProcessBasePriority
:
861 case ProcessRaisePriority
:
862 case ProcessExceptionPort
:
863 case ProcessAccessToken
:
865 case ProcessIoPortHandlers
:
866 case ProcessUserModeIOPL
:
867 case ProcessEnableAlignmentFaultFixup
:
868 case ProcessPriorityClass
:
869 case ProcessAffinityMask
:
870 case ProcessForegroundInformation
:
872 Status
= STATUS_INVALID_INFO_CLASS
;
874 ObDereferenceObject(Process
);
879 PspAssignPrimaryToken(PEPROCESS Process
,
883 PACCESS_TOKEN OldToken
;
886 Status
= ObReferenceObjectByHandle(TokenHandle
,
892 if (!NT_SUCCESS(Status
))
896 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
897 if (NT_SUCCESS(Status
))
899 ObDereferenceObject(OldToken
);
901 ObDereferenceObject(Token
);
906 NtSetInformationProcess(IN HANDLE ProcessHandle
,
907 IN CINT ProcessInformationClass
,
908 IN PVOID ProcessInformation
,
909 IN ULONG ProcessInformationLength
)
913 PHANDLE ProcessAccessTokenP
;
915 Status
= ObReferenceObjectByHandle(ProcessHandle
,
916 PROCESS_SET_INFORMATION
,
921 if (!NT_SUCCESS(Status
))
926 switch (ProcessInformationClass
)
928 case ProcessQuotaLimits
:
929 case ProcessBasePriority
:
930 case ProcessRaisePriority
:
931 case ProcessDebugPort
:
932 case ProcessExceptionPort
:
933 Status
= STATUS_NOT_IMPLEMENTED
;
936 case ProcessAccessToken
:
937 ProcessAccessTokenP
= (PHANDLE
)ProcessInformation
;
938 Status
= PspAssignPrimaryToken(Process
, *ProcessAccessTokenP
);
941 case ProcessImageFileName
:
942 memcpy(Process
->ImageFileName
, ProcessInformation
, 8);
943 Status
= STATUS_SUCCESS
;
946 case ProcessLdtInformation
:
948 case ProcessDefaultHardErrorMode
:
949 case ProcessIoPortHandlers
:
950 case ProcessWorkingSetWatch
:
951 case ProcessUserModeIOPL
:
952 case ProcessEnableAlignmentFaultFixup
:
953 case ProcessPriorityClass
:
954 case ProcessAffinityMask
:
955 Status
= STATUS_NOT_IMPLEMENTED
;
958 case ProcessBasicInformation
:
959 case ProcessIoCounters
:
960 case ProcessVmCounters
:
962 case ProcessPooledUsageAndLimits
:
963 case ProcessWx86Information
:
964 case ProcessHandleCount
:
965 case ProcessWow64Information
:
967 Status
= STATUS_INVALID_INFO_CLASS
;
970 Process
->Win32Desktop
= *(PHANDLE
)ProcessInformation
;
971 Status
= STATUS_SUCCESS
;
974 ObDereferenceObject(Process
);
979 /**********************************************************************
981 * PiQuerySystemProcessInformation
984 * Compute the size of a process+thread snapshot as
985 * expected by NtQuerySystemInformation.
988 * 0 on error; otherwise the size, in bytes of the buffer
989 * required to write a full snapshot.
992 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
995 PiQuerySystemProcessInformation(PVOID Buffer
,
999 return STATUS_NOT_IMPLEMENTED
;
1003 PLIST_ENTRY CurrentEntryP
;
1005 PLIST_ENTRY CurrentEntryT
;
1008 ULONG RequiredSize
= 0L;
1009 BOOLEAN SizeOnly
= FALSE
;
1013 PSYSTEM_PROCESS_INFORMATION pInfoP
= (PSYSTEM_PROCESS_INFORMATION
) SnapshotBuffer
;
1014 PSYSTEM_PROCESS_INFORMATION pInfoPLast
= NULL
;
1015 PSYSTEM_THREAD_INFO pInfoT
= NULL
;
1018 /* Lock the process list. */
1019 KeAcquireSpinLock(&PsProcessListLock
,
1023 * Scan the process list. Since the
1024 * list is circular, the guard is false
1025 * after the last process.
1027 for ( CurrentEntryP
= PsProcessListHead
.Flink
;
1028 (CurrentEntryP
!= & PsProcessListHead
);
1029 CurrentEntryP
= CurrentEntryP
->Flink
1033 * Compute how much space is
1034 * occupied in the snapshot
1035 * by adding this process info.
1036 * (at least one thread).
1038 SpiSizeCurrent
= sizeof (SYSTEM_PROCESS_INFORMATION
);
1039 RequiredSize
+= SpiSizeCurrent
;
1041 * Do not write process data in the
1042 * buffer if it is too small.
1044 if (TRUE
== SizeOnly
) continue;
1046 * Check if the buffer can contain
1047 * the full snapshot.
1049 if (Size
< RequiredSize
)
1055 * Get a reference to the
1056 * process descriptor we are
1059 CurrentP
= CONTAINING_RECORD(
1065 * Write process data in the buffer.
1067 RtlZeroMemory (pInfoP
, sizeof (SYSTEM_PROCESS_INFORMATION
));
1069 pInfoP
->ThreadCount
= 0L;
1070 pInfoP
->ProcessId
= CurrentP
->UniqueProcessId
;
1071 RtlInitUnicodeString (
1073 CurrentP
->ImageFileName
1076 for ( pInfoT
= & CurrentP
->ThreadSysInfo
[0],
1077 CurrentEntryT
= CurrentP
->ThreadListHead
.Flink
;
1079 (CurrentEntryT
!= & CurrentP
->ThreadListHead
);
1081 pInfoT
= & CurrentP
->ThreadSysInfo
[pInfoP
->ThreadCount
],
1082 CurrentEntryT
= CurrentEntryT
->Flink
1086 * Recalculate the size of the
1087 * information block.
1089 if (0 < pInfoP
->ThreadCount
)
1091 RequiredSize
+= sizeof (SYSTEM_THREAD_INFORMATION
);
1094 * Do not write thread data in the
1095 * buffer if it is too small.
1097 if (TRUE
== SizeOnly
) continue;
1099 * Check if the buffer can contain
1100 * the full snapshot.
1102 if (Size
< RequiredSize
)
1108 * Get a reference to the
1109 * thread descriptor we are
1112 CurrentT
= CONTAINING_RECORD(
1118 * Write thread data.
1122 sizeof (SYSTEM_THREAD_INFORMATION
)
1124 pInfoT
->KernelTime
= CurrentT
-> ; /* TIME */
1125 pInfoT
->UserTime
= CurrentT
-> ; /* TIME */
1126 pInfoT
->CreateTime
= CurrentT
-> ; /* TIME */
1127 pInfoT
->TickCount
= CurrentT
-> ; /* ULONG */
1128 pInfoT
->StartEIP
= CurrentT
-> ; /* ULONG */
1129 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
1130 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
1131 pInfoT
->DynamicPriority
= CurrentT
-> ; /* ULONG */
1132 pInfoT
->BasePriority
= CurrentT
-> ; /* ULONG */
1133 pInfoT
->nSwitches
= CurrentT
-> ; /* ULONG */
1134 pInfoT
->State
= CurrentT
-> ; /* DWORD */
1135 pInfoT
->WaitReason
= CurrentT
-> ; /* KWAIT_REASON */
1137 * Count the number of threads
1140 ++ pInfoP
->ThreadCount
;
1143 * Save the size of information
1144 * stored in the buffer for the
1147 pInfoP
->RelativeOffset
= SpiSize
;
1149 * Save a reference to the last
1150 * valid information block.
1152 pInfoPLast
= pInfoP
;
1154 * Compute the offset of the
1155 * SYSTEM_PROCESS_INFORMATION
1156 * descriptor in the snapshot
1157 * buffer for the next process.
1159 (ULONG
) pInfoP
+= SpiSize
;
1162 * Unlock the process list.
1165 & PsProcessListLock
,
1169 * Return the proper error status code,
1170 * if the buffer was too small.
1172 if (TRUE
== SizeOnly
)
1174 if (NULL
!= RequiredSize
)
1176 *pRequiredSize
= RequiredSize
;
1178 return STATUS_INFO_LENGTH_MISMATCH
;
1181 * Mark the end of the snapshot.
1183 pInfoP
->RelativeOffset
= 0L;
1185 return STATUS_SUCCESS
;
1189 LARGE_INTEGER STDCALL
1190 PsGetProcessExitTime(VOID
)
1193 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
1198 PsIsThreadTerminating(IN PETHREAD Thread
)
1200 return(Thread
->DeadThread
);
1205 PsLookupProcessByProcessId(IN PVOID ProcessId
,
1206 OUT PEPROCESS
*Process
)
1209 PLIST_ENTRY current_entry
;
1212 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
1214 current_entry
= PsProcessListHead
.Flink
;
1215 while (current_entry
!= &PsProcessListHead
)
1217 current
= CONTAINING_RECORD(current_entry
,
1220 if (current
->UniqueProcessId
== (ULONG
)ProcessId
)
1223 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1224 return(STATUS_SUCCESS
);
1226 current_entry
= current_entry
->Flink
;
1229 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1231 return(STATUS_INVALID_PARAMETER
);
1236 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
1239 if (PiProcessNotifyRoutineCount
>= MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
1240 return(STATUS_INSUFFICIENT_RESOURCES
);
1242 PiProcessNotifyRoutine
[PiProcessNotifyRoutineCount
] = NotifyRoutine
;
1243 PiProcessNotifyRoutineCount
++;
1245 return(STATUS_SUCCESS
);