Thread/Process Termination/Repeaing Rewrite + Fixes
[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 ExInitializeFastMutex(&Process->TebLock);
671 Process->Pcb.State = PROCESS_STATE_ACTIVE;
672
673 /*
674 * Now we have created the process proper
675 */
676
677 MmLockAddressSpace(&Process->AddressSpace);
678
679 /* Protect the highest 64KB of the process address space */
680 BaseAddress = (PVOID)MmUserProbeAddress;
681 Status = MmCreateMemoryArea(Process,
682 &Process->AddressSpace,
683 MEMORY_AREA_NO_ACCESS,
684 &BaseAddress,
685 0x10000,
686 PAGE_NOACCESS,
687 &MemoryArea,
688 FALSE,
689 FALSE,
690 BoundaryAddressMultiple);
691 if (!NT_SUCCESS(Status))
692 {
693 MmUnlockAddressSpace(&Process->AddressSpace);
694 DPRINT1("Failed to protect the highest 64KB of the process address space\n");
695 ObDereferenceObject(Process);
696 goto exitdereferenceobjects;
697 }
698
699 /* Protect the lowest 64KB of the process address space */
700 #if 0
701 BaseAddress = (PVOID)0x00000000;
702 Status = MmCreateMemoryArea(Process,
703 &Process->AddressSpace,
704 MEMORY_AREA_NO_ACCESS,
705 &BaseAddress,
706 0x10000,
707 PAGE_NOACCESS,
708 &MemoryArea,
709 FALSE,
710 FALSE,
711 BoundaryAddressMultiple);
712 if (!NT_SUCCESS(Status))
713 {
714 MmUnlockAddressSpace(&Process->AddressSpace);
715 DPRINT1("Failed to protect the lowest 64KB of the process address space\n");
716 ObDereferenceObject(Process);
717 goto exitdereferenceobjects;
718 }
719 #endif
720
721 /* Protect the 60KB above the shared user page */
722 BaseAddress = (char*)USER_SHARED_DATA + PAGE_SIZE;
723 Status = MmCreateMemoryArea(Process,
724 &Process->AddressSpace,
725 MEMORY_AREA_NO_ACCESS,
726 &BaseAddress,
727 0x10000 - PAGE_SIZE,
728 PAGE_NOACCESS,
729 &MemoryArea,
730 FALSE,
731 FALSE,
732 BoundaryAddressMultiple);
733 if (!NT_SUCCESS(Status))
734 {
735 MmUnlockAddressSpace(&Process->AddressSpace);
736 DPRINT1("Failed to protect the memory above the shared user page\n");
737 ObDereferenceObject(Process);
738 goto exitdereferenceobjects;
739 }
740
741 /* Create the shared data page */
742 BaseAddress = (PVOID)USER_SHARED_DATA;
743 Status = MmCreateMemoryArea(Process,
744 &Process->AddressSpace,
745 MEMORY_AREA_SHARED_DATA,
746 &BaseAddress,
747 PAGE_SIZE,
748 PAGE_READONLY,
749 &MemoryArea,
750 FALSE,
751 FALSE,
752 BoundaryAddressMultiple);
753 MmUnlockAddressSpace(&Process->AddressSpace);
754 if (!NT_SUCCESS(Status))
755 {
756 DPRINT1("Failed to create shared data page\n");
757 ObDereferenceObject(Process);
758 goto exitdereferenceobjects;
759 }
760
761 #if 1
762 /*
763 * FIXME - the handle should be created after all things are initialized, NOT HERE!
764 */
765 Status = ObInsertObject ((PVOID)Process,
766 NULL,
767 DesiredAccess,
768 0,
769 NULL,
770 &hProcess);
771 if (!NT_SUCCESS(Status))
772 {
773 DPRINT1("Failed to create a handle for the process\n");
774 ObDereferenceObject(Process);
775 goto exitdereferenceobjects;
776 }
777 #endif
778
779 /*
780 * FIXME - Map ntdll
781 */
782 Status = LdrpMapSystemDll(hProcess, /* FIXME - hProcess shouldn't be available at this point! */
783 &LdrStartupAddr);
784 if (!NT_SUCCESS(Status))
785 {
786 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
787 ObDereferenceObject(Process);
788 goto exitdereferenceobjects;
789 }
790
791 /*
792 * Map the process image
793 */
794 if (SectionObject != NULL)
795 {
796 ULONG ViewSize = 0;
797 DPRINT("Mapping process image\n");
798 Status = MmMapViewOfSection(SectionObject,
799 Process,
800 (PVOID*)&ImageBase,
801 0,
802 ViewSize,
803 NULL,
804 &ViewSize,
805 0,
806 MEM_COMMIT,
807 PAGE_READWRITE);
808 ObDereferenceObject(SectionObject);
809 if (!NT_SUCCESS(Status))
810 {
811 DbgPrint("Failed to map the process section (Status %x)\n", Status);
812 ObDereferenceObject(Process);
813 goto exitdereferenceobjects;
814 }
815 }
816
817 if(pParentProcess != NULL)
818 {
819 /*
820 * Duplicate the token
821 */
822 Status = SepInitializeNewProcess(Process, pParentProcess);
823 if (!NT_SUCCESS(Status))
824 {
825 DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
826 ObDereferenceObject(Process);
827 goto exitdereferenceobjects;
828 }
829 }
830 else
831 {
832 /* FIXME */
833 }
834
835 /*
836 * FIXME - Create PEB
837 */
838 DPRINT("Creating PEB\n");
839 Status = PsCreatePeb(hProcess, /* FIXME - hProcess shouldn't be available at this point! */
840 Process,
841 ImageBase);
842 if (!NT_SUCCESS(Status))
843 {
844 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
845 ObDereferenceObject(Process);
846 goto exitdereferenceobjects;
847 }
848
849 /*
850 * Maybe send a message to the creator process's debugger
851 */
852 #if 0
853 if (pParentProcess->DebugPort != NULL)
854 {
855 LPC_DBG_MESSAGE Message;
856 HANDLE FileHandle;
857
858 ObCreateHandle(NULL, // Debugger Process
859 NULL, // SectionHandle
860 FILE_ALL_ACCESS,
861 FALSE,
862 &FileHandle);
863
864 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
865 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
866 sizeof(LPC_MESSAGE);
867 Message.Type = DBG_EVENT_CREATE_PROCESS;
868 Message.Data.CreateProcess.FileHandle = FileHandle;
869 Message.Data.CreateProcess.Base = ImageBase;
870 Message.Data.CreateProcess.EntryPoint = NULL; //
871
872 Status = LpcSendDebugMessagePort(pParentProcess->DebugPort,
873 &Message);
874 }
875 #endif
876
877 PspRunCreateProcessNotifyRoutines(Process, TRUE);
878
879 /*
880 * FIXME - the handle should be created not before this point!
881 */
882 #if 0
883 Status = ObInsertObject ((PVOID)Process,
884 NULL,
885 DesiredAccess,
886 0,
887 NULL,
888 &hProcess);
889 #endif
890 if (NT_SUCCESS(Status))
891 {
892 _SEH_TRY
893 {
894 *ProcessHandle = hProcess;
895 }
896 _SEH_HANDLE
897 {
898 Status = _SEH_GetExceptionCode();
899 }
900 _SEH_END;
901 }
902
903 /*
904 * don't dereference the debug port, exception port and section object even
905 * if ObInsertObject() failed, the process is alive! We just couldn't return
906 * the handle to the caller!
907 */
908
909 ObDereferenceObject(Process);
910 if(pParentProcess != NULL)
911 ObDereferenceObject(pParentProcess);
912
913 return Status;
914 }
915
916
917 /*
918 * @implemented
919 */
920 NTSTATUS STDCALL
921 PsCreateSystemProcess(PHANDLE ProcessHandle,
922 ACCESS_MASK DesiredAccess,
923 POBJECT_ATTRIBUTES ObjectAttributes)
924 {
925 return PspCreateProcess(ProcessHandle,
926 DesiredAccess,
927 ObjectAttributes,
928 NULL, /* no parent process */
929 FALSE,
930 NULL,
931 NULL,
932 NULL);
933 }
934
935
936 /*
937 * @implemented
938 */
939 NTSTATUS STDCALL
940 NtCreateProcess(OUT PHANDLE ProcessHandle,
941 IN ACCESS_MASK DesiredAccess,
942 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
943 IN HANDLE ParentProcess,
944 IN BOOLEAN InheritObjectTable,
945 IN HANDLE SectionHandle OPTIONAL,
946 IN HANDLE DebugPort OPTIONAL,
947 IN HANDLE ExceptionPort OPTIONAL)
948 /*
949 * FUNCTION: Creates a process.
950 * ARGUMENTS:
951 * ProcessHandle (OUT) = Caller supplied storage for the resulting
952 * handle
953 * DesiredAccess = Specifies the allowed or desired access to the
954 * process can be a combination of
955 * STANDARD_RIGHTS_REQUIRED| ..
956 * ObjectAttribute = Initialized attributes for the object, contains
957 * the rootdirectory and the filename
958 * ParentProcess = Handle to the parent process.
959 * InheritObjectTable = Specifies to inherit the objects of the parent
960 * process if true.
961 * SectionHandle = Handle to a section object to back the image file
962 * DebugPort = Handle to a DebugPort if NULL the system default debug
963 * port will be used.
964 * ExceptionPort = Handle to a exception port.
965 * REMARKS:
966 * This function maps to the win32 CreateProcess.
967 * RETURNS: Status
968 */
969 {
970 KPROCESSOR_MODE PreviousMode;
971 NTSTATUS Status = STATUS_SUCCESS;
972
973 PAGED_CODE();
974
975 PreviousMode = ExGetPreviousMode();
976
977 if(PreviousMode != KernelMode)
978 {
979 _SEH_TRY
980 {
981 ProbeForWrite(ProcessHandle,
982 sizeof(HANDLE),
983 sizeof(ULONG));
984 }
985 _SEH_HANDLE
986 {
987 Status = _SEH_GetExceptionCode();
988 }
989 _SEH_END;
990
991 if(!NT_SUCCESS(Status))
992 {
993 return Status;
994 }
995 }
996
997 if(ParentProcess == NULL)
998 {
999 Status = STATUS_INVALID_PARAMETER;
1000 }
1001 else
1002 {
1003 Status = PspCreateProcess(ProcessHandle,
1004 DesiredAccess,
1005 ObjectAttributes,
1006 ParentProcess,
1007 InheritObjectTable,
1008 SectionHandle,
1009 DebugPort,
1010 ExceptionPort);
1011 }
1012
1013 return Status;
1014 }
1015
1016
1017 /*
1018 * @unimplemented
1019 */
1020 NTSTATUS STDCALL
1021 NtOpenProcess(OUT PHANDLE ProcessHandle,
1022 IN ACCESS_MASK DesiredAccess,
1023 IN POBJECT_ATTRIBUTES ObjectAttributes,
1024 IN PCLIENT_ID ClientId)
1025 {
1026 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
1027 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
1028 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
1029 ClientId->UniqueProcess, ClientId->UniqueThread);
1030
1031 PAGED_CODE();
1032
1033 /*
1034 * Not sure of the exact semantics
1035 */
1036 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
1037 ObjectAttributes->ObjectName->Buffer != NULL)
1038 {
1039 NTSTATUS Status;
1040 PEPROCESS Process;
1041
1042 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
1043 ObjectAttributes->Attributes,
1044 NULL,
1045 DesiredAccess,
1046 PsProcessType,
1047 UserMode,
1048 NULL,
1049 (PVOID*)&Process);
1050 if (Status != STATUS_SUCCESS)
1051 {
1052 return(Status);
1053 }
1054
1055 Status = ObCreateHandle(PsGetCurrentProcess(),
1056 Process,
1057 DesiredAccess,
1058 FALSE,
1059 ProcessHandle);
1060 ObDereferenceObject(Process);
1061
1062 return(Status);
1063 }
1064 else
1065 {
1066 PLIST_ENTRY current_entry;
1067 PEPROCESS current;
1068 NTSTATUS Status;
1069
1070 ExAcquireFastMutex(&PspActiveProcessMutex);
1071 current_entry = PsActiveProcessHead.Flink;
1072 while (current_entry != &PsActiveProcessHead)
1073 {
1074 current = CONTAINING_RECORD(current_entry, EPROCESS,
1075 ProcessListEntry);
1076 if (current->UniqueProcessId == ClientId->UniqueProcess)
1077 {
1078 if (current->Pcb.State == PROCESS_STATE_TERMINATED)
1079 {
1080 Status = STATUS_PROCESS_IS_TERMINATING;
1081 }
1082 else
1083 {
1084 Status = ObReferenceObjectByPointer(current,
1085 DesiredAccess,
1086 PsProcessType,
1087 UserMode);
1088 }
1089 ExReleaseFastMutex(&PspActiveProcessMutex);
1090 if (NT_SUCCESS(Status))
1091 {
1092 Status = ObCreateHandle(PsGetCurrentProcess(),
1093 current,
1094 DesiredAccess,
1095 FALSE,
1096 ProcessHandle);
1097 ObDereferenceObject(current);
1098 DPRINT("*ProcessHandle %x\n", ProcessHandle);
1099 DPRINT("NtOpenProcess() = %x\n", Status);
1100 }
1101 return(Status);
1102 }
1103 current_entry = current_entry->Flink;
1104 }
1105 ExReleaseFastMutex(&PspActiveProcessMutex);
1106 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
1107 return(STATUS_UNSUCCESSFUL);
1108 }
1109 }
1110
1111 /*
1112 * @implemented
1113 */
1114 LARGE_INTEGER STDCALL
1115 PsGetProcessExitTime(VOID)
1116 {
1117 LARGE_INTEGER Li;
1118 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1119 return Li;
1120 }
1121
1122 /*
1123 * @implemented
1124 */
1125 LONGLONG
1126 STDCALL
1127 PsGetProcessCreateTimeQuadPart(
1128 PEPROCESS Process
1129 )
1130 {
1131 return Process->CreateTime.QuadPart;
1132 }
1133
1134 /*
1135 * @implemented
1136 */
1137 PVOID
1138 STDCALL
1139 PsGetProcessDebugPort(
1140 PEPROCESS Process
1141 )
1142 {
1143 return Process->DebugPort;
1144 }
1145
1146 /*
1147 * @implemented
1148 */
1149 BOOLEAN
1150 STDCALL
1151 PsGetProcessExitProcessCalled(
1152 PEPROCESS Process
1153 )
1154 {
1155 return Process->ExitProcessCalled;
1156 }
1157
1158 /*
1159 * @implemented
1160 */
1161 NTSTATUS
1162 STDCALL
1163 PsGetProcessExitStatus(
1164 PEPROCESS Process
1165 )
1166 {
1167 return Process->ExitStatus;
1168 }
1169
1170 /*
1171 * @implemented
1172 */
1173 HANDLE
1174 STDCALL
1175 PsGetProcessId(
1176 PEPROCESS Process
1177 )
1178 {
1179 return (HANDLE)Process->UniqueProcessId;
1180 }
1181
1182 /*
1183 * @implemented
1184 */
1185 LPSTR
1186 STDCALL
1187 PsGetProcessImageFileName(
1188 PEPROCESS Process
1189 )
1190 {
1191 return (LPSTR)Process->ImageFileName;
1192 }
1193
1194 /*
1195 * @implemented
1196 */
1197 HANDLE
1198 STDCALL
1199 PsGetProcessInheritedFromUniqueProcessId(
1200 PEPROCESS Process
1201 )
1202 {
1203 return Process->InheritedFromUniqueProcessId;
1204 }
1205
1206 /*
1207 * @implemented
1208 */
1209 PEJOB
1210 STDCALL
1211 PsGetProcessJob(
1212 PEPROCESS Process
1213 )
1214 {
1215 return Process->Job;
1216 }
1217
1218 /*
1219 * @implemented
1220 */
1221 PPEB
1222 STDCALL
1223 PsGetProcessPeb(
1224 PEPROCESS Process
1225 )
1226 {
1227 return Process->Peb;
1228 }
1229
1230 /*
1231 * @implemented
1232 */
1233 ULONG
1234 STDCALL
1235 PsGetProcessPriorityClass(
1236 PEPROCESS Process
1237 )
1238 {
1239 return Process->PriorityClass;
1240 }
1241
1242 /*
1243 * @implemented
1244 */
1245 PVOID
1246 STDCALL
1247 PsGetProcessSectionBaseAddress(
1248 PEPROCESS Process
1249 )
1250 {
1251 return Process->SectionBaseAddress;
1252 }
1253
1254 /*
1255 * @implemented
1256 */
1257 PVOID
1258 STDCALL
1259 PsGetProcessSecurityPort(
1260 PEPROCESS Process
1261 )
1262 {
1263 return Process->SecurityPort;
1264 }
1265
1266 /*
1267 * @implemented
1268 */
1269 HANDLE
1270 STDCALL
1271 PsGetProcessSessionId(
1272 PEPROCESS Process
1273 )
1274 {
1275 return (HANDLE)Process->SessionId;
1276 }
1277
1278 /*
1279 * @implemented
1280 */
1281 PVOID
1282 STDCALL
1283 PsGetProcessWin32Process(
1284 PEPROCESS Process
1285 )
1286 {
1287 return Process->Win32Process;
1288 }
1289
1290 /*
1291 * @implemented
1292 */
1293 PVOID
1294 STDCALL
1295 PsGetProcessWin32WindowStation(
1296 PEPROCESS Process
1297 )
1298 {
1299 return Process->Win32WindowStation;
1300 }
1301
1302 /*
1303 * @implemented
1304 */
1305 BOOLEAN
1306 STDCALL
1307 PsIsProcessBeingDebugged(
1308 PEPROCESS Process
1309 )
1310 {
1311 return FALSE/*Process->IsProcessBeingDebugged*/;
1312 }
1313
1314
1315 /*
1316 * @implemented
1317 */
1318 NTSTATUS STDCALL
1319 PsLookupProcessByProcessId(IN HANDLE ProcessId,
1320 OUT PEPROCESS *Process)
1321 {
1322 PHANDLE_TABLE_ENTRY CidEntry;
1323 PEPROCESS FoundProcess;
1324
1325 PAGED_CODE();
1326
1327 ASSERT(Process);
1328
1329 CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess);
1330 if(CidEntry != NULL)
1331 {
1332 ObReferenceObject(FoundProcess);
1333
1334 PsUnlockCidHandle(CidEntry);
1335
1336 *Process = FoundProcess;
1337 return STATUS_SUCCESS;
1338 }
1339
1340 return STATUS_INVALID_PARAMETER;
1341 }
1342
1343 VOID
1344 STDCALL
1345 PspRunCreateProcessNotifyRoutines
1346 (
1347 PEPROCESS CurrentProcess,
1348 BOOLEAN Create
1349 )
1350 {
1351 ULONG i;
1352 HANDLE ProcessId = (HANDLE)CurrentProcess->UniqueProcessId;
1353 HANDLE ParentId = CurrentProcess->InheritedFromUniqueProcessId;
1354
1355 for(i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
1356 if(PiProcessNotifyRoutine[i])
1357 PiProcessNotifyRoutine[i](ParentId, ProcessId, Create);
1358 }
1359
1360 /*
1361 * @implemented
1362 */
1363 NTSTATUS STDCALL
1364 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
1365 IN BOOLEAN Remove)
1366 {
1367 ULONG i;
1368
1369 if (Remove)
1370 {
1371 for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
1372 {
1373 if ((PVOID)PiProcessNotifyRoutine[i] == (PVOID)NotifyRoutine)
1374 {
1375 PiProcessNotifyRoutine[i] = NULL;
1376 break;
1377 }
1378 }
1379
1380 return(STATUS_SUCCESS);
1381 }
1382
1383 /*insert*/
1384 for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
1385 {
1386 if (PiProcessNotifyRoutine[i] == NULL)
1387 {
1388 PiProcessNotifyRoutine[i] = NotifyRoutine;
1389 break;
1390 }
1391 }
1392
1393 if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1394 {
1395 return STATUS_INSUFFICIENT_RESOURCES;
1396 }
1397
1398 return STATUS_SUCCESS;
1399 }
1400
1401 VOID STDCALL
1402 PspRunLoadImageNotifyRoutines(
1403 PUNICODE_STRING FullImageName,
1404 HANDLE ProcessId,
1405 PIMAGE_INFO ImageInfo)
1406 {
1407 ULONG i;
1408
1409 for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
1410 if (PiLoadImageNotifyRoutine[i])
1411 PiLoadImageNotifyRoutine[i](FullImageName, ProcessId, ImageInfo);
1412 }
1413
1414 /*
1415 * @unimplemented
1416 */
1417 NTSTATUS
1418 STDCALL
1419 PsRemoveLoadImageNotifyRoutine(
1420 IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine
1421 )
1422 {
1423 UNIMPLEMENTED;
1424 return STATUS_NOT_IMPLEMENTED;
1425 }
1426
1427 /*
1428 * @implemented
1429 */
1430 NTSTATUS STDCALL
1431 PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
1432 {
1433 ULONG i;
1434
1435 for (i = 0; i < MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT; i++)
1436 {
1437 if (PiLoadImageNotifyRoutine[i] == NULL)
1438 {
1439 PiLoadImageNotifyRoutine[i] = NotifyRoutine;
1440 break;
1441 }
1442 }
1443
1444 if (i == MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1445 {
1446 return STATUS_INSUFFICIENT_RESOURCES;
1447 }
1448
1449 return STATUS_SUCCESS;
1450 }
1451
1452 /*
1453 * @implemented
1454 */
1455 VOID
1456 STDCALL
1457 PsSetProcessPriorityClass(
1458 PEPROCESS Process,
1459 ULONG PriorityClass
1460 )
1461 {
1462 Process->PriorityClass = PriorityClass;
1463 }
1464
1465 /*
1466 * @implemented
1467 */
1468 VOID
1469 STDCALL
1470 PsSetProcessSecurityPort(
1471 PEPROCESS Process,
1472 PVOID SecurityPort
1473 )
1474 {
1475 Process->SecurityPort = SecurityPort;
1476 }
1477
1478 /*
1479 * @implemented
1480 */
1481 VOID
1482 STDCALL
1483 PsSetProcessWin32Process(
1484 PEPROCESS Process,
1485 PVOID Win32Process
1486 )
1487 {
1488 Process->Win32Process = Win32Process;
1489 }
1490
1491 /*
1492 * @implemented
1493 */
1494 VOID
1495 STDCALL
1496 PsSetProcessWin32WindowStation(
1497 PEPROCESS Process,
1498 PVOID WindowStation
1499 )
1500 {
1501 Process->Win32WindowStation = WindowStation;
1502 }
1503
1504 /* Pool Quotas */
1505 /*
1506 * @implemented
1507 */
1508 VOID
1509 STDCALL
1510 PsChargePoolQuota(
1511 IN PEPROCESS Process,
1512 IN POOL_TYPE PoolType,
1513 IN ULONG_PTR Amount
1514 )
1515 {
1516 NTSTATUS Status;
1517
1518 /* Charge the usage */
1519 Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
1520
1521 /* Raise Exception */
1522 if (!NT_SUCCESS(Status)) {
1523 ExRaiseStatus(Status);
1524 }
1525 }
1526
1527 /*
1528 * @implemented
1529 */
1530 NTSTATUS
1531 STDCALL
1532 PsChargeProcessNonPagedPoolQuota (
1533 IN PEPROCESS Process,
1534 IN ULONG_PTR Amount
1535 )
1536 {
1537 /* Call the general function */
1538 return PsChargeProcessPoolQuota(Process, NonPagedPool, Amount);
1539 }
1540
1541 /*
1542 * @implemented
1543 */
1544 NTSTATUS
1545 STDCALL
1546 PsChargeProcessPagedPoolQuota (
1547 IN PEPROCESS Process,
1548 IN ULONG_PTR Amount
1549 )
1550 {
1551 /* Call the general function */
1552 return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
1553 }
1554
1555 /*
1556 * @implemented
1557 */
1558 NTSTATUS
1559 STDCALL
1560 PsChargeProcessPoolQuota(
1561 IN PEPROCESS Process,
1562 IN POOL_TYPE PoolType,
1563 IN ULONG_PTR Amount
1564 )
1565 {
1566 PEPROCESS_QUOTA_BLOCK QuotaBlock;
1567 ULONG NewUsageSize;
1568 ULONG NewMaxQuota;
1569
1570 /* Get current Quota Block */
1571 QuotaBlock = Process->QuotaBlock;
1572
1573 /* Quota Operations are not to be done on the SYSTEM Process */
1574 if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
1575
1576 /* New Size in use */
1577 NewUsageSize = QuotaBlock->QuotaEntry[PoolType].Usage + Amount;
1578
1579 /* Does this size respect the quota? */
1580 if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Limit) {
1581
1582 /* It doesn't, so keep raising the Quota */
1583 while (MiRaisePoolQuota(PoolType, QuotaBlock->QuotaEntry[PoolType].Limit, &NewMaxQuota)) {
1584 /* Save new Maximum Quota */
1585 QuotaBlock->QuotaEntry[PoolType].Limit = NewMaxQuota;
1586
1587 /* See if the new Maximum Quota fulfills our need */
1588 if (NewUsageSize <= NewMaxQuota) goto QuotaChanged;
1589 }
1590
1591 return STATUS_QUOTA_EXCEEDED;
1592 }
1593
1594 QuotaChanged:
1595 /* Save new Usage */
1596 QuotaBlock->QuotaEntry[PoolType].Usage = NewUsageSize;
1597
1598 /* Is this a new peak? */
1599 if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Peak) {
1600 QuotaBlock->QuotaEntry[PoolType].Peak = NewUsageSize;
1601 }
1602
1603 /* All went well */
1604 return STATUS_SUCCESS;
1605 }
1606
1607 /*
1608 * @unimplemented
1609 */
1610 VOID
1611 STDCALL
1612 PsReturnPoolQuota(
1613 IN PEPROCESS Process,
1614 IN POOL_TYPE PoolType,
1615 IN ULONG_PTR Amount
1616 )
1617 {
1618 UNIMPLEMENTED;
1619 }
1620
1621 /*
1622 * @unimplemented
1623 */
1624 VOID
1625 STDCALL
1626 PsReturnProcessNonPagedPoolQuota(
1627 IN PEPROCESS Process,
1628 IN ULONG_PTR Amount
1629 )
1630 {
1631 UNIMPLEMENTED;
1632 }
1633
1634 /*
1635 * @unimplemented
1636 */
1637 VOID
1638 STDCALL
1639 PsReturnProcessPagedPoolQuota(
1640 IN PEPROCESS Process,
1641 IN ULONG_PTR Amount
1642 )
1643 {
1644 UNIMPLEMENTED;
1645 }
1646
1647 NTSTATUS
1648 PsLockProcess(PEPROCESS Process, BOOL Timeout)
1649 {
1650 ULONG Attempts = 0;
1651 PKTHREAD PrevLockOwner;
1652 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1653 PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL);
1654 PKTHREAD CallingThread = KeGetCurrentThread();
1655
1656 PAGED_CODE();
1657
1658 KeEnterCriticalRegion();
1659
1660 for(;;)
1661 {
1662 PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
1663 &Process->LockOwner, CallingThread, NULL);
1664 if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
1665 {
1666 /* we got the lock or already locked it */
1667 if(InterlockedIncrementUL(&Process->LockCount) == 1)
1668 {
1669 KeClearEvent(&Process->LockEvent);
1670 }
1671
1672 return STATUS_SUCCESS;
1673 }
1674 else
1675 {
1676 if(++Attempts > 2)
1677 {
1678 Status = KeWaitForSingleObject(&Process->LockEvent,
1679 Executive,
1680 KernelMode,
1681 FALSE,
1682 Delay);
1683 if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT)
1684 {
1685 #ifndef NDEBUG
1686 if(Status == STATUS_TIMEOUT)
1687 {
1688 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process);
1689 }
1690 #endif
1691 KeLeaveCriticalRegion();
1692
1693 }
1694 break;
1695 }
1696 else
1697 {
1698 KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
1699 }
1700 }
1701 }
1702
1703 return Status;
1704 }
1705
1706 VOID
1707 PsUnlockProcess(PEPROCESS Process)
1708 {
1709 PAGED_CODE();
1710
1711 ASSERT(Process->LockOwner == KeGetCurrentThread());
1712
1713 if(InterlockedDecrementUL(&Process->LockCount) == 0)
1714 {
1715 InterlockedExchangePointer(&Process->LockOwner, NULL);
1716 KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
1717 }
1718
1719 KeLeaveCriticalRegion();
1720 }
1721
1722 /* EOF */