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