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