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
)
136 return NtOpenProcessTokenEx(ProcessHandle
,
148 NtOpenProcessTokenEx(
149 IN HANDLE ProcessHandle
,
150 IN ACCESS_MASK DesiredAccess
,
151 IN ULONG HandleAttributes
,
152 OUT PHANDLE TokenHandle
159 Status
= PsOpenTokenOfProcess(ProcessHandle
,
161 if (!NT_SUCCESS(Status
))
165 Status
= ObCreateHandle(PsGetCurrentProcess(),
170 ObDereferenceObject(Token
);
172 if(NT_SUCCESS(Status
))
174 Status
= MmCopyToCaller(TokenHandle
, &hToken
, sizeof(HANDLE
));
183 PACCESS_TOKEN STDCALL
184 PsReferencePrimaryToken(PEPROCESS Process
)
186 ObReferenceObjectByPointer(Process
->Token
,
190 return(Process
->Token
);
195 PsOpenTokenOfProcess(HANDLE ProcessHandle
,
196 PACCESS_TOKEN
* Token
)
201 Status
= ObReferenceObjectByHandle(ProcessHandle
,
202 PROCESS_QUERY_INFORMATION
,
207 if (!NT_SUCCESS(Status
))
211 *Token
= PsReferencePrimaryToken(Process
);
212 ObDereferenceObject(Process
);
213 return(STATUS_SUCCESS
);
218 PiKillMostProcesses(VOID
)
221 PLIST_ENTRY current_entry
;
224 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
226 current_entry
= PsProcessListHead
.Flink
;
227 while (current_entry
!= &PsProcessListHead
)
229 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
231 current_entry
= current_entry
->Flink
;
233 if (current
->UniqueProcessId
!= PsInitialSystemProcess
->UniqueProcessId
&&
234 current
->UniqueProcessId
!= (ULONG
)PsGetCurrentProcessId())
236 PiTerminateProcessThreads(current
, STATUS_SUCCESS
);
240 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
245 PsInitProcessManagment(VOID
)
251 ShortPsLockDelay
.QuadPart
= -100LL;
252 PsLockTimeout
.QuadPart
= -10000000LL; /* one second */
254 * Register the process object type
257 PsProcessType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
259 PsProcessType
->Tag
= TAG('P', 'R', 'O', 'C');
260 PsProcessType
->TotalObjects
= 0;
261 PsProcessType
->TotalHandles
= 0;
262 PsProcessType
->PeakObjects
= 0;
263 PsProcessType
->PeakHandles
= 0;
264 PsProcessType
->PagedPoolCharge
= 0;
265 PsProcessType
->NonpagedPoolCharge
= sizeof(EPROCESS
);
266 PsProcessType
->Mapping
= &PiProcessMapping
;
267 PsProcessType
->Dump
= NULL
;
268 PsProcessType
->Open
= NULL
;
269 PsProcessType
->Close
= NULL
;
270 PsProcessType
->Delete
= PiDeleteProcess
;
271 PsProcessType
->Parse
= NULL
;
272 PsProcessType
->Security
= NULL
;
273 PsProcessType
->QueryName
= NULL
;
274 PsProcessType
->OkayToClose
= NULL
;
275 PsProcessType
->Create
= NULL
;
276 PsProcessType
->DuplicationNotify
= NULL
;
278 RtlRosInitUnicodeStringFromLiteral(&PsProcessType
->TypeName
, L
"Process");
280 ObpCreateTypeObject(PsProcessType
);
282 InitializeListHead(&PsProcessListHead
);
283 KeInitializeSpinLock(&PsProcessListLock
);
285 RtlZeroMemory(PiProcessNotifyRoutine
, sizeof(PiProcessNotifyRoutine
));
286 RtlZeroMemory(PiLoadImageNotifyRoutine
, sizeof(PiLoadImageNotifyRoutine
));
289 * Initialize the system process
291 Status
= ObCreateObject(KernelMode
,
299 (PVOID
*)&PsInitialSystemProcess
);
300 if (!NT_SUCCESS(Status
))
305 /* System threads may run on any processor. */
306 PsInitialSystemProcess
->Pcb
.Affinity
= 0xFFFFFFFF;
307 PsInitialSystemProcess
->Pcb
.IopmOffset
= 0xffff;
308 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[0] = 0;
309 PsInitialSystemProcess
->Pcb
.LdtDescriptor
[1] = 0;
310 PsInitialSystemProcess
->Pcb
.BasePriority
= PROCESS_PRIO_NORMAL
;
311 PsInitialSystemProcess
->Pcb
.ThreadQuantum
= 6;
312 InitializeListHead(&PsInitialSystemProcess
->Pcb
.ThreadListHead
);
313 KeInitializeDispatcherHeader(&PsInitialSystemProcess
->Pcb
.DispatcherHeader
,
317 KProcess
= &PsInitialSystemProcess
->Pcb
;
319 MmInitializeAddressSpace(PsInitialSystemProcess
,
320 &PsInitialSystemProcess
->AddressSpace
);
321 ObCreateHandleTable(NULL
,FALSE
,PsInitialSystemProcess
);
323 KeInitializeEvent(&PsInitialSystemProcess
->LockEvent
, SynchronizationEvent
, FALSE
);
324 PsInitialSystemProcess
->LockCount
= 0;
325 PsInitialSystemProcess
->LockOwner
= NULL
;
327 #if defined(__GNUC__)
328 KProcess
->DirectoryTableBase
=
329 (LARGE_INTEGER
)(LONGLONG
)(ULONG
)MmGetPageDirectory();
333 dummy
.QuadPart
= (LONGLONG
)(ULONG
)MmGetPageDirectory();
334 KProcess
->DirectoryTableBase
= dummy
;
338 PsInitialSystemProcess
->UniqueProcessId
=
339 InterlockedIncrementUL(&PiNextProcessUniqueId
); /* TODO */
340 PsInitialSystemProcess
->Win32WindowStation
= (HANDLE
)0;
342 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
343 InsertHeadList(&PsProcessListHead
,
344 &PsInitialSystemProcess
->ProcessListEntry
);
345 InitializeListHead(&PsInitialSystemProcess
->ThreadListHead
);
346 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
348 strcpy(PsInitialSystemProcess
->ImageFileName
, "SYSTEM");
350 SepCreateSystemProcessToken(PsInitialSystemProcess
);
354 PiDeleteProcessWorker(PVOID pContext
)
357 PDEL_CONTEXT Context
;
358 PEPROCESS CurrentProcess
;
361 Context
= (PDEL_CONTEXT
)pContext
;
362 Process
= Context
->Process
;
363 CurrentProcess
= PsGetCurrentProcess();
365 DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process
);
367 if (CurrentProcess
!= Process
)
369 KeAttachProcess(&Process
->Pcb
);
372 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
373 RemoveEntryList(&Process
->ProcessListEntry
);
374 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
377 KDB_DELETEPROCESS_HOOK(Process
);
379 ObDereferenceObject(Process
->Token
);
380 ObDeleteHandleTable(Process
);
382 if (CurrentProcess
!= Process
)
387 MmReleaseMmInfo(Process
);
388 if (Context
->IsWorkerQueue
)
390 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
395 PiDeleteProcess(PVOID ObjectBody
)
399 Context
.Process
= (PEPROCESS
)ObjectBody
;
401 if (PsGetCurrentProcess() == Context
.Process
||
402 PsGetCurrentThread()->ThreadsProcess
== Context
.Process
)
407 if (PsGetCurrentThread()->ThreadsProcess
== PsGetCurrentProcess())
409 Context
.IsWorkerQueue
= FALSE
;
410 PiDeleteProcessWorker(&Context
);
414 Context
.IsWorkerQueue
= TRUE
;
415 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
416 ExInitializeWorkItem (&Context
.WorkQueueItem
, PiDeleteProcessWorker
, &Context
);
417 ExQueueWorkItem(&Context
.WorkQueueItem
, HyperCriticalWorkQueue
);
418 if (KeReadStateEvent(&Context
.Event
) == 0)
420 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
424 if(((PEPROCESS
)ObjectBody
)->Win32Process
!= NULL
)
426 /* delete the W32PROCESS structure if there's one associated */
427 ExFreePool (((PEPROCESS
)ObjectBody
)->Win32Process
);
432 PsCreatePeb(HANDLE ProcessHandle
,
439 LARGE_INTEGER SectionOffset
;
444 /* Allocate the Process Environment Block (PEB) */
445 Process
->TebBlock
= (PVOID
) MM_ROUND_DOWN(PEB_BASE
, MM_VIRTMEM_GRANULARITY
);
446 AllocSize
= MM_VIRTMEM_GRANULARITY
;
447 Status
= NtAllocateVirtualMemory(ProcessHandle
,
453 if (!NT_SUCCESS(Status
))
455 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
458 ASSERT((ULONG_PTR
) Process
->TebBlock
<= PEB_BASE
&&
459 PEB_BASE
+ PAGE_SIZE
<= (ULONG_PTR
) Process
->TebBlock
+ AllocSize
);
460 Peb
= (PPEB
)PEB_BASE
;
462 Status
= NtAllocateVirtualMemory(ProcessHandle
,
468 if (!NT_SUCCESS(Status
))
470 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
473 DPRINT("Peb %p PebSize %lu\n", Peb
, PebSize
);
474 ASSERT((PPEB
) PEB_BASE
== Peb
&& PAGE_SIZE
<= PebSize
);
475 Process
->TebLastAllocated
= (PVOID
) Peb
;
478 SectionOffset
.QuadPart
= (ULONGLONG
)0;
480 Status
= MmMapViewOfSection(NlsSectionObject
,
490 if (!NT_SUCCESS(Status
))
492 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status
);
495 DPRINT("TableBase %p ViewSize %lx\n", TableBase
, ViewSize
);
497 KeAttachProcess(&Process
->Pcb
);
499 /* Initialize the PEB */
500 RtlZeroMemory(Peb
, sizeof(PEB
));
501 Peb
->ImageBaseAddress
= ImageBase
;
503 Peb
->OSMajorVersion
= 4;
504 Peb
->OSMinorVersion
= 0;
505 Peb
->OSBuildNumber
= 1381;
506 Peb
->OSPlatformId
= 2; //VER_PLATFORM_WIN32_NT;
507 Peb
->SPMajorVersion
= 6;
509 Peb
->AnsiCodePageData
= (char*)TableBase
+ NlsAnsiTableOffset
;
510 Peb
->OemCodePageData
= (char*)TableBase
+ NlsOemTableOffset
;
511 Peb
->UnicodeCaseTableData
= (char*)TableBase
+ NlsUnicodeTableOffset
;
516 DPRINT("PsCreatePeb: Peb created at %p\n", Peb
);
518 return(STATUS_SUCCESS
);
523 KeGetCurrentProcess(VOID
)
525 * FUNCTION: Returns a pointer to the current process
528 return(&(PsGetCurrentProcess()->Pcb
));
532 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
533 * ULONG ProcessId! (Skywing)
539 PsGetCurrentProcessId(VOID
)
541 return((HANDLE
)PsGetCurrentProcess()->UniqueProcessId
);
549 PsGetCurrentProcessSessionId (
553 return PsGetCurrentProcess()->SessionId
;
557 * FUNCTION: Returns a pointer to the current process
562 IoGetCurrentProcess(VOID
)
564 if (PsGetCurrentThread() == NULL
||
565 PsGetCurrentThread()->Tcb
.ApcState
.Process
== NULL
)
567 return(PsInitialSystemProcess
);
571 return(PEPROCESS
)(PsGetCurrentThread()->Tcb
.ApcState
.Process
);
579 PsCreateSystemProcess(PHANDLE ProcessHandle
,
580 ACCESS_MASK DesiredAccess
,
581 POBJECT_ATTRIBUTES ObjectAttributes
)
583 HANDLE SystemProcessHandle
;
586 /* FIXME - what about security? should there be any privilege checks or something
589 Status
= ObCreateHandle(PsGetCurrentProcess(),
590 PsInitialSystemProcess
,
591 PROCESS_CREATE_PROCESS
| PROCESS_CREATE_THREAD
| PROCESS_QUERY_INFORMATION
,
593 &SystemProcessHandle
);
594 if(!NT_SUCCESS(Status
))
596 DPRINT1("Failed to create a handle for the system process!\n");
600 Status
= NtCreateProcess(ProcessHandle
,
609 NtClose(SystemProcessHandle
);
615 NtCreateProcess(OUT PHANDLE ProcessHandle
,
616 IN ACCESS_MASK DesiredAccess
,
617 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
,
618 IN HANDLE ParentProcess
,
619 IN BOOLEAN InheritObjectTable
,
620 IN HANDLE SectionHandle OPTIONAL
,
621 IN HANDLE DebugPort OPTIONAL
,
622 IN HANDLE ExceptionPort OPTIONAL
)
624 * FUNCTION: Creates a process.
626 * ProcessHandle (OUT) = Caller supplied storage for the resulting
628 * DesiredAccess = Specifies the allowed or desired access to the
629 * process can be a combination of
630 * STANDARD_RIGHTS_REQUIRED| ..
631 * ObjectAttribute = Initialized attributes for the object, contains
632 * the rootdirectory and the filename
633 * ParentProcess = Handle to the parent process.
634 * InheritObjectTable = Specifies to inherit the objects of the parent
636 * SectionHandle = Handle to a section object to back the image file
637 * DebugPort = Handle to a DebugPort if NULL the system default debug
639 * ExceptionPort = Handle to a exception port.
641 * This function maps to the win32 CreateProcess.
646 PEPROCESS pParentProcess
;
650 PVOID LdrStartupAddr
;
653 PEPORT pExceptionPort
;
655 PMEMORY_AREA MemoryArea
;
656 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
658 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes
);
660 BoundaryAddressMultiple
.QuadPart
= 0;
662 Status
= ObReferenceObjectByHandle(ParentProcess
,
663 PROCESS_CREATE_PROCESS
,
666 (PVOID
*)&pParentProcess
,
668 if (!NT_SUCCESS(Status
))
670 DPRINT("NtCreateProcess() = %x\n",Status
);
674 Status
= ObCreateObject(ExGetPreviousMode(),
683 if (!NT_SUCCESS(Status
))
685 ObDereferenceObject(pParentProcess
);
686 DPRINT("ObCreateObject() = %x\n",Status
);
690 Status
= ObInsertObject ((PVOID
)Process
,
696 if (!NT_SUCCESS(Status
))
698 ObDereferenceObject (Process
);
699 ObDereferenceObject (pParentProcess
);
700 DPRINT("ObInsertObject() = %x\n",Status
);
704 KeInitializeDispatcherHeader(&Process
->Pcb
.DispatcherHeader
,
708 KProcess
= &Process
->Pcb
;
709 /* Inherit parent process's affinity. */
710 KProcess
->Affinity
= pParentProcess
->Pcb
.Affinity
;
711 KProcess
->BasePriority
= PROCESS_PRIO_NORMAL
;
712 KProcess
->IopmOffset
= 0xffff;
713 KProcess
->LdtDescriptor
[0] = 0;
714 KProcess
->LdtDescriptor
[1] = 0;
715 InitializeListHead(&KProcess
->ThreadListHead
);
716 KProcess
->ThreadQuantum
= 6;
717 KProcess
->AutoAlignment
= 0;
718 MmInitializeAddressSpace(Process
,
719 &Process
->AddressSpace
);
720 Process
->UniqueProcessId
= InterlockedIncrementUL(&PiNextProcessUniqueId
); /* TODO */
721 Process
->InheritedFromUniqueProcessId
=
722 (HANDLE
)pParentProcess
->UniqueProcessId
;
723 ObCreateHandleTable(pParentProcess
,
726 MmCopyMmInfo(ParentProcess
, Process
);
728 KeInitializeEvent(&Process
->LockEvent
, SynchronizationEvent
, FALSE
);
729 Process
->LockCount
= 0;
730 Process
->LockOwner
= NULL
;
732 Process
->Win32WindowStation
= (HANDLE
)0;
734 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
735 InsertHeadList(&PsProcessListHead
, &Process
->ProcessListEntry
);
736 InitializeListHead(&Process
->ThreadListHead
);
737 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
739 ExInitializeFastMutex(&Process
->TebLock
);
740 Process
->Pcb
.State
= PROCESS_STATE_ACTIVE
;
745 if (DebugPort
!= NULL
)
747 Status
= ObReferenceObjectByHandle(DebugPort
,
753 if (!NT_SUCCESS(Status
))
755 ObDereferenceObject(Process
);
756 ObDereferenceObject(pParentProcess
);
757 ZwClose(*ProcessHandle
);
758 *ProcessHandle
= NULL
;
761 Process
->DebugPort
= pDebugPort
;
765 * Add the exception port
767 if (ExceptionPort
!= NULL
)
769 Status
= ObReferenceObjectByHandle(ExceptionPort
,
773 (PVOID
*)&pExceptionPort
,
775 if (!NT_SUCCESS(Status
))
777 ObDereferenceObject(Process
);
778 ObDereferenceObject(pParentProcess
);
779 ZwClose(*ProcessHandle
);
780 *ProcessHandle
= NULL
;
783 Process
->ExceptionPort
= pExceptionPort
;
787 * Now we have created the process proper
790 MmLockAddressSpace(&Process
->AddressSpace
);
792 /* Protect the highest 64KB of the process address space */
793 BaseAddress
= (PVOID
)MmUserProbeAddress
;
794 Status
= MmCreateMemoryArea(Process
,
795 &Process
->AddressSpace
,
796 MEMORY_AREA_NO_ACCESS
,
803 BoundaryAddressMultiple
);
804 if (!NT_SUCCESS(Status
))
806 MmUnlockAddressSpace(&Process
->AddressSpace
);
807 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
811 /* Protect the lowest 64KB of the process address space */
813 BaseAddress
= (PVOID
)0x00000000;
814 Status
= MmCreateMemoryArea(Process
,
815 &Process
->AddressSpace
,
816 MEMORY_AREA_NO_ACCESS
,
823 BoundaryAddressMultiple
);
824 if (!NT_SUCCESS(Status
))
826 MmUnlockAddressSpace(&Process
->AddressSpace
);
827 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
832 /* Protect the 60KB above the shared user page */
833 BaseAddress
= (char*)USER_SHARED_DATA
+ PAGE_SIZE
;
834 Status
= MmCreateMemoryArea(Process
,
835 &Process
->AddressSpace
,
836 MEMORY_AREA_NO_ACCESS
,
843 BoundaryAddressMultiple
);
844 if (!NT_SUCCESS(Status
))
846 MmUnlockAddressSpace(&Process
->AddressSpace
);
847 DPRINT1("Failed to protect the memory above the shared user page\n");
851 /* Create the shared data page */
852 BaseAddress
= (PVOID
)USER_SHARED_DATA
;
853 Status
= MmCreateMemoryArea(Process
,
854 &Process
->AddressSpace
,
855 MEMORY_AREA_SHARED_DATA
,
862 BoundaryAddressMultiple
);
863 MmUnlockAddressSpace(&Process
->AddressSpace
);
864 if (!NT_SUCCESS(Status
))
866 DPRINT1("Failed to create shared data page\n");
870 if (SectionHandle
!= NULL
)
872 PSECTION_OBJECT SectionObject
;
873 UNICODE_STRING FileName
;
879 * Determine the image file name and save it to the EPROCESS structure
881 Status
= ObReferenceObjectByHandle(SectionHandle
,
885 (PVOID
*)&SectionObject
,
887 if (!NT_SUCCESS(Status
))
889 DbgPrint("Failed to reference section object\n", Status
);
890 ObDereferenceObject(Process
);
891 ObDereferenceObject(pParentProcess
);
895 FileName
= SectionObject
->FileObject
->FileName
;
896 szSrc
= (PWCHAR
)(FileName
.Buffer
+ (FileName
.Length
/ sizeof(WCHAR
)) - 1);
897 while(szSrc
>= FileName
.Buffer
)
911 /* copy the image file name to the process and truncate it to 15 characters
913 szDest
= Process
->ImageFileName
;
914 lnFName
= min(lnFName
, sizeof(Process
->ImageFileName
) - 1);
917 *(szDest
++) = (UCHAR
)*(szSrc
++);
922 ObDereferenceObject(SectionObject
);
926 Process
->ImageFileName
[0] = '\0';
932 Status
= LdrpMapSystemDll(*ProcessHandle
,
934 if (!NT_SUCCESS(Status
))
936 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status
);
937 ObDereferenceObject(Process
);
938 ObDereferenceObject(pParentProcess
);
943 * Map the process image
945 if (SectionHandle
!= NULL
)
947 DPRINT("Mapping process image\n");
948 Status
= LdrpMapImage(*ProcessHandle
,
951 if (!NT_SUCCESS(Status
))
953 DbgPrint("LdrpMapImage failed (Status %x)\n", Status
);
954 ObDereferenceObject(Process
);
955 ObDereferenceObject(pParentProcess
);
965 * Duplicate the token
967 Status
= SepInitializeNewProcess(Process
, pParentProcess
);
968 if (!NT_SUCCESS(Status
))
970 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status
);
971 ObDereferenceObject(Process
);
972 ObDereferenceObject(pParentProcess
);
979 DPRINT("Creating PEB\n");
980 Status
= PsCreatePeb(*ProcessHandle
,
983 if (!NT_SUCCESS(Status
))
985 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status
);
986 ObDereferenceObject(Process
);
987 ObDereferenceObject(pParentProcess
);
988 ZwClose(*ProcessHandle
);
989 *ProcessHandle
= NULL
;
994 * Maybe send a message to the creator process's debugger
997 if (pParentProcess
->DebugPort
!= NULL
)
999 LPC_DBG_MESSAGE Message
;
1002 ObCreateHandle(NULL
, // Debugger Process
1003 NULL
, // SectionHandle
1008 Message
.Header
.MessageSize
= sizeof(LPC_DBG_MESSAGE
);
1009 Message
.Header
.DataSize
= sizeof(LPC_DBG_MESSAGE
) -
1010 sizeof(LPC_MESSAGE
);
1011 Message
.Type
= DBG_EVENT_CREATE_PROCESS
;
1012 Message
.Data
.CreateProcess
.FileHandle
= FileHandle
;
1013 Message
.Data
.CreateProcess
.Base
= ImageBase
;
1014 Message
.Data
.CreateProcess
.EntryPoint
= NULL
; //
1016 Status
= LpcSendDebugMessagePort(pParentProcess
->DebugPort
,
1021 PspRunCreateProcessNotifyRoutines(Process
, TRUE
);
1023 ObDereferenceObject(Process
);
1024 ObDereferenceObject(pParentProcess
);
1025 return(STATUS_SUCCESS
);
1033 NtOpenProcess(OUT PHANDLE ProcessHandle
,
1034 IN ACCESS_MASK DesiredAccess
,
1035 IN POBJECT_ATTRIBUTES ObjectAttributes
,
1036 IN PCLIENT_ID ClientId
)
1038 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1039 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1040 ProcessHandle
, DesiredAccess
, ObjectAttributes
, ClientId
,
1041 ClientId
->UniqueProcess
, ClientId
->UniqueThread
);
1045 * Not sure of the exact semantics
1047 if (ObjectAttributes
!= NULL
&& ObjectAttributes
->ObjectName
!= NULL
&&
1048 ObjectAttributes
->ObjectName
->Buffer
!= NULL
)
1053 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
1054 ObjectAttributes
->Attributes
,
1061 if (Status
!= STATUS_SUCCESS
)
1066 Status
= ObCreateHandle(PsGetCurrentProcess(),
1071 ObDereferenceObject(Process
);
1078 PLIST_ENTRY current_entry
;
1082 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
1083 current_entry
= PsProcessListHead
.Flink
;
1084 while (current_entry
!= &PsProcessListHead
)
1086 current
= CONTAINING_RECORD(current_entry
, EPROCESS
,
1088 if (current
->UniqueProcessId
== (ULONG
)ClientId
->UniqueProcess
)
1090 if (current
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
1092 Status
= STATUS_PROCESS_IS_TERMINATING
;
1096 Status
= ObReferenceObjectByPointer(current
,
1101 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1102 if (NT_SUCCESS(Status
))
1104 Status
= ObCreateHandle(PsGetCurrentProcess(),
1109 ObDereferenceObject(current
);
1110 DPRINT("*ProcessHandle %x\n", ProcessHandle
);
1111 DPRINT("NtOpenProcess() = %x\n", Status
);
1115 current_entry
= current_entry
->Flink
;
1117 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
1118 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1119 return(STATUS_UNSUCCESSFUL
);
1121 return(STATUS_UNSUCCESSFUL
);
1129 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
1130 IN PROCESSINFOCLASS ProcessInformationClass
,
1131 OUT PVOID ProcessInformation
,
1132 IN ULONG ProcessInformationLength
,
1133 OUT PULONG ReturnLength OPTIONAL
)
1137 KPROCESSOR_MODE PreviousMode
;
1139 PreviousMode
= ExGetPreviousMode();
1141 /* check for valid buffers */
1142 if(PreviousMode
== UserMode
)
1146 /* probe with 32bit alignment */
1147 ProbeForWrite(ProcessInformation
,
1148 ProcessInformationLength
,
1152 ProbeForWrite(ReturnLength
,
1157 Status
= STATUS_SUCCESS
;
1161 Status
= _SEH_GetExceptionCode();
1165 if(!NT_SUCCESS(Status
))
1172 * TODO: Here we should probably check that ProcessInformationLength
1173 * bytes indeed are writable at address ProcessInformation.
1176 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1177 PROCESS_QUERY_INFORMATION
,
1182 if (!NT_SUCCESS(Status
))
1187 switch (ProcessInformationClass
)
1189 case ProcessBasicInformation
:
1190 if (ProcessInformationLength
!= sizeof(PROCESS_BASIC_INFORMATION
))
1192 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1196 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP
=
1197 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
1201 ProcessBasicInformationP
->ExitStatus
= Process
->ExitStatus
;
1202 ProcessBasicInformationP
->PebBaseAddress
= Process
->Peb
;
1203 ProcessBasicInformationP
->AffinityMask
= Process
->Pcb
.Affinity
;
1204 ProcessBasicInformationP
->UniqueProcessId
=
1205 Process
->UniqueProcessId
;
1206 ProcessBasicInformationP
->InheritedFromUniqueProcessId
=
1207 (ULONG
)Process
->InheritedFromUniqueProcessId
;
1208 ProcessBasicInformationP
->BasePriority
=
1209 Process
->Pcb
.BasePriority
;
1213 *ReturnLength
= sizeof(PROCESS_BASIC_INFORMATION
);
1218 Status
= _SEH_GetExceptionCode();
1224 case ProcessQuotaLimits
:
1225 case ProcessIoCounters
:
1226 Status
= STATUS_NOT_IMPLEMENTED
;
1230 if (ProcessInformationLength
!= sizeof(KERNEL_USER_TIMES
))
1232 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1236 PKERNEL_USER_TIMES ProcessTimeP
= (PKERNEL_USER_TIMES
)ProcessInformation
;
1239 ProcessTimeP
->CreateTime
= Process
->CreateTime
;
1240 ProcessTimeP
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
* 100000LL;
1241 ProcessTimeP
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
* 100000LL;
1242 ProcessTimeP
->ExitTime
= Process
->ExitTime
;
1246 *ReturnLength
= sizeof(KERNEL_USER_TIMES
);
1251 Status
= _SEH_GetExceptionCode();
1257 case ProcessDebugPort
:
1259 if (ProcessInformationLength
!= sizeof(HANDLE
))
1261 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1268 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
!= NULL
? (HANDLE
)-1 : NULL
);
1271 *ReturnLength
= sizeof(HANDLE
);
1276 Status
= _SEH_GetExceptionCode();
1283 case ProcessLdtInformation
:
1284 case ProcessWorkingSetWatch
:
1285 case ProcessWx86Information
:
1286 Status
= STATUS_NOT_IMPLEMENTED
;
1289 case ProcessHandleCount
:
1290 if (ProcessInformationLength
!= sizeof(ULONG
))
1292 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1296 ULONG HandleCount
= ObpGetHandleCountByHandleTable(&Process
->HandleTable
);
1300 *(PULONG
)ProcessInformation
= HandleCount
;
1303 *ReturnLength
= sizeof(ULONG
);
1308 Status
= _SEH_GetExceptionCode();
1314 case ProcessSessionInformation
:
1316 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1318 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1322 PPROCESS_SESSION_INFORMATION SessionInfo
= (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1326 SessionInfo
->SessionId
= Process
->SessionId
;
1329 *ReturnLength
= sizeof(PROCESS_SESSION_INFORMATION
);
1334 Status
= _SEH_GetExceptionCode();
1341 case ProcessWow64Information
:
1342 DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
1343 Status
= STATUS_NOT_IMPLEMENTED
;
1346 case ProcessVmCounters
:
1347 if (ProcessInformationLength
!= sizeof(VM_COUNTERS
))
1349 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1353 PVM_COUNTERS pOut
= (PVM_COUNTERS
)ProcessInformation
;
1357 pOut
->PeakVirtualSize
= Process
->PeakVirtualSize
;
1359 * Here we should probably use VirtualSize.LowPart, but due to
1360 * incompatibilities in current headers (no unnamed union),
1363 pOut
->VirtualSize
= (ULONG
)Process
->VirtualSize
.QuadPart
;
1364 pOut
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
1365 pOut
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
1366 pOut
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
1367 pOut
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[0]; // TODO: Verify!
1368 pOut
->QuotaPagedPoolUsage
= Process
->QuotaPoolUsage
[0]; // TODO: Verify!
1369 pOut
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeakPoolUsage
[1]; // TODO: Verify!
1370 pOut
->QuotaNonPagedPoolUsage
= Process
->QuotaPoolUsage
[1]; // TODO: Verify!
1371 pOut
->PagefileUsage
= Process
->PagefileUsage
;
1372 pOut
->PeakPagefileUsage
= Process
->PeakPagefileUsage
;
1376 *ReturnLength
= sizeof(VM_COUNTERS
);
1381 Status
= _SEH_GetExceptionCode();
1387 case ProcessDefaultHardErrorMode
:
1388 if (ProcessInformationLength
!= sizeof(ULONG
))
1390 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1394 PULONG HardErrMode
= (PULONG
)ProcessInformation
;
1397 *HardErrMode
= Process
->DefaultHardErrorProcessing
;
1400 *ReturnLength
= sizeof(ULONG
);
1405 Status
= _SEH_GetExceptionCode();
1411 case ProcessPriorityBoost
:
1412 if (ProcessInformationLength
!= sizeof(ULONG
))
1414 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1418 PULONG BoostEnabled
= (PULONG
)ProcessInformation
;
1422 *BoostEnabled
= Process
->Pcb
.DisableBoost
? FALSE
: TRUE
;
1426 *ReturnLength
= sizeof(ULONG
);
1431 Status
= _SEH_GetExceptionCode();
1437 case ProcessDeviceMap
:
1438 if (ProcessInformationLength
!= sizeof(PROCESS_DEVICEMAP_INFORMATION
))
1440 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1444 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
1446 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
1450 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
1453 *ReturnLength
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
1458 Status
= _SEH_GetExceptionCode();
1464 case ProcessPriorityClass
:
1465 if (ProcessInformationLength
!= sizeof(USHORT
))
1467 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1471 PUSHORT Priority
= (PUSHORT
)ProcessInformation
;
1475 *Priority
= Process
->PriorityClass
;
1479 *ReturnLength
= sizeof(USHORT
);
1484 Status
= _SEH_GetExceptionCode();
1490 case ProcessImageFileName
:
1493 * We DO NOT return the file name stored in the EPROCESS structure.
1494 * Propably if we can't find a PEB or ProcessParameters structure for the
1497 if(Process
->Peb
!= NULL
)
1499 PRTL_USER_PROCESS_PARAMETERS ProcParams
= NULL
;
1500 UNICODE_STRING LocalDest
;
1501 ULONG ImagePathLen
= 0;
1502 PUNICODE_STRING DstPath
= (PUNICODE_STRING
)ProcessInformation
;
1504 /* we need to attach to the process to make sure we're in the right context! */
1505 KeAttachProcess(&Process
->Pcb
);
1509 ProcParams
= Process
->Peb
->ProcessParameters
;
1510 ImagePathLen
= ProcParams
->ImagePathName
.Length
;
1514 Status
= _SEH_GetExceptionCode();
1518 if(NT_SUCCESS(Status
))
1520 if(ProcessInformationLength
< sizeof(UNICODE_STRING
) + ImagePathLen
+ sizeof(WCHAR
))
1522 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1526 PWSTR StrSource
= NULL
;
1528 /* create a DstPath structure on the stack */
1531 LocalDest
.Length
= ImagePathLen
;
1532 LocalDest
.MaximumLength
= ImagePathLen
+ sizeof(WCHAR
);
1533 LocalDest
.Buffer
= (PWSTR
)(DstPath
+ 1);
1535 /* save a copy of the pointer to the source buffer */
1536 StrSource
= ProcParams
->ImagePathName
.Buffer
;
1540 Status
= _SEH_GetExceptionCode();
1544 if(NT_SUCCESS(Status
))
1546 /* now, let's allocate some anonymous memory to copy the string to.
1547 we can't just copy it to the buffer the caller pointed as it might
1548 be user memory in another context */
1549 PWSTR PathCopy
= ExAllocatePool(PagedPool
, LocalDest
.Length
+ sizeof(WCHAR
));
1550 if(PathCopy
!= NULL
)
1552 /* make a copy of the buffer to the temporary buffer */
1555 RtlCopyMemory(PathCopy
, StrSource
, LocalDest
.Length
);
1556 PathCopy
[LocalDest
.Length
/ sizeof(WCHAR
)] = L
'\0';
1560 Status
= _SEH_GetExceptionCode();
1564 /* detach from the process */
1567 /* only copy the string back to the caller if we were able to
1568 copy it into the temporary buffer! */
1569 if(NT_SUCCESS(Status
))
1571 /* now let's copy the buffer back to the caller */
1574 *DstPath
= LocalDest
;
1575 RtlCopyMemory(LocalDest
.Buffer
, PathCopy
, LocalDest
.Length
+ sizeof(WCHAR
));
1578 *ReturnLength
= sizeof(UNICODE_STRING
) + LocalDest
.Length
+ sizeof(WCHAR
);
1583 Status
= _SEH_GetExceptionCode();
1588 /* we're done with the copy operation, free the temporary kernel buffer */
1589 ExFreePool(PathCopy
);
1591 /* we need to bail because we're already detached from the process */
1596 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1606 /* FIXME - what to do here? */
1607 Status
= STATUS_UNSUCCESSFUL
;
1613 * Note: The following 10 information classes are verified to not be
1614 * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
1616 case ProcessBasePriority
:
1617 case ProcessRaisePriority
:
1618 case ProcessExceptionPort
:
1619 case ProcessAccessToken
:
1620 case ProcessLdtSize
:
1621 case ProcessIoPortHandlers
:
1622 case ProcessUserModeIOPL
:
1623 case ProcessEnableAlignmentFaultFixup
:
1624 case ProcessAffinityMask
:
1625 case ProcessForegroundInformation
:
1627 Status
= STATUS_INVALID_INFO_CLASS
;
1630 ObDereferenceObject(Process
);
1636 PspAssignPrimaryToken(PEPROCESS Process
,
1639 PACCESS_TOKEN Token
;
1640 PACCESS_TOKEN OldToken
;
1643 Status
= ObReferenceObjectByHandle(TokenHandle
,
1649 if (!NT_SUCCESS(Status
))
1653 Status
= SeExchangePrimaryToken(Process
, Token
, &OldToken
);
1654 if (NT_SUCCESS(Status
))
1656 ObDereferenceObject(OldToken
);
1658 ObDereferenceObject(Token
);
1666 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1667 IN PROCESSINFOCLASS ProcessInformationClass
,
1668 IN PVOID ProcessInformation
,
1669 IN ULONG ProcessInformationLength
)
1673 KPROCESSOR_MODE PreviousMode
;
1676 PreviousMode
= ExGetPreviousMode();
1678 /* check for valid buffers */
1679 if(PreviousMode
== UserMode
)
1683 /* probe with 32bit alignment */
1684 ProbeForRead(ProcessInformation
,
1685 ProcessInformationLength
,
1687 Status
= STATUS_SUCCESS
;
1691 Status
= _SEH_GetExceptionCode();
1695 if(!NT_SUCCESS(Status
))
1701 Access
= PROCESS_SET_INFORMATION
;
1703 switch(ProcessInformationClass
)
1705 case ProcessSessionInformation
:
1706 Access
|= PROCESS_SET_SESSIONID
;
1708 case ProcessExceptionPort
:
1709 case ProcessDebugPort
:
1710 Access
|= PROCESS_SET_PORT
;
1714 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1720 if (!NT_SUCCESS(Status
))
1725 switch (ProcessInformationClass
)
1727 case ProcessQuotaLimits
:
1728 case ProcessBasePriority
:
1729 case ProcessRaisePriority
:
1730 Status
= STATUS_NOT_IMPLEMENTED
;
1733 case ProcessDebugPort
:
1735 if(ProcessInformationLength
!= sizeof(HANDLE
))
1737 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1743 /* make a safe copy of the buffer on the stack */
1746 PortHandle
= *(PHANDLE
)ProcessInformation
;
1747 Status
= (PortHandle
!= NULL
? STATUS_SUCCESS
: STATUS_INVALID_PARAMETER
);
1751 Status
= _SEH_GetExceptionCode();
1755 if(NT_SUCCESS(Status
))
1759 /* in case we had success reading from the buffer, verify the provided
1762 Status
= ObReferenceObjectByHandle(PortHandle
,
1768 if(NT_SUCCESS(Status
))
1770 /* lock the process to be thread-safe! */
1772 Status
= PsLockProcess(Process
, FALSE
);
1773 if(NT_SUCCESS(Status
))
1776 * according to "NT Native API" documentation, setting the debug
1777 * port is only permitted once!
1779 if(Process
->DebugPort
== NULL
)
1781 /* keep the reference to the handle! */
1782 Process
->DebugPort
= DebugPort
;
1786 /* we're now debugging the process, so set the flag in the PEB
1787 structure. However, to access it we need to attach to the
1788 process so we're sure we're in the right context! */
1790 KeAttachProcess(&Process
->Pcb
);
1793 Process
->Peb
->BeingDebugged
= TRUE
;
1797 DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process
, _SEH_GetExceptionCode());
1802 Status
= STATUS_SUCCESS
;
1806 ObDereferenceObject(DebugPort
);
1807 Status
= STATUS_PORT_ALREADY_SET
;
1809 PsUnlockProcess(Process
);
1813 ObDereferenceObject(DebugPort
);
1821 case ProcessExceptionPort
:
1823 if(ProcessInformationLength
!= sizeof(HANDLE
))
1825 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1831 /* make a safe copy of the buffer on the stack */
1834 PortHandle
= *(PHANDLE
)ProcessInformation
;
1835 Status
= STATUS_SUCCESS
;
1839 Status
= _SEH_GetExceptionCode();
1843 if(NT_SUCCESS(Status
))
1845 PEPORT ExceptionPort
;
1847 /* in case we had success reading from the buffer, verify the provided
1850 Status
= ObReferenceObjectByHandle(PortHandle
,
1854 (PVOID
)&ExceptionPort
,
1856 if(NT_SUCCESS(Status
))
1858 /* lock the process to be thread-safe! */
1860 Status
= PsLockProcess(Process
, FALSE
);
1861 if(NT_SUCCESS(Status
))
1864 * according to "NT Native API" documentation, setting the exception
1865 * port is only permitted once!
1867 if(Process
->ExceptionPort
== NULL
)
1869 /* keep the reference to the handle! */
1870 Process
->ExceptionPort
= ExceptionPort
;
1871 Status
= STATUS_SUCCESS
;
1875 ObDereferenceObject(ExceptionPort
);
1876 Status
= STATUS_PORT_ALREADY_SET
;
1878 PsUnlockProcess(Process
);
1882 ObDereferenceObject(ExceptionPort
);
1890 case ProcessAccessToken
:
1892 if(ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
1894 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1900 /* make a safe copy of the buffer on the stack */
1903 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->Token
;
1904 Status
= STATUS_SUCCESS
;
1908 Status
= _SEH_GetExceptionCode();
1912 if(NT_SUCCESS(Status
))
1914 /* in case we had success reading from the buffer, perform the actual task */
1915 Status
= PspAssignPrimaryToken(Process
, TokenHandle
);
1921 case ProcessDefaultHardErrorMode
:
1923 if(ProcessInformationLength
!= sizeof(UINT
))
1925 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1931 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
1932 *(PLONG
)ProcessInformation
);
1933 Status
= STATUS_SUCCESS
;
1937 Status
= _SEH_GetExceptionCode();
1944 case ProcessSessionInformation
:
1946 if(ProcessInformationLength
!= sizeof(UINT
))
1948 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1952 PROCESS_SESSION_INFORMATION SessionInfo
;
1953 Status
= STATUS_SUCCESS
;
1957 /* copy the structure to the stack */
1958 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1962 Status
= _SEH_GetExceptionCode();
1966 if(NT_SUCCESS(Status
))
1968 /* we successfully copied the structure to the stack, continue processing */
1971 * setting the session id requires the SeTcbPrivilege!
1973 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
,
1976 /* can't set the session id, bail! */
1977 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1981 /* FIXME - update the session id for the process token */
1983 Status
= PsLockProcess(Process
, FALSE
);
1984 if(NT_SUCCESS(Status
))
1986 Process
->SessionId
= SessionInfo
.SessionId
;
1988 /* Update the session id in the PEB structure */
1989 if(Process
->Peb
!= NULL
)
1991 /* we need to attach to the process to make sure we're in the right
1992 context to access the PEB structure */
1993 KeAttachProcess(&Process
->Pcb
);
1997 /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
1999 Status
= STATUS_SUCCESS
;
2003 Status
= _SEH_GetExceptionCode();
2010 PsUnlockProcess(Process
);
2017 case ProcessLdtInformation
:
2018 case ProcessLdtSize
:
2019 case ProcessIoPortHandlers
:
2020 case ProcessWorkingSetWatch
:
2021 case ProcessUserModeIOPL
:
2022 case ProcessEnableAlignmentFaultFixup
:
2023 case ProcessPriorityClass
:
2024 case ProcessAffinityMask
:
2025 Status
= STATUS_NOT_IMPLEMENTED
;
2028 case ProcessBasicInformation
:
2029 case ProcessIoCounters
:
2031 case ProcessPooledUsageAndLimits
:
2032 case ProcessWx86Information
:
2033 case ProcessHandleCount
:
2034 case ProcessWow64Information
:
2036 Status
= STATUS_INVALID_INFO_CLASS
;
2038 ObDereferenceObject(Process
);
2043 /**********************************************************************
2045 * PiQuerySystemProcessInformation
2048 * Compute the size of a process+thread snapshot as
2049 * expected by NtQuerySystemInformation.
2052 * 0 on error; otherwise the size, in bytes of the buffer
2053 * required to write a full snapshot.
2056 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
2059 PiQuerySystemProcessInformation(PVOID Buffer
,
2063 return STATUS_NOT_IMPLEMENTED
;
2067 PLIST_ENTRY CurrentEntryP
;
2069 PLIST_ENTRY CurrentEntryT
;
2072 ULONG RequiredSize
= 0L;
2073 BOOLEAN SizeOnly
= FALSE
;
2077 PSYSTEM_PROCESS_INFORMATION pInfoP
= (PSYSTEM_PROCESS_INFORMATION
) SnapshotBuffer
;
2078 PSYSTEM_PROCESS_INFORMATION pInfoPLast
= NULL
;
2079 PSYSTEM_THREAD_INFO pInfoT
= NULL
;
2082 /* Lock the process list. */
2083 KeAcquireSpinLock(&PsProcessListLock
,
2087 * Scan the process list. Since the
2088 * list is circular, the guard is false
2089 * after the last process.
2091 for ( CurrentEntryP
= PsProcessListHead
.Flink
;
2092 (CurrentEntryP
!= & PsProcessListHead
);
2093 CurrentEntryP
= CurrentEntryP
->Flink
2097 * Compute how much space is
2098 * occupied in the snapshot
2099 * by adding this process info.
2100 * (at least one thread).
2102 SpiSizeCurrent
= sizeof (SYSTEM_PROCESS_INFORMATION
);
2103 RequiredSize
+= SpiSizeCurrent
;
2105 * Do not write process data in the
2106 * buffer if it is too small.
2108 if (TRUE
== SizeOnly
) continue;
2110 * Check if the buffer can contain
2111 * the full snapshot.
2113 if (Size
< RequiredSize
)
2119 * Get a reference to the
2120 * process descriptor we are
2123 CurrentP
= CONTAINING_RECORD(
2129 * Write process data in the buffer.
2131 RtlZeroMemory (pInfoP
, sizeof (SYSTEM_PROCESS_INFORMATION
));
2133 pInfoP
->ThreadCount
= 0L;
2134 pInfoP
->ProcessId
= CurrentP
->UniqueProcessId
;
2135 RtlInitUnicodeString (
2137 CurrentP
->ImageFileName
2140 for ( pInfoT
= & CurrentP
->ThreadSysInfo
[0],
2141 CurrentEntryT
= CurrentP
->ThreadListHead
.Flink
;
2143 (CurrentEntryT
!= & CurrentP
->ThreadListHead
);
2145 pInfoT
= & CurrentP
->ThreadSysInfo
[pInfoP
->ThreadCount
],
2146 CurrentEntryT
= CurrentEntryT
->Flink
2150 * Recalculate the size of the
2151 * information block.
2153 if (0 < pInfoP
->ThreadCount
)
2155 RequiredSize
+= sizeof (SYSTEM_THREAD_INFORMATION
);
2158 * Do not write thread data in the
2159 * buffer if it is too small.
2161 if (TRUE
== SizeOnly
) continue;
2163 * Check if the buffer can contain
2164 * the full snapshot.
2166 if (Size
< RequiredSize
)
2172 * Get a reference to the
2173 * thread descriptor we are
2176 CurrentT
= CONTAINING_RECORD(
2182 * Write thread data.
2186 sizeof (SYSTEM_THREAD_INFORMATION
)
2188 pInfoT
->KernelTime
= CurrentT
-> ; /* TIME */
2189 pInfoT
->UserTime
= CurrentT
-> ; /* TIME */
2190 pInfoT
->CreateTime
= CurrentT
-> ; /* TIME */
2191 pInfoT
->TickCount
= CurrentT
-> ; /* ULONG */
2192 pInfoT
->StartEIP
= CurrentT
-> ; /* ULONG */
2193 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2194 pInfoT
->ClientId
= CurrentT
-> ; /* CLIENT_ID */
2195 pInfoT
->DynamicPriority
= CurrentT
-> ; /* ULONG */
2196 pInfoT
->BasePriority
= CurrentT
-> ; /* ULONG */
2197 pInfoT
->nSwitches
= CurrentT
-> ; /* ULONG */
2198 pInfoT
->State
= CurrentT
-> ; /* DWORD */
2199 pInfoT
->WaitReason
= CurrentT
-> ; /* KWAIT_REASON */
2201 * Count the number of threads
2204 ++ pInfoP
->ThreadCount
;
2207 * Save the size of information
2208 * stored in the buffer for the
2211 pInfoP
->RelativeOffset
= SpiSize
;
2213 * Save a reference to the last
2214 * valid information block.
2216 pInfoPLast
= pInfoP
;
2218 * Compute the offset of the
2219 * SYSTEM_PROCESS_INFORMATION
2220 * descriptor in the snapshot
2221 * buffer for the next process.
2223 (ULONG
) pInfoP
+= SpiSize
;
2226 * Unlock the process list.
2229 & PsProcessListLock
,
2233 * Return the proper error status code,
2234 * if the buffer was too small.
2236 if (TRUE
== SizeOnly
)
2238 if (NULL
!= RequiredSize
)
2240 *pRequiredSize
= RequiredSize
;
2242 return STATUS_INFO_LENGTH_MISMATCH
;
2245 * Mark the end of the snapshot.
2247 pInfoP
->RelativeOffset
= 0L;
2249 return STATUS_SUCCESS
;
2256 LARGE_INTEGER STDCALL
2257 PsGetProcessExitTime(VOID
)
2260 Li
.QuadPart
= PsGetCurrentProcess()->ExitTime
.QuadPart
;
2269 PsGetProcessCreateTimeQuadPart(
2273 return Process
->CreateTime
.QuadPart
;
2281 PsGetProcessDebugPort(
2285 return Process
->DebugPort
;
2293 PsGetProcessExitProcessCalled(
2297 return Process
->ExitProcessCalled
;
2305 PsGetProcessExitStatus(
2309 return Process
->ExitStatus
;
2321 return (HANDLE
)Process
->UniqueProcessId
;
2329 PsGetProcessImageFileName(
2333 return (LPSTR
)Process
->ImageFileName
;
2341 PsGetProcessInheritedFromUniqueProcessId(
2345 return Process
->InheritedFromUniqueProcessId
;
2357 return Process
->Job
;
2369 return Process
->Peb
;
2377 PsGetProcessPriorityClass(
2381 return Process
->PriorityClass
;
2389 PsGetProcessSectionBaseAddress(
2393 return Process
->SectionBaseAddress
;
2401 PsGetProcessSecurityPort(
2405 return Process
->SecurityPort
;
2413 PsGetProcessSessionId(
2417 return (HANDLE
)Process
->SessionId
;
2425 PsGetProcessWin32Process(
2429 return Process
->Win32Process
;
2437 PsGetProcessWin32WindowStation(
2441 return Process
->Win32WindowStation
;
2449 PsIsProcessBeingDebugged(
2453 return FALSE
/*Process->IsProcessBeingDebugged*/;
2461 PsLookupProcessByProcessId(IN PVOID ProcessId
,
2462 OUT PEPROCESS
*Process
)
2465 PLIST_ENTRY current_entry
;
2468 KeAcquireSpinLock(&PsProcessListLock
, &oldIrql
);
2470 current_entry
= PsProcessListHead
.Flink
;
2471 while (current_entry
!= &PsProcessListHead
)
2473 current
= CONTAINING_RECORD(current_entry
,
2476 if (current
->UniqueProcessId
== (ULONG
)ProcessId
)
2479 ObReferenceObject(current
);
2480 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
2481 return(STATUS_SUCCESS
);
2483 current_entry
= current_entry
->Flink
;
2486 KeReleaseSpinLock(&PsProcessListLock
, oldIrql
);
2488 return(STATUS_INVALID_PARAMETER
);
2493 PspRunCreateProcessNotifyRoutines
2495 PEPROCESS CurrentProcess
,
2500 HANDLE ProcessId
= (HANDLE
)CurrentProcess
->UniqueProcessId
;
2501 HANDLE ParentId
= CurrentProcess
->InheritedFromUniqueProcessId
;
2503 for(i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2504 if(PiProcessNotifyRoutine
[i
])
2505 PiProcessNotifyRoutine
[i
](ParentId
, ProcessId
, Create
);
2512 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine
,
2519 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2521 if ((PVOID
)PiProcessNotifyRoutine
[i
] == (PVOID
)NotifyRoutine
)
2523 PiProcessNotifyRoutine
[i
] = NULL
;
2528 return(STATUS_SUCCESS
);
2532 for(i
=0;i
<MAX_PROCESS_NOTIFY_ROUTINE_COUNT
;i
++)
2534 if (PiProcessNotifyRoutine
[i
] == NULL
)
2536 PiProcessNotifyRoutine
[i
] = NotifyRoutine
;
2541 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2543 return STATUS_INSUFFICIENT_RESOURCES
;
2546 return STATUS_SUCCESS
;
2550 PspRunLoadImageNotifyRoutines(
2551 PUNICODE_STRING FullImageName
,
2553 PIMAGE_INFO ImageInfo
)
2557 for (i
= 0; i
< MAX_PROCESS_NOTIFY_ROUTINE_COUNT
; ++ i
)
2558 if (PiLoadImageNotifyRoutine
[i
])
2559 PiLoadImageNotifyRoutine
[i
](FullImageName
, ProcessId
, ImageInfo
);
2567 PsRemoveLoadImageNotifyRoutine(
2568 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
2572 return STATUS_NOT_IMPLEMENTED
;
2579 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
)
2583 for (i
= 0; i
< MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT
; i
++)
2585 if (PiLoadImageNotifyRoutine
[i
] == NULL
)
2587 PiLoadImageNotifyRoutine
[i
] = NotifyRoutine
;
2592 if (i
== MAX_PROCESS_NOTIFY_ROUTINE_COUNT
)
2594 return STATUS_INSUFFICIENT_RESOURCES
;
2597 return STATUS_SUCCESS
;
2605 PsSetProcessPriorityClass(
2610 Process
->PriorityClass
= PriorityClass
;
2618 PsSetProcessSecurityPort(
2623 Process
->SecurityPort
= SecurityPort
;
2631 PsSetProcessWin32Process(
2636 Process
->Win32Process
= Win32Process
;
2644 PsSetProcessWin32WindowStation(
2649 Process
->Win32WindowStation
= WindowStation
;
2659 IN PEPROCESS Process
,
2660 IN POOL_TYPE PoolType
,
2666 /* Charge the usage */
2667 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
2669 /* Raise Exception */
2670 if (!NT_SUCCESS(Status
)) {
2671 ExRaiseStatus(Status
);
2680 PsChargeProcessNonPagedPoolQuota (
2681 IN PEPROCESS Process
,
2685 /* Call the general function */
2686 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
2694 PsChargeProcessPagedPoolQuota (
2695 IN PEPROCESS Process
,
2699 /* Call the general function */
2700 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
2708 PsChargeProcessPoolQuota(
2709 IN PEPROCESS Process
,
2710 IN POOL_TYPE PoolType
,
2714 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
2718 /* Get current Quota Block */
2719 QuotaBlock
= Process
->QuotaBlock
;
2721 /* Quota Operations are not to be done on the SYSTEM Process */
2722 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
2724 /* New Size in use */
2725 NewUsageSize
= QuotaBlock
->QuotaEntry
[PoolType
].Usage
+ Amount
;
2727 /* Does this size respect the quota? */
2728 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Limit
) {
2730 /* It doesn't, so keep raising the Quota */
2731 while (MiRaisePoolQuota(PoolType
, QuotaBlock
->QuotaEntry
[PoolType
].Limit
, &NewMaxQuota
)) {
2732 /* Save new Maximum Quota */
2733 QuotaBlock
->QuotaEntry
[PoolType
].Limit
= NewMaxQuota
;
2735 /* See if the new Maximum Quota fulfills our need */
2736 if (NewUsageSize
<= NewMaxQuota
) goto QuotaChanged
;
2739 return STATUS_QUOTA_EXCEEDED
;
2743 /* Save new Usage */
2744 QuotaBlock
->QuotaEntry
[PoolType
].Usage
= NewUsageSize
;
2746 /* Is this a new peak? */
2747 if (NewUsageSize
> QuotaBlock
->QuotaEntry
[PoolType
].Peak
) {
2748 QuotaBlock
->QuotaEntry
[PoolType
].Peak
= NewUsageSize
;
2752 return STATUS_SUCCESS
;
2761 IN PEPROCESS Process
,
2762 IN POOL_TYPE PoolType
,
2774 PsReturnProcessNonPagedPoolQuota(
2775 IN PEPROCESS Process
,
2787 PsReturnProcessPagedPoolQuota(
2788 IN PEPROCESS Process
,
2796 PsLockProcess(PEPROCESS Process
, BOOL Timeout
)
2799 PKTHREAD PrevLockOwner
;
2800 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
2801 PLARGE_INTEGER Delay
= (Timeout
? &PsLockTimeout
: NULL
);
2802 PKTHREAD CallingThread
= KeGetCurrentThread();
2804 KeEnterCriticalRegion();
2808 if(Process
->Pcb
.State
== PROCESS_STATE_TERMINATED
)
2810 KeLeaveCriticalRegion();
2811 return STATUS_PROCESS_IS_TERMINATING
;
2814 PrevLockOwner
= (PKTHREAD
)InterlockedCompareExchangePointer(
2815 &Process
->LockOwner
, CallingThread
, NULL
);
2816 if(PrevLockOwner
== NULL
|| PrevLockOwner
== CallingThread
)
2818 /* we got the lock or already locked it */
2819 if(InterlockedIncrementUL(&Process
->LockCount
) == 1)
2821 KeClearEvent(&Process
->LockEvent
);
2824 return STATUS_SUCCESS
;
2830 Status
= KeWaitForSingleObject(&Process
->LockEvent
,
2835 if(!NT_SUCCESS(Status
))
2838 if(Status
== STATUS_TIMEOUT
)
2840 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process
);
2843 KeLeaveCriticalRegion();
2850 KeDelayExecutionThread(KernelMode
, FALSE
, &ShortPsLockDelay
);
2859 PsUnlockProcess(PEPROCESS Process
)
2861 ASSERT(Process
->LockOwner
== KeGetCurrentThread());
2863 if(InterlockedDecrementUL(&Process
->LockCount
) == 0)
2865 InterlockedExchangePointer(&Process
->LockOwner
, NULL
);
2866 KeSetEvent(&Process
->LockEvent
, IO_NO_INCREMENT
, FALSE
);
2869 KeLeaveCriticalRegion();