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 ******************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS ******************************************************************/
20 PEPROCESS EXPORTED PsInitialSystemProcess
= NULL
;
22 POBJECT_TYPE EXPORTED PsProcessType
= NULL
;
24 LIST_ENTRY PsProcessListHead
;
25 static KSPIN_LOCK PsProcessListLock
;
26 static ULONG PiNextProcessUniqueId
= 0; /* TODO */
27 static LARGE_INTEGER ShortPsLockDelay
, PsLockTimeout
;
29 static GENERIC_MAPPING PiProcessMapping
= {STANDARD_RIGHTS_READ
| PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
30 STANDARD_RIGHTS_WRITE
| PROCESS_CREATE_PROCESS
| PROCESS_CREATE_THREAD
|
31 PROCESS_VM_OPERATION
| PROCESS_VM_WRITE
| PROCESS_DUP_HANDLE
|
32 PROCESS_TERMINATE
| PROCESS_SET_QUOTA
| PROCESS_SET_INFORMATION
| PROCESS_SET_PORT
,
33 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
36 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
37 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
39 static PCREATE_PROCESS_NOTIFY_ROUTINE
40 PiProcessNotifyRoutine
[MAX_PROCESS_NOTIFY_ROUTINE_COUNT
];
41 static PLOAD_IMAGE_NOTIFY_ROUTINE
42 PiLoadImageNotifyRoutine
[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
];
47 WORK_QUEUE_ITEM WorkQueueItem
;
50 BOOLEAN IsWorkerQueue
;
51 } DEL_CONTEXT
, *PDEL_CONTEXT
;
53 /* FUNCTIONS *****************************************************************/
57 PsExitSpecialApc(PKAPC Apc
,
58 PKNORMAL_ROUTINE
*NormalRoutine
,
60 PVOID
*SystemArgument1
,
61 PVOID
*SystemArgument2
)
66 PsGetNextProcess(PEPROCESS OldProcess
)
69 PEPROCESS NextProcess
;
72 if (OldProcess
== NULL
)
74 Status
= ObReferenceObjectByPointer(PsInitialSystemProcess
,
78 if (!NT_SUCCESS(Status
))
80 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsInitialSystemProcess\n");
83 return PsInitialSystemProcess
;
86 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
87 NextProcess
= OldProcess
;
90 if (NextProcess
->ProcessListEntry
.Blink
== &PsProcessListHead
)
92 NextProcess
= CONTAINING_RECORD(PsProcessListHead
.Blink
,
98 NextProcess
= CONTAINING_RECORD(NextProcess
->ProcessListEntry
.Blink
,
102 Status
= ObReferenceObjectByPointer(NextProcess
,
106 if (NT_SUCCESS(Status
))
110 else if (Status
== STATUS_PROCESS_IS_TERMINATING
)
114 else if (!NT_SUCCESS(Status
))
116 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
121 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
122 ObDereferenceObject(OldProcess
);
132 NtOpenProcessToken(IN HANDLE ProcessHandle
,
133 IN ACCESS_MASK DesiredAccess
,
134 OUT PHANDLE TokenHandle
)
140 Status
= PsOpenTokenOfProcess(ProcessHandle
,
142 if (!NT_SUCCESS(Status
))
146 Status
= ObCreateHandle(PsGetCurrentProcess(),
151 ObDereferenceObject(Token
);
153 if(NT_SUCCESS(Status
))
155 Status
= MmCopyToCaller(TokenHandle
, &hToken
, sizeof(HANDLE
));
166 NtOpenProcessTokenEx(
167 IN HANDLE ProcessHandle
,
168 IN ACCESS_MASK DesiredAccess
,
169 IN ULONG HandleAttributes
,
170 OUT PHANDLE TokenHandle
174 return STATUS_NOT_IMPLEMENTED
;
181 PACCESS_TOKEN STDCALL
182 PsReferencePrimaryToken(PEPROCESS Process
)
184 ObReferenceObjectByPointer(Process
->Token
,
188 return(Process
->Token
);
193 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
194 PACCESS_TOKEN
* Token
)
199 Status
= ObReferenceObjectByHandle(ProcessHandle
,
200 PROCESS_QUERY_INFORMATION
,
205 if (!NT_SUCCESS(Status
))
209 *Token
= PsReferencePrimaryToken(Process
);
210 ObDereferenceObject(Process
);
211 return(STATUS_SUCCESS
);
216 PiKillMostProcesses(VOID
)
219 PLIST_ENTRY current_entry
;
222 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
224 current_entry
= PsProcessListHead
.Flink
;
225 while (current_entry
!= &PsProcessListHead
)
227 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
229 current_entry
= current_entry
->Flink
;
231 if (current
->UniqueProcessId
!= PsInitialSystemProcess
->UniqueProcessId
&&
232 current
->UniqueProcessId
!= (ULONG
)PsGetCurrentProcessId())
234 PiTerminateProcessThreads(current
, STATUS_SUCCESS
);
238 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
243 PsInitProcessManagment(VOID
)
249 ShortPsLockDelay
.QuadPart
= -100LL;
250 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
252 * Register the process object type
255 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
257 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
258 PsProcessType
->TotalObjects
= 0;
259 PsProcessType
->TotalHandles
= 0;
260 PsProcessType
->PeakObjects
= 0;
261 PsProcessType
->PeakHandles
= 0;
262 PsProcessType
->PagedPoolCharge
= 0;
263 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
264 PsProcessType
->Mapping
= &PiProcessMapping
;
265 PsProcessType
->Dump
= NULL
;
266 PsProcessType
->Open
= NULL
;
267 PsProcessType
->Close
= NULL
;
268 PsProcessType
->Delete
= PiDeleteProcess
;
269 PsProcessType
->Parse
= NULL
;
270 PsProcessType
->Security
= NULL
;
271 PsProcessType
->QueryName
= NULL
;
272 PsProcessType
->OkayToClose
= NULL
;
273 PsProcessType
->Create
= NULL
;
274 PsProcessType
->DuplicationNotify
= NULL
;
276 RtlRosInitUnicodeStringFromLiteral(&PsProcessType
->TypeName
, L
"Process");
278 ObpCreateTypeObject(PsProcessType
);
280 InitializeListHead(&PsProcessListHead
);
281 KeInitializeSpinLock(&PsProcessListLock
);
283 RtlZeroMemory(PiProcessNotifyRoutine
, sizeof(PiProcessNotifyRoutine
));
284 RtlZeroMemory(PiLoadImageNotifyRoutine
, sizeof(PiLoadImageNotifyRoutine
));
287 * Initialize the system process
289 Status
= ObCreateObject(KernelMode
,
297 (PVOID
*)&PsInitialSystemProcess
);
298 if (!NT_SUCCESS(Status
))
303 /* System threads may run on any processor. */
304 PsInitialSystemProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
305 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
306 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[0] = 0;
307 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[1] = 0;
308 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
309 PsInitialSystemProcess
->Pcb
.ThreadQuantum
= 6;
310 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
311 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
315 KProcess
= &PsInitialSystemProcess
->Pcb
;
317 MmInitializeAddressSpace(PsInitialSystemProcess
,
318 &PsInitialSystemProcess
->AddressSpace
);
319 ObCreateHandleTable(NULL
,FALSE
,PsInitialSystemProcess
);
321 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
322 PsInitialSystemProcess
->LockCount
= 0;
323 PsInitialSystemProcess
->LockOwner
= NULL
;
325 #if defined(__GNUC__)
326 KProcess
->DirectoryTableBase
=
327 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
331 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
332 KProcess
->DirectoryTableBase
= dummy
;
336 PsInitialSystemProcess
->UniqueProcessId
=
337 InterlockedIncrementUL(&PiNextProcessUniqueId
); /* TODO */
338 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
340 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
341 InsertHeadList(&PsProcessListHead
,
342 &PsInitialSystemProcess
->ProcessListEntry
);
343 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
344 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
346 strcpy(PsInitialSystemProcess
->ImageFileName
, "SYSTEM");
348 SepCreateSystemProcessToken(PsInitialSystemProcess
);
352 PiDeleteProcessWorker(PVOID pContext
)
355 PDEL_CONTEXT Context
;
356 PEPROCESS CurrentProcess
;
359 Context
= (PDEL_CONTEXT
)pContext
;
360 Process
= Context
->Process
;
361 CurrentProcess
= PsGetCurrentProcess();
363 DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process
);
365 if (CurrentProcess
!= Process
)
367 KeAttachProcess(&Process
->Pcb
);
370 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
371 RemoveEntryList(&Process
->ProcessListEntry
);
372 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
375 KDB_DELETEPROCESS_HOOK(Process
);
377 ObDereferenceObject(Process
->Token
);
378 ObDeleteHandleTable(Process
);
380 if (CurrentProcess
!= Process
)
385 MmReleaseMmInfo(Process
);
386 if (Context
->IsWorkerQueue
)
388 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
393 PiDeleteProcess(PVOID ObjectBody
)
397 Context
.Process
= (PEPROCESS
)ObjectBody
;
399 if (PsGetCurrentProcess() == Context
.Process
||
400 PsGetCurrentThread()->ThreadsProcess
== Context
.Process
)
405 if (PsGetCurrentThread()->ThreadsProcess
== PsGetCurrentProcess())
407 Context
.IsWorkerQueue
= FALSE
;
408 PiDeleteProcessWorker(&Context
);
412 Context
.IsWorkerQueue
= TRUE
;
413 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
414 ExInitializeWorkItem (&Context
.WorkQueueItem
, PiDeleteProcessWorker
, &Context
);
415 ExQueueWorkItem(&Context
.WorkQueueItem
, HyperCriticalWorkQueue
);
416 if (KeReadStateEvent(&Context
.Event
) == 0)
418 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
422 if(((PEPROCESS
)ObjectBody
)->Win32Process
!= NULL
)
424 /* delete the W32PROCESS structure if there's one associated */
425 ExFreePool (((PEPROCESS
)ObjectBody
)->Win32Process
);
430 PsCreatePeb(HANDLE ProcessHandle
,
437 LARGE_INTEGER SectionOffset
;
442 /* Allocate the Process Environment Block (PEB) */
443 Process
->TebBlock
= (PVOID
) MM_ROUND_DOWN(PEB_BASE
, MM_VIRTMEM_GRANULARITY
);
444 AllocSize
= MM_VIRTMEM_GRANULARITY
;
445 Status
= NtAllocateVirtualMemory(ProcessHandle
,
451 if (!NT_SUCCESS(Status
))
453 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
456 ASSERT((ULONG_PTR
) Process
->TebBlock
<= PEB_BASE
&&
457 PEB_BASE
+ PAGE_SIZE
<= (ULONG_PTR
) Process
->TebBlock
+ AllocSize
);
458 Peb
= (PPEB
)PEB_BASE
;
460 Status
= NtAllocateVirtualMemory(ProcessHandle
,
466 if (!NT_SUCCESS(Status
))
468 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
471 DPRINT("Peb %p PebSize %lu\n", Peb
, PebSize
);
472 ASSERT((PPEB
) PEB_BASE
== Peb
&& PAGE_SIZE
<= PebSize
);
473 Process
->TebLastAllocated
= (PVOID
) Peb
;
476 SectionOffset
.QuadPart
= (ULONGLONG
)0;
478 Status
= MmMapViewOfSection(NlsSectionObject
,
488 if (!NT_SUCCESS(Status
))
490 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
493 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
495 KeAttachProcess(&Process
->Pcb
);
497 /* Initialize the PEB */
498 RtlZeroMemory(Peb
, sizeof(PEB
));
499 Peb
->ImageBaseAddress
= ImageBase
;
501 Peb
->OSMajorVersion
= 4;
502 Peb
->OSMinorVersion
= 0;
503 Peb
->OSBuildNumber
= 1381;
504 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
505 Peb
->SPMajorVersion
= 6;
507 Peb
->AnsiCodePageData
= (char*)TableBase
+ NlsAnsiTableOffset
;
508 Peb
->OemCodePageData
= (char*)TableBase
+ NlsOemTableOffset
;
509 Peb
->UnicodeCaseTableData
= (char*)TableBase
+ NlsUnicodeTableOffset
;
514 DPRINT("PsCreatePeb: Peb created at %p\n", Peb
);
516 return(STATUS_SUCCESS
);
521 KeGetCurrentProcess(VOID
)
523 * FUNCTION: Returns a pointer to the current process
526 return(&(PsGetCurrentProcess()->Pcb
));
530 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
531 * ULONG ProcessId! (Skywing)
537 PsGetCurrentProcessId(VOID
)
539 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
547 PsGetCurrentProcessSessionId (
551 return PsGetCurrentProcess()->SessionId
;
555 * FUNCTION: Returns a pointer to the current process
560 IoGetCurrentProcess(VOID
)
562 if (PsGetCurrentThread() == NULL
||
563 PsGetCurrentThread()->Tcb
.ApcState
.Process
== NULL
)
565 return(PsInitialSystemProcess
);
569 return(PEPROCESS
)(PsGetCurrentThread()->Tcb
.ApcState
.Process
);
577 PsCreateSystemProcess(PHANDLE ProcessHandle
,
578 ACCESS_MASK DesiredAccess
,
579 POBJECT_ATTRIBUTES ObjectAttributes
)
581 HANDLE SystemProcessHandle
;
584 /* FIXME - what about security? should there be any privilege checks or something
587 Status
= ObCreateHandle(PsGetCurrentProcess(),
588 PsInitialSystemProcess
,
589 PROCESS_CREATE_PROCESS
| PROCESS_CREATE_THREAD
| PROCESS_QUERY_INFORMATION
,
591 &SystemProcessHandle
);
592 if(!NT_SUCCESS(Status
))
594 DPRINT1("Failed to create a handle for the system process!\n");
598 Status
= NtCreateProcess(ProcessHandle
,
607 NtClose(SystemProcessHandle
);
613 NtCreateProcess(OUT PHANDLE ProcessHandle
,
614 IN ACCESS_MASK DesiredAccess
,
615 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
616 IN HANDLE ParentProcess
,
617 IN BOOLEAN InheritObjectTable
,
618 IN HANDLE SectionHandle OPTIONAL
,
619 IN HANDLE DebugPort OPTIONAL
,
620 IN HANDLE ExceptionPort OPTIONAL
)
622 * FUNCTION: Creates a process.
624 * ProcessHandle (OUT) = Caller supplied storage for the resulting
626 * DesiredAccess = Specifies the allowed or desired access to the
627 * process can be a combination of
628 * STANDARD_RIGHTS_REQUIRED| ..
629 * ObjectAttribute = Initialized attributes for the object, contains
630 * the rootdirectory and the filename
631 * ParentProcess = Handle to the parent process.
632 * InheritObjectTable = Specifies to inherit the objects of the parent
634 * SectionHandle = Handle to a section object to back the image file
635 * DebugPort = Handle to a DebugPort if NULL the system default debug
637 * ExceptionPort = Handle to a exception port.
639 * This function maps to the win32 CreateProcess.
644 PEPROCESS pParentProcess
;
648 PVOID LdrStartupAddr
;
651 PEPORT pExceptionPort
;
653 PMEMORY_AREA MemoryArea
;
654 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
656 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes
);
658 BoundaryAddressMultiple
.QuadPart
= 0;
660 Status
= ObReferenceObjectByHandle(ParentProcess
,
661 PROCESS_CREATE_PROCESS
,
664 (PVOID
*)&pParentProcess
,
666 if (!NT_SUCCESS(Status
))
668 DPRINT("NtCreateProcess() = %x\n",Status
);
672 Status
= ObCreateObject(ExGetPreviousMode(),
681 if (!NT_SUCCESS(Status
))
683 ObDereferenceObject(pParentProcess
);
684 DPRINT("ObCreateObject() = %x\n",Status
);
688 Status
= ObInsertObject ((PVOID
)Process
,
694 if (!NT_SUCCESS(Status
))
696 ObDereferenceObject (Process
);
697 ObDereferenceObject (pParentProcess
);
698 DPRINT("ObInsertObject() = %x\n",Status
);
702 KeInitializeDispatcherHeader(&Process
->Pcb
.DispatcherHeader
,
706 KProcess
= &Process
->Pcb
;
707 /* Inherit parent process's affinity. */
708 KProcess
->Affinity
= pParentProcess
->Pcb
.Affinity
;
709 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
710 KProcess
->IopmOffset
= 0xffff;
711 KProcess
->LdtDescriptor
[0] = 0;
712 KProcess
->LdtDescriptor
[1] = 0;
713 InitializeListHead(&KProcess
->ThreadListHead
);
714 KProcess
->ThreadQuantum
= 6;
715 KProcess
->AutoAlignment
= 0;
716 MmInitializeAddressSpace(Process
,
717 &Process
->AddressSpace
);
718 Process
->UniqueProcessId
= InterlockedIncrementUL(&PiNextProcessUniqueId
); /* TODO */
719 Process
->InheritedFromUniqueProcessId
=
720 (HANDLE
)pParentProcess
->UniqueProcessId
;
721 ObCreateHandleTable(pParentProcess
,
724 MmCopyMmInfo(ParentProcess
, Process
);
726 KeInitializeEvent(&Process
->LockEvent
, SynchronizationEvent
, FALSE
);
727 Process
->LockCount
= 0;
728 Process
->LockOwner
= NULL
;
730 Process
->Win32WindowStation
= (HANDLE
)0;
732 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
733 InsertHeadList(&PsProcessListHead
, &Process
->ProcessListEntry
);
734 InitializeListHead(&Process
->ThreadListHead
);
735 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
737 ExInitializeFastMutex(&Process
->TebLock
);
738 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
743 if (DebugPort
!= NULL
)
745 Status
= ObReferenceObjectByHandle(DebugPort
,
751 if (!NT_SUCCESS(Status
))
753 ObDereferenceObject(Process
);
754 ObDereferenceObject(pParentProcess
);
755 ZwClose(*ProcessHandle
);
756 *ProcessHandle
= NULL
;
759 Process
->DebugPort
= pDebugPort
;
763 * Add the exception port
765 if (ExceptionPort
!= NULL
)
767 Status
= ObReferenceObjectByHandle(ExceptionPort
,
771 (PVOID
*)&pExceptionPort
,
773 if (!NT_SUCCESS(Status
))
775 ObDereferenceObject(Process
);
776 ObDereferenceObject(pParentProcess
);
777 ZwClose(*ProcessHandle
);
778 *ProcessHandle
= NULL
;
781 Process
->ExceptionPort
= pExceptionPort
;
785 * Now we have created the process proper
788 MmLockAddressSpace(&Process
->AddressSpace
);
790 /* Protect the highest 64KB of the process address space */
791 BaseAddress
= (PVOID
)MmUserProbeAddress
;
792 Status
= MmCreateMemoryArea(Process
,
793 &Process
->AddressSpace
,
794 MEMORY_AREA_NO_ACCESS
,
801 BoundaryAddressMultiple
);
802 if (!NT_SUCCESS(Status
))
804 MmUnlockAddressSpace(&Process
->AddressSpace
);
805 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
809 /* Protect the lowest 64KB of the process address space */
811 BaseAddress
= (PVOID
)0x00000000;
812 Status
= MmCreateMemoryArea(Process
,
813 &Process
->AddressSpace
,
814 MEMORY_AREA_NO_ACCESS
,
821 BoundaryAddressMultiple
);
822 if (!NT_SUCCESS(Status
))
824 MmUnlockAddressSpace(&Process
->AddressSpace
);
825 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
830 /* Protect the 60KB above the shared user page */
831 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
832 Status
= MmCreateMemoryArea(Process
,
833 &Process
->AddressSpace
,
834 MEMORY_AREA_NO_ACCESS
,
841 BoundaryAddressMultiple
);
842 if (!NT_SUCCESS(Status
))
844 MmUnlockAddressSpace(&Process
->AddressSpace
);
845 DPRINT1("Failed to protect the memory above the shared user page\n");
849 /* Create the shared data page */
850 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
851 Status
= MmCreateMemoryArea(Process
,
852 &Process
->AddressSpace
,
853 MEMORY_AREA_SHARED_DATA
,
860 BoundaryAddressMultiple
);
861 MmUnlockAddressSpace(&Process
->AddressSpace
);
862 if (!NT_SUCCESS(Status
))
864 DPRINT1("Failed to create shared data page\n");
868 if (SectionHandle
!= NULL
)
870 PSECTION_OBJECT SectionObject
;
871 UNICODE_STRING FileName
;
877 * Determine the image file name and save it to the EPROCESS structure
879 Status
= ObReferenceObjectByHandle(SectionHandle
,
883 (PVOID
*)&SectionObject
,
885 if (!NT_SUCCESS(Status
))
887 DbgPrint("Failed to reference section object\n", Status
);
888 ObDereferenceObject(Process
);
889 ObDereferenceObject(pParentProcess
);
893 FileName
= SectionObject
->FileObject
->FileName
;
894 szSrc
= (PWCHAR
)(FileName
.Buffer
+ (FileName
.Length
/ sizeof(WCHAR
)) - 1);
895 while(szSrc
>= FileName
.Buffer
)
909 /* copy the image file name to the process and truncate it to 15 characters
911 szDest
= Process
->ImageFileName
;
912 lnFName
= min(lnFName
, sizeof(Process
->ImageFileName
) - 1);
915 *(szDest
++) = (UCHAR
)*(szSrc
++);
920 ObDereferenceObject(SectionObject
);
924 Process
->ImageFileName
[0] = '\0';
930 Status
= LdrpMapSystemDll(*ProcessHandle
,
932 if (!NT_SUCCESS(Status
))
934 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
935 ObDereferenceObject(Process
);
936 ObDereferenceObject(pParentProcess
);
941 * Map the process image
943 if (SectionHandle
!= NULL
)
945 DPRINT("Mapping process image\n");
946 Status
= LdrpMapImage(*ProcessHandle
,
949 if (!NT_SUCCESS(Status
))
951 DbgPrint("LdrpMapImage failed (Status %x)\n", Status
);
952 ObDereferenceObject(Process
);
953 ObDereferenceObject(pParentProcess
);
963 * Duplicate the token
965 Status
= SepInitializeNewProcess(Process
, pParentProcess
);
966 if (!NT_SUCCESS(Status
))
968 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
969 ObDereferenceObject(Process
);
970 ObDereferenceObject(pParentProcess
);
977 DPRINT("Creating PEB\n");
978 Status
= PsCreatePeb(*ProcessHandle
,
981 if (!NT_SUCCESS(Status
))
983 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
984 ObDereferenceObject(Process
);
985 ObDereferenceObject(pParentProcess
);
986 ZwClose(*ProcessHandle
);
987 *ProcessHandle
= NULL
;
992 * Maybe send a message to the creator process's debugger
995 if (pParentProcess
->DebugPort
!= NULL
)
997 LPC_DBG_MESSAGE Message
;
1000 ObCreateHandle(NULL
, // Debugger Process
1001 NULL
, // SectionHandle
1006 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
1007 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
1008 sizeof(LPC_MESSAGE
);
1009 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
1010 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
1011 Message
.Data
.CreateProcess
.Base
= ImageBase
;
1012 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
1014 Status
= LpcSendDebugMessagePort(pParentProcess
->DebugPort
,
1019 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
1021 ObDereferenceObject(Process
);
1022 ObDereferenceObject(pParentProcess
);
1023 return(STATUS_SUCCESS
);
1031 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1032 IN ACCESS_MASK DesiredAccess
,
1033 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1034 IN PCLIENT_ID ClientId
)
1036 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1037 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1038 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
1039 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
1043 * Not sure of the exact semantics
1045 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
1046 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
1051 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
1052 ObjectAttributes
->Attributes
,
1059 if (Status
!= STATUS_SUCCESS
)
1064 Status
= ObCreateHandle(PsGetCurrentProcess(),
1069 ObDereferenceObject(Process
);
1076 PLIST_ENTRY current_entry
;
1080 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
1081 current_entry
= PsProcessListHead
.Flink
;
1082 while (current_entry
!= &PsProcessListHead
)
1084 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
1086 if (current
->UniqueProcessId
== (ULONG
)ClientId
->UniqueProcess
)
1088 if (current
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
1090 Status
= STATUS_PROCESS_IS_TERMINATING
;
1094 Status
= ObReferenceObjectByPointer(current
,
1099 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1100 if (NT_SUCCESS(Status
))
1102 Status
= ObCreateHandle(PsGetCurrentProcess(),
1107 ObDereferenceObject(current
);
1108 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
1109 DPRINT("NtOpenProcess() = %x\n", Status
);
1113 current_entry
= current_entry
->Flink
;
1115 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1116 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1117 return(STATUS_UNSUCCESSFUL
);
1119 return(STATUS_UNSUCCESSFUL
);
1127 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
1128 IN PROCESSINFOCLASS ProcessInformationClass
,
1129 OUT PVOID ProcessInformation
,
1130 IN ULONG ProcessInformationLength
,
1131 OUT PULONG ReturnLength OPTIONAL
)
1135 KPROCESSOR_MODE PreviousMode
;
1137 PreviousMode
= ExGetPreviousMode();
1140 * TODO: Here we should probably check that ProcessInformationLength
1141 * bytes indeed are writable at address ProcessInformation.
1144 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1145 PROCESS_QUERY_INFORMATION
,
1150 if (!NT_SUCCESS(Status
))
1155 switch (ProcessInformationClass
)
1157 case ProcessBasicInformation
:
1158 if (ProcessInformationLength
!= sizeof(PROCESS_BASIC_INFORMATION
))
1160 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1164 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
=
1165 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
1169 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
1170 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
1171 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
1172 ProcessBasicInformationP
->UniqueProcessId
=
1173 Process
->UniqueProcessId
;
1174 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
1175 (ULONG
)Process
->InheritedFromUniqueProcessId
;
1176 ProcessBasicInformationP
->BasePriority
=
1177 Process
->Pcb
.BasePriority
;
1181 *ReturnLength
= sizeof(PROCESS_BASIC_INFORMATION
);
1186 Status
= _SEH_GetExceptionCode();
1192 case ProcessQuotaLimits
:
1193 case ProcessIoCounters
:
1194 Status
= STATUS_NOT_IMPLEMENTED
;
1198 if (ProcessInformationLength
!= sizeof(KERNEL_USER_TIMES
))
1200 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1204 PKERNEL_USER_TIMES ProcessTimeP
= (PKERNEL_USER_TIMES
)ProcessInformation
;
1207 ProcessTimeP
->CreateTime
= Process
->CreateTime
;
1208 ProcessTimeP
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
* 100000LL;
1209 ProcessTimeP
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
* 100000LL;
1210 ProcessTimeP
->ExitTime
= Process
->ExitTime
;
1214 *ReturnLength
= sizeof(KERNEL_USER_TIMES
);
1219 Status
= _SEH_GetExceptionCode();
1225 case ProcessDebugPort
:
1226 case ProcessLdtInformation
:
1227 case ProcessWorkingSetWatch
:
1228 case ProcessWx86Information
:
1229 Status
= STATUS_NOT_IMPLEMENTED
;
1232 case ProcessHandleCount
:
1233 if (ProcessInformationLength
!= sizeof(ULONG
))
1235 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1239 ULONG HandleCount
= ObpGetHandleCountByHandleTable(&Process
->HandleTable
);
1243 *(PULONG
)ProcessInformation
= HandleCount
;
1246 *ReturnLength
= sizeof(ULONG
);
1251 Status
= _SEH_GetExceptionCode();
1257 case ProcessSessionInformation
:
1259 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1261 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1265 PPROCESS_SESSION_INFORMATION SessionInfo
= (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1269 SessionInfo
->SessionId
= Process
->SessionId
;
1272 *ReturnLength
= sizeof(PROCESS_SESSION_INFORMATION
);
1277 Status
= _SEH_GetExceptionCode();
1284 case ProcessWow64Information
:
1285 DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
1286 Status
= STATUS_NOT_IMPLEMENTED
;
1289 case ProcessVmCounters
:
1290 if (ProcessInformationLength
!= sizeof(VM_COUNTERS
))
1292 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1296 PVM_COUNTERS pOut
= (PVM_COUNTERS
)ProcessInformation
;
1300 pOut
->PeakVirtualSize
= Process
->PeakVirtualSize
;
1302 * Here we should probably use VirtualSize.LowPart, but due to
1303 * incompatibilities in current headers (no unnamed union),
1306 pOut
->VirtualSize
= (ULONG
)Process
->VirtualSize
.QuadPart
;
1307 pOut
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
1308 pOut
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
1309 pOut
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
1310 pOut
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[0]; // TODO: Verify!
1311 pOut
->QuotaPagedPoolUsage
= Process
->QuotaPoolUsage
[0]; // TODO: Verify!
1312 pOut
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[1]; // TODO: Verify!
1313 pOut
->QuotaNonPagedPoolUsage
= Process
->QuotaPoolUsage
[1]; // TODO: Verify!
1314 pOut
->PagefileUsage
= Process
->PagefileUsage
;
1315 pOut
->PeakPagefileUsage
= Process
->PeakPagefileUsage
;
1319 *ReturnLength
= sizeof(VM_COUNTERS
);
1324 Status
= _SEH_GetExceptionCode();
1330 case ProcessDefaultHardErrorMode
:
1331 if (ProcessInformationLength
!= sizeof(ULONG
))
1333 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1337 PULONG HardErrMode
= (PULONG
)ProcessInformation
;
1340 *HardErrMode
= Process
->DefaultHardErrorProcessing
;
1343 *ReturnLength
= sizeof(ULONG
);
1348 Status
= _SEH_GetExceptionCode();
1354 case ProcessPriorityBoost
:
1355 if (ProcessInformationLength
!= sizeof(ULONG
))
1357 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1361 PULONG BoostEnabled
= (PULONG
)ProcessInformation
;
1365 *BoostEnabled
= Process
->Pcb
.DisableBoost
? FALSE
: TRUE
;
1369 *ReturnLength
= sizeof(ULONG
);
1374 Status
= _SEH_GetExceptionCode();
1380 case ProcessDeviceMap
:
1381 if (ProcessInformationLength
!= sizeof(PROCESS_DEVICEMAP_INFORMATION
))
1383 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1387 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
1389 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
1393 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
1396 *ReturnLength
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
1401 Status
= _SEH_GetExceptionCode();
1407 case ProcessPriorityClass
:
1408 if (ProcessInformationLength
!= sizeof(USHORT
))
1410 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1414 PUSHORT Priority
= (PUSHORT
)ProcessInformation
;
1418 *Priority
= Process
->PriorityClass
;
1422 *ReturnLength
= sizeof(USHORT
);
1427 Status
= _SEH_GetExceptionCode();
1433 case ProcessImageFileName
:
1436 * We DO NOT return the file name stored in the EPROCESS structure.
1437 * Propably if we can't find a PEB or ProcessParameters structure for the
1440 if(Process
->Peb
!= NULL
)
1442 PRTL_USER_PROCESS_PARAMETERS ProcParams
;
1444 /* we need to attach to the process to make sure we're in the right context! */
1445 KeAttachProcess(&Process
->Pcb
);
1447 ASSERT(Process
->Peb
->ProcessParameters
); /* FIXME - must ProcessParameters be really != NULL? */
1449 ProcParams
= Process
->Peb
->ProcessParameters
;
1450 if(ProcessInformationLength
< sizeof(UNICODE_STRING
) + ProcParams
->ImagePathName
.Length
+ sizeof(WCHAR
))
1452 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1456 PUNICODE_STRING DstPath
= (PUNICODE_STRING
)ProcessInformation
;
1460 DstPath
->Length
= ProcParams
->ImagePathName
.Length
;
1461 DstPath
->MaximumLength
= DstPath
->Length
+ sizeof(WCHAR
);
1462 DstPath
->Buffer
= (PWSTR
)(DstPath
+ 1);
1464 RtlCopyMemory(DstPath
->Buffer
, ProcParams
->ImagePathName
.Buffer
, ProcParams
->ImagePathName
.Length
);
1465 DstPath
->Buffer
[DstPath
->Length
/ sizeof(WCHAR
)] = L
'\0';
1469 *ReturnLength
= sizeof(UNICODE_STRING
) + ProcParams
->ImagePathName
.Length
+ sizeof(WCHAR
);
1474 Status
= _SEH_GetExceptionCode();
1483 /* FIXME - what to do here? */
1484 Status
= STATUS_UNSUCCESSFUL
;
1490 * Note: The following 10 information classes are verified to not be
1491 * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
1493 case ProcessBasePriority
:
1494 case ProcessRaisePriority
:
1495 case ProcessExceptionPort
:
1496 case ProcessAccessToken
:
1497 case ProcessLdtSize
:
1498 case ProcessIoPortHandlers
:
1499 case ProcessUserModeIOPL
:
1500 case ProcessEnableAlignmentFaultFixup
:
1501 case ProcessAffinityMask
:
1502 case ProcessForegroundInformation
:
1504 Status
= STATUS_INVALID_INFO_CLASS
;
1507 ObDereferenceObject(Process
);
1513 PspAssignPrimaryToken(PEPROCESS Process
,
1516 PACCESS_TOKEN Token
;
1517 PACCESS_TOKEN OldToken
;
1520 Status
= ObReferenceObjectByHandle(TokenHandle
,
1526 if (!NT_SUCCESS(Status
))
1530 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
1531 if (NT_SUCCESS(Status
))
1533 ObDereferenceObject(OldToken
);
1535 ObDereferenceObject(Token
);
1543 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1544 IN PROCESSINFOCLASS ProcessInformationClass
,
1545 IN PVOID ProcessInformation
,
1546 IN ULONG ProcessInformationLength
)
1550 KPROCESSOR_MODE PreviousMode
;
1552 PreviousMode
= ExGetPreviousMode();
1554 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1555 PROCESS_SET_INFORMATION
,
1560 if (!NT_SUCCESS(Status
))
1565 switch (ProcessInformationClass
)
1567 case ProcessQuotaLimits
:
1568 case ProcessBasePriority
:
1569 case ProcessRaisePriority
:
1570 case ProcessDebugPort
:
1571 Status
= STATUS_NOT_IMPLEMENTED
;
1574 case ProcessExceptionPort
:
1576 if(ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
1578 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1584 /* make a safe copy of the buffer on the stack */
1587 PortHandle
= *(PHANDLE
)ProcessInformation
;
1588 Status
= STATUS_SUCCESS
;
1592 Status
= _SEH_GetExceptionCode();
1596 if(NT_SUCCESS(Status
))
1598 PEPORT ExceptionPort
;
1600 /* in case we had success reading from the buffer, verify the provided
1603 Status
= ObReferenceObjectByHandle(PortHandle
,
1607 (PVOID
)&ExceptionPort
,
1609 if(NT_SUCCESS(Status
))
1611 /* lock the process to be thread-safe! */
1613 Status
= PsLockProcess(Process
, FALSE
);
1614 if(NT_SUCCESS(Status
))
1617 * according to "NT Native API" documentation, setting the exception
1618 * port is only permitted once!
1620 if(Process
->ExceptionPort
== NULL
)
1622 Process
->ExceptionPort
= ExceptionPort
;
1623 Status
= STATUS_SUCCESS
;
1627 Status
= STATUS_PORT_ALREADY_SET
;
1629 PsUnlockProcess(Process
);
1632 ObDereferenceObject(ExceptionPort
);
1639 case ProcessAccessToken
:
1641 if(ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
1643 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1649 /* make a safe copy of the buffer on the stack */
1652 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->Token
;
1653 Status
= STATUS_SUCCESS
;
1657 Status
= _SEH_GetExceptionCode();
1661 if(NT_SUCCESS(Status
))
1663 /* in case we had success reading from the buffer, perform the actual task */
1664 Status
= PspAssignPrimaryToken(Process
, TokenHandle
);
1670 case ProcessDefaultHardErrorMode
:
1672 if(ProcessInformationLength
!= sizeof(UINT
))
1674 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1680 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
1681 *(PLONG
)ProcessInformation
);
1682 Status
= STATUS_SUCCESS
;
1686 Status
= _SEH_GetExceptionCode();
1693 case ProcessSessionInformation
:
1695 if(ProcessInformationLength
!= sizeof(UINT
))
1697 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1701 PROCESS_SESSION_INFORMATION SessionInfo
;
1702 Status
= STATUS_SUCCESS
;
1706 /* copy the structure to the stack */
1707 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1711 Status
= _SEH_GetExceptionCode();
1715 if(NT_SUCCESS(Status
))
1718 /* we successfully copied the structure to the stack, continue processing */
1721 * setting the session id requires the SeTcbPrivilege!
1723 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1726 /* can't set the session id, bail! */
1727 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1732 * ntinternals documents a PROCESS_SET_SESSIONID flag for NtOpenProcess,
1733 * so we need to open the handle again with this access flag to make
1734 * sure the handle has the required permissions to change the session id!
1736 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1737 PROCESS_SET_INFORMATION
| PROCESS_SET_SESSIONID
,
1742 if(!NT_SUCCESS(Status
))
1744 /* the handle doesn't have the access rights */
1748 /* SANITY check, Process2 MUST be the same as Process as it's the same handle! */
1749 ASSERT(Process2
== Process
);
1751 /* FIXME - update the session id for the process token */
1753 Status
= PsLockProcess(Process
, FALSE
);
1754 if(NT_SUCCESS(Status
))
1756 Process
->SessionId
= SessionInfo
.SessionId
;
1758 /* Update the session id in the PEB structure */
1759 if(Process
->Peb
!= NULL
)
1761 /* we need to attach to the process to make sure we're in the right
1762 context to access the PEB structure */
1763 KeAttachProcess(&Process
->Pcb
);
1767 /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
1769 Status
= STATUS_SUCCESS
;
1773 Status
= _SEH_GetExceptionCode();
1780 PsUnlockProcess(Process
);
1783 ObDereferenceObject(Process2
);
1789 case ProcessLdtInformation
:
1790 case ProcessLdtSize
:
1791 case ProcessIoPortHandlers
:
1792 case ProcessWorkingSetWatch
:
1793 case ProcessUserModeIOPL
:
1794 case ProcessEnableAlignmentFaultFixup
:
1795 case ProcessPriorityClass
:
1796 case ProcessAffinityMask
:
1797 Status
= STATUS_NOT_IMPLEMENTED
;
1800 case ProcessBasicInformation
:
1801 case ProcessIoCounters
:
1803 case ProcessPooledUsageAndLimits
:
1804 case ProcessWx86Information
:
1805 case ProcessHandleCount
:
1806 case ProcessWow64Information
:
1808 Status
= STATUS_INVALID_INFO_CLASS
;
1810 ObDereferenceObject(Process
);
1815 /**********************************************************************
1817 * PiQuerySystemProcessInformation
1820 * Compute the size of a process+thread snapshot as
1821 * expected by NtQuerySystemInformation.
1824 * 0 on error; otherwise the size, in bytes of the buffer
1825 * required to write a full snapshot.
1828 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
1831 PiQuerySystemProcessInformation(PVOID Buffer
,
1835 return STATUS_NOT_IMPLEMENTED
;
1839 PLIST_ENTRY CurrentEntryP
;
1841 PLIST_ENTRY CurrentEntryT
;
1844 ULONG RequiredSize
= 0L;
1845 BOOLEAN SizeOnly
= FALSE
;
1849 PSYSTEM_PROCESS_INFORMATION pInfoP
= (PSYSTEM_PROCESS_INFORMATION
) SnapshotBuffer
;
1850 PSYSTEM_PROCESS_INFORMATION pInfoPLast
= NULL
;
1851 PSYSTEM_THREAD_INFO pInfoT
= NULL
;
1854 /* Lock the process list. */
1855 KeAcquireSpinLock(&PsProcessListLock
,
1859 * Scan the process list. Since the
1860 * list is circular, the guard is false
1861 * after the last process.
1863 for ( CurrentEntryP
= PsProcessListHead
.Flink
;
1864 (CurrentEntryP
!= & PsProcessListHead
);
1865 CurrentEntryP
= CurrentEntryP
->Flink
1869 * Compute how much space is
1870 * occupied in the snapshot
1871 * by adding this process info.
1872 * (at least one thread).
1874 SpiSizeCurrent
= sizeof (SYSTEM_PROCESS_INFORMATION
);
1875 RequiredSize
+= SpiSizeCurrent
;
1877 * Do not write process data in the
1878 * buffer if it is too small.
1880 if (TRUE
== SizeOnly
) continue;
1882 * Check if the buffer can contain
1883 * the full snapshot.
1885 if (Size
< RequiredSize
)
1891 * Get a reference to the
1892 * process descriptor we are
1895 CurrentP
= CONTAINING_RECORD(
1901 * Write process data in the buffer.
1903 RtlZeroMemory (pInfoP
, sizeof (SYSTEM_PROCESS_INFORMATION
));
1905 pInfoP
->ThreadCount
= 0L;
1906 pInfoP
->ProcessId
= CurrentP
->UniqueProcessId
;
1907 RtlInitUnicodeString (
1909 CurrentP
->ImageFileName
1912 for ( pInfoT
= & CurrentP
->ThreadSysInfo
[0],
1913 CurrentEntryT
= CurrentP
->ThreadListHead
.Flink
;
1915 (CurrentEntryT
!= & CurrentP
->ThreadListHead
);
1917 pInfoT
= & CurrentP
->ThreadSysInfo
[pInfoP
->ThreadCount
],
1918 CurrentEntryT
= CurrentEntryT
->Flink
1922 * Recalculate the size of the
1923 * information block.
1925 if (0 < pInfoP
->ThreadCount
)
1927 RequiredSize
+= sizeof (SYSTEM_THREAD_INFORMATION
);
1930 * Do not write thread data in the
1931 * buffer if it is too small.
1933 if (TRUE
== SizeOnly
) continue;
1935 * Check if the buffer can contain
1936 * the full snapshot.
1938 if (Size
< RequiredSize
)
1944 * Get a reference to the
1945 * thread descriptor we are
1948 CurrentT
= CONTAINING_RECORD(
1954 * Write thread data.
1958 sizeof (SYSTEM_THREAD_INFORMATION
)
1960 pInfoT
->KernelTime
= CurrentT
-> ; /* TIME */
1961 pInfoT
->UserTime
= CurrentT
-> ; /* TIME */
1962 pInfoT
->CreateTime
= CurrentT
-> ; /* TIME */
1963 pInfoT
->TickCount
= CurrentT
-> ; /* ULONG */
1964 pInfoT
->StartEIP
= CurrentT
-> ; /* ULONG */
1965 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
1966 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
1967 pInfoT
->DynamicPriority
= CurrentT
-> ; /* ULONG */
1968 pInfoT
->BasePriority
= CurrentT
-> ; /* ULONG */
1969 pInfoT
->nSwitches
= CurrentT
-> ; /* ULONG */
1970 pInfoT
->State
= CurrentT
-> ; /* DWORD */
1971 pInfoT
->WaitReason
= CurrentT
-> ; /* KWAIT_REASON */
1973 * Count the number of threads
1976 ++ pInfoP
->ThreadCount
;
1979 * Save the size of information
1980 * stored in the buffer for the
1983 pInfoP
->RelativeOffset
= SpiSize
;
1985 * Save a reference to the last
1986 * valid information block.
1988 pInfoPLast
= pInfoP
;
1990 * Compute the offset of the
1991 * SYSTEM_PROCESS_INFORMATION
1992 * descriptor in the snapshot
1993 * buffer for the next process.
1995 (ULONG
) pInfoP
+= SpiSize
;
1998 * Unlock the process list.
2001 & PsProcessListLock
,
2005 * Return the proper error status code,
2006 * if the buffer was too small.
2008 if (TRUE
== SizeOnly
)
2010 if (NULL
!= RequiredSize
)
2012 *pRequiredSize
= RequiredSize
;
2014 return STATUS_INFO_LENGTH_MISMATCH
;
2017 * Mark the end of the snapshot.
2019 pInfoP
->RelativeOffset
= 0L;
2021 return STATUS_SUCCESS
;
2028 LARGE_INTEGER STDCALL
2029 PsGetProcessExitTime(VOID
)
2032 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
2041 PsGetProcessCreateTimeQuadPart(
2045 return Process
->CreateTime
.QuadPart
;
2053 PsGetProcessDebugPort(
2057 return Process
->DebugPort
;
2065 PsGetProcessExitProcessCalled(
2069 return Process
->ExitProcessCalled
;
2077 PsGetProcessExitStatus(
2081 return Process
->ExitStatus
;
2093 return (HANDLE
)Process
->UniqueProcessId
;
2101 PsGetProcessImageFileName(
2105 return (LPSTR
)Process
->ImageFileName
;
2113 PsGetProcessInheritedFromUniqueProcessId(
2117 return Process
->InheritedFromUniqueProcessId
;
2129 return Process
->Job
;
2141 return Process
->Peb
;
2149 PsGetProcessPriorityClass(
2153 return Process
->PriorityClass
;
2161 PsGetProcessSectionBaseAddress(
2165 return Process
->SectionBaseAddress
;
2173 PsGetProcessSecurityPort(
2177 return Process
->SecurityPort
;
2185 PsGetProcessSessionId(
2189 return (HANDLE
)Process
->SessionId
;
2197 PsGetProcessWin32Process(
2201 return Process
->Win32Process
;
2209 PsGetProcessWin32WindowStation(
2213 return Process
->Win32WindowStation
;
2221 PsIsProcessBeingDebugged(
2225 return FALSE
/*Process->IsProcessBeingDebugged*/;
2233 PsLookupProcessByProcessId(IN PVOID ProcessId
,
2234 OUT PEPROCESS
*Process
)
2237 PLIST_ENTRY current_entry
;
2240 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
2242 current_entry
= PsProcessListHead
.Flink
;
2243 while (current_entry
!= &PsProcessListHead
)
2245 current
= CONTAINING_RECORD(current_entry
,
2248 if (current
->UniqueProcessId
== (ULONG
)ProcessId
)
2251 ObReferenceObject(current
);
2252 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
2253 return(STATUS_SUCCESS
);
2255 current_entry
= current_entry
->Flink
;
2258 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
2260 return(STATUS_INVALID_PARAMETER
);
2265 PspRunCreateProcessNotifyRoutines
2267 PEPROCESS CurrentProcess
,
2272 HANDLE ProcessId
= (HANDLE
)CurrentProcess
->UniqueProcessId
;
2273 HANDLE ParentId
= CurrentProcess
->InheritedFromUniqueProcessId
;
2275 for(i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2276 if(PiProcessNotifyRoutine
[i
])
2277 PiProcessNotifyRoutine
[i
](ParentId
, ProcessId
, Create
);
2284 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
2291 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2293 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
2295 PiProcessNotifyRoutine
[i
] = NULL
;
2300 return(STATUS_SUCCESS
);
2304 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2306 if (PiProcessNotifyRoutine
[i
] == NULL
)
2308 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
2313 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2315 return STATUS_INSUFFICIENT_RESOURCES
;
2318 return STATUS_SUCCESS
;
2322 PspRunLoadImageNotifyRoutines(
2323 PUNICODE_STRING FullImageName
,
2325 PIMAGE_INFO ImageInfo
)
2329 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2330 if (PiLoadImageNotifyRoutine
[i
])
2331 PiLoadImageNotifyRoutine
[i
](FullImageName
, ProcessId
, ImageInfo
);
2339 PsRemoveLoadImageNotifyRoutine(
2340 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
2344 return STATUS_NOT_IMPLEMENTED
;
2351 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
2355 for (i
= 0; i
< MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
; i
++)
2357 if (PiLoadImageNotifyRoutine
[i
] == NULL
)
2359 PiLoadImageNotifyRoutine
[i
] = NotifyRoutine
;
2364 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2366 return STATUS_INSUFFICIENT_RESOURCES
;
2369 return STATUS_SUCCESS
;
2377 PsSetProcessPriorityClass(
2382 Process
->PriorityClass
= PriorityClass
;
2390 PsSetProcessSecurityPort(
2395 Process
->SecurityPort
= SecurityPort
;
2403 PsSetProcessWin32Process(
2408 Process
->Win32Process
= Win32Process
;
2416 PsSetProcessWin32WindowStation(
2421 Process
->Win32WindowStation
= WindowStation
;
2431 IN PEPROCESS Process
,
2432 IN POOL_TYPE PoolType
,
2438 /* Charge the usage */
2439 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
2441 /* Raise Exception */
2442 if (!NT_SUCCESS(Status
)) {
2443 ExRaiseStatus(Status
);
2452 PsChargeProcessNonPagedPoolQuota (
2453 IN PEPROCESS Process
,
2457 /* Call the general function */
2458 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
2466 PsChargeProcessPagedPoolQuota (
2467 IN PEPROCESS Process
,
2471 /* Call the general function */
2472 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
2480 PsChargeProcessPoolQuota(
2481 IN PEPROCESS Process
,
2482 IN POOL_TYPE PoolType
,
2486 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
2490 /* Get current Quota Block */
2491 QuotaBlock
= Process
->QuotaBlock
;
2493 /* Quota Operations are not to be done on the SYSTEM Process */
2494 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
2496 /* New Size in use */
2497 NewUsageSize
= QuotaBlock
->QuotaEntry
[PoolType
].Usage
+ Amount
;
2499 /* Does this size respect the quota? */
2500 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Limit
) {
2502 /* It doesn't, so keep raising the Quota */
2503 while (MiRaisePoolQuota(PoolType
, QuotaBlock
->QuotaEntry
[PoolType
].Limit
, &NewMaxQuota
)) {
2504 /* Save new Maximum Quota */
2505 QuotaBlock
->QuotaEntry
[PoolType
].Limit
= NewMaxQuota
;
2507 /* See if the new Maximum Quota fulfills our need */
2508 if (NewUsageSize
<= NewMaxQuota
) goto QuotaChanged
;
2511 return STATUS_QUOTA_EXCEEDED
;
2515 /* Save new Usage */
2516 QuotaBlock
->QuotaEntry
[PoolType
].Usage
= NewUsageSize
;
2518 /* Is this a new peak? */
2519 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Peak
) {
2520 QuotaBlock
->QuotaEntry
[PoolType
].Peak
= NewUsageSize
;
2524 return STATUS_SUCCESS
;
2533 IN PEPROCESS Process
,
2534 IN POOL_TYPE PoolType
,
2546 PsReturnProcessNonPagedPoolQuota(
2547 IN PEPROCESS Process
,
2559 PsReturnProcessPagedPoolQuota(
2560 IN PEPROCESS Process
,
2568 PsLockProcess(PEPROCESS Process
, BOOL Timeout
)
2571 PKTHREAD PrevLockOwner
;
2572 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2573 PLARGE_INTEGER Delay
= (Timeout
? &PsLockTimeout
: NULL
);
2574 PKTHREAD CallingThread
= KeGetCurrentThread();
2576 KeEnterCriticalRegion();
2580 if(Process
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
2582 KeLeaveCriticalRegion();
2583 return STATUS_PROCESS_IS_TERMINATING
;
2586 PrevLockOwner
= (PKTHREAD
)InterlockedCompareExchangePointer(
2587 &Process
->LockOwner
, CallingThread
, NULL
);
2588 if(PrevLockOwner
== NULL
|| PrevLockOwner
== CallingThread
)
2590 /* we got the lock or already locked it */
2591 if(InterlockedIncrementUL(&Process
->LockCount
) == 1)
2593 KeClearEvent(&Process
->LockEvent
);
2596 return STATUS_SUCCESS
;
2602 Status
= KeWaitForSingleObject(&Process
->LockEvent
,
2607 if(!NT_SUCCESS(Status
))
2610 if(Status
== STATUS_TIMEOUT
)
2612 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process
);
2615 KeLeaveCriticalRegion();
2622 KeDelayExecutionThread(KernelMode
, FALSE
, &ShortPsLockDelay
);
2631 PsUnlockProcess(PEPROCESS Process
)
2633 ASSERT(Process
->LockOwner
== KeGetCurrentThread());
2635 if(InterlockedDecrementUL(&Process
->LockCount
) == 0)
2637 InterlockedExchangePointer(&Process
->LockOwner
, NULL
);
2638 KeSetEvent(&Process
->LockEvent
, IO_NO_INCREMENT
, FALSE
);
2641 KeLeaveCriticalRegion();