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