1 /* $Id: process.c,v 1.109 2003/07/11 01:23:15 royce 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 #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
];
60 /* FUNCTIONS *****************************************************************/
63 PsGetNextProcess(PEPROCESS OldProcess
)
66 PEPROCESS NextProcess
;
69 if (OldProcess
== NULL
)
71 return(PsInitialSystemProcess
);
74 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
75 if (OldProcess
->ProcessListEntry
.Flink
== &PsProcessListHead
)
77 NextProcess
= CONTAINING_RECORD(PsProcessListHead
.Flink
,
83 NextProcess
= CONTAINING_RECORD(OldProcess
->ProcessListEntry
.Flink
,
87 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
88 Status
= ObReferenceObjectByPointer(NextProcess
,
92 if (!NT_SUCCESS(Status
))
94 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
97 ObDereferenceObject(OldProcess
);
104 _NtOpenProcessToken(IN HANDLE ProcessHandle
,
105 IN ACCESS_MASK DesiredAccess
,
106 OUT PHANDLE TokenHandle
)
111 Status
= PsOpenTokenOfProcess(ProcessHandle
,
113 if (!NT_SUCCESS(Status
))
117 Status
= ObCreateHandle(PsGetCurrentProcess(),
122 ObDereferenceObject(Token
);
131 NtOpenProcessToken(IN HANDLE ProcessHandle
,
132 IN ACCESS_MASK DesiredAccess
,
133 OUT PHANDLE TokenHandle
)
135 return _NtOpenProcessToken(ProcessHandle
, DesiredAccess
, TokenHandle
);
142 PACCESS_TOKEN STDCALL
143 PsReferencePrimaryToken(PEPROCESS Process
)
145 ObReferenceObjectByPointer(Process
->Token
,
149 return(Process
->Token
);
154 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
155 PACCESS_TOKEN
* Token
)
160 Status
= ObReferenceObjectByHandle(ProcessHandle
,
161 PROCESS_QUERY_INFORMATION
,
166 if (!NT_SUCCESS(Status
))
170 *Token
= PsReferencePrimaryToken(Process
);
171 ObDereferenceObject(Process
);
172 return(STATUS_SUCCESS
);
177 PiKillMostProcesses(VOID
)
180 PLIST_ENTRY current_entry
;
183 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
185 current_entry
= PsProcessListHead
.Flink
;
186 while (current_entry
!= &PsProcessListHead
)
188 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
190 current_entry
= current_entry
->Flink
;
192 if (current
->UniqueProcessId
!= PsInitialSystemProcess
->UniqueProcessId
&&
193 current
->UniqueProcessId
!= (ULONG
)PsGetCurrentProcessId())
195 PiTerminateProcessThreads(current
, STATUS_SUCCESS
);
199 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
204 PsInitProcessManagment(VOID
)
211 * Register the process object type
214 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
216 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
217 PsProcessType
->TotalObjects
= 0;
218 PsProcessType
->TotalHandles
= 0;
219 PsProcessType
->MaxObjects
= ULONG_MAX
;
220 PsProcessType
->MaxHandles
= ULONG_MAX
;
221 PsProcessType
->PagedPoolCharge
= 0;
222 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
223 PsProcessType
->Mapping
= &PiProcessMapping
;
224 PsProcessType
->Dump
= NULL
;
225 PsProcessType
->Open
= NULL
;
226 PsProcessType
->Close
= NULL
;
227 PsProcessType
->Delete
= PiDeleteProcess
;
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
, L
"Process");
237 InitializeListHead(&PsProcessListHead
);
238 KeInitializeSpinLock(&PsProcessListLock
);
241 * Initialize the system process
243 Status
= ObRosCreateObject(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
;
256 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
260 KProcess
= &PsInitialSystemProcess
->Pcb
;
262 MmInitializeAddressSpace(PsInitialSystemProcess
,
263 &PsInitialSystemProcess
->AddressSpace
);
264 ObCreateHandleTable(NULL
,FALSE
,PsInitialSystemProcess
);
265 KProcess
->DirectoryTableBase
=
266 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
267 PsInitialSystemProcess
->UniqueProcessId
=
268 InterlockedIncrement((LONG
*)&PiNextProcessUniqueId
);
269 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
270 PsInitialSystemProcess
->Win32Desktop
= (HANDLE
)0;
272 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
273 InsertHeadList(&PsProcessListHead
,
274 &PsInitialSystemProcess
->ProcessListEntry
);
275 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
276 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
278 strcpy(PsInitialSystemProcess
->ImageFileName
, "SYSTEM");
280 SepCreateSystemProcessToken(PsInitialSystemProcess
);
282 ObCreateHandle(PsInitialSystemProcess
,
283 PsInitialSystemProcess
,
286 &SystemProcessHandle
);
290 PiDeleteProcess(PVOID ObjectBody
)
295 PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
[MAX_PROCESS_NOTIFY_ROUTINE_COUNT
];
296 ULONG NotifyRoutineCount
;
298 DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody
);
300 Process
= (PEPROCESS
)ObjectBody
;
302 /* Terminate Win32 Process */
303 PsTerminateWin32Process (Process
);
305 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
306 NotifyRoutineCount
= 0;
307 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; i
++)
309 if (PiProcessNotifyRoutine
[i
])
311 NotifyRoutine
[NotifyRoutineCount
++] = PiProcessNotifyRoutine
[i
];
314 RemoveEntryList(&Process
->ProcessListEntry
);
315 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
317 for (i
= 0;i
< NotifyRoutineCount
; i
++)
319 /* must be called below DISPATCH_LVL */
320 NotifyRoutine
[i
](Process
->InheritedFromUniqueProcessId
,
321 (HANDLE
)Process
->UniqueProcessId
,
326 KDB_DELETEPROCESS_HOOK(Process
);
328 ObDereferenceObject(Process
->Token
);
329 ObDeleteHandleTable(Process
);
331 (VOID
)MmReleaseMmInfo(Process
);
336 PsCreatePeb(HANDLE ProcessHandle
,
342 LARGE_INTEGER SectionOffset
;
347 /* Allocate the Process Environment Block (PEB) */
348 Peb
= (PPEB
)PEB_BASE
;
350 Status
= NtAllocateVirtualMemory(ProcessHandle
,
354 MEM_RESERVE
| MEM_COMMIT
,
356 if (!NT_SUCCESS(Status
))
358 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
361 DPRINT("Peb %p PebSize %lu\n", Peb
, PebSize
);
364 SectionOffset
.QuadPart
= 0LL;
366 Status
= MmMapViewOfSection(NlsSectionObject
,
376 if (!NT_SUCCESS(Status
))
378 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
381 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
383 KeAttachProcess(Process
);
385 /* Initialize the PEB */
386 RtlZeroMemory(Peb
, sizeof(PEB
));
387 Peb
->ImageBaseAddress
= ImageBase
;
389 Peb
->OSMajorVersion
= 4;
390 Peb
->OSMinorVersion
= 0;
391 Peb
->OSBuildNumber
= 0;
392 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
394 Peb
->AnsiCodePageData
= TableBase
+ NlsAnsiTableOffset
;
395 Peb
->OemCodePageData
= TableBase
+ NlsOemTableOffset
;
396 Peb
->UnicodeCaseTableData
= TableBase
+ NlsUnicodeTableOffset
;
401 DPRINT("PsCreatePeb: Peb created at %p\n", Peb
);
403 return(STATUS_SUCCESS
);
408 KeGetCurrentProcess(VOID
)
410 * FUNCTION: Returns a pointer to the current process
413 return(&(PsGetCurrentProcess()->Pcb
));
420 PsGetCurrentProcessId(VOID
)
422 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
426 * FUNCTION: Returns a pointer to the current process
431 IoGetCurrentProcess(VOID
)
433 if (PsGetCurrentThread() == NULL
||
434 PsGetCurrentThread()->ThreadsProcess
== NULL
)
436 return(PsInitialSystemProcess
);
440 return(PsGetCurrentThread()->ThreadsProcess
);
448 PsCreateSystemProcess(PHANDLE ProcessHandle
,
449 ACCESS_MASK DesiredAccess
,
450 POBJECT_ATTRIBUTES ObjectAttributes
)
452 return NtCreateProcess(ProcessHandle
,
463 NtCreateProcess(OUT PHANDLE ProcessHandle
,
464 IN ACCESS_MASK DesiredAccess
,
465 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
466 IN HANDLE ParentProcessHandle
,
467 IN BOOLEAN InheritObjectTable
,
468 IN HANDLE SectionHandle OPTIONAL
,
469 IN HANDLE DebugPortHandle OPTIONAL
,
470 IN HANDLE ExceptionPortHandle OPTIONAL
)
472 * FUNCTION: Creates a process.
474 * ProcessHandle (OUT) = Caller supplied storage for the resulting
476 * DesiredAccess = Specifies the allowed or desired access to the
477 * process can be a combination of
478 * STANDARD_RIGHTS_REQUIRED| ..
479 * ObjectAttribute = Initialized attributes for the object, contains
480 * the rootdirectory and the filename
481 * ParentProcess = Handle to the parent process.
482 * InheritObjectTable = Specifies to inherit the objects of the parent
484 * SectionHandle = Handle to a section object to back the image file
485 * DebugPort = Handle to a DebugPort if NULL the system default debug
487 * ExceptionPort = Handle to a exception port.
489 * This function maps to the win32 CreateProcess.
494 PEPROCESS ParentProcess
;
498 PVOID LdrStartupAddr
;
501 PEPORT ExceptionPort
;
503 PMEMORY_AREA MemoryArea
;
505 PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
[MAX_PROCESS_NOTIFY_ROUTINE_COUNT
];
506 ULONG NotifyRoutineCount
;
508 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes
);
510 Status
= ObReferenceObjectByHandle(ParentProcessHandle
,
511 PROCESS_CREATE_PROCESS
,
514 (PVOID
*)&ParentProcess
,
516 if (!NT_SUCCESS(Status
))
518 DPRINT("NtCreateProcess() = %x\n",Status
);
522 Status
= ObRosCreateObject(ProcessHandle
,
527 if (!NT_SUCCESS(Status
))
529 ObDereferenceObject(ParentProcess
);
530 DPRINT("ObRosCreateObject() = %x\n",Status
);
534 KeInitializeDispatcherHeader(&Process
->Pcb
.DispatcherHeader
,
538 KProcess
= &Process
->Pcb
;
539 /* Inherit parent process's affinity. */
540 KProcess
->Affinity
= ParentProcess
->Pcb
.Affinity
;
541 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
542 MmInitializeAddressSpace(Process
,
543 &Process
->AddressSpace
);
544 Process
->UniqueProcessId
= InterlockedIncrement((LONG
*)&PiNextProcessUniqueId
);
545 Process
->InheritedFromUniqueProcessId
=
546 (HANDLE
)ParentProcess
->UniqueProcessId
;
547 ObCreateHandleTable(ParentProcess
,
550 MmCopyMmInfo(ParentProcess
, Process
);
551 if (ParentProcess
->Win32WindowStation
!= (HANDLE
)0)
553 /* Always duplicate the process window station. */
554 Process
->Win32WindowStation
= 0;
555 Status
= ObDuplicateObject(ParentProcess
,
557 ParentProcess
->Win32WindowStation
,
558 &Process
->Win32WindowStation
,
561 DUPLICATE_SAME_ACCESS
);
562 if (!NT_SUCCESS(Status
))
569 Process
->Win32WindowStation
= (HANDLE
)0;
571 if (ParentProcess
->Win32Desktop
!= (HANDLE
)0)
573 /* Always duplicate the process window station. */
574 Process
->Win32Desktop
= 0;
575 Status
= ObDuplicateObject(ParentProcess
,
577 ParentProcess
->Win32Desktop
,
578 &Process
->Win32Desktop
,
581 DUPLICATE_SAME_ACCESS
);
582 if (!NT_SUCCESS(Status
))
589 Process
->Win32Desktop
= (HANDLE
)0;
592 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
593 NotifyRoutineCount
= 0;
594 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; i
++)
596 if (PiProcessNotifyRoutine
[i
])
598 NotifyRoutine
[NotifyRoutineCount
++] = PiProcessNotifyRoutine
[i
];
601 InsertHeadList(&PsProcessListHead
, &Process
->ProcessListEntry
);
602 InitializeListHead(&Process
->ThreadListHead
);
603 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
605 for (i
= 0;i
< NotifyRoutineCount
; i
++)
607 //must be called below DISPATCH_LVL
608 NotifyRoutine
[i
](Process
->InheritedFromUniqueProcessId
,
609 (HANDLE
)Process
->UniqueProcessId
,
613 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
618 if (DebugPortHandle
!= NULL
)
620 Status
= ObReferenceObjectByHandle(DebugPortHandle
,
626 if (!NT_SUCCESS(Status
))
628 ObDereferenceObject(Process
);
629 ObDereferenceObject(ParentProcess
);
630 ZwClose(*ProcessHandle
);
631 *ProcessHandle
= NULL
;
634 Process
->DebugPort
= DebugPort
;
638 * Add the exception port
640 if (ExceptionPortHandle
!= NULL
)
642 Status
= ObReferenceObjectByHandle(ExceptionPortHandle
,
646 (PVOID
*)&ExceptionPort
,
648 if (!NT_SUCCESS(Status
))
650 ObDereferenceObject(Process
);
651 ObDereferenceObject(ParentProcess
);
652 ZwClose(*ProcessHandle
);
653 *ProcessHandle
= NULL
;
656 Process
->ExceptionPort
= ExceptionPort
;
660 * Now we have created the process proper
663 MmLockAddressSpace(&Process
->AddressSpace
);
665 /* Protect the highest 64KB of the process address space */
666 BaseAddress
= MmUserProbeAddress
;
667 Status
= MmCreateMemoryArea(Process
,
668 &Process
->AddressSpace
,
669 MEMORY_AREA_NO_ACCESS
,
676 if (!NT_SUCCESS(Status
))
678 MmUnlockAddressSpace(&Process
->AddressSpace
);
679 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
683 /* Protect the lowest 64KB of the process address space */
685 BaseAddress
= (PVOID
)0x00000000;
686 Status
= MmCreateMemoryArea(Process
,
687 &Process
->AddressSpace
,
688 MEMORY_AREA_NO_ACCESS
,
695 if (!NT_SUCCESS(Status
))
697 MmUnlockAddressSpace(&Process
->AddressSpace
);
698 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
703 /* Protect the 60KB above the shared user page */
704 BaseAddress
= (PVOID
)USER_SHARED_DATA
+ PAGE_SIZE
;
705 Status
= MmCreateMemoryArea(Process
,
706 &Process
->AddressSpace
,
707 MEMORY_AREA_NO_ACCESS
,
714 if (!NT_SUCCESS(Status
))
716 MmUnlockAddressSpace(&Process
->AddressSpace
);
717 DPRINT1("Failed to protect the memory above the shared user page\n");
721 /* Create the shared data page */
722 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
723 Status
= MmCreateMemoryArea(Process
,
724 &Process
->AddressSpace
,
725 MEMORY_AREA_SHARED_DATA
,
732 MmUnlockAddressSpace(&Process
->AddressSpace
);
733 if (!NT_SUCCESS(Status
))
735 DPRINT1("Failed to create shared data page\n");
742 Status
= LdrpMapSystemDll(*ProcessHandle
,
744 if (!NT_SUCCESS(Status
))
746 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
747 ObDereferenceObject(Process
);
748 ObDereferenceObject(ParentProcess
);
753 * Map the process image
755 if (SectionHandle
!= NULL
)
757 DPRINT("Mapping process image\n");
758 Status
= LdrpMapImage(*ProcessHandle
,
761 if (!NT_SUCCESS(Status
))
763 DbgPrint("LdrpMapImage failed (Status %x)\n", Status
);
764 ObDereferenceObject(Process
);
765 ObDereferenceObject(ParentProcess
);
775 * Duplicate the token
777 Status
= SepInitializeNewProcess(Process
, ParentProcess
);
778 if (!NT_SUCCESS(Status
))
780 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
781 ObDereferenceObject(Process
);
782 ObDereferenceObject(ParentProcess
);
789 DPRINT("Creating PEB\n");
790 Status
= PsCreatePeb(*ProcessHandle
,
793 if (!NT_SUCCESS(Status
))
795 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
796 ObDereferenceObject(Process
);
797 ObDereferenceObject(ParentProcess
);
798 ZwClose(*ProcessHandle
);
799 *ProcessHandle
= NULL
;
804 * Maybe send a message to the creator process's debugger
807 if (ParentProcess
->DebugPort
!= NULL
)
809 LPC_DBG_MESSAGE Message
;
812 ObCreateHandle(NULL
, // Debugger Process
813 NULL
, // SectionHandle
818 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
819 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
821 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
822 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
823 Message
.Data
.CreateProcess
.Base
= ImageBase
;
824 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
826 Status
= LpcSendDebugMessagePort(ParentProcess
->DebugPort
,
831 ObDereferenceObject(Process
);
832 ObDereferenceObject(ParentProcess
);
833 return(STATUS_SUCCESS
);
841 NtOpenProcess(OUT PHANDLE ProcessHandle
,
842 IN ACCESS_MASK DesiredAccess
,
843 IN POBJECT_ATTRIBUTES ObjectAttributes
,
844 IN PCLIENT_ID ClientId
)
846 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
847 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
848 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
849 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
853 * Not sure of the exact semantics
855 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
856 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
861 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
862 ObjectAttributes
->Attributes
,
869 if (Status
!= STATUS_SUCCESS
)
874 Status
= ObCreateHandle(PsGetCurrentProcess(),
879 ObDereferenceObject(Process
);
886 PLIST_ENTRY current_entry
;
890 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
891 current_entry
= PsProcessListHead
.Flink
;
892 while (current_entry
!= &PsProcessListHead
)
894 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
896 if (current
->UniqueProcessId
== (ULONG
)ClientId
->UniqueProcess
)
898 ObReferenceObjectByPointer(current
,
902 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
903 Status
= ObCreateHandle(PsGetCurrentProcess(),
908 ObDereferenceObject(current
);
909 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
910 DPRINT("NtOpenProcess() = %x\n", Status
);
913 current_entry
= current_entry
->Flink
;
915 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
916 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
917 return(STATUS_UNSUCCESSFUL
);
919 return(STATUS_UNSUCCESSFUL
);
927 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
928 IN CINT ProcessInformationClass
,
929 OUT PVOID ProcessInformation
,
930 IN ULONG ProcessInformationLength
,
931 OUT PULONG ReturnLength
)
935 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
;
937 Status
= ObReferenceObjectByHandle(ProcessHandle
,
938 PROCESS_SET_INFORMATION
,
943 if (Status
!= STATUS_SUCCESS
)
948 switch (ProcessInformationClass
)
950 case ProcessBasicInformation
:
951 ProcessBasicInformationP
= (PPROCESS_BASIC_INFORMATION
)
953 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
954 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
955 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
956 ProcessBasicInformationP
->UniqueProcessId
=
957 Process
->UniqueProcessId
;
958 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
959 (ULONG
)Process
->InheritedFromUniqueProcessId
;
960 Status
= STATUS_SUCCESS
;
963 case ProcessQuotaLimits
:
964 case ProcessIoCounters
:
965 case ProcessVmCounters
:
967 case ProcessDebugPort
:
968 case ProcessLdtInformation
:
969 Status
= STATUS_NOT_IMPLEMENTED
;
972 case ProcessDefaultHardErrorMode
:
973 *((PULONG
)ProcessInformation
) = Process
->DefaultHardErrorProcessing
;
976 case ProcessWorkingSetWatch
:
977 Status
= STATUS_NOT_IMPLEMENTED
;
980 case ProcessWx86Information
:
981 case ProcessHandleCount
:
982 case ProcessPriorityBoost
:
983 case ProcessDeviceMap
:
984 case ProcessSessionInformation
:
985 case ProcessWow64Information
:
986 Status
= STATUS_NOT_IMPLEMENTED
;
989 case ProcessBasePriority
:
990 case ProcessRaisePriority
:
991 case ProcessExceptionPort
:
992 case ProcessAccessToken
:
994 case ProcessIoPortHandlers
:
995 case ProcessUserModeIOPL
:
996 case ProcessEnableAlignmentFaultFixup
:
997 case ProcessPriorityClass
:
998 case ProcessAffinityMask
:
999 case ProcessForegroundInformation
:
1001 Status
= STATUS_INVALID_INFO_CLASS
;
1003 ObDereferenceObject(Process
);
1008 PspAssignPrimaryToken(PEPROCESS Process
,
1011 PACCESS_TOKEN Token
;
1012 PACCESS_TOKEN OldToken
;
1015 Status
= ObReferenceObjectByHandle(TokenHandle
,
1021 if (!NT_SUCCESS(Status
))
1025 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
1026 if (NT_SUCCESS(Status
))
1028 ObDereferenceObject(OldToken
);
1030 ObDereferenceObject(Token
);
1038 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1039 IN CINT ProcessInformationClass
,
1040 IN PVOID ProcessInformation
,
1041 IN ULONG ProcessInformationLength
)
1045 PHANDLE ProcessAccessTokenP
;
1047 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1048 PROCESS_SET_INFORMATION
,
1053 if (!NT_SUCCESS(Status
))
1058 switch (ProcessInformationClass
)
1060 case ProcessQuotaLimits
:
1061 case ProcessBasePriority
:
1062 case ProcessRaisePriority
:
1063 case ProcessDebugPort
:
1064 case ProcessExceptionPort
:
1065 Status
= STATUS_NOT_IMPLEMENTED
;
1068 case ProcessAccessToken
:
1069 ProcessAccessTokenP
= (PHANDLE
)ProcessInformation
;
1070 Status
= PspAssignPrimaryToken(Process
, *ProcessAccessTokenP
);
1073 case ProcessImageFileName
:
1074 memcpy(Process
->ImageFileName
, ProcessInformation
, 8);
1075 Status
= STATUS_SUCCESS
;
1078 case ProcessLdtInformation
:
1079 case ProcessLdtSize
:
1080 case ProcessDefaultHardErrorMode
:
1081 case ProcessIoPortHandlers
:
1082 case ProcessWorkingSetWatch
:
1083 case ProcessUserModeIOPL
:
1084 case ProcessEnableAlignmentFaultFixup
:
1085 case ProcessPriorityClass
:
1086 case ProcessAffinityMask
:
1087 Status
= STATUS_NOT_IMPLEMENTED
;
1090 case ProcessBasicInformation
:
1091 case ProcessIoCounters
:
1092 case ProcessVmCounters
:
1094 case ProcessPooledUsageAndLimits
:
1095 case ProcessWx86Information
:
1096 case ProcessHandleCount
:
1097 case ProcessWow64Information
:
1099 Status
= STATUS_INVALID_INFO_CLASS
;
1101 case ProcessDesktop
:
1102 Process
->Win32Desktop
= *(PHANDLE
)ProcessInformation
;
1103 Status
= STATUS_SUCCESS
;
1106 ObDereferenceObject(Process
);
1111 /**********************************************************************
1113 * PiQuerySystemProcessInformation
1116 * Compute the size of a process+thread snapshot as
1117 * expected by NtQuerySystemInformation.
1120 * 0 on error; otherwise the size, in bytes of the buffer
1121 * required to write a full snapshot.
1124 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
1127 PiQuerySystemProcessInformation(PVOID Buffer
,
1131 return STATUS_NOT_IMPLEMENTED
;
1135 PLIST_ENTRY CurrentEntryP
;
1137 PLIST_ENTRY CurrentEntryT
;
1140 ULONG RequiredSize
= 0L;
1141 BOOLEAN SizeOnly
= FALSE
;
1145 PSYSTEM_PROCESS_INFORMATION pInfoP
= (PSYSTEM_PROCESS_INFORMATION
) SnapshotBuffer
;
1146 PSYSTEM_PROCESS_INFORMATION pInfoPLast
= NULL
;
1147 PSYSTEM_THREAD_INFO pInfoT
= NULL
;
1150 /* Lock the process list. */
1151 KeAcquireSpinLock(&PsProcessListLock
,
1155 * Scan the process list. Since the
1156 * list is circular, the guard is false
1157 * after the last process.
1159 for ( CurrentEntryP
= PsProcessListHead
.Flink
;
1160 (CurrentEntryP
!= & PsProcessListHead
);
1161 CurrentEntryP
= CurrentEntryP
->Flink
1165 * Compute how much space is
1166 * occupied in the snapshot
1167 * by adding this process info.
1168 * (at least one thread).
1170 SpiSizeCurrent
= sizeof (SYSTEM_PROCESS_INFORMATION
);
1171 RequiredSize
+= SpiSizeCurrent
;
1173 * Do not write process data in the
1174 * buffer if it is too small.
1176 if (TRUE
== SizeOnly
) continue;
1178 * Check if the buffer can contain
1179 * the full snapshot.
1181 if (Size
< RequiredSize
)
1187 * Get a reference to the
1188 * process descriptor we are
1191 CurrentP
= CONTAINING_RECORD(
1197 * Write process data in the buffer.
1199 RtlZeroMemory (pInfoP
, sizeof (SYSTEM_PROCESS_INFORMATION
));
1201 pInfoP
->ThreadCount
= 0L;
1202 pInfoP
->ProcessId
= CurrentP
->UniqueProcessId
;
1203 RtlInitUnicodeString (
1205 CurrentP
->ImageFileName
1208 for ( pInfoT
= & CurrentP
->ThreadSysInfo
[0],
1209 CurrentEntryT
= CurrentP
->ThreadListHead
.Flink
;
1211 (CurrentEntryT
!= & CurrentP
->ThreadListHead
);
1213 pInfoT
= & CurrentP
->ThreadSysInfo
[pInfoP
->ThreadCount
],
1214 CurrentEntryT
= CurrentEntryT
->Flink
1218 * Recalculate the size of the
1219 * information block.
1221 if (0 < pInfoP
->ThreadCount
)
1223 RequiredSize
+= sizeof (SYSTEM_THREAD_INFORMATION
);
1226 * Do not write thread data in the
1227 * buffer if it is too small.
1229 if (TRUE
== SizeOnly
) continue;
1231 * Check if the buffer can contain
1232 * the full snapshot.
1234 if (Size
< RequiredSize
)
1240 * Get a reference to the
1241 * thread descriptor we are
1244 CurrentT
= CONTAINING_RECORD(
1250 * Write thread data.
1254 sizeof (SYSTEM_THREAD_INFORMATION
)
1256 pInfoT
->KernelTime
= CurrentT
-> ; /* TIME */
1257 pInfoT
->UserTime
= CurrentT
-> ; /* TIME */
1258 pInfoT
->CreateTime
= CurrentT
-> ; /* TIME */
1259 pInfoT
->TickCount
= CurrentT
-> ; /* ULONG */
1260 pInfoT
->StartEIP
= CurrentT
-> ; /* ULONG */
1261 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
1262 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
1263 pInfoT
->DynamicPriority
= CurrentT
-> ; /* ULONG */
1264 pInfoT
->BasePriority
= CurrentT
-> ; /* ULONG */
1265 pInfoT
->nSwitches
= CurrentT
-> ; /* ULONG */
1266 pInfoT
->State
= CurrentT
-> ; /* DWORD */
1267 pInfoT
->WaitReason
= CurrentT
-> ; /* KWAIT_REASON */
1269 * Count the number of threads
1272 ++ pInfoP
->ThreadCount
;
1275 * Save the size of information
1276 * stored in the buffer for the
1279 pInfoP
->RelativeOffset
= SpiSize
;
1281 * Save a reference to the last
1282 * valid information block.
1284 pInfoPLast
= pInfoP
;
1286 * Compute the offset of the
1287 * SYSTEM_PROCESS_INFORMATION
1288 * descriptor in the snapshot
1289 * buffer for the next process.
1291 (ULONG
) pInfoP
+= SpiSize
;
1294 * Unlock the process list.
1297 & PsProcessListLock
,
1301 * Return the proper error status code,
1302 * if the buffer was too small.
1304 if (TRUE
== SizeOnly
)
1306 if (NULL
!= RequiredSize
)
1308 *pRequiredSize
= RequiredSize
;
1310 return STATUS_INFO_LENGTH_MISMATCH
;
1313 * Mark the end of the snapshot.
1315 pInfoP
->RelativeOffset
= 0L;
1317 return STATUS_SUCCESS
;
1324 LARGE_INTEGER STDCALL
1325 PsGetProcessExitTime(VOID
)
1328 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
1336 PsIsThreadTerminating(IN PETHREAD Thread
)
1338 return(Thread
->DeadThread
);
1346 PsLookupProcessByProcessId(IN PVOID ProcessId
,
1347 OUT PEPROCESS
*Process
)
1350 PLIST_ENTRY current_entry
;
1353 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
1355 current_entry
= PsProcessListHead
.Flink
;
1356 while (current_entry
!= &PsProcessListHead
)
1358 current
= CONTAINING_RECORD(current_entry
,
1361 if (current
->UniqueProcessId
== (ULONG
)ProcessId
)
1364 ObReferenceObject(current
);
1365 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1366 return(STATUS_SUCCESS
);
1368 current_entry
= current_entry
->Flink
;
1371 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1373 return(STATUS_INVALID_PARAMETER
);
1381 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
1387 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
1391 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
1393 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
1395 PiProcessNotifyRoutine
[i
] = NULL
;
1400 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1401 return(STATUS_SUCCESS
);
1405 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
1407 if (PiProcessNotifyRoutine
[i
] == NULL
)
1409 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
1414 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1416 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
1418 return STATUS_INSUFFICIENT_RESOURCES
;
1421 return STATUS_SUCCESS
;