6211a6a2afce685bf3e09cd3cb8e284a70b3ae0f
[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 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
38 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
39
40 static PCREATE_PROCESS_NOTIFY_ROUTINE
41 PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
42 static PLOAD_IMAGE_NOTIFY_ROUTINE
43 PiLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT];
44
45
46 /* FUNCTIONS *****************************************************************/
47
48 PEPROCESS
49 PsGetNextProcess(PEPROCESS OldProcess)
50 {
51 PEPROCESS NextProcess;
52 NTSTATUS Status;
53
54 if (OldProcess == NULL)
55 {
56 Status = ObReferenceObjectByPointer(PsIdleProcess,
57 PROCESS_ALL_ACCESS,
58 PsProcessType,
59 KernelMode);
60 if (!NT_SUCCESS(Status))
61 {
62 CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsIdleProcess\n");
63 KEBUGCHECK(0);
64 }
65 return PsIdleProcess;
66 }
67
68 ExAcquireFastMutex(&PspActiveProcessMutex);
69 NextProcess = OldProcess;
70 while (1)
71 {
72 PLIST_ENTRY Flink = (NextProcess == PsIdleProcess ? PsActiveProcessHead.Flink :
73 NextProcess->ProcessListEntry.Flink);
74 if (Flink != &PsActiveProcessHead)
75 {
76 NextProcess = CONTAINING_RECORD(Flink,
77 EPROCESS,
78 ProcessListEntry);
79 }
80 else
81 {
82 NextProcess = NULL;
83 break;
84 }
85
86 Status = ObReferenceObjectByPointer(NextProcess,
87 PROCESS_ALL_ACCESS,
88 PsProcessType,
89 KernelMode);
90 if (NT_SUCCESS(Status))
91 {
92 break;
93 }
94 else if (Status == STATUS_PROCESS_IS_TERMINATING)
95 {
96 continue;
97 }
98 else if (!NT_SUCCESS(Status))
99 {
100 continue;
101 }
102 }
103
104 ExReleaseFastMutex(&PspActiveProcessMutex);
105 ObDereferenceObject(OldProcess);
106
107 return(NextProcess);
108 }
109
110 VOID
111 PiKillMostProcesses(VOID)
112 {
113 PLIST_ENTRY current_entry;
114 PEPROCESS current;
115
116 ExAcquireFastMutex(&PspActiveProcessMutex);
117
118 current_entry = PsActiveProcessHead.Flink;
119 while (current_entry != &PsActiveProcessHead)
120 {
121 current = CONTAINING_RECORD(current_entry, EPROCESS,
122 ProcessListEntry);
123 current_entry = current_entry->Flink;
124
125 if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
126 current->UniqueProcessId != PsGetCurrentProcessId())
127 {
128 PspTerminateProcessThreads(current, STATUS_SUCCESS);
129 }
130 }
131
132 ExReleaseFastMutex(&PspActiveProcessMutex);
133 }
134
135 VOID INIT_FUNCTION
136 PsInitProcessManagment(VOID)
137 {
138 PKPROCESS KProcess;
139 NTSTATUS Status;
140
141 ShortPsLockDelay.QuadPart = -100LL;
142 PsLockTimeout.QuadPart = -10000000LL; /* one second */
143 /*
144 * Register the process object type
145 */
146
147 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
148
149 PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
150 PsProcessType->TotalObjects = 0;
151 PsProcessType->TotalHandles = 0;
152 PsProcessType->PeakObjects = 0;
153 PsProcessType->PeakHandles = 0;
154 PsProcessType->PagedPoolCharge = 0;
155 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
156 PsProcessType->Mapping = &PiProcessMapping;
157 PsProcessType->Dump = NULL;
158 PsProcessType->Open = NULL;
159 PsProcessType->Close = NULL;
160 PsProcessType->Delete = PspDeleteProcess;
161 PsProcessType->Parse = NULL;
162 PsProcessType->Security = NULL;
163 PsProcessType->QueryName = NULL;
164 PsProcessType->OkayToClose = NULL;
165 PsProcessType->Create = NULL;
166 PsProcessType->DuplicationNotify = NULL;
167
168 RtlInitUnicodeString(&PsProcessType->TypeName, L"Process");
169
170 ObpCreateTypeObject(PsProcessType);
171
172 InitializeListHead(&PsActiveProcessHead);
173 ExInitializeFastMutex(&PspActiveProcessMutex);
174
175 RtlZeroMemory(PiProcessNotifyRoutine, sizeof(PiProcessNotifyRoutine));
176 RtlZeroMemory(PiLoadImageNotifyRoutine, sizeof(PiLoadImageNotifyRoutine));
177
178 /*
179 * Initialize the idle process
180 */
181 Status = ObCreateObject(KernelMode,
182 PsProcessType,
183 NULL,
184 KernelMode,
185 NULL,
186 sizeof(EPROCESS),
187 0,
188 0,
189 (PVOID*)&PsIdleProcess);
190 if (!NT_SUCCESS(Status))
191 {
192 DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status);
193 KEBUGCHECK(0);
194 return;
195 }
196
197 RtlZeroMemory(PsIdleProcess, sizeof(EPROCESS));
198
199 PsIdleProcess->Pcb.Affinity = 0xFFFFFFFF;
200 PsIdleProcess->Pcb.IopmOffset = 0xffff;
201 PsIdleProcess->Pcb.LdtDescriptor[0] = 0;
202 PsIdleProcess->Pcb.LdtDescriptor[1] = 0;
203 PsIdleProcess->Pcb.BasePriority = PROCESS_PRIO_IDLE;
204 PsIdleProcess->Pcb.ThreadQuantum = 6;
205 InitializeListHead(&PsIdleProcess->Pcb.ThreadListHead);
206 InitializeListHead(&PsIdleProcess->ThreadListHead);
207 InitializeListHead(&PsIdleProcess->ProcessListEntry);
208 KeInitializeDispatcherHeader(&PsIdleProcess->Pcb.DispatcherHeader,
209 ProcessObject,
210 sizeof(EPROCESS),
211 FALSE);
212 PsIdleProcess->Pcb.DirectoryTableBase =
213 (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
214 strcpy(PsIdleProcess->ImageFileName, "Idle");
215
216 /*
217 * Initialize the system process
218 */
219 Status = ObCreateObject(KernelMode,
220 PsProcessType,
221 NULL,
222 KernelMode,
223 NULL,
224 sizeof(EPROCESS),
225 0,
226 0,
227 (PVOID*)&PsInitialSystemProcess);
228 if (!NT_SUCCESS(Status))
229 {
230 DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status);
231 KEBUGCHECK(0);
232 return;
233 }
234
235 /* System threads may run on any processor. */
236 PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
237 PsInitialSystemProcess->Pcb.IopmOffset = 0xffff;
238 PsInitialSystemProcess->Pcb.LdtDescriptor[0] = 0;
239 PsInitialSystemProcess->Pcb.LdtDescriptor[1] = 0;
240 PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
241 PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
242 InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
243 KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
244 ProcessObject,
245 sizeof(EPROCESS),
246 FALSE);
247 KProcess = &PsInitialSystemProcess->Pcb;
248
249 MmInitializeAddressSpace(PsInitialSystemProcess,
250 &PsInitialSystemProcess->AddressSpace);
251
252 KeInitializeEvent(&PsInitialSystemProcess->LockEvent, SynchronizationEvent, FALSE);
253 PsInitialSystemProcess->LockCount = 0;
254 PsInitialSystemProcess->LockOwner = NULL;
255
256 #if defined(__GNUC__)
257 KProcess->DirectoryTableBase =
258 (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
259 #else
260 {
261 LARGE_INTEGER dummy;
262 dummy.QuadPart = (LONGLONG)(ULONG)MmGetPageDirectory();
263 KProcess->DirectoryTableBase = dummy;
264 }
265 #endif
266
267 strcpy(PsInitialSystemProcess->ImageFileName, "System");
268
269 PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
270
271 InsertHeadList(&PsActiveProcessHead,
272 &PsInitialSystemProcess->ProcessListEntry);
273 InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
274
275 SepCreateSystemProcessToken(PsInitialSystemProcess);
276 }
277
278 VOID
279 PspPostInitSystemProcess(VOID)
280 {
281 NTSTATUS Status;
282
283 /* this routine is called directly after the exectuive handle tables were
284 initialized. We'll set up the Client ID handle table and assign the system
285 process a PID */
286 PsInitClientIDManagment();
287
288 ObCreateHandleTable(NULL, FALSE, PsInitialSystemProcess);
289
290 Status = PsCreateCidHandle(PsInitialSystemProcess,
291 PsProcessType,
292 &PsInitialSystemProcess->UniqueProcessId);
293 if(!NT_SUCCESS(Status))
294 {
295 DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
296 KEBUGCHECK(0);
297 }
298 }
299
300 static NTSTATUS
301 PsCreatePeb(HANDLE ProcessHandle,
302 PEPROCESS Process,
303 PVOID ImageBase)
304 {
305 ULONG AllocSize;
306 ULONG PebSize;
307 PPEB Peb;
308 LARGE_INTEGER SectionOffset;
309 ULONG ViewSize;
310 PVOID TableBase;
311 NTSTATUS Status;
312
313 PAGED_CODE();
314
315 /* Allocate the Process Environment Block (PEB) */
316 Process->TebBlock = (PVOID) MM_ROUND_DOWN(PEB_BASE, MM_VIRTMEM_GRANULARITY);
317 AllocSize = MM_VIRTMEM_GRANULARITY;
318 Status = NtAllocateVirtualMemory(ProcessHandle,
319 &Process->TebBlock,
320 0,
321 &AllocSize,
322 MEM_RESERVE,
323 PAGE_READWRITE);
324 if (!NT_SUCCESS(Status))
325 {
326 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
327 return(Status);
328 }
329 ASSERT((ULONG_PTR) Process->TebBlock <= PEB_BASE &&
330 PEB_BASE + PAGE_SIZE <= (ULONG_PTR) Process->TebBlock + AllocSize);
331 Peb = (PPEB)PEB_BASE;
332 PebSize = PAGE_SIZE;
333 Status = NtAllocateVirtualMemory(ProcessHandle,
334 (PVOID*)&Peb,
335 0,
336 &PebSize,
337 MEM_COMMIT,
338 PAGE_READWRITE);
339 if (!NT_SUCCESS(Status))
340 {
341 DPRINT1("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
342 return(Status);
343 }
344 DPRINT("Peb %p PebSize %lu\n", Peb, PebSize);
345 ASSERT((PPEB) PEB_BASE == Peb && PAGE_SIZE <= PebSize);
346 Process->TebLastAllocated = (PVOID) Peb;
347
348 ViewSize = 0;
349 SectionOffset.QuadPart = (ULONGLONG)0;
350 TableBase = NULL;
351 Status = MmMapViewOfSection(NlsSectionObject,
352 Process,
353 &TableBase,
354 0,
355 0,
356 &SectionOffset,
357 &ViewSize,
358 ViewShare,
359 MEM_TOP_DOWN,
360 PAGE_READONLY);
361 if (!NT_SUCCESS(Status))
362 {
363 DPRINT1("MmMapViewOfSection() failed (Status %lx)\n", Status);
364 return(Status);
365 }
366 DPRINT("TableBase %p ViewSize %lx\n", TableBase, ViewSize);
367
368 KeAttachProcess(&Process->Pcb);
369
370 /* Initialize the PEB */
371 RtlZeroMemory(Peb, sizeof(PEB));
372 Peb->ImageBaseAddress = ImageBase;
373
374 Peb->OSMajorVersion = 4;
375 Peb->OSMinorVersion = 0;
376 Peb->OSBuildNumber = 1381;
377 Peb->OSPlatformId = 2; //VER_PLATFORM_WIN32_NT;
378 Peb->OSCSDVersion = 6 << 8;
379
380 Peb->AnsiCodePageData = (char*)TableBase + NlsAnsiTableOffset;
381 Peb->OemCodePageData = (char*)TableBase + NlsOemTableOffset;
382 Peb->UnicodeCaseTableData = (char*)TableBase + NlsUnicodeTableOffset;
383
384 Process->Peb = Peb;
385 KeDetachProcess();
386
387 DPRINT("PsCreatePeb: Peb created at %p\n", Peb);
388
389 return(STATUS_SUCCESS);
390 }
391
392
393 PKPROCESS
394 KeGetCurrentProcess(VOID)
395 /*
396 * FUNCTION: Returns a pointer to the current process
397 */
398 {
399 return(&(PsGetCurrentProcess()->Pcb));
400 }
401
402 /*
403 * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a
404 * ULONG ProcessId! (Skywing)
405 */
406 /*
407 * @implemented
408 */
409 HANDLE STDCALL
410 PsGetCurrentProcessId(VOID)
411 {
412 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
413 }
414
415 /*
416 * @unimplemented
417 */
418 ULONG
419 STDCALL
420 PsGetCurrentProcessSessionId (
421 VOID
422 )
423 {
424 return PsGetCurrentProcess()->SessionId;
425 }
426
427 /*
428 * FUNCTION: Returns a pointer to the current process
429 *
430 * @implemented
431 */
432 PEPROCESS STDCALL
433 IoGetCurrentProcess(VOID)
434 {
435 if (PsGetCurrentThread() == NULL ||
436 PsGetCurrentThread()->Tcb.ApcState.Process == NULL)
437 {
438 return(PsInitialSystemProcess);
439 }
440 else
441 {
442 return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process);
443 }
444 }
445
446 NTSTATUS
447 PspCreateProcess(OUT PHANDLE ProcessHandle,
448 IN ACCESS_MASK DesiredAccess,
449 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
450 IN HANDLE ParentProcess OPTIONAL,
451 IN BOOLEAN InheritObjectTable,
452 IN HANDLE SectionHandle OPTIONAL,
453 IN HANDLE DebugPort OPTIONAL,
454 IN HANDLE ExceptionPort OPTIONAL)
455 {
456 HANDLE hProcess;
457 PEPROCESS Process;
458 PEPROCESS pParentProcess;
459 PKPROCESS KProcess;
460 PVOID LdrStartupAddr;
461 PVOID BaseAddress;
462 PMEMORY_AREA MemoryArea;
463 PHYSICAL_ADDRESS BoundaryAddressMultiple;
464 KPROCESSOR_MODE PreviousMode;
465 PVOID ImageBase = NULL;
466 PEPORT pDebugPort = NULL;
467 PEPORT pExceptionPort = NULL;
468 PSECTION_OBJECT SectionObject = NULL;
469 NTSTATUS Status = STATUS_SUCCESS;
470
471 DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes);
472
473 PreviousMode = ExGetPreviousMode();
474
475 BoundaryAddressMultiple.QuadPart = 0;
476
477 if(ParentProcess != NULL)
478 {
479 Status = ObReferenceObjectByHandle(ParentProcess,
480 PROCESS_CREATE_PROCESS,
481 PsProcessType,
482 PreviousMode,
483 (PVOID*)&pParentProcess,
484 NULL);
485 if (!NT_SUCCESS(Status))
486 {
487 DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status);
488 return(Status);
489 }
490 }
491 else
492 {
493 pParentProcess = NULL;
494 }
495
496 /*
497 * Add the debug port
498 */
499 if (DebugPort != NULL)
500 {
501 Status = ObReferenceObjectByHandle(DebugPort,
502 PORT_ALL_ACCESS,
503 LpcPortObjectType,
504 PreviousMode,
505 (PVOID*)&pDebugPort,
506 NULL);
507 if (!NT_SUCCESS(Status))
508 {
509 DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status);
510 goto exitdereferenceobjects;
511 }
512 }
513
514 /*
515 * Add the exception port
516 */
517 if (ExceptionPort != NULL)
518 {
519 Status = ObReferenceObjectByHandle(ExceptionPort,
520 PORT_ALL_ACCESS,
521 LpcPortObjectType,
522 PreviousMode,
523 (PVOID*)&pExceptionPort,
524 NULL);
525 if (!NT_SUCCESS(Status))
526 {
527 DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status);
528 goto exitdereferenceobjects;
529 }
530 }
531
532 if (SectionHandle != NULL)
533 {
534 Status = ObReferenceObjectByHandle(SectionHandle,
535 0,
536 MmSectionObjectType,
537 PreviousMode,
538 (PVOID*)&SectionObject,
539 NULL);
540 if (!NT_SUCCESS(Status))
541 {
542 DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status);
543 goto exitdereferenceobjects;
544 }
545 }
546
547 Status = ObCreateObject(PreviousMode,
548 PsProcessType,
549 ObjectAttributes,
550 PreviousMode,
551 NULL,
552 sizeof(EPROCESS),
553 0,
554 0,
555 (PVOID*)&Process);
556 if (!NT_SUCCESS(Status))
557 {
558 DPRINT1("Failed to create process object, Status: 0x%x\n", Status);
559
560 exitdereferenceobjects:
561 if(SectionObject != NULL)
562 ObDereferenceObject(SectionObject);
563 if(pExceptionPort != NULL)
564 ObDereferenceObject(pExceptionPort);
565 if(pDebugPort != NULL)
566 ObDereferenceObject(pDebugPort);
567 if(pParentProcess != NULL)
568 ObDereferenceObject(pParentProcess);
569 return Status;
570 }
571
572 KProcess = &Process->Pcb;
573
574 RtlZeroMemory(Process, sizeof(EPROCESS));
575
576 Status = PsCreateCidHandle(Process,
577 PsProcessType,
578 &Process->UniqueProcessId);
579 if(!NT_SUCCESS(Status))
580 {
581 DPRINT1("Failed to create CID handle (unique process ID)! Status: 0x%x\n", Status);
582 ObDereferenceObject(Process);
583 goto exitdereferenceobjects;
584 }
585
586 Process->DebugPort = pDebugPort;
587 Process->ExceptionPort = pExceptionPort;
588
589 if(SectionObject != NULL)
590 {
591 UNICODE_STRING FileName;
592 PWCHAR szSrc;
593 PCHAR szDest;
594 USHORT lnFName = 0;
595
596 /*
597 * Determine the image file name and save it to the EPROCESS structure
598 */
599
600 FileName = SectionObject->FileObject->FileName;
601 szSrc = (PWCHAR)(FileName.Buffer + (FileName.Length / sizeof(WCHAR)) - 1);
602 while(szSrc >= FileName.Buffer)
603 {
604 if(*szSrc == L'\\')
605 {
606 szSrc++;
607 break;
608 }
609 else
610 {
611 szSrc--;
612 lnFName++;
613 }
614 }
615
616 /* copy the image file name to the process and truncate it to 15 characters
617 if necessary */
618 szDest = Process->ImageFileName;
619 lnFName = min(lnFName, sizeof(Process->ImageFileName) - 1);
620 while(lnFName-- > 0)
621 {
622 *(szDest++) = (UCHAR)*(szSrc++);
623 }
624 /* *szDest = '\0'; */
625 }
626
627 KeInitializeDispatcherHeader(&KProcess->DispatcherHeader,
628 ProcessObject,
629 sizeof(EPROCESS),
630 FALSE);
631
632 /* Inherit parent process's affinity. */
633 if(pParentProcess != NULL)
634 {
635 KProcess->Affinity = pParentProcess->Pcb.Affinity;
636 Process->InheritedFromUniqueProcessId = pParentProcess->UniqueProcessId;
637 Process->SessionId = pParentProcess->SessionId;
638 }
639 else
640 {
641 KProcess->Affinity = KeActiveProcessors;
642 }
643
644 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
645 KProcess->IopmOffset = 0xffff;
646 KProcess->LdtDescriptor[0] = 0;
647 KProcess->LdtDescriptor[1] = 0;
648 InitializeListHead(&KProcess->ThreadListHead);
649 KProcess->ThreadQuantum = 6;
650 KProcess->AutoAlignment = 0;
651 MmInitializeAddressSpace(Process,
652 &Process->AddressSpace);
653
654 ObCreateHandleTable(pParentProcess,
655 InheritObjectTable,
656 Process);
657 MmCopyMmInfo(pParentProcess ? pParentProcess : PsInitialSystemProcess, Process);
658
659 KeInitializeEvent(&Process->LockEvent, SynchronizationEvent, FALSE);
660 Process->LockCount = 0;
661 Process->LockOwner = NULL;
662
663 Process->Win32WindowStation = (HANDLE)0;
664
665 ExAcquireFastMutex(&PspActiveProcessMutex);
666 InsertTailList(&PsActiveProcessHead, &Process->ProcessListEntry);
667 InitializeListHead(&Process->ThreadListHead);
668 ExReleaseFastMutex(&PspActiveProcessMutex);
669
670 Process->Pcb.State = PROCESS_STATE_ACTIVE;
671
672 /*
673 * Now we have created the process proper
674 */
675
676 MmLockAddressSpace(&Process->AddressSpace);
677
678 /* Protect the highest 64KB of the process address space */
679 BaseAddress = (PVOID)MmUserProbeAddress;
680 Status = MmCreateMemoryArea(Process,
681 &Process->AddressSpace,
682 MEMORY_AREA_NO_ACCESS,
683 &BaseAddress,
684 0x10000,
685 PAGE_NOACCESS,
686 &MemoryArea,
687 FALSE,
688 FALSE,
689 BoundaryAddressMultiple);
690 if (!NT_SUCCESS(Status))
691 {
692 MmUnlockAddressSpace(&Process->AddressSpace);
693 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
694 ObDereferenceObject(Process);
695 goto exitdereferenceobjects;
696 }
697
698 /* Protect the lowest 64KB of the process address space */
699 #if 0
700 BaseAddress = (PVOID)0x00000000;
701 Status = MmCreateMemoryArea(Process,
702 &Process->AddressSpace,
703 MEMORY_AREA_NO_ACCESS,
704 &BaseAddress,
705 0x10000,
706 PAGE_NOACCESS,
707 &MemoryArea,
708 FALSE,
709 FALSE,
710 BoundaryAddressMultiple);
711 if (!NT_SUCCESS(Status))
712 {
713 MmUnlockAddressSpace(&Process->AddressSpace);
714 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
715 ObDereferenceObject(Process);
716 goto exitdereferenceobjects;
717 }
718 #endif
719
720 /* Protect the 60KB above the shared user page */
721 BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
722 Status = MmCreateMemoryArea(Process,
723 &Process->AddressSpace,
724 MEMORY_AREA_NO_ACCESS,
725 &BaseAddress,
726 0x10000 - PAGE_SIZE,
727 PAGE_NOACCESS,
728 &MemoryArea,
729 FALSE,
730 FALSE,
731 BoundaryAddressMultiple);
732 if (!NT_SUCCESS(Status))
733 {
734 MmUnlockAddressSpace(&Process->AddressSpace);
735 DPRINT1("Failed to protect the memory above the shared user page\n");
736 ObDereferenceObject(Process);
737 goto exitdereferenceobjects;
738 }
739
740 /* Create the shared data page */
741 BaseAddress = (PVOID)USER_SHARED_DATA;
742 Status = MmCreateMemoryArea(Process,
743 &Process->AddressSpace,
744 MEMORY_AREA_SHARED_DATA,
745 &BaseAddress,
746 PAGE_SIZE,
747 PAGE_READONLY,
748 &MemoryArea,
749 FALSE,
750 FALSE,
751 BoundaryAddressMultiple);
752 MmUnlockAddressSpace(&Process->AddressSpace);
753 if (!NT_SUCCESS(Status))
754 {
755 DPRINT1("Failed to create shared data page\n");
756 ObDereferenceObject(Process);
757 goto exitdereferenceobjects;
758 }
759
760 #if 1
761 /*
762 * FIXME - the handle should be created after all things are initialized, NOT HERE!
763 */
764 Status = ObInsertObject ((PVOID)Process,
765 NULL,
766 DesiredAccess,
767 0,
768 NULL,
769 &hProcess);
770 if (!NT_SUCCESS(Status))
771 {
772 DPRINT1("Failed to create a handle for the process\n");
773 ObDereferenceObject(Process);
774 goto exitdereferenceobjects;
775 }
776 #endif
777
778 /*
779 * FIXME - Map ntdll
780 */
781 Status = LdrpMapSystemDll(hProcess, /* FIXME - hProcess shouldn't be available at this point! */
782 &LdrStartupAddr);
783 if (!NT_SUCCESS(Status))
784 {
785 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
786 ObDereferenceObject(Process);
787 goto exitdereferenceobjects;
788 }
789
790 /*
791 * Map the process image
792 */
793 if (SectionObject != NULL)
794 {
795 ULONG ViewSize = 0;
796 DPRINT("Mapping process image\n");
797 Status = MmMapViewOfSection(SectionObject,
798 Process,
799 (PVOID*)&ImageBase,
800 0,
801 ViewSize,
802 NULL,
803 &ViewSize,
804 0,
805 MEM_COMMIT,
806 PAGE_READWRITE);
807 ObDereferenceObject(SectionObject);
808 if (!NT_SUCCESS(Status))
809 {
810 DbgPrint("Failed to map the process section (Status %x)\n", Status);
811 ObDereferenceObject(Process);
812 goto exitdereferenceobjects;
813 }
814 }
815
816 if(pParentProcess != NULL)
817 {
818 /*
819 * Duplicate the token
820 */
821 Status = SepInitializeNewProcess(Process, pParentProcess);
822 if (!NT_SUCCESS(Status))
823 {
824 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
825 ObDereferenceObject(Process);
826 goto exitdereferenceobjects;
827 }
828 }
829 else
830 {
831 /* FIXME */
832 }
833
834 /*
835 * FIXME - Create PEB
836 */
837 DPRINT("Creating PEB\n");
838 Status = PsCreatePeb(hProcess, /* FIXME - hProcess shouldn't be available at this point! */
839 Process,
840 ImageBase);
841 if (!NT_SUCCESS(Status))
842 {
843 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
844 ObDereferenceObject(Process);
845 goto exitdereferenceobjects;
846 }
847
848 /*
849 * Maybe send a message to the creator process's debugger
850 */
851 #if 0
852 if (pParentProcess->DebugPort != NULL)
853 {
854 LPC_DBG_MESSAGE Message;
855 HANDLE FileHandle;
856
857 ObCreateHandle(NULL, // Debugger Process
858 NULL, // SectionHandle
859 FILE_ALL_ACCESS,
860 FALSE,
861 &FileHandle);
862
863 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
864 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
865 sizeof(LPC_MESSAGE);
866 Message.Type = DBG_EVENT_CREATE_PROCESS;
867 Message.Data.CreateProcess.FileHandle = FileHandle;
868 Message.Data.CreateProcess.Base = ImageBase;
869 Message.Data.CreateProcess.EntryPoint = NULL; //
870
871 Status = LpcSendDebugMessagePort(pParentProcess->DebugPort,
872 &Message);
873 }
874 #endif
875
876 PspRunCreateProcessNotifyRoutines(Process, TRUE);
877
878 /*
879 * FIXME - the handle should be created not before this point!
880 */
881 #if 0
882 Status = ObInsertObject ((PVOID)Process,
883 NULL,
884 DesiredAccess,
885 0,
886 NULL,
887 &hProcess);
888 #endif
889 if (NT_SUCCESS(Status))
890 {
891 _SEH_TRY
892 {
893 *ProcessHandle = hProcess;
894 }
895 _SEH_HANDLE
896 {
897 Status = _SEH_GetExceptionCode();
898 }
899 _SEH_END;
900 }
901
902 /*
903 * don't dereference the debug port, exception port and section object even
904 * if ObInsertObject() failed, the process is alive! We just couldn't return
905 * the handle to the caller!
906 */
907
908 ObDereferenceObject(Process);
909 if(pParentProcess != NULL)
910 ObDereferenceObject(pParentProcess);
911
912 return Status;
913 }
914
915
916 /*
917 * @implemented
918 */
919 NTSTATUS STDCALL
920 PsCreateSystemProcess(PHANDLE ProcessHandle,
921 ACCESS_MASK DesiredAccess,
922 POBJECT_ATTRIBUTES ObjectAttributes)
923 {
924 return PspCreateProcess(ProcessHandle,
925 DesiredAccess,
926 ObjectAttributes,
927 NULL, /* no parent process */
928 FALSE,
929 NULL,
930 NULL,
931 NULL);
932 }
933
934
935 /*
936 * @implemented
937 */
938 NTSTATUS STDCALL
939 NtCreateProcess(OUT PHANDLE ProcessHandle,
940 IN ACCESS_MASK DesiredAccess,
941 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
942 IN HANDLE ParentProcess,
943 IN BOOLEAN InheritObjectTable,
944 IN HANDLE SectionHandle OPTIONAL,
945 IN HANDLE DebugPort OPTIONAL,
946 IN HANDLE ExceptionPort OPTIONAL)
947 /*
948 * FUNCTION: Creates a process.
949 * ARGUMENTS:
950 * ProcessHandle (OUT) = Caller supplied storage for the resulting
951 * handle
952 * DesiredAccess = Specifies the allowed or desired access to the
953 * process can be a combination of
954 * STANDARD_RIGHTS_REQUIRED| ..
955 * ObjectAttribute = Initialized attributes for the object, contains
956 * the rootdirectory and the filename
957 * ParentProcess = Handle to the parent process.
958 * InheritObjectTable = Specifies to inherit the objects of the parent
959 * process if true.
960 * SectionHandle = Handle to a section object to back the image file
961 * DebugPort = Handle to a DebugPort if NULL the system default debug
962 * port will be used.
963 * ExceptionPort = Handle to a exception port.
964 * REMARKS:
965 * This function maps to the win32 CreateProcess.
966 * RETURNS: Status
967 */
968 {
969 KPROCESSOR_MODE PreviousMode;
970 NTSTATUS Status = STATUS_SUCCESS;
971
972 PAGED_CODE();
973
974 PreviousMode = ExGetPreviousMode();
975
976 if(PreviousMode != KernelMode)
977 {
978 _SEH_TRY
979 {
980 ProbeForWrite(ProcessHandle,
981 sizeof(HANDLE),
982 sizeof(ULONG));
983 }
984 _SEH_HANDLE
985 {
986 Status = _SEH_GetExceptionCode();
987 }
988 _SEH_END;
989
990 if(!NT_SUCCESS(Status))
991 {
992 return Status;
993 }
994 }
995
996 if(ParentProcess == NULL)
997 {
998 Status = STATUS_INVALID_PARAMETER;
999 }
1000 else
1001 {
1002 Status = PspCreateProcess(ProcessHandle,
1003 DesiredAccess,
1004 ObjectAttributes,
1005 ParentProcess,
1006 InheritObjectTable,
1007 SectionHandle,
1008 DebugPort,
1009 ExceptionPort);
1010 }
1011
1012 return Status;
1013 }
1014
1015
1016 /*
1017 * @unimplemented
1018 */
1019 NTSTATUS STDCALL
1020 NtOpenProcess(OUT PHANDLE ProcessHandle,
1021 IN ACCESS_MASK DesiredAccess,
1022 IN POBJECT_ATTRIBUTES ObjectAttributes,
1023 IN PCLIENT_ID ClientId)
1024 {
1025 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1026 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1027 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
1028 ClientId->UniqueProcess, ClientId->UniqueThread);
1029
1030 PAGED_CODE();
1031
1032 /*
1033 * Not sure of the exact semantics
1034 */
1035 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
1036 ObjectAttributes->ObjectName->Buffer != NULL)
1037 {
1038 NTSTATUS Status;
1039 PEPROCESS Process;
1040
1041 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
1042 ObjectAttributes->Attributes,
1043 NULL,
1044 DesiredAccess,
1045 PsProcessType,
1046 UserMode,
1047 NULL,
1048 (PVOID*)&Process);
1049 if (Status != STATUS_SUCCESS)
1050 {
1051 return(Status);
1052 }
1053
1054 Status = ObCreateHandle(PsGetCurrentProcess(),
1055 Process,
1056 DesiredAccess,
1057 FALSE,
1058 ProcessHandle);
1059 ObDereferenceObject(Process);
1060
1061 return(Status);
1062 }
1063 else
1064 {
1065 PLIST_ENTRY current_entry;
1066 PEPROCESS current;
1067 NTSTATUS Status;
1068
1069 ExAcquireFastMutex(&PspActiveProcessMutex);
1070 current_entry = PsActiveProcessHead.Flink;
1071 while (current_entry != &PsActiveProcessHead)
1072 {
1073 current = CONTAINING_RECORD(current_entry, EPROCESS,
1074 ProcessListEntry);
1075 if (current->UniqueProcessId == ClientId->UniqueProcess)
1076 {
1077 if (current->Pcb.State == PROCESS_STATE_TERMINATED)
1078 {
1079 Status = STATUS_PROCESS_IS_TERMINATING;
1080 }
1081 else
1082 {
1083 Status = ObReferenceObjectByPointer(current,
1084 DesiredAccess,
1085 PsProcessType,
1086 UserMode);
1087 }
1088 ExReleaseFastMutex(&PspActiveProcessMutex);
1089 if (NT_SUCCESS(Status))
1090 {
1091 Status = ObCreateHandle(PsGetCurrentProcess(),
1092 current,
1093 DesiredAccess,
1094 FALSE,
1095 ProcessHandle);
1096 ObDereferenceObject(current);
1097 DPRINT("*ProcessHandle %x\n", ProcessHandle);
1098 DPRINT("NtOpenProcess() = %x\n", Status);
1099 }
1100 return(Status);
1101 }
1102 current_entry = current_entry->Flink;
1103 }
1104 ExReleaseFastMutex(&PspActiveProcessMutex);
1105 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1106 return(STATUS_UNSUCCESSFUL);
1107 }
1108 }
1109
1110 /*
1111 * @implemented
1112 */
1113 LARGE_INTEGER STDCALL
1114 PsGetProcessExitTime(VOID)
1115 {
1116 LARGE_INTEGER Li;
1117 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1118 return Li;
1119 }
1120
1121 /*
1122 * @implemented
1123 */
1124 LONGLONG
1125 STDCALL
1126 PsGetProcessCreateTimeQuadPart(
1127 PEPROCESS Process
1128 )
1129 {
1130 return Process->CreateTime.QuadPart;
1131 }
1132
1133 /*
1134 * @implemented
1135 */
1136 PVOID
1137 STDCALL
1138 PsGetProcessDebugPort(
1139 PEPROCESS Process
1140 )
1141 {
1142 return Process->DebugPort;
1143 }
1144
1145 /*
1146 * @implemented
1147 */
1148 BOOLEAN
1149 STDCALL
1150 PsGetProcessExitProcessCalled(
1151 PEPROCESS Process
1152 )
1153 {
1154 return Process->ExitProcessCalled;
1155 }
1156
1157 /*
1158 * @implemented
1159 */
1160 NTSTATUS
1161 STDCALL
1162 PsGetProcessExitStatus(
1163 PEPROCESS Process
1164 )
1165 {
1166 return Process->ExitStatus;
1167 }
1168
1169 /*
1170 * @implemented
1171 */
1172 HANDLE
1173 STDCALL
1174 PsGetProcessId(
1175 PEPROCESS Process
1176 )
1177 {
1178 return (HANDLE)Process->UniqueProcessId;
1179 }
1180
1181 /*
1182 * @implemented
1183 */
1184 LPSTR
1185 STDCALL
1186 PsGetProcessImageFileName(
1187 PEPROCESS Process
1188 )
1189 {
1190 return (LPSTR)Process->ImageFileName;
1191 }
1192
1193 /*
1194 * @implemented
1195 */
1196 HANDLE
1197 STDCALL
1198 PsGetProcessInheritedFromUniqueProcessId(
1199 PEPROCESS Process
1200 )
1201 {
1202 return Process->InheritedFromUniqueProcessId;
1203 }
1204
1205 /*
1206 * @implemented
1207 */
1208 PEJOB
1209 STDCALL
1210 PsGetProcessJob(
1211 PEPROCESS Process
1212 )
1213 {
1214 return Process->Job;
1215 }
1216
1217 /*
1218 * @implemented
1219 */
1220 PPEB
1221 STDCALL
1222 PsGetProcessPeb(
1223 PEPROCESS Process
1224 )
1225 {
1226 return Process->Peb;
1227 }
1228
1229 /*
1230 * @implemented
1231 */
1232 ULONG
1233 STDCALL
1234 PsGetProcessPriorityClass(
1235 PEPROCESS Process
1236 )
1237 {
1238 return Process->PriorityClass;
1239 }
1240
1241 /*
1242 * @implemented
1243 */
1244 PVOID
1245 STDCALL
1246 PsGetProcessSectionBaseAddress(
1247 PEPROCESS Process
1248 )
1249 {
1250 return Process->SectionBaseAddress;
1251 }
1252
1253 /*
1254 * @implemented
1255 */
1256 PVOID
1257 STDCALL
1258 PsGetProcessSecurityPort(
1259 PEPROCESS Process
1260 )
1261 {
1262 return Process->SecurityPort;
1263 }
1264
1265 /*
1266 * @implemented
1267 */
1268 HANDLE
1269 STDCALL
1270 PsGetProcessSessionId(
1271 PEPROCESS Process
1272 )
1273 {
1274 return (HANDLE)Process->SessionId;
1275 }
1276
1277 /*
1278 * @implemented
1279 */
1280 PVOID
1281 STDCALL
1282 PsGetProcessWin32Process(
1283 PEPROCESS Process
1284 )
1285 {
1286 return Process->Win32Process;
1287 }
1288
1289 /*
1290 * @implemented
1291 */
1292 PVOID
1293 STDCALL
1294 PsGetProcessWin32WindowStation(
1295 PEPROCESS Process
1296 )
1297 {
1298 return Process->Win32WindowStation;
1299 }
1300
1301 /*
1302 * @implemented
1303 */
1304 BOOLEAN
1305 STDCALL
1306 PsIsProcessBeingDebugged(
1307 PEPROCESS Process
1308 )
1309 {
1310 return FALSE/*Process->IsProcessBeingDebugged*/;
1311 }
1312
1313
1314 /*
1315 * @implemented
1316 */
1317 NTSTATUS STDCALL
1318 PsLookupProcessByProcessId(IN HANDLE ProcessId,
1319 OUT PEPROCESS *Process)
1320 {
1321 PHANDLE_TABLE_ENTRY CidEntry;
1322 PEPROCESS FoundProcess;
1323
1324 PAGED_CODE();
1325
1326 ASSERT(Process);
1327
1328 CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess);
1329 if(CidEntry != NULL)
1330 {
1331 ObReferenceObject(FoundProcess);
1332
1333 PsUnlockCidHandle(CidEntry);
1334
1335 *Process = FoundProcess;
1336 return STATUS_SUCCESS;
1337 }
1338
1339 return STATUS_INVALID_PARAMETER;
1340 }
1341
1342 VOID
1343 STDCALL
1344 PspRunCreateProcessNotifyRoutines
1345 (
1346 PEPROCESS CurrentProcess,
1347 BOOLEAN Create
1348 )
1349 {
1350 ULONG i;
1351 HANDLE ProcessId = (HANDLE)CurrentProcess->UniqueProcessId;
1352 HANDLE ParentId = CurrentProcess->InheritedFromUniqueProcessId;
1353
1354 for(i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
1355 if(PiProcessNotifyRoutine[i])
1356 PiProcessNotifyRoutine[i](ParentId, ProcessId, Create);
1357 }
1358
1359 /*
1360 * @implemented
1361 */
1362 NTSTATUS STDCALL
1363 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
1364 IN BOOLEAN Remove)
1365 {
1366 ULONG i;
1367
1368 if (Remove)
1369 {
1370 for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
1371 {
1372 if ((PVOID)PiProcessNotifyRoutine[i] == (PVOID)NotifyRoutine)
1373 {
1374 PiProcessNotifyRoutine[i] = NULL;
1375 break;
1376 }
1377 }
1378
1379 return(STATUS_SUCCESS);
1380 }
1381
1382 /*insert*/
1383 for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
1384 {
1385 if (PiProcessNotifyRoutine[i] == NULL)
1386 {
1387 PiProcessNotifyRoutine[i] = NotifyRoutine;
1388 break;
1389 }
1390 }
1391
1392 if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1393 {
1394 return STATUS_INSUFFICIENT_RESOURCES;
1395 }
1396
1397 return STATUS_SUCCESS;
1398 }
1399
1400 VOID STDCALL
1401 PspRunLoadImageNotifyRoutines(
1402 PUNICODE_STRING FullImageName,
1403 HANDLE ProcessId,
1404 PIMAGE_INFO ImageInfo)
1405 {
1406 ULONG i;
1407
1408 for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
1409 if (PiLoadImageNotifyRoutine[i])
1410 PiLoadImageNotifyRoutine[i](FullImageName, ProcessId, ImageInfo);
1411 }
1412
1413 /*
1414 * @unimplemented
1415 */
1416 NTSTATUS
1417 STDCALL
1418 PsRemoveLoadImageNotifyRoutine(
1419 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
1420 )
1421 {
1422 UNIMPLEMENTED;
1423 return STATUS_NOT_IMPLEMENTED;
1424 }
1425
1426 /*
1427 * @implemented
1428 */
1429 NTSTATUS STDCALL
1430 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
1431 {
1432 ULONG i;
1433
1434 for (i = 0; i < MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT; i++)
1435 {
1436 if (PiLoadImageNotifyRoutine[i] == NULL)
1437 {
1438 PiLoadImageNotifyRoutine[i] = NotifyRoutine;
1439 break;
1440 }
1441 }
1442
1443 if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1444 {
1445 return STATUS_INSUFFICIENT_RESOURCES;
1446 }
1447
1448 return STATUS_SUCCESS;
1449 }
1450
1451 /*
1452 * @implemented
1453 */
1454 VOID
1455 STDCALL
1456 PsSetProcessPriorityClass(
1457 PEPROCESS Process,
1458 ULONG PriorityClass
1459 )
1460 {
1461 Process->PriorityClass = PriorityClass;
1462 }
1463
1464 /*
1465 * @implemented
1466 */
1467 VOID
1468 STDCALL
1469 PsSetProcessSecurityPort(
1470 PEPROCESS Process,
1471 PVOID SecurityPort
1472 )
1473 {
1474 Process->SecurityPort = SecurityPort;
1475 }
1476
1477 /*
1478 * @implemented
1479 */
1480 VOID
1481 STDCALL
1482 PsSetProcessWin32Process(
1483 PEPROCESS Process,
1484 PVOID Win32Process
1485 )
1486 {
1487 Process->Win32Process = Win32Process;
1488 }
1489
1490 /*
1491 * @implemented
1492 */
1493 VOID
1494 STDCALL
1495 PsSetProcessWin32WindowStation(
1496 PEPROCESS Process,
1497 PVOID WindowStation
1498 )
1499 {
1500 Process->Win32WindowStation = WindowStation;
1501 }
1502
1503 /* Pool Quotas */
1504 /*
1505 * @implemented
1506 */
1507 VOID
1508 STDCALL
1509 PsChargePoolQuota(
1510 IN PEPROCESS Process,
1511 IN POOL_TYPE PoolType,
1512 IN ULONG_PTR Amount
1513 )
1514 {
1515 NTSTATUS Status;
1516
1517 /* Charge the usage */
1518 Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
1519
1520 /* Raise Exception */
1521 if (!NT_SUCCESS(Status)) {
1522 ExRaiseStatus(Status);
1523 }
1524 }
1525
1526 /*
1527 * @implemented
1528 */
1529 NTSTATUS
1530 STDCALL
1531 PsChargeProcessNonPagedPoolQuota (
1532 IN PEPROCESS Process,
1533 IN ULONG_PTR Amount
1534 )
1535 {
1536 /* Call the general function */
1537 return PsChargeProcessPoolQuota(Process, NonPagedPool, Amount);
1538 }
1539
1540 /*
1541 * @implemented
1542 */
1543 NTSTATUS
1544 STDCALL
1545 PsChargeProcessPagedPoolQuota (
1546 IN PEPROCESS Process,
1547 IN ULONG_PTR Amount
1548 )
1549 {
1550 /* Call the general function */
1551 return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
1552 }
1553
1554 /*
1555 * @implemented
1556 */
1557 NTSTATUS
1558 STDCALL
1559 PsChargeProcessPoolQuota(
1560 IN PEPROCESS Process,
1561 IN POOL_TYPE PoolType,
1562 IN ULONG_PTR Amount
1563 )
1564 {
1565 PEPROCESS_QUOTA_BLOCK QuotaBlock;
1566 ULONG NewUsageSize;
1567 ULONG NewMaxQuota;
1568
1569 /* Get current Quota Block */
1570 QuotaBlock = Process->QuotaBlock;
1571
1572 /* Quota Operations are not to be done on the SYSTEM Process */
1573 if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
1574
1575 /* New Size in use */
1576 NewUsageSize = QuotaBlock->QuotaEntry[PoolType].Usage + Amount;
1577
1578 /* Does this size respect the quota? */
1579 if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Limit) {
1580
1581 /* It doesn't, so keep raising the Quota */
1582 while (MiRaisePoolQuota(PoolType, QuotaBlock->QuotaEntry[PoolType].Limit, &NewMaxQuota)) {
1583 /* Save new Maximum Quota */
1584 QuotaBlock->QuotaEntry[PoolType].Limit = NewMaxQuota;
1585
1586 /* See if the new Maximum Quota fulfills our need */
1587 if (NewUsageSize <= NewMaxQuota) goto QuotaChanged;
1588 }
1589
1590 return STATUS_QUOTA_EXCEEDED;
1591 }
1592
1593 QuotaChanged:
1594 /* Save new Usage */
1595 QuotaBlock->QuotaEntry[PoolType].Usage = NewUsageSize;
1596
1597 /* Is this a new peak? */
1598 if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Peak) {
1599 QuotaBlock->QuotaEntry[PoolType].Peak = NewUsageSize;
1600 }
1601
1602 /* All went well */
1603 return STATUS_SUCCESS;
1604 }
1605
1606 /*
1607 * @unimplemented
1608 */
1609 VOID
1610 STDCALL
1611 PsReturnPoolQuota(
1612 IN PEPROCESS Process,
1613 IN POOL_TYPE PoolType,
1614 IN ULONG_PTR Amount
1615 )
1616 {
1617 UNIMPLEMENTED;
1618 }
1619
1620 /*
1621 * @unimplemented
1622 */
1623 VOID
1624 STDCALL
1625 PsReturnProcessNonPagedPoolQuota(
1626 IN PEPROCESS Process,
1627 IN ULONG_PTR Amount
1628 )
1629 {
1630 UNIMPLEMENTED;
1631 }
1632
1633 /*
1634 * @unimplemented
1635 */
1636 VOID
1637 STDCALL
1638 PsReturnProcessPagedPoolQuota(
1639 IN PEPROCESS Process,
1640 IN ULONG_PTR Amount
1641 )
1642 {
1643 UNIMPLEMENTED;
1644 }
1645
1646 NTSTATUS
1647 PsLockProcess(PEPROCESS Process, BOOLEAN Timeout)
1648 {
1649 ULONG Attempts = 0;
1650 PKTHREAD PrevLockOwner;
1651 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1652 PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL);
1653 PKTHREAD CallingThread = KeGetCurrentThread();
1654
1655 PAGED_CODE();
1656
1657 KeEnterCriticalRegion();
1658
1659 for(;;)
1660 {
1661 PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
1662 &Process->LockOwner, CallingThread, NULL);
1663 if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
1664 {
1665 /* we got the lock or already locked it */
1666 if(InterlockedIncrementUL(&Process->LockCount) == 1)
1667 {
1668 KeClearEvent(&Process->LockEvent);
1669 }
1670
1671 return STATUS_SUCCESS;
1672 }
1673 else
1674 {
1675 if(++Attempts > 2)
1676 {
1677 Status = KeWaitForSingleObject(&Process->LockEvent,
1678 Executive,
1679 KernelMode,
1680 FALSE,
1681 Delay);
1682 if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT)
1683 {
1684 #ifndef NDEBUG
1685 if(Status == STATUS_TIMEOUT)
1686 {
1687 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process);
1688 }
1689 #endif
1690 KeLeaveCriticalRegion();
1691 break;
1692 }
1693 }
1694 else
1695 {
1696 KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
1697 }
1698 }
1699 }
1700
1701 return Status;
1702 }
1703
1704 VOID
1705 PsUnlockProcess(PEPROCESS Process)
1706 {
1707 PAGED_CODE();
1708
1709 ASSERT(Process->LockOwner == KeGetCurrentThread());
1710
1711 if(InterlockedDecrementUL(&Process->LockCount) == 0)
1712 {
1713 InterlockedExchangePointer(&Process->LockOwner, NULL);
1714 KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
1715 }
1716
1717 KeLeaveCriticalRegion();
1718 }
1719
1720 /* EOF */