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