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