Copy makefile
[reactos.git] / reactos / ntoskrnl / ps / process.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/process.c
6 * PURPOSE: Process managment
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
20
21 POBJECT_TYPE EXPORTED PsProcessType = NULL;
22
23 LIST_ENTRY PsActiveProcessHead;
24 FAST_MUTEX PspActiveProcessMutex;
25 static LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
26
27 static GENERIC_MAPPING PiProcessMapping = {STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
28 STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
29 PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE |
30 PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SET_PORT,
31 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
32 PROCESS_ALL_ACCESS};
33
34 static const INFORMATION_CLASS_INFO PsProcessInfoClass[] =
35 {
36 ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* ProcessBasicInformation */
37 ICI_SQ_SAME( sizeof(QUOTA_LIMITS), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessQuotaLimits */
38 ICI_SQ_SAME( sizeof(IO_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessIoCounters */
39 ICI_SQ_SAME( sizeof(VM_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessVmCounters */
40 ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES), sizeof(ULONG), ICIF_QUERY ), /* ProcessTimes */
41 ICI_SQ_SAME( sizeof(KPRIORITY), sizeof(ULONG), ICIF_SET ), /* ProcessBasePriority */
42 ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_SET ), /* ProcessRaisePriority */
43 ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessDebugPort */
44 ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_SET ), /* ProcessExceptionPort */
45 ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN), sizeof(ULONG), ICIF_SET ), /* ProcessAccessToken */
46 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessLdtInformation */
47 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessLdtSize */
48 ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessDefaultHardErrorMode */
49 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessIoPortHandlers */
50 ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS), sizeof(ULONG), ICIF_QUERY ), /* ProcessPooledUsageAndLimits */
51 ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessWorkingSetWatch */
52 ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessUserModeIOPL */
53 ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(ULONG), ICIF_SET ), /* ProcessEnableAlignmentFaultFixup */
54 ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS), sizeof(USHORT), ICIF_QUERY | ICIF_SET ), /* ProcessPriorityClass */
55 ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWx86Information */
56 ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessHandleCount */
57 ICI_SQ_SAME( sizeof(KAFFINITY), sizeof(ULONG), ICIF_SET ), /* ProcessAffinityMask */
58 ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessPriorityBoost */
59
60 ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Query), /* ProcessDeviceMap */
61 /*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Set),
62 /*Q*/ sizeof(ULONG),
63 /*S*/ sizeof(ULONG),
64 ICIF_QUERY | ICIF_SET ),
65
66 ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessSessionInformation */
67 ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(ULONG), ICIF_SET ), /* ProcessForegroundInformation */
68 ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWow64Information */
69 ICI_SQ_SAME( sizeof(UNICODE_STRING), sizeof(ULONG), ICIF_QUERY | ICIF_SIZE_VARIABLE), /* ProcessImageFileName */
70 };
71
72 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
73 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
74
75 static PCREATE_PROCESS_NOTIFY_ROUTINE
76 PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
77 static PLOAD_IMAGE_NOTIFY_ROUTINE
78 PiLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT];
79
80
81 typedef struct
82 {
83 WORK_QUEUE_ITEM WorkQueueItem;
84 KEVENT Event;
85 PEPROCESS Process;
86 BOOLEAN IsWorkerQueue;
87 } DEL_CONTEXT, *PDEL_CONTEXT;
88
89 /* FUNCTIONS *****************************************************************/
90
91 VOID
92 STDCALL
93 PsExitSpecialApc(PKAPC Apc,
94 PKNORMAL_ROUTINE *NormalRoutine,
95 PVOID *NormalContext,
96 PVOID *SystemArgument1,
97 PVOID *SystemArgument2)
98 {
99 }
100
101 PEPROCESS
102 PsGetNextProcess(PEPROCESS OldProcess)
103 {
104 PEPROCESS NextProcess;
105 NTSTATUS Status;
106
107 if (OldProcess == NULL)
108 {
109 Status = ObReferenceObjectByPointer(PsInitialSystemProcess,
110 PROCESS_ALL_ACCESS,
111 PsProcessType,
112 KernelMode);
113 if (!NT_SUCCESS(Status))
114 {
115 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsInitialSystemProcess\n");
116 KEBUGCHECK(0);
117 }
118 return PsInitialSystemProcess;
119 }
120
121 ExAcquireFastMutex(&PspActiveProcessMutex);
122 NextProcess = OldProcess;
123 while (1)
124 {
125 if (NextProcess->ProcessListEntry.Blink == &PsActiveProcessHead)
126 {
127 NextProcess = CONTAINING_RECORD(PsActiveProcessHead.Blink,
128 EPROCESS,
129 ProcessListEntry);
130 }
131 else
132 {
133 NextProcess = CONTAINING_RECORD(NextProcess->ProcessListEntry.Blink,
134 EPROCESS,
135 ProcessListEntry);
136 }
137 Status = ObReferenceObjectByPointer(NextProcess,
138 PROCESS_ALL_ACCESS,
139 PsProcessType,
140 KernelMode);
141 if (NT_SUCCESS(Status))
142 {
143 break;
144 }
145 else if (Status == STATUS_PROCESS_IS_TERMINATING)
146 {
147 continue;
148 }
149 else if (!NT_SUCCESS(Status))
150 {
151 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
152 KEBUGCHECK(0);
153 }
154 }
155
156 ExReleaseFastMutex(&PspActiveProcessMutex);
157 ObDereferenceObject(OldProcess);
158
159 return(NextProcess);
160 }
161
162
163 /*
164 * @implemented
165 */
166 NTSTATUS STDCALL
167 NtOpenProcessToken(IN HANDLE ProcessHandle,
168 IN ACCESS_MASK DesiredAccess,
169 OUT PHANDLE TokenHandle)
170 {
171 return NtOpenProcessTokenEx(ProcessHandle,
172 DesiredAccess,
173 0,
174 TokenHandle);
175 }
176
177
178 /*
179 * @unimplemented
180 */
181 NTSTATUS
182 STDCALL
183 NtOpenProcessTokenEx(
184 IN HANDLE ProcessHandle,
185 IN ACCESS_MASK DesiredAccess,
186 IN ULONG HandleAttributes,
187 OUT PHANDLE TokenHandle
188 )
189 {
190 PACCESS_TOKEN Token;
191 HANDLE hToken;
192 KPROCESSOR_MODE PreviousMode;
193 NTSTATUS Status = STATUS_SUCCESS;
194
195 PAGED_CODE();
196
197 PreviousMode = ExGetPreviousMode();
198
199 if(PreviousMode == UserMode)
200 {
201 _SEH_TRY
202 {
203 ProbeForWrite(TokenHandle,
204 sizeof(HANDLE),
205 sizeof(ULONG));
206 }
207 _SEH_HANDLE
208 {
209 Status = _SEH_GetExceptionCode();
210 }
211 _SEH_END;
212
213 if(!NT_SUCCESS(Status))
214 {
215 return Status;
216 }
217 }
218
219 Status = PsOpenTokenOfProcess(ProcessHandle,
220 &Token);
221 if(NT_SUCCESS(Status))
222 {
223 Status = ObCreateHandle(PsGetCurrentProcess(),
224 Token,
225 DesiredAccess,
226 FALSE,
227 &hToken);
228 ObDereferenceObject(Token);
229
230 _SEH_TRY
231 {
232 *TokenHandle = hToken;
233 }
234 _SEH_HANDLE
235 {
236 Status = _SEH_GetExceptionCode();
237 }
238 _SEH_END;
239 }
240
241 return Status;
242 }
243
244
245 /*
246 * @implemented
247 */
248 PACCESS_TOKEN STDCALL
249 PsReferencePrimaryToken(PEPROCESS Process)
250 {
251 ObReferenceObjectByPointer(Process->Token,
252 TOKEN_ALL_ACCESS,
253 SepTokenObjectType,
254 KernelMode);
255 return(Process->Token);
256 }
257
258
259 NTSTATUS
260 PsOpenTokenOfProcess(HANDLE ProcessHandle,
261 PACCESS_TOKEN* Token)
262 {
263 PEPROCESS Process;
264 NTSTATUS Status;
265
266 Status = ObReferenceObjectByHandle(ProcessHandle,
267 PROCESS_QUERY_INFORMATION,
268 PsProcessType,
269 ExGetPreviousMode(),
270 (PVOID*)&Process,
271 NULL);
272 if(NT_SUCCESS(Status))
273 {
274 *Token = PsReferencePrimaryToken(Process);
275 ObDereferenceObject(Process);
276 }
277
278 return Status;
279 }
280
281
282 VOID
283 PiKillMostProcesses(VOID)
284 {
285 PLIST_ENTRY current_entry;
286 PEPROCESS current;
287
288 ExAcquireFastMutex(&PspActiveProcessMutex);
289
290 current_entry = PsActiveProcessHead.Flink;
291 while (current_entry != &PsActiveProcessHead)
292 {
293 current = CONTAINING_RECORD(current_entry, EPROCESS,
294 ProcessListEntry);
295 current_entry = current_entry->Flink;
296
297 if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
298 current->UniqueProcessId != PsGetCurrentProcessId())
299 {
300 PiTerminateProcessThreads(current, STATUS_SUCCESS);
301 }
302 }
303
304 ExReleaseFastMutex(&PspActiveProcessMutex);
305 }
306
307
308 VOID INIT_FUNCTION
309 PsInitProcessManagment(VOID)
310 {
311 PKPROCESS KProcess;
312 NTSTATUS Status;
313
314 ShortPsLockDelay.QuadPart = -100LL;
315 PsLockTimeout.QuadPart = -10000000LL; /* one second */
316 /*
317 * Register the process object type
318 */
319
320 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
321
322 PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
323 PsProcessType->TotalObjects = 0;
324 PsProcessType->TotalHandles = 0;
325 PsProcessType->PeakObjects = 0;
326 PsProcessType->PeakHandles = 0;
327 PsProcessType->PagedPoolCharge = 0;
328 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
329 PsProcessType->Mapping = &PiProcessMapping;
330 PsProcessType->Dump = NULL;
331 PsProcessType->Open = NULL;
332 PsProcessType->Close = NULL;
333 PsProcessType->Delete = PiDeleteProcess;
334 PsProcessType->Parse = NULL;
335 PsProcessType->Security = NULL;
336 PsProcessType->QueryName = NULL;
337 PsProcessType->OkayToClose = NULL;
338 PsProcessType->Create = NULL;
339 PsProcessType->DuplicationNotify = NULL;
340
341 RtlInitUnicodeString(&PsProcessType->TypeName, L"Process");
342
343 ObpCreateTypeObject(PsProcessType);
344
345 InitializeListHead(&PsActiveProcessHead);
346 ExInitializeFastMutex(&PspActiveProcessMutex);
347
348 RtlZeroMemory(PiProcessNotifyRoutine, sizeof(PiProcessNotifyRoutine));
349 RtlZeroMemory(PiLoadImageNotifyRoutine, sizeof(PiLoadImageNotifyRoutine));
350
351 /*
352 * Initialize the system process
353 */
354 Status = ObCreateObject(KernelMode,
355 PsProcessType,
356 NULL,
357 KernelMode,
358 NULL,
359 sizeof(EPROCESS),
360 0,
361 0,
362 (PVOID*)&PsInitialSystemProcess);
363 if (!NT_SUCCESS(Status))
364 {
365 return;
366 }
367
368 /* System threads may run on any processor. */
369 PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
370 PsInitialSystemProcess->Pcb.IopmOffset = 0xffff;
371 PsInitialSystemProcess->Pcb.LdtDescriptor[0] = 0;
372 PsInitialSystemProcess->Pcb.LdtDescriptor[1] = 0;
373 PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
374 PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
375 InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
376 KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
377 InternalProcessType,
378 sizeof(EPROCESS),
379 FALSE);
380 KProcess = &PsInitialSystemProcess->Pcb;
381
382 MmInitializeAddressSpace(PsInitialSystemProcess,
383 &PsInitialSystemProcess->AddressSpace);
384 ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess);
385
386 KeInitializeEvent(&PsInitialSystemProcess->LockEvent, SynchronizationEvent, FALSE);
387 PsInitialSystemProcess->LockCount = 0;
388 PsInitialSystemProcess->LockOwner = NULL;
389
390 #if defined(__GNUC__)
391 KProcess->DirectoryTableBase =
392 (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
393 #else
394 {
395 LARGE_INTEGER dummy;
396 dummy.QuadPart = (LONGLONG)(ULONG)MmGetPageDirectory();
397 KProcess->DirectoryTableBase = dummy;
398 }
399 #endif
400
401 strcpy(PsInitialSystemProcess->ImageFileName, "System");
402
403 Status = PsCreateCidHandle(PsInitialSystemProcess,
404 PsProcessType,
405 &PsInitialSystemProcess->UniqueProcessId);
406 if(!NT_SUCCESS(Status))
407 {
408 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
409 return;
410 }
411
412 PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
413
414 InsertHeadList(&PsActiveProcessHead,
415 &PsInitialSystemProcess->ProcessListEntry);
416 InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
417
418 SepCreateSystemProcessToken(PsInitialSystemProcess);
419 }
420
421 VOID STDCALL
422 PiDeleteProcessWorker(PVOID pContext)
423 {
424 PDEL_CONTEXT Context;
425 PEPROCESS CurrentProcess;
426 PEPROCESS Process;
427
428 Context = (PDEL_CONTEXT)pContext;
429 Process = Context->Process;
430 CurrentProcess = PsGetCurrentProcess();
431
432 DPRINT("PiDeleteProcess(ObjectBody %x)\n",Process);
433
434 if (CurrentProcess != Process)
435 {
436 KeAttachProcess(&Process->Pcb);
437 }
438
439 ExAcquireFastMutex(&PspActiveProcessMutex);
440 RemoveEntryList(&Process->ProcessListEntry);
441 ExReleaseFastMutex(&PspActiveProcessMutex);
442
443 /* KDB hook */
444 KDB_DELETEPROCESS_HOOK(Process);
445
446 ObDereferenceObject(Process->Token);
447 ObDeleteHandleTable(Process);
448
449 if (CurrentProcess != Process)
450 {
451 KeDetachProcess();
452 }
453
454 MmReleaseMmInfo(Process);
455 if (Context->IsWorkerQueue)
456 {
457 KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
458 }
459 }
460
461 VOID STDCALL
462 PiDeleteProcess(PVOID ObjectBody)
463 {
464 DEL_CONTEXT Context;
465
466 Context.Process = (PEPROCESS)ObjectBody;
467
468 if (PsGetCurrentProcess() == Context.Process ||
469 PsGetCurrentThread()->ThreadsProcess == Context.Process)
470 {
471 KEBUGCHECK(0);
472 }
473
474 if (PsGetCurrentThread()->ThreadsProcess == PsGetCurrentProcess())
475 {
476 Context.IsWorkerQueue = FALSE;
477 PiDeleteProcessWorker(&Context);
478 }
479 else
480 {
481 Context.IsWorkerQueue = TRUE;
482 KeInitializeEvent(&Context.Event, NotificationEvent, FALSE);
483 ExInitializeWorkItem (&Context.WorkQueueItem, PiDeleteProcessWorker, &Context);
484 ExQueueWorkItem(&Context.WorkQueueItem, HyperCriticalWorkQueue);
485 if (KeReadStateEvent(&Context.Event) == 0)
486 {
487 KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL);
488 }
489 }
490
491 if(((PEPROCESS)ObjectBody)->Win32Process != NULL)
492 {
493 /* delete the W32PROCESS structure if there's one associated */
494 ExFreePool (((PEPROCESS)ObjectBody)->Win32Process);
495 }
496 }
497
498 static NTSTATUS
499 PsCreatePeb(HANDLE ProcessHandle,
500 PEPROCESS Process,
501 PVOID ImageBase)
502 {
503 ULONG AllocSize;
504 ULONG PebSize;
505 PPEB Peb;
506 LARGE_INTEGER SectionOffset;
507 ULONG ViewSize;
508 PVOID TableBase;
509 NTSTATUS Status;
510
511 PAGED_CODE();
512
513 /* Allocate the Process Environment Block (PEB) */
514 Process->TebBlock = (PVOID) MM_ROUND_DOWN(PEB_BASE, MM_VIRTMEM_GRANULARITY);
515 AllocSize = MM_VIRTMEM_GRANULARITY;
516 Status = NtAllocateVirtualMemory(ProcessHandle,
517 &Process->TebBlock,
518 0,
519 &AllocSize,
520 MEM_RESERVE,
521 PAGE_READWRITE);
522 if (!NT_SUCCESS(Status))
523 {
524 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
525 return(Status);
526 }
527 ASSERT((ULONG_PTR) Process->TebBlock <= PEB_BASE &&
528 PEB_BASE + PAGE_SIZE <= (ULONG_PTR) Process->TebBlock + AllocSize);
529 Peb = (PPEB)PEB_BASE;
530 PebSize = PAGE_SIZE;
531 Status = NtAllocateVirtualMemory(ProcessHandle,
532 (PVOID*)&Peb,
533 0,
534 &PebSize,
535 MEM_COMMIT,
536 PAGE_READWRITE);
537 if (!NT_SUCCESS(Status))
538 {
539 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
540 return(Status);
541 }
542 DPRINT("Peb %p PebSize %lu\n", Peb, PebSize);
543 ASSERT((PPEB) PEB_BASE == Peb && PAGE_SIZE <= PebSize);
544 Process->TebLastAllocated = (PVOID) Peb;
545
546 ViewSize = 0;
547 SectionOffset.QuadPart = (ULONGLONG)0;
548 TableBase = NULL;
549 Status = MmMapViewOfSection(NlsSectionObject,
550 Process,
551 &TableBase,
552 0,
553 0,
554 &SectionOffset,
555 &ViewSize,
556 ViewShare,
557 MEM_TOP_DOWN,
558 PAGE_READONLY);
559 if (!NT_SUCCESS(Status))
560 {
561 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
562 return(Status);
563 }
564 DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
565
566 KeAttachProcess(&Process->Pcb);
567
568 /* Initialize the PEB */
569 RtlZeroMemory(Peb, sizeof(PEB));
570 Peb->ImageBaseAddress = ImageBase;
571
572 Peb->OSMajorVersion = 4;
573 Peb->OSMinorVersion = 0;
574 Peb->OSBuildNumber = 1381;
575 Peb->OSPlatformId = 2; //VER_PLATFORM_WIN32_NT;
576 Peb->OSCSDVersion = 6 << 8;
577
578 Peb->AnsiCodePageData = (char*)TableBase + NlsAnsiTableOffset;
579 Peb->OemCodePageData = (char*)TableBase + NlsOemTableOffset;
580 Peb->UnicodeCaseTableData = (char*)TableBase + NlsUnicodeTableOffset;
581
582 Process->Peb = Peb;
583 KeDetachProcess();
584
585 DPRINT("PsCreatePeb: Peb created at %p\n", Peb);
586
587 return(STATUS_SUCCESS);
588 }
589
590
591 PKPROCESS
592 KeGetCurrentProcess(VOID)
593 /*
594 * FUNCTION: Returns a pointer to the current process
595 */
596 {
597 return(&(PsGetCurrentProcess()->Pcb));
598 }
599
600 /*
601 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
602 * ULONG ProcessId! (Skywing)
603 */
604 /*
605 * @implemented
606 */
607 HANDLE STDCALL
608 PsGetCurrentProcessId(VOID)
609 {
610 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
611 }
612
613 /*
614 * @unimplemented
615 */
616 ULONG
617 STDCALL
618 PsGetCurrentProcessSessionId (
619 VOID
620 )
621 {
622 return PsGetCurrentProcess()->SessionId;
623 }
624
625 /*
626 * FUNCTION: Returns a pointer to the current process
627 *
628 * @implemented
629 */
630 PEPROCESS STDCALL
631 IoGetCurrentProcess(VOID)
632 {
633 if (PsGetCurrentThread() == NULL ||
634 PsGetCurrentThread()->Tcb.ApcState.Process == NULL)
635 {
636 return(PsInitialSystemProcess);
637 }
638 else
639 {
640 return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process);
641 }
642 }
643
644 NTSTATUS
645 PspCreateProcess(OUT PHANDLE ProcessHandle,
646 IN ACCESS_MASK DesiredAccess,
647 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
648 IN HANDLE ParentProcess OPTIONAL,
649 IN BOOLEAN InheritObjectTable,
650 IN HANDLE SectionHandle OPTIONAL,
651 IN HANDLE DebugPort OPTIONAL,
652 IN HANDLE ExceptionPort OPTIONAL)
653 {
654 HANDLE hProcess;
655 PEPROCESS Process;
656 PEPROCESS pParentProcess;
657 PKPROCESS KProcess;
658 PVOID LdrStartupAddr;
659 PVOID BaseAddress;
660 PMEMORY_AREA MemoryArea;
661 PHYSICAL_ADDRESS BoundaryAddressMultiple;
662 KPROCESSOR_MODE PreviousMode;
663 PVOID ImageBase = NULL;
664 PEPORT pDebugPort = NULL;
665 PEPORT pExceptionPort = NULL;
666 PSECTION_OBJECT SectionObject = NULL;
667 NTSTATUS Status = STATUS_SUCCESS;
668
669 DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes);
670
671 PreviousMode = ExGetPreviousMode();
672
673 BoundaryAddressMultiple.QuadPart = 0;
674
675 if(ParentProcess != NULL)
676 {
677 Status = ObReferenceObjectByHandle(ParentProcess,
678 PROCESS_CREATE_PROCESS,
679 PsProcessType,
680 PreviousMode,
681 (PVOID*)&pParentProcess,
682 NULL);
683 if (!NT_SUCCESS(Status))
684 {
685 DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status);
686 return(Status);
687 }
688 }
689 else
690 {
691 pParentProcess = NULL;
692 }
693
694 /*
695 * Add the debug port
696 */
697 if (DebugPort != NULL)
698 {
699 Status = ObReferenceObjectByHandle(DebugPort,
700 PORT_ALL_ACCESS,
701 LpcPortObjectType,
702 PreviousMode,
703 (PVOID*)&pDebugPort,
704 NULL);
705 if (!NT_SUCCESS(Status))
706 {
707 DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status);
708 goto exitdereferenceobjects;
709 }
710 }
711
712 /*
713 * Add the exception port
714 */
715 if (ExceptionPort != NULL)
716 {
717 Status = ObReferenceObjectByHandle(ExceptionPort,
718 PORT_ALL_ACCESS,
719 LpcPortObjectType,
720 PreviousMode,
721 (PVOID*)&pExceptionPort,
722 NULL);
723 if (!NT_SUCCESS(Status))
724 {
725 DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status);
726 goto exitdereferenceobjects;
727 }
728 }
729
730 if (SectionHandle != NULL)
731 {
732 Status = ObReferenceObjectByHandle(SectionHandle,
733 0,
734 MmSectionObjectType,
735 PreviousMode,
736 (PVOID*)&SectionObject,
737 NULL);
738 if (!NT_SUCCESS(Status))
739 {
740 DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status);
741 goto exitdereferenceobjects;
742 }
743 }
744
745 Status = ObCreateObject(PreviousMode,
746 PsProcessType,
747 ObjectAttributes,
748 PreviousMode,
749 NULL,
750 sizeof(EPROCESS),
751 0,
752 0,
753 (PVOID*)&Process);
754 if (!NT_SUCCESS(Status))
755 {
756 DPRINT1("Failed to create process object, Status: 0x%x\n", Status);
757
758 exitdereferenceobjects:
759 if(SectionObject != NULL)
760 ObDereferenceObject(SectionObject);
761 if(pExceptionPort != NULL)
762 ObDereferenceObject(pExceptionPort);
763 if(pDebugPort != NULL)
764 ObDereferenceObject(pDebugPort);
765 if(pParentProcess != NULL)
766 ObDereferenceObject(pParentProcess);
767 return Status;
768 }
769
770 KProcess = &Process->Pcb;
771
772 RtlZeroMemory(Process, sizeof(EPROCESS));
773
774 Status = PsCreateCidHandle(Process,
775 PsProcessType,
776 &Process->UniqueProcessId);
777 if(!NT_SUCCESS(Status))
778 {
779 DPRINT1("Failed to create CID handle (unique process ID)! Status: 0x%x\n", Status);
780 ObDereferenceObject(Process);
781 goto exitdereferenceobjects;
782 }
783
784 Process->DebugPort = pDebugPort;
785 Process->ExceptionPort = pExceptionPort;
786
787 if(SectionObject != NULL)
788 {
789 UNICODE_STRING FileName;
790 PWCHAR szSrc;
791 PCHAR szDest;
792 USHORT lnFName = 0;
793
794 /*
795 * Determine the image file name and save it to the EPROCESS structure
796 */
797
798 FileName = SectionObject->FileObject->FileName;
799 szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1);
800 while(szSrc >= FileName.Buffer)
801 {
802 if(*szSrc == L'\\')
803 {
804 szSrc++;
805 break;
806 }
807 else
808 {
809 szSrc--;
810 lnFName++;
811 }
812 }
813
814 /* copy the image file name to the process and truncate it to 15 characters
815 if necessary */
816 szDest = Process->ImageFileName;
817 lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
818 while(lnFName-- > 0)
819 {
820 *(szDest++) = (UCHAR)*(szSrc++);
821 }
822 /* *szDest = '\0'; */
823 }
824
825 KeInitializeDispatcherHeader(&KProcess->DispatcherHeader,
826 InternalProcessType,
827 sizeof(EPROCESS),
828 FALSE);
829
830 /* Inherit parent process's affinity. */
831 if(pParentProcess != NULL)
832 {
833 KProcess->Affinity = pParentProcess->Pcb.Affinity;
834 Process->InheritedFromUniqueProcessId = pParentProcess->UniqueProcessId;
835 Process->SessionId = pParentProcess->SessionId;
836 }
837 else
838 {
839 KProcess->Affinity = KeActiveProcessors;
840 }
841
842 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
843 KProcess->IopmOffset = 0xffff;
844 KProcess->LdtDescriptor[0] = 0;
845 KProcess->LdtDescriptor[1] = 0;
846 InitializeListHead(&KProcess->ThreadListHead);
847 KProcess->ThreadQuantum = 6;
848 KProcess->AutoAlignment = 0;
849 MmInitializeAddressSpace(Process,
850 &Process->AddressSpace);
851
852 ObCreateHandleTable(pParentProcess,
853 InheritObjectTable,
854 Process);
855 MmCopyMmInfo(pParentProcess ? pParentProcess : PsInitialSystemProcess, Process);
856
857 KeInitializeEvent(&Process->LockEvent, SynchronizationEvent, FALSE);
858 Process->LockCount = 0;
859 Process->LockOwner = NULL;
860
861 Process->Win32WindowStation = (HANDLE)0;
862
863 ExAcquireFastMutex(&PspActiveProcessMutex);
864 InsertHeadList(&PsActiveProcessHead, &Process->ProcessListEntry);
865 InitializeListHead(&Process->ThreadListHead);
866 ExReleaseFastMutex(&PspActiveProcessMutex);
867
868 ExInitializeFastMutex(&Process->TebLock);
869 Process->Pcb.State = PROCESS_STATE_ACTIVE;
870
871 /*
872 * Now we have created the process proper
873 */
874
875 MmLockAddressSpace(&Process->AddressSpace);
876
877 /* Protect the highest 64KB of the process address space */
878 BaseAddress = (PVOID)MmUserProbeAddress;
879 Status = MmCreateMemoryArea(Process,
880 &Process->AddressSpace,
881 MEMORY_AREA_NO_ACCESS,
882 &BaseAddress,
883 0x10000,
884 PAGE_NOACCESS,
885 &MemoryArea,
886 FALSE,
887 FALSE,
888 BoundaryAddressMultiple);
889 if (!NT_SUCCESS(Status))
890 {
891 MmUnlockAddressSpace(&Process->AddressSpace);
892 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
893 ObDereferenceObject(Process);
894 goto exitdereferenceobjects;
895 }
896
897 /* Protect the lowest 64KB of the process address space */
898 #if 0
899 BaseAddress = (PVOID)0x00000000;
900 Status = MmCreateMemoryArea(Process,
901 &Process->AddressSpace,
902 MEMORY_AREA_NO_ACCESS,
903 &BaseAddress,
904 0x10000,
905 PAGE_NOACCESS,
906 &MemoryArea,
907 FALSE,
908 FALSE,
909 BoundaryAddressMultiple);
910 if (!NT_SUCCESS(Status))
911 {
912 MmUnlockAddressSpace(&Process->AddressSpace);
913 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
914 ObDereferenceObject(Process);
915 goto exitdereferenceobjects;
916 }
917 #endif
918
919 /* Protect the 60KB above the shared user page */
920 BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
921 Status = MmCreateMemoryArea(Process,
922 &Process->AddressSpace,
923 MEMORY_AREA_NO_ACCESS,
924 &BaseAddress,
925 0x10000 - PAGE_SIZE,
926 PAGE_NOACCESS,
927 &MemoryArea,
928 FALSE,
929 FALSE,
930 BoundaryAddressMultiple);
931 if (!NT_SUCCESS(Status))
932 {
933 MmUnlockAddressSpace(&Process->AddressSpace);
934 DPRINT1("Failed to protect the memory above the shared user page\n");
935 ObDereferenceObject(Process);
936 goto exitdereferenceobjects;
937 }
938
939 /* Create the shared data page */
940 BaseAddress = (PVOID)USER_SHARED_DATA;
941 Status = MmCreateMemoryArea(Process,
942 &Process->AddressSpace,
943 MEMORY_AREA_SHARED_DATA,
944 &BaseAddress,
945 PAGE_SIZE,
946 PAGE_READONLY,
947 &MemoryArea,
948 FALSE,
949 FALSE,
950 BoundaryAddressMultiple);
951 MmUnlockAddressSpace(&Process->AddressSpace);
952 if (!NT_SUCCESS(Status))
953 {
954 DPRINT1("Failed to create shared data page\n");
955 ObDereferenceObject(Process);
956 goto exitdereferenceobjects;
957 }
958
959 #if 1
960 /*
961 * FIXME - the handle should be created after all things are initialized, NOT HERE!
962 */
963 Status = ObInsertObject ((PVOID)Process,
964 NULL,
965 DesiredAccess,
966 0,
967 NULL,
968 &hProcess);
969 if (!NT_SUCCESS(Status))
970 {
971 DPRINT1("Failed to create a handle for the process\n");
972 ObDereferenceObject(Process);
973 goto exitdereferenceobjects;
974 }
975 #endif
976
977 /*
978 * FIXME - Map ntdll
979 */
980 Status = LdrpMapSystemDll(hProcess, /* FIXME - hProcess shouldn't be available at this point! */
981 &LdrStartupAddr);
982 if (!NT_SUCCESS(Status))
983 {
984 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
985 ObDereferenceObject(Process);
986 goto exitdereferenceobjects;
987 }
988
989 /*
990 * Map the process image
991 */
992 if (SectionObject != NULL)
993 {
994 ULONG ViewSize = 0;
995 DPRINT("Mapping process image\n");
996 Status = MmMapViewOfSection(SectionObject,
997 Process,
998 (PVOID*)&ImageBase,
999 0,
1000 ViewSize,
1001 NULL,
1002 &ViewSize,
1003 0,
1004 MEM_COMMIT,
1005 PAGE_READWRITE);
1006 ObDereferenceObject(SectionObject);
1007 if (!NT_SUCCESS(Status))
1008 {
1009 DbgPrint("Failed to map the process section (Status %x)\n", Status);
1010 ObDereferenceObject(Process);
1011 goto exitdereferenceobjects;
1012 }
1013 }
1014
1015 if(pParentProcess != NULL)
1016 {
1017 /*
1018 * Duplicate the token
1019 */
1020 Status = SepInitializeNewProcess(Process, pParentProcess);
1021 if (!NT_SUCCESS(Status))
1022 {
1023 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
1024 ObDereferenceObject(Process);
1025 goto exitdereferenceobjects;
1026 }
1027 }
1028 else
1029 {
1030 /* FIXME */
1031 }
1032
1033 /*
1034 * FIXME - Create PEB
1035 */
1036 DPRINT("Creating PEB\n");
1037 Status = PsCreatePeb(hProcess, /* FIXME - hProcess shouldn't be available at this point! */
1038 Process,
1039 ImageBase);
1040 if (!NT_SUCCESS(Status))
1041 {
1042 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
1043 ObDereferenceObject(Process);
1044 goto exitdereferenceobjects;
1045 }
1046
1047 /*
1048 * Maybe send a message to the creator process's debugger
1049 */
1050 #if 0
1051 if (pParentProcess->DebugPort != NULL)
1052 {
1053 LPC_DBG_MESSAGE Message;
1054 HANDLE FileHandle;
1055
1056 ObCreateHandle(NULL, // Debugger Process
1057 NULL, // SectionHandle
1058 FILE_ALL_ACCESS,
1059 FALSE,
1060 &FileHandle);
1061
1062 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
1063 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
1064 sizeof(LPC_MESSAGE);
1065 Message.Type = DBG_EVENT_CREATE_PROCESS;
1066 Message.Data.CreateProcess.FileHandle = FileHandle;
1067 Message.Data.CreateProcess.Base = ImageBase;
1068 Message.Data.CreateProcess.EntryPoint = NULL; //
1069
1070 Status = LpcSendDebugMessagePort(pParentProcess->DebugPort,
1071 &Message);
1072 }
1073 #endif
1074
1075 PspRunCreateProcessNotifyRoutines(Process, TRUE);
1076
1077 /*
1078 * FIXME - the handle should be created not before this point!
1079 */
1080 #if 0
1081 Status = ObInsertObject ((PVOID)Process,
1082 NULL,
1083 DesiredAccess,
1084 0,
1085 NULL,
1086 &hProcess);
1087 #endif
1088 if (NT_SUCCESS(Status))
1089 {
1090 _SEH_TRY
1091 {
1092 *ProcessHandle = hProcess;
1093 }
1094 _SEH_HANDLE
1095 {
1096 Status = _SEH_GetExceptionCode();
1097 }
1098 _SEH_END;
1099 }
1100
1101 /*
1102 * don't dereference the debug port, exception port and section object even
1103 * if ObInsertObject() failed, the process is alive! We just couldn't return
1104 * the handle to the caller!
1105 */
1106
1107 ObDereferenceObject(Process);
1108 if(pParentProcess != NULL)
1109 ObDereferenceObject(pParentProcess);
1110
1111 return Status;
1112 }
1113
1114
1115 /*
1116 * @implemented
1117 */
1118 NTSTATUS STDCALL
1119 PsCreateSystemProcess(PHANDLE ProcessHandle,
1120 ACCESS_MASK DesiredAccess,
1121 POBJECT_ATTRIBUTES ObjectAttributes)
1122 {
1123 return PspCreateProcess(ProcessHandle,
1124 DesiredAccess,
1125 ObjectAttributes,
1126 NULL, /* no parent process */
1127 FALSE,
1128 NULL,
1129 NULL,
1130 NULL);
1131 }
1132
1133
1134 /*
1135 * @implemented
1136 */
1137 NTSTATUS STDCALL
1138 NtCreateProcess(OUT PHANDLE ProcessHandle,
1139 IN ACCESS_MASK DesiredAccess,
1140 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
1141 IN HANDLE ParentProcess,
1142 IN BOOLEAN InheritObjectTable,
1143 IN HANDLE SectionHandle OPTIONAL,
1144 IN HANDLE DebugPort OPTIONAL,
1145 IN HANDLE ExceptionPort OPTIONAL)
1146 /*
1147 * FUNCTION: Creates a process.
1148 * ARGUMENTS:
1149 * ProcessHandle (OUT) = Caller supplied storage for the resulting
1150 * handle
1151 * DesiredAccess = Specifies the allowed or desired access to the
1152 * process can be a combination of
1153 * STANDARD_RIGHTS_REQUIRED| ..
1154 * ObjectAttribute = Initialized attributes for the object, contains
1155 * the rootdirectory and the filename
1156 * ParentProcess = Handle to the parent process.
1157 * InheritObjectTable = Specifies to inherit the objects of the parent
1158 * process if true.
1159 * SectionHandle = Handle to a section object to back the image file
1160 * DebugPort = Handle to a DebugPort if NULL the system default debug
1161 * port will be used.
1162 * ExceptionPort = Handle to a exception port.
1163 * REMARKS:
1164 * This function maps to the win32 CreateProcess.
1165 * RETURNS: Status
1166 */
1167 {
1168 KPROCESSOR_MODE PreviousMode;
1169 NTSTATUS Status = STATUS_SUCCESS;
1170
1171 PAGED_CODE();
1172
1173 PreviousMode = ExGetPreviousMode();
1174
1175 if(PreviousMode != KernelMode)
1176 {
1177 _SEH_TRY
1178 {
1179 ProbeForWrite(ProcessHandle,
1180 sizeof(HANDLE),
1181 sizeof(ULONG));
1182 }
1183 _SEH_HANDLE
1184 {
1185 Status = _SEH_GetExceptionCode();
1186 }
1187 _SEH_END;
1188
1189 if(!NT_SUCCESS(Status))
1190 {
1191 return Status;
1192 }
1193 }
1194
1195 if(ParentProcess == NULL)
1196 {
1197 Status = STATUS_INVALID_PARAMETER;
1198 }
1199 else
1200 {
1201 Status = PspCreateProcess(ProcessHandle,
1202 DesiredAccess,
1203 ObjectAttributes,
1204 ParentProcess,
1205 InheritObjectTable,
1206 SectionHandle,
1207 DebugPort,
1208 ExceptionPort);
1209 }
1210
1211 return Status;
1212 }
1213
1214
1215 /*
1216 * @unimplemented
1217 */
1218 NTSTATUS STDCALL
1219 NtOpenProcess(OUT PHANDLE ProcessHandle,
1220 IN ACCESS_MASK DesiredAccess,
1221 IN POBJECT_ATTRIBUTES ObjectAttributes,
1222 IN PCLIENT_ID ClientId)
1223 {
1224 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1225 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1226 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
1227 ClientId->UniqueProcess, ClientId->UniqueThread);
1228
1229 PAGED_CODE();
1230
1231 /*
1232 * Not sure of the exact semantics
1233 */
1234 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
1235 ObjectAttributes->ObjectName->Buffer != NULL)
1236 {
1237 NTSTATUS Status;
1238 PEPROCESS Process;
1239
1240 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
1241 ObjectAttributes->Attributes,
1242 NULL,
1243 DesiredAccess,
1244 PsProcessType,
1245 UserMode,
1246 NULL,
1247 (PVOID*)&Process);
1248 if (Status != STATUS_SUCCESS)
1249 {
1250 return(Status);
1251 }
1252
1253 Status = ObCreateHandle(PsGetCurrentProcess(),
1254 Process,
1255 DesiredAccess,
1256 FALSE,
1257 ProcessHandle);
1258 ObDereferenceObject(Process);
1259
1260 return(Status);
1261 }
1262 else
1263 {
1264 PLIST_ENTRY current_entry;
1265 PEPROCESS current;
1266 NTSTATUS Status;
1267
1268 ExAcquireFastMutex(&PspActiveProcessMutex);
1269 current_entry = PsActiveProcessHead.Flink;
1270 while (current_entry != &PsActiveProcessHead)
1271 {
1272 current = CONTAINING_RECORD(current_entry, EPROCESS,
1273 ProcessListEntry);
1274 if (current->UniqueProcessId == ClientId->UniqueProcess)
1275 {
1276 if (current->Pcb.State == PROCESS_STATE_TERMINATED)
1277 {
1278 Status = STATUS_PROCESS_IS_TERMINATING;
1279 }
1280 else
1281 {
1282 Status = ObReferenceObjectByPointer(current,
1283 DesiredAccess,
1284 PsProcessType,
1285 UserMode);
1286 }
1287 ExReleaseFastMutex(&PspActiveProcessMutex);
1288 if (NT_SUCCESS(Status))
1289 {
1290 Status = ObCreateHandle(PsGetCurrentProcess(),
1291 current,
1292 DesiredAccess,
1293 FALSE,
1294 ProcessHandle);
1295 ObDereferenceObject(current);
1296 DPRINT("*ProcessHandle %x\n", ProcessHandle);
1297 DPRINT("NtOpenProcess() = %x\n", Status);
1298 }
1299 return(Status);
1300 }
1301 current_entry = current_entry->Flink;
1302 }
1303 ExReleaseFastMutex(&PspActiveProcessMutex);
1304 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1305 return(STATUS_UNSUCCESSFUL);
1306 }
1307 return(STATUS_UNSUCCESSFUL);
1308 }
1309
1310
1311 /*
1312 * @unimplemented
1313 */
1314 NTSTATUS STDCALL
1315 NtQueryInformationProcess(IN HANDLE ProcessHandle,
1316 IN PROCESSINFOCLASS ProcessInformationClass,
1317 OUT PVOID ProcessInformation,
1318 IN ULONG ProcessInformationLength,
1319 OUT PULONG ReturnLength OPTIONAL)
1320 {
1321 PEPROCESS Process;
1322 KPROCESSOR_MODE PreviousMode;
1323 NTSTATUS Status = STATUS_SUCCESS;
1324
1325 PAGED_CODE();
1326
1327 PreviousMode = ExGetPreviousMode();
1328
1329 DefaultQueryInfoBufferCheck(ProcessInformationClass,
1330 PsProcessInfoClass,
1331 ProcessInformation,
1332 ProcessInformationLength,
1333 ReturnLength,
1334 PreviousMode,
1335 &Status);
1336 if(!NT_SUCCESS(Status))
1337 {
1338 DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status);
1339 return Status;
1340 }
1341
1342 /*
1343 * TODO: Here we should probably check that ProcessInformationLength
1344 * bytes indeed are writable at address ProcessInformation.
1345 */
1346
1347 Status = ObReferenceObjectByHandle(ProcessHandle,
1348 PROCESS_QUERY_INFORMATION,
1349 PsProcessType,
1350 PreviousMode,
1351 (PVOID*)&Process,
1352 NULL);
1353 if (!NT_SUCCESS(Status))
1354 {
1355 return(Status);
1356 }
1357
1358 switch (ProcessInformationClass)
1359 {
1360 case ProcessBasicInformation:
1361 {
1362 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP =
1363 (PPROCESS_BASIC_INFORMATION)ProcessInformation;
1364
1365 _SEH_TRY
1366 {
1367 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
1368 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
1369 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
1370 ProcessBasicInformationP->UniqueProcessId =
1371 Process->UniqueProcessId;
1372 ProcessBasicInformationP->InheritedFromUniqueProcessId =
1373 Process->InheritedFromUniqueProcessId;
1374 ProcessBasicInformationP->BasePriority =
1375 Process->Pcb.BasePriority;
1376
1377 if (ReturnLength)
1378 {
1379 *ReturnLength = sizeof(PROCESS_BASIC_INFORMATION);
1380 }
1381 }
1382 _SEH_HANDLE
1383 {
1384 Status = _SEH_GetExceptionCode();
1385 }
1386 _SEH_END;
1387 break;
1388 }
1389
1390 case ProcessQuotaLimits:
1391 case ProcessIoCounters:
1392 Status = STATUS_NOT_IMPLEMENTED;
1393 break;
1394
1395 case ProcessTimes:
1396 {
1397 PKERNEL_USER_TIMES ProcessTimeP = (PKERNEL_USER_TIMES)ProcessInformation;
1398 _SEH_TRY
1399 {
1400 ProcessTimeP->CreateTime = Process->CreateTime;
1401 ProcessTimeP->UserTime.QuadPart = Process->Pcb.UserTime * 100000LL;
1402 ProcessTimeP->KernelTime.QuadPart = Process->Pcb.KernelTime * 100000LL;
1403 ProcessTimeP->ExitTime = Process->ExitTime;
1404
1405 if (ReturnLength)
1406 {
1407 *ReturnLength = sizeof(KERNEL_USER_TIMES);
1408 }
1409 }
1410 _SEH_HANDLE
1411 {
1412 Status = _SEH_GetExceptionCode();
1413 }
1414 _SEH_END;
1415 break;
1416 }
1417
1418 case ProcessDebugPort:
1419 {
1420 _SEH_TRY
1421 {
1422 *(PHANDLE)ProcessInformation = (Process->DebugPort != NULL ? (HANDLE)-1 : NULL);
1423 if (ReturnLength)
1424 {
1425 *ReturnLength = sizeof(HANDLE);
1426 }
1427 }
1428 _SEH_HANDLE
1429 {
1430 Status = _SEH_GetExceptionCode();
1431 }
1432 _SEH_END;
1433 break;
1434 }
1435
1436 case ProcessLdtInformation:
1437 case ProcessWorkingSetWatch:
1438 case ProcessWx86Information:
1439 Status = STATUS_NOT_IMPLEMENTED;
1440 break;
1441
1442 case ProcessHandleCount:
1443 {
1444 ULONG HandleCount = ObpGetHandleCountByHandleTable(&Process->HandleTable);
1445
1446 _SEH_TRY
1447 {
1448 *(PULONG)ProcessInformation = HandleCount;
1449 if (ReturnLength)
1450 {
1451 *ReturnLength = sizeof(ULONG);
1452 }
1453 }
1454 _SEH_HANDLE
1455 {
1456 Status = _SEH_GetExceptionCode();
1457 }
1458 _SEH_END;
1459 break;
1460 }
1461
1462 case ProcessSessionInformation:
1463 {
1464 PPROCESS_SESSION_INFORMATION SessionInfo = (PPROCESS_SESSION_INFORMATION)ProcessInformation;
1465
1466 _SEH_TRY
1467 {
1468 SessionInfo->SessionId = Process->SessionId;
1469 if (ReturnLength)
1470 {
1471 *ReturnLength = sizeof(PROCESS_SESSION_INFORMATION);
1472 }
1473 }
1474 _SEH_HANDLE
1475 {
1476 Status = _SEH_GetExceptionCode();
1477 }
1478 _SEH_END;
1479 break;
1480 }
1481
1482 case ProcessWow64Information:
1483 DPRINT1("We currently don't support the ProcessWow64Information information class!\n");
1484 Status = STATUS_NOT_IMPLEMENTED;
1485 break;
1486
1487 case ProcessVmCounters:
1488 {
1489 PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation;
1490
1491 _SEH_TRY
1492 {
1493 pOut->PeakVirtualSize = Process->PeakVirtualSize;
1494 /*
1495 * Here we should probably use VirtualSize.LowPart, but due to
1496 * incompatibilities in current headers (no unnamed union),
1497 * I opted for cast.
1498 */
1499 pOut->VirtualSize = (ULONG)Process->VirtualSize.QuadPart;
1500 pOut->PageFaultCount = Process->Vm.PageFaultCount;
1501 pOut->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
1502 pOut->WorkingSetSize = Process->Vm.WorkingSetSize;
1503 pOut->QuotaPeakPagedPoolUsage = Process->QuotaPeakPoolUsage[0]; // TODO: Verify!
1504 pOut->QuotaPagedPoolUsage = Process->QuotaPoolUsage[0]; // TODO: Verify!
1505 pOut->QuotaPeakNonPagedPoolUsage = Process->QuotaPeakPoolUsage[1]; // TODO: Verify!
1506 pOut->QuotaNonPagedPoolUsage = Process->QuotaPoolUsage[1]; // TODO: Verify!
1507 pOut->PagefileUsage = Process->PagefileUsage;
1508 pOut->PeakPagefileUsage = Process->PeakPagefileUsage;
1509
1510 if (ReturnLength)
1511 {
1512 *ReturnLength = sizeof(VM_COUNTERS);
1513 }
1514 }
1515 _SEH_HANDLE
1516 {
1517 Status = _SEH_GetExceptionCode();
1518 }
1519 _SEH_END;
1520 break;
1521 }
1522
1523 case ProcessDefaultHardErrorMode:
1524 {
1525 PULONG HardErrMode = (PULONG)ProcessInformation;
1526 _SEH_TRY
1527 {
1528 *HardErrMode = Process->DefaultHardErrorProcessing;
1529 if (ReturnLength)
1530 {
1531 *ReturnLength = sizeof(ULONG);
1532 }
1533 }
1534 _SEH_HANDLE
1535 {
1536 Status = _SEH_GetExceptionCode();
1537 }
1538 _SEH_END;
1539 break;
1540 }
1541
1542 case ProcessPriorityBoost:
1543 {
1544 PULONG BoostEnabled = (PULONG)ProcessInformation;
1545
1546 _SEH_TRY
1547 {
1548 *BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE;
1549
1550 if (ReturnLength)
1551 {
1552 *ReturnLength = sizeof(ULONG);
1553 }
1554 }
1555 _SEH_HANDLE
1556 {
1557 Status = _SEH_GetExceptionCode();
1558 }
1559 _SEH_END;
1560 break;
1561 }
1562
1563 case ProcessDeviceMap:
1564 {
1565 PROCESS_DEVICEMAP_INFORMATION DeviceMap;
1566
1567 ObQueryDeviceMapInformation(Process, &DeviceMap);
1568
1569 _SEH_TRY
1570 {
1571 *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
1572 if (ReturnLength)
1573 {
1574 *ReturnLength = sizeof(PROCESS_DEVICEMAP_INFORMATION);
1575 }
1576 }
1577 _SEH_HANDLE
1578 {
1579 Status = _SEH_GetExceptionCode();
1580 }
1581 _SEH_END;
1582 break;
1583 }
1584
1585 case ProcessPriorityClass:
1586 {
1587 PUSHORT Priority = (PUSHORT)ProcessInformation;
1588
1589 _SEH_TRY
1590 {
1591 *Priority = Process->PriorityClass;
1592
1593 if (ReturnLength)
1594 {
1595 *ReturnLength = sizeof(USHORT);
1596 }
1597 }
1598 _SEH_HANDLE
1599 {
1600 Status = _SEH_GetExceptionCode();
1601 }
1602 _SEH_END;
1603 break;
1604 }
1605
1606 case ProcessImageFileName:
1607 {
1608 /*
1609 * We DO NOT return the file name stored in the EPROCESS structure.
1610 * Propably if we can't find a PEB or ProcessParameters structure for the
1611 * process!
1612 */
1613 if(Process->Peb != NULL)
1614 {
1615 PRTL_USER_PROCESS_PARAMETERS ProcParams = NULL;
1616 UNICODE_STRING LocalDest;
1617 BOOLEAN Attached;
1618 ULONG ImagePathLen = 0;
1619 PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation;
1620
1621 /* we need to attach to the process to make sure we're in the right context! */
1622 Attached = Process != PsGetCurrentProcess();
1623
1624 if(Attached)
1625 KeAttachProcess(&Process->Pcb);
1626
1627 _SEH_TRY
1628 {
1629 ProcParams = Process->Peb->ProcessParameters;
1630 ImagePathLen = ProcParams->ImagePathName.Length;
1631 }
1632 _SEH_HANDLE
1633 {
1634 Status = _SEH_GetExceptionCode();
1635 }
1636 _SEH_END;
1637
1638 if(NT_SUCCESS(Status))
1639 {
1640 if(ProcessInformationLength < sizeof(UNICODE_STRING) + ImagePathLen + sizeof(WCHAR))
1641 {
1642 Status = STATUS_INFO_LENGTH_MISMATCH;
1643 }
1644 else
1645 {
1646 PWSTR StrSource = NULL;
1647
1648 /* create a DstPath structure on the stack */
1649 _SEH_TRY
1650 {
1651 LocalDest.Length = ImagePathLen;
1652 LocalDest.MaximumLength = ImagePathLen + sizeof(WCHAR);
1653 LocalDest.Buffer = (PWSTR)(DstPath + 1);
1654
1655 /* save a copy of the pointer to the source buffer */
1656 StrSource = ProcParams->ImagePathName.Buffer;
1657 }
1658 _SEH_HANDLE
1659 {
1660 Status = _SEH_GetExceptionCode();
1661 }
1662 _SEH_END;
1663
1664 if(NT_SUCCESS(Status))
1665 {
1666 /* now, let's allocate some anonymous memory to copy the string to.
1667 we can't just copy it to the buffer the caller pointed as it might
1668 be user memory in another context */
1669 PWSTR PathCopy = ExAllocatePool(PagedPool, LocalDest.Length + sizeof(WCHAR));
1670 if(PathCopy != NULL)
1671 {
1672 /* make a copy of the buffer to the temporary buffer */
1673 _SEH_TRY
1674 {
1675 RtlCopyMemory(PathCopy, StrSource, LocalDest.Length);
1676 PathCopy[LocalDest.Length / sizeof(WCHAR)] = L'\0';
1677 }
1678 _SEH_HANDLE
1679 {
1680 Status = _SEH_GetExceptionCode();
1681 }
1682 _SEH_END;
1683
1684 /* detach from the process */
1685 if(Attached)
1686 KeDetachProcess();
1687
1688 /* only copy the string back to the caller if we were able to
1689 copy it into the temporary buffer! */
1690 if(NT_SUCCESS(Status))
1691 {
1692 /* now let's copy the buffer back to the caller */
1693 _SEH_TRY
1694 {
1695 *DstPath = LocalDest;
1696 RtlCopyMemory(LocalDest.Buffer, PathCopy, LocalDest.Length + sizeof(WCHAR));
1697 if (ReturnLength)
1698 {
1699 *ReturnLength = sizeof(UNICODE_STRING) + LocalDest.Length + sizeof(WCHAR);
1700 }
1701 }
1702 _SEH_HANDLE
1703 {
1704 Status = _SEH_GetExceptionCode();
1705 }
1706 _SEH_END;
1707 }
1708
1709 /* we're done with the copy operation, free the temporary kernel buffer */
1710 ExFreePool(PathCopy);
1711
1712 /* we need to bail because we're already detached from the process */
1713 break;
1714 }
1715 else
1716 {
1717 Status = STATUS_INSUFFICIENT_RESOURCES;
1718 }
1719 }
1720 }
1721 }
1722
1723 /* don't forget to detach from the process!!! */
1724 if(Attached)
1725 KeDetachProcess();
1726 }
1727 else
1728 {
1729 /* FIXME - what to do here? */
1730 Status = STATUS_UNSUCCESSFUL;
1731 }
1732 break;
1733 }
1734
1735 /*
1736 * Note: The following 10 information classes are verified to not be
1737 * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
1738 */
1739 case ProcessBasePriority:
1740 case ProcessRaisePriority:
1741 case ProcessExceptionPort:
1742 case ProcessAccessToken:
1743 case ProcessLdtSize:
1744 case ProcessIoPortHandlers:
1745 case ProcessUserModeIOPL:
1746 case ProcessEnableAlignmentFaultFixup:
1747 case ProcessAffinityMask:
1748 case ProcessForegroundInformation:
1749 default:
1750 Status = STATUS_INVALID_INFO_CLASS;
1751 }
1752
1753 ObDereferenceObject(Process);
1754 return Status;
1755 }
1756
1757
1758 NTSTATUS
1759 PspAssignPrimaryToken(PEPROCESS Process,
1760 HANDLE TokenHandle)
1761 {
1762 PACCESS_TOKEN Token;
1763 PACCESS_TOKEN OldToken;
1764 NTSTATUS Status;
1765
1766 Status = ObReferenceObjectByHandle(TokenHandle,
1767 0,
1768 SepTokenObjectType,
1769 UserMode,
1770 (PVOID*)&Token,
1771 NULL);
1772 if (!NT_SUCCESS(Status))
1773 {
1774 return(Status);
1775 }
1776 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
1777 if (NT_SUCCESS(Status))
1778 {
1779 ObDereferenceObject(OldToken);
1780 }
1781 ObDereferenceObject(Token);
1782 return(Status);
1783 }
1784
1785 /*
1786 * @unimplemented
1787 */
1788 NTSTATUS STDCALL
1789 NtSetInformationProcess(IN HANDLE ProcessHandle,
1790 IN PROCESSINFOCLASS ProcessInformationClass,
1791 IN PVOID ProcessInformation,
1792 IN ULONG ProcessInformationLength)
1793 {
1794 PEPROCESS Process;
1795 KPROCESSOR_MODE PreviousMode;
1796 ACCESS_MASK Access;
1797 NTSTATUS Status = STATUS_SUCCESS;
1798
1799 PAGED_CODE();
1800
1801 PreviousMode = ExGetPreviousMode();
1802
1803 DefaultSetInfoBufferCheck(ProcessInformationClass,
1804 PsProcessInfoClass,
1805 ProcessInformation,
1806 ProcessInformationLength,
1807 PreviousMode,
1808 &Status);
1809 if(!NT_SUCCESS(Status))
1810 {
1811 DPRINT1("NtSetInformationProcess() %d %x %x called\n", ProcessInformationClass, ProcessInformation, ProcessInformationLength);
1812 DPRINT1("NtSetInformationProcess() %x failed, Status: 0x%x\n", Status);
1813 return Status;
1814 }
1815
1816 switch(ProcessInformationClass)
1817 {
1818 case ProcessSessionInformation:
1819 Access = PROCESS_SET_INFORMATION | PROCESS_SET_SESSIONID;
1820 break;
1821 case ProcessExceptionPort:
1822 case ProcessDebugPort:
1823 Access = PROCESS_SET_INFORMATION | PROCESS_SET_PORT;
1824 break;
1825
1826 default:
1827 Access = PROCESS_SET_INFORMATION;
1828 break;
1829 }
1830
1831 Status = ObReferenceObjectByHandle(ProcessHandle,
1832 Access,
1833 PsProcessType,
1834 PreviousMode,
1835 (PVOID*)&Process,
1836 NULL);
1837 if (!NT_SUCCESS(Status))
1838 {
1839 return(Status);
1840 }
1841
1842 switch (ProcessInformationClass)
1843 {
1844 case ProcessQuotaLimits:
1845 case ProcessBasePriority:
1846 case ProcessRaisePriority:
1847 Status = STATUS_NOT_IMPLEMENTED;
1848 break;
1849
1850 case ProcessDebugPort:
1851 {
1852 HANDLE PortHandle = NULL;
1853
1854 /* make a safe copy of the buffer on the stack */
1855 _SEH_TRY
1856 {
1857 PortHandle = *(PHANDLE)ProcessInformation;
1858 Status = (PortHandle != NULL ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER);
1859 }
1860 _SEH_HANDLE
1861 {
1862 Status = _SEH_GetExceptionCode();
1863 }
1864 _SEH_END;
1865
1866 if(NT_SUCCESS(Status))
1867 {
1868 PEPORT DebugPort;
1869
1870 /* in case we had success reading from the buffer, verify the provided
1871 * LPC port handle
1872 */
1873 Status = ObReferenceObjectByHandle(PortHandle,
1874 0,
1875 LpcPortObjectType,
1876 PreviousMode,
1877 (PVOID)&DebugPort,
1878 NULL);
1879 if(NT_SUCCESS(Status))
1880 {
1881 /* lock the process to be thread-safe! */
1882
1883 Status = PsLockProcess(Process, FALSE);
1884 if(NT_SUCCESS(Status))
1885 {
1886 /*
1887 * according to "NT Native API" documentation, setting the debug
1888 * port is only permitted once!
1889 */
1890 if(Process->DebugPort == NULL)
1891 {
1892 /* keep the reference to the handle! */
1893 Process->DebugPort = DebugPort;
1894
1895 if(Process->Peb)
1896 {
1897 /* we're now debugging the process, so set the flag in the PEB
1898 structure. However, to access it we need to attach to the
1899 process so we're sure we're in the right context! */
1900
1901 KeAttachProcess(&Process->Pcb);
1902 _SEH_TRY
1903 {
1904 Process->Peb->BeingDebugged = TRUE;
1905 }
1906 _SEH_HANDLE
1907 {
1908 DPRINT1("Trying to set the Peb->BeingDebugged field of process 0x%x failed, exception: 0x%x\n", Process, _SEH_GetExceptionCode());
1909 }
1910 _SEH_END;
1911 KeDetachProcess();
1912 }
1913 Status = STATUS_SUCCESS;
1914 }
1915 else
1916 {
1917 ObDereferenceObject(DebugPort);
1918 Status = STATUS_PORT_ALREADY_SET;
1919 }
1920 PsUnlockProcess(Process);
1921 }
1922 else
1923 {
1924 ObDereferenceObject(DebugPort);
1925 }
1926 }
1927 }
1928 break;
1929 }
1930
1931 case ProcessExceptionPort:
1932 {
1933 HANDLE PortHandle = NULL;
1934
1935 /* make a safe copy of the buffer on the stack */
1936 _SEH_TRY
1937 {
1938 PortHandle = *(PHANDLE)ProcessInformation;
1939 Status = STATUS_SUCCESS;
1940 }
1941 _SEH_HANDLE
1942 {
1943 Status = _SEH_GetExceptionCode();
1944 }
1945 _SEH_END;
1946
1947 if(NT_SUCCESS(Status))
1948 {
1949 PEPORT ExceptionPort;
1950
1951 /* in case we had success reading from the buffer, verify the provided
1952 * LPC port handle
1953 */
1954 Status = ObReferenceObjectByHandle(PortHandle,
1955 0,
1956 LpcPortObjectType,
1957 PreviousMode,
1958 (PVOID)&ExceptionPort,
1959 NULL);
1960 if(NT_SUCCESS(Status))
1961 {
1962 /* lock the process to be thread-safe! */
1963
1964 Status = PsLockProcess(Process, FALSE);
1965 if(NT_SUCCESS(Status))
1966 {
1967 /*
1968 * according to "NT Native API" documentation, setting the exception
1969 * port is only permitted once!
1970 */
1971 if(Process->ExceptionPort == NULL)
1972 {
1973 /* keep the reference to the handle! */
1974 Process->ExceptionPort = ExceptionPort;
1975 Status = STATUS_SUCCESS;
1976 }
1977 else
1978 {
1979 ObDereferenceObject(ExceptionPort);
1980 Status = STATUS_PORT_ALREADY_SET;
1981 }
1982 PsUnlockProcess(Process);
1983 }
1984 else
1985 {
1986 ObDereferenceObject(ExceptionPort);
1987 }
1988 }
1989 }
1990 break;
1991 }
1992
1993 case ProcessAccessToken:
1994 {
1995 HANDLE TokenHandle = NULL;
1996
1997 /* make a safe copy of the buffer on the stack */
1998 _SEH_TRY
1999 {
2000 TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)->Token;
2001 Status = STATUS_SUCCESS;
2002 }
2003 _SEH_HANDLE
2004 {
2005 Status = _SEH_GetExceptionCode();
2006 }
2007 _SEH_END;
2008
2009 if(NT_SUCCESS(Status))
2010 {
2011 /* in case we had success reading from the buffer, perform the actual task */
2012 Status = PspAssignPrimaryToken(Process, TokenHandle);
2013 }
2014 break;
2015 }
2016
2017 case ProcessDefaultHardErrorMode:
2018 {
2019 _SEH_TRY
2020 {
2021 InterlockedExchange((LONG*)&Process->DefaultHardErrorProcessing,
2022 *(PLONG)ProcessInformation);
2023 Status = STATUS_SUCCESS;
2024 }
2025 _SEH_HANDLE
2026 {
2027 Status = _SEH_GetExceptionCode();
2028 }
2029 _SEH_END;
2030 break;
2031 }
2032
2033 case ProcessSessionInformation:
2034 {
2035 PROCESS_SESSION_INFORMATION SessionInfo;
2036 Status = STATUS_SUCCESS;
2037
2038 _SEH_TRY
2039 {
2040 /* copy the structure to the stack */
2041 SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation;
2042 }
2043 _SEH_HANDLE
2044 {
2045 Status = _SEH_GetExceptionCode();
2046 }
2047 _SEH_END;
2048
2049 if(NT_SUCCESS(Status))
2050 {
2051 /* we successfully copied the structure to the stack, continue processing */
2052
2053 /*
2054 * setting the session id requires the SeTcbPrivilege!
2055 */
2056 if(!SeSinglePrivilegeCheck(SeTcbPrivilege,
2057 PreviousMode))
2058 {
2059 DPRINT1("NtSetInformationProcess: Caller requires the SeTcbPrivilege privilege for setting ProcessSessionInformation!\n");
2060 /* can't set the session id, bail! */
2061 Status = STATUS_PRIVILEGE_NOT_HELD;
2062 break;
2063 }
2064
2065 /* FIXME - update the session id for the process token */
2066
2067 Status = PsLockProcess(Process, FALSE);
2068 if(NT_SUCCESS(Status))
2069 {
2070 Process->SessionId = SessionInfo.SessionId;
2071
2072 /* Update the session id in the PEB structure */
2073 if(Process->Peb != NULL)
2074 {
2075 /* we need to attach to the process to make sure we're in the right
2076 context to access the PEB structure */
2077 KeAttachProcess(&Process->Pcb);
2078
2079 _SEH_TRY
2080 {
2081 /* FIXME: Process->Peb->SessionId = SessionInfo.SessionId; */
2082
2083 Status = STATUS_SUCCESS;
2084 }
2085 _SEH_HANDLE
2086 {
2087 Status = _SEH_GetExceptionCode();
2088 }
2089 _SEH_END;
2090
2091 KeDetachProcess();
2092 }
2093
2094 PsUnlockProcess(Process);
2095 }
2096 }
2097 break;
2098 }
2099
2100 case ProcessPriorityClass:
2101 {
2102 PROCESS_PRIORITY_CLASS ppc;
2103
2104 _SEH_TRY
2105 {
2106 ppc = *(PPROCESS_PRIORITY_CLASS)ProcessInformation;
2107 }
2108 _SEH_HANDLE
2109 {
2110 Status = _SEH_GetExceptionCode();
2111 }
2112 _SEH_END;
2113
2114 if(NT_SUCCESS(Status))
2115 {
2116 }
2117
2118 break;
2119 }
2120
2121 case ProcessLdtInformation:
2122 case ProcessLdtSize:
2123 case ProcessIoPortHandlers:
2124 case ProcessWorkingSetWatch:
2125 case ProcessUserModeIOPL:
2126 case ProcessEnableAlignmentFaultFixup:
2127 case ProcessAffinityMask:
2128 Status = STATUS_NOT_IMPLEMENTED;
2129 break;
2130
2131 case ProcessBasicInformation:
2132 case ProcessIoCounters:
2133 case ProcessTimes:
2134 case ProcessPooledUsageAndLimits:
2135 case ProcessWx86Information:
2136 case ProcessHandleCount:
2137 case ProcessWow64Information:
2138 default:
2139 Status = STATUS_INVALID_INFO_CLASS;
2140 }
2141 ObDereferenceObject(Process);
2142 return(Status);
2143 }
2144
2145
2146 /**********************************************************************
2147 * NAME INTERNAL
2148 * PiQuerySystemProcessInformation
2149 *
2150 * DESCRIPTION
2151 * Compute the size of a process+thread snapshot as
2152 * expected by NtQuerySystemInformation.
2153 *
2154 * RETURN VALUE
2155 * 0 on error; otherwise the size, in bytes of the buffer
2156 * required to write a full snapshot.
2157 *
2158 * NOTE
2159 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
2160 */
2161 NTSTATUS
2162 PiQuerySystemProcessInformation(PVOID Buffer,
2163 ULONG Size,
2164 PULONG ReqSize)
2165 {
2166 return STATUS_NOT_IMPLEMENTED;
2167
2168 #if 0
2169 PLIST_ENTRY CurrentEntryP;
2170 PEPROCESS CurrentP;
2171 PLIST_ENTRY CurrentEntryT;
2172 PETHREAD CurrentT;
2173
2174 ULONG RequiredSize = 0L;
2175 BOOLEAN SizeOnly = FALSE;
2176
2177 ULONG SpiSize = 0L;
2178
2179 PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
2180 PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
2181 PSYSTEM_THREAD_INFO pInfoT = NULL;
2182
2183
2184 /* Lock the process list. */
2185 ExAcquireFastMutex(&PspActiveProcessMutex);
2186
2187 /*
2188 * Scan the process list. Since the
2189 * list is circular, the guard is false
2190 * after the last process.
2191 */
2192 for ( CurrentEntryP = PsActiveProcessHead.Flink;
2193 (CurrentEntryP != & PsActiveProcessHead);
2194 CurrentEntryP = CurrentEntryP->Flink
2195 )
2196 {
2197 /*
2198 * Compute how much space is
2199 * occupied in the snapshot
2200 * by adding this process info.
2201 * (at least one thread).
2202 */
2203 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
2204 RequiredSize += SpiSizeCurrent;
2205 /*
2206 * Do not write process data in the
2207 * buffer if it is too small.
2208 */
2209 if (TRUE == SizeOnly) continue;
2210 /*
2211 * Check if the buffer can contain
2212 * the full snapshot.
2213 */
2214 if (Size < RequiredSize)
2215 {
2216 SizeOnly = TRUE;
2217 continue;
2218 }
2219 /*
2220 * Get a reference to the
2221 * process descriptor we are
2222 * handling.
2223 */
2224 CurrentP = CONTAINING_RECORD(
2225 CurrentEntryP,
2226 EPROCESS,
2227 ProcessListEntry
2228 );
2229 /*
2230 * Write process data in the buffer.
2231 */
2232 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
2233 /* PROCESS */
2234 pInfoP->ThreadCount = 0L;
2235 pInfoP->ProcessId = CurrentP->UniqueProcessId;
2236 RtlInitUnicodeString (
2237 & pInfoP->Name,
2238 CurrentP->ImageFileName
2239 );
2240 /* THREAD */
2241 for ( pInfoT = & CurrentP->ThreadSysInfo [0],
2242 CurrentEntryT = CurrentP->ThreadListHead.Flink;
2243
2244 (CurrentEntryT != & CurrentP->ThreadListHead);
2245
2246 pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
2247 CurrentEntryT = CurrentEntryT->Flink
2248 )
2249 {
2250 /*
2251 * Recalculate the size of the
2252 * information block.
2253 */
2254 if (0 < pInfoP->ThreadCount)
2255 {
2256 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
2257 }
2258 /*
2259 * Do not write thread data in the
2260 * buffer if it is too small.
2261 */
2262 if (TRUE == SizeOnly) continue;
2263 /*
2264 * Check if the buffer can contain
2265 * the full snapshot.
2266 */
2267 if (Size < RequiredSize)
2268 {
2269 SizeOnly = TRUE;
2270 continue;
2271 }
2272 /*
2273 * Get a reference to the
2274 * thread descriptor we are
2275 * handling.
2276 */
2277 CurrentT = CONTAINING_RECORD(
2278 CurrentEntryT,
2279 KTHREAD,
2280 ThreadListEntry
2281 );
2282 /*
2283 * Write thread data.
2284 */
2285 RtlZeroMemory (
2286 pInfoT,
2287 sizeof (SYSTEM_THREAD_INFORMATION)
2288 );
2289 pInfoT->KernelTime = CurrentT-> ; /* TIME */
2290 pInfoT->UserTime = CurrentT-> ; /* TIME */
2291 pInfoT->CreateTime = CurrentT-> ; /* TIME */
2292 pInfoT->TickCount = CurrentT-> ; /* ULONG */
2293 pInfoT->StartEIP = CurrentT-> ; /* ULONG */
2294 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
2295 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
2296 pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
2297 pInfoT->BasePriority = CurrentT-> ; /* ULONG */
2298 pInfoT->nSwitches = CurrentT-> ; /* ULONG */
2299 pInfoT->State = CurrentT-> ; /* DWORD */
2300 pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
2301 /*
2302 * Count the number of threads
2303 * this process has.
2304 */
2305 ++ pInfoP->ThreadCount;
2306 }
2307 /*
2308 * Save the size of information
2309 * stored in the buffer for the
2310 * current process.
2311 */
2312 pInfoP->RelativeOffset = SpiSize;
2313 /*
2314 * Save a reference to the last
2315 * valid information block.
2316 */
2317 pInfoPLast = pInfoP;
2318 /*
2319 * Compute the offset of the
2320 * SYSTEM_PROCESS_INFORMATION
2321 * descriptor in the snapshot
2322 * buffer for the next process.
2323 */
2324 (ULONG) pInfoP += SpiSize;
2325 }
2326 /*
2327 * Unlock the process list.
2328 */
2329 ExReleaseFastMutex (
2330 & PspActiveProcessMutex
2331 );
2332 /*
2333 * Return the proper error status code,
2334 * if the buffer was too small.
2335 */
2336 if (TRUE == SizeOnly)
2337 {
2338 if (NULL != RequiredSize)
2339 {
2340 *pRequiredSize = RequiredSize;
2341 }
2342 return STATUS_INFO_LENGTH_MISMATCH;
2343 }
2344 /*
2345 * Mark the end of the snapshot.
2346 */
2347 pInfoP->RelativeOffset = 0L;
2348 /* OK */
2349 return STATUS_SUCCESS;
2350 #endif
2351 }
2352
2353 /*
2354 * @implemented
2355 */
2356 LARGE_INTEGER STDCALL
2357 PsGetProcessExitTime(VOID)
2358 {
2359 LARGE_INTEGER Li;
2360 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
2361 return Li;
2362 }
2363
2364 /*
2365 * @implemented
2366 */
2367 LONGLONG
2368 STDCALL
2369 PsGetProcessCreateTimeQuadPart(
2370 PEPROCESS Process
2371 )
2372 {
2373 return Process->CreateTime.QuadPart;
2374 }
2375
2376 /*
2377 * @implemented
2378 */
2379 PVOID
2380 STDCALL
2381 PsGetProcessDebugPort(
2382 PEPROCESS Process
2383 )
2384 {
2385 return Process->DebugPort;
2386 }
2387
2388 /*
2389 * @implemented
2390 */
2391 BOOLEAN
2392 STDCALL
2393 PsGetProcessExitProcessCalled(
2394 PEPROCESS Process
2395 )
2396 {
2397 return Process->ExitProcessCalled;
2398 }
2399
2400 /*
2401 * @implemented
2402 */
2403 NTSTATUS
2404 STDCALL
2405 PsGetProcessExitStatus(
2406 PEPROCESS Process
2407 )
2408 {
2409 return Process->ExitStatus;
2410 }
2411
2412 /*
2413 * @implemented
2414 */
2415 HANDLE
2416 STDCALL
2417 PsGetProcessId(
2418 PEPROCESS Process
2419 )
2420 {
2421 return (HANDLE)Process->UniqueProcessId;
2422 }
2423
2424 /*
2425 * @implemented
2426 */
2427 LPSTR
2428 STDCALL
2429 PsGetProcessImageFileName(
2430 PEPROCESS Process
2431 )
2432 {
2433 return (LPSTR)Process->ImageFileName;
2434 }
2435
2436 /*
2437 * @implemented
2438 */
2439 HANDLE
2440 STDCALL
2441 PsGetProcessInheritedFromUniqueProcessId(
2442 PEPROCESS Process
2443 )
2444 {
2445 return Process->InheritedFromUniqueProcessId;
2446 }
2447
2448 /*
2449 * @implemented
2450 */
2451 PEJOB
2452 STDCALL
2453 PsGetProcessJob(
2454 PEPROCESS Process
2455 )
2456 {
2457 return Process->Job;
2458 }
2459
2460 /*
2461 * @implemented
2462 */
2463 PPEB
2464 STDCALL
2465 PsGetProcessPeb(
2466 PEPROCESS Process
2467 )
2468 {
2469 return Process->Peb;
2470 }
2471
2472 /*
2473 * @implemented
2474 */
2475 ULONG
2476 STDCALL
2477 PsGetProcessPriorityClass(
2478 PEPROCESS Process
2479 )
2480 {
2481 return Process->PriorityClass;
2482 }
2483
2484 /*
2485 * @implemented
2486 */
2487 PVOID
2488 STDCALL
2489 PsGetProcessSectionBaseAddress(
2490 PEPROCESS Process
2491 )
2492 {
2493 return Process->SectionBaseAddress;
2494 }
2495
2496 /*
2497 * @implemented
2498 */
2499 PVOID
2500 STDCALL
2501 PsGetProcessSecurityPort(
2502 PEPROCESS Process
2503 )
2504 {
2505 return Process->SecurityPort;
2506 }
2507
2508 /*
2509 * @implemented
2510 */
2511 HANDLE
2512 STDCALL
2513 PsGetProcessSessionId(
2514 PEPROCESS Process
2515 )
2516 {
2517 return (HANDLE)Process->SessionId;
2518 }
2519
2520 /*
2521 * @implemented
2522 */
2523 PVOID
2524 STDCALL
2525 PsGetProcessWin32Process(
2526 PEPROCESS Process
2527 )
2528 {
2529 return Process->Win32Process;
2530 }
2531
2532 /*
2533 * @implemented
2534 */
2535 PVOID
2536 STDCALL
2537 PsGetProcessWin32WindowStation(
2538 PEPROCESS Process
2539 )
2540 {
2541 return Process->Win32WindowStation;
2542 }
2543
2544 /*
2545 * @implemented
2546 */
2547 BOOLEAN
2548 STDCALL
2549 PsIsProcessBeingDebugged(
2550 PEPROCESS Process
2551 )
2552 {
2553 return FALSE/*Process->IsProcessBeingDebugged*/;
2554 }
2555
2556
2557 /*
2558 * @implemented
2559 */
2560 NTSTATUS STDCALL
2561 PsLookupProcessByProcessId(IN HANDLE ProcessId,
2562 OUT PEPROCESS *Process)
2563 {
2564 PLIST_ENTRY current_entry;
2565 PEPROCESS current;
2566
2567 ExAcquireFastMutex(&PspActiveProcessMutex);
2568
2569 current_entry = PsActiveProcessHead.Flink;
2570 while (current_entry != &PsActiveProcessHead)
2571 {
2572 current = CONTAINING_RECORD(current_entry,
2573 EPROCESS,
2574 ProcessListEntry);
2575 if (current->UniqueProcessId == ProcessId)
2576 {
2577 *Process = current;
2578 ObReferenceObject(current);
2579 ExReleaseFastMutex(&PspActiveProcessMutex);
2580 return(STATUS_SUCCESS);
2581 }
2582 current_entry = current_entry->Flink;
2583 }
2584
2585 ExReleaseFastMutex(&PspActiveProcessMutex);
2586
2587 return(STATUS_INVALID_PARAMETER);
2588 }
2589
2590 VOID
2591 STDCALL
2592 PspRunCreateProcessNotifyRoutines
2593 (
2594 PEPROCESS CurrentProcess,
2595 BOOLEAN Create
2596 )
2597 {
2598 ULONG i;
2599 HANDLE ProcessId = (HANDLE)CurrentProcess->UniqueProcessId;
2600 HANDLE ParentId = CurrentProcess->InheritedFromUniqueProcessId;
2601
2602 for(i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
2603 if(PiProcessNotifyRoutine[i])
2604 PiProcessNotifyRoutine[i](ParentId, ProcessId, Create);
2605 }
2606
2607 /*
2608 * @implemented
2609 */
2610 NTSTATUS STDCALL
2611 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
2612 IN BOOLEAN Remove)
2613 {
2614 ULONG i;
2615
2616 if (Remove)
2617 {
2618 for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
2619 {
2620 if ((PVOID)PiProcessNotifyRoutine[i] == (PVOID)NotifyRoutine)
2621 {
2622 PiProcessNotifyRoutine[i] = NULL;
2623 break;
2624 }
2625 }
2626
2627 return(STATUS_SUCCESS);
2628 }
2629
2630 /*insert*/
2631 for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
2632 {
2633 if (PiProcessNotifyRoutine[i] == NULL)
2634 {
2635 PiProcessNotifyRoutine[i] = NotifyRoutine;
2636 break;
2637 }
2638 }
2639
2640 if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
2641 {
2642 return STATUS_INSUFFICIENT_RESOURCES;
2643 }
2644
2645 return STATUS_SUCCESS;
2646 }
2647
2648 VOID STDCALL
2649 PspRunLoadImageNotifyRoutines(
2650 PUNICODE_STRING FullImageName,
2651 HANDLE ProcessId,
2652 PIMAGE_INFO ImageInfo)
2653 {
2654 ULONG i;
2655
2656 for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
2657 if (PiLoadImageNotifyRoutine[i])
2658 PiLoadImageNotifyRoutine[i](FullImageName, ProcessId, ImageInfo);
2659 }
2660
2661 /*
2662 * @unimplemented
2663 */
2664 NTSTATUS
2665 STDCALL
2666 PsRemoveLoadImageNotifyRoutine(
2667 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
2668 )
2669 {
2670 UNIMPLEMENTED;
2671 return STATUS_NOT_IMPLEMENTED;
2672 }
2673
2674 /*
2675 * @implemented
2676 */
2677 NTSTATUS STDCALL
2678 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
2679 {
2680 ULONG i;
2681
2682 for (i = 0; i < MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT; i++)
2683 {
2684 if (PiLoadImageNotifyRoutine[i] == NULL)
2685 {
2686 PiLoadImageNotifyRoutine[i] = NotifyRoutine;
2687 break;
2688 }
2689 }
2690
2691 if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
2692 {
2693 return STATUS_INSUFFICIENT_RESOURCES;
2694 }
2695
2696 return STATUS_SUCCESS;
2697 }
2698
2699 /*
2700 * @implemented
2701 */
2702 VOID
2703 STDCALL
2704 PsSetProcessPriorityClass(
2705 PEPROCESS Process,
2706 ULONG PriorityClass
2707 )
2708 {
2709 Process->PriorityClass = PriorityClass;
2710 }
2711
2712 /*
2713 * @implemented
2714 */
2715 VOID
2716 STDCALL
2717 PsSetProcessSecurityPort(
2718 PEPROCESS Process,
2719 PVOID SecurityPort
2720 )
2721 {
2722 Process->SecurityPort = SecurityPort;
2723 }
2724
2725 /*
2726 * @implemented
2727 */
2728 VOID
2729 STDCALL
2730 PsSetProcessWin32Process(
2731 PEPROCESS Process,
2732 PVOID Win32Process
2733 )
2734 {
2735 Process->Win32Process = Win32Process;
2736 }
2737
2738 /*
2739 * @implemented
2740 */
2741 VOID
2742 STDCALL
2743 PsSetProcessWin32WindowStation(
2744 PEPROCESS Process,
2745 PVOID WindowStation
2746 )
2747 {
2748 Process->Win32WindowStation = WindowStation;
2749 }
2750
2751 /* Pool Quotas */
2752 /*
2753 * @implemented
2754 */
2755 VOID
2756 STDCALL
2757 PsChargePoolQuota(
2758 IN PEPROCESS Process,
2759 IN POOL_TYPE PoolType,
2760 IN ULONG_PTR Amount
2761 )
2762 {
2763 NTSTATUS Status;
2764
2765 /* Charge the usage */
2766 Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
2767
2768 /* Raise Exception */
2769 if (!NT_SUCCESS(Status)) {
2770 ExRaiseStatus(Status);
2771 }
2772 }
2773
2774 /*
2775 * @implemented
2776 */
2777 NTSTATUS
2778 STDCALL
2779 PsChargeProcessNonPagedPoolQuota (
2780 IN PEPROCESS Process,
2781 IN ULONG_PTR Amount
2782 )
2783 {
2784 /* Call the general function */
2785 return PsChargeProcessPoolQuota(Process, NonPagedPool, Amount);
2786 }
2787
2788 /*
2789 * @implemented
2790 */
2791 NTSTATUS
2792 STDCALL
2793 PsChargeProcessPagedPoolQuota (
2794 IN PEPROCESS Process,
2795 IN ULONG_PTR Amount
2796 )
2797 {
2798 /* Call the general function */
2799 return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
2800 }
2801
2802 /*
2803 * @implemented
2804 */
2805 NTSTATUS
2806 STDCALL
2807 PsChargeProcessPoolQuota(
2808 IN PEPROCESS Process,
2809 IN POOL_TYPE PoolType,
2810 IN ULONG_PTR Amount
2811 )
2812 {
2813 PEPROCESS_QUOTA_BLOCK QuotaBlock;
2814 ULONG NewUsageSize;
2815 ULONG NewMaxQuota;
2816
2817 /* Get current Quota Block */
2818 QuotaBlock = Process->QuotaBlock;
2819
2820 /* Quota Operations are not to be done on the SYSTEM Process */
2821 if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
2822
2823 /* New Size in use */
2824 NewUsageSize = QuotaBlock->QuotaEntry[PoolType].Usage + Amount;
2825
2826 /* Does this size respect the quota? */
2827 if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Limit) {
2828
2829 /* It doesn't, so keep raising the Quota */
2830 while (MiRaisePoolQuota(PoolType, QuotaBlock->QuotaEntry[PoolType].Limit, &NewMaxQuota)) {
2831 /* Save new Maximum Quota */
2832 QuotaBlock->QuotaEntry[PoolType].Limit = NewMaxQuota;
2833
2834 /* See if the new Maximum Quota fulfills our need */
2835 if (NewUsageSize <= NewMaxQuota) goto QuotaChanged;
2836 }
2837
2838 return STATUS_QUOTA_EXCEEDED;
2839 }
2840
2841 QuotaChanged:
2842 /* Save new Usage */
2843 QuotaBlock->QuotaEntry[PoolType].Usage = NewUsageSize;
2844
2845 /* Is this a new peak? */
2846 if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Peak) {
2847 QuotaBlock->QuotaEntry[PoolType].Peak = NewUsageSize;
2848 }
2849
2850 /* All went well */
2851 return STATUS_SUCCESS;
2852 }
2853
2854 /*
2855 * @unimplemented
2856 */
2857 VOID
2858 STDCALL
2859 PsReturnPoolQuota(
2860 IN PEPROCESS Process,
2861 IN POOL_TYPE PoolType,
2862 IN ULONG_PTR Amount
2863 )
2864 {
2865 UNIMPLEMENTED;
2866 }
2867
2868 /*
2869 * @unimplemented
2870 */
2871 VOID
2872 STDCALL
2873 PsReturnProcessNonPagedPoolQuota(
2874 IN PEPROCESS Process,
2875 IN ULONG_PTR Amount
2876 )
2877 {
2878 UNIMPLEMENTED;
2879 }
2880
2881 /*
2882 * @unimplemented
2883 */
2884 VOID
2885 STDCALL
2886 PsReturnProcessPagedPoolQuota(
2887 IN PEPROCESS Process,
2888 IN ULONG_PTR Amount
2889 )
2890 {
2891 UNIMPLEMENTED;
2892 }
2893
2894 NTSTATUS
2895 PsLockProcess(PEPROCESS Process, BOOL Timeout)
2896 {
2897 ULONG Attempts = 0;
2898 PKTHREAD PrevLockOwner;
2899 NTSTATUS Status = STATUS_UNSUCCESSFUL;
2900 PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL);
2901 PKTHREAD CallingThread = KeGetCurrentThread();
2902
2903 PAGED_CODE();
2904
2905 KeEnterCriticalRegion();
2906
2907 for(;;)
2908 {
2909 if(Process->Pcb.State == PROCESS_STATE_TERMINATED)
2910 {
2911 KeLeaveCriticalRegion();
2912 return STATUS_PROCESS_IS_TERMINATING;
2913 }
2914
2915 PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
2916 &Process->LockOwner, CallingThread, NULL);
2917 if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
2918 {
2919 /* we got the lock or already locked it */
2920 if(InterlockedIncrementUL(&Process->LockCount) == 1)
2921 {
2922 KeClearEvent(&Process->LockEvent);
2923 }
2924
2925 return STATUS_SUCCESS;
2926 }
2927 else
2928 {
2929 if(++Attempts > 2)
2930 {
2931 Status = KeWaitForSingleObject(&Process->LockEvent,
2932 Executive,
2933 KernelMode,
2934 FALSE,
2935 Delay);
2936 if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT)
2937 {
2938 #ifndef NDEBUG
2939 if(Status == STATUS_TIMEOUT)
2940 {
2941 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process);
2942 }
2943 #endif
2944 KeLeaveCriticalRegion();
2945
2946 }
2947 break;
2948 }
2949 else
2950 {
2951 KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
2952 }
2953 }
2954 }
2955
2956 return Status;
2957 }
2958
2959 VOID
2960 PsUnlockProcess(PEPROCESS Process)
2961 {
2962 PAGED_CODE();
2963
2964 ASSERT(Process->LockOwner == KeGetCurrentThread());
2965
2966 if(InterlockedDecrementUL(&Process->LockCount) == 0)
2967 {
2968 InterlockedExchangePointer(&Process->LockOwner, NULL);
2969 KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
2970 }
2971
2972 KeLeaveCriticalRegion();
2973 }
2974
2975 /* EOF */