8391c29132d1618632cd51a83c300bf6f997c9ee
[reactos.git] / reactos / ntoskrnl / ps / process.c
1 /* $Id: process.c,v 1.73 2002/01/03 12:48:02 chorns Exp $
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 <limits.h>
15 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
17 #include <internal/mm.h>
18 #include <internal/ke.h>
19 #include <internal/ps.h>
20 #include <internal/id.h>
21 #include <napi/teb.h>
22 #include <internal/ldr.h>
23 #include <internal/port.h>
24 #include <napi/dbg.h>
25 #include <internal/dbg.h>
26 #include <napi/shared_data.h>
27 #include <internal/pool.h>
28 #include <roscfg.h>
29
30 #define NDEBUG
31 #include <internal/debug.h>
32
33 /* GLOBALS ******************************************************************/
34
35 PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
36 HANDLE SystemProcessHandle = NULL;
37
38 POBJECT_TYPE EXPORTED PsProcessType = NULL;
39
40 LIST_ENTRY PsProcessListHead;
41 static KSPIN_LOCK PsProcessListLock;
42 static ULONG PiNextProcessUniqueId = 0;
43
44 static GENERIC_MAPPING PiProcessMapping = {PROCESS_READ,
45 PROCESS_WRITE,
46 PROCESS_EXECUTE,
47 PROCESS_ALL_ACCESS};
48
49 /* FUNCTIONS *****************************************************************/
50
51
52 PEPROCESS
53 PsGetNextProcess(PEPROCESS OldProcess)
54 {
55 KIRQL oldIrql;
56 PEPROCESS NextProcess;
57 NTSTATUS Status;
58
59 if (OldProcess == NULL)
60 {
61 return(PsInitialSystemProcess);
62 }
63
64 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
65 if (OldProcess->ProcessListEntry.Flink == &PsProcessListHead)
66 {
67 NextProcess = CONTAINING_RECORD(PsProcessListHead.Flink,
68 EPROCESS,
69 ProcessListEntry);
70 }
71 else
72 {
73 NextProcess = CONTAINING_RECORD(OldProcess->ProcessListEntry.Flink,
74 EPROCESS,
75 ProcessListEntry);
76 }
77 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
78 Status = ObReferenceObjectByPointer(NextProcess,
79 PROCESS_ALL_ACCESS,
80 PsProcessType,
81 KernelMode);
82 if (!NT_SUCCESS(Status))
83 {
84 DbgPrint("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
85 KeBugCheck(0);
86 }
87 ObDereferenceObject(OldProcess);
88
89 return(NextProcess);
90 }
91
92 NTSTATUS STDCALL
93 NtOpenProcessToken(IN HANDLE ProcessHandle,
94 IN ACCESS_MASK DesiredAccess,
95 OUT PHANDLE TokenHandle)
96 {
97 return(STATUS_UNSUCCESSFUL);
98 }
99
100 NTSTATUS STDCALL
101 _NtOpenProcessToken(IN HANDLE ProcessHandle,
102 IN ACCESS_MASK DesiredAccess,
103 OUT PHANDLE TokenHandle)
104 {
105 PACCESS_TOKEN Token;
106 NTSTATUS Status;
107
108 Status = PsOpenTokenOfProcess(ProcessHandle,
109 &Token);
110 if (!NT_SUCCESS(Status))
111 {
112 return(Status);
113 }
114 Status = ObCreateHandle(PsGetCurrentProcess(),
115 Token,
116 DesiredAccess,
117 FALSE,
118 ProcessHandle);
119 ObDereferenceObject(Token);
120 return(Status);
121 }
122
123
124 PACCESS_TOKEN STDCALL
125 PsReferencePrimaryToken(PEPROCESS Process)
126 {
127 ObReferenceObjectByPointer(Process->Token,
128 TOKEN_ALL_ACCESS,
129 SeTokenType,
130 UserMode);
131 return(Process->Token);
132 }
133
134
135 NTSTATUS
136 PsOpenTokenOfProcess(HANDLE ProcessHandle,
137 PACCESS_TOKEN* Token)
138 {
139 PEPROCESS Process;
140 NTSTATUS Status;
141
142 Status = ObReferenceObjectByHandle(ProcessHandle,
143 PROCESS_QUERY_INFORMATION,
144 PsProcessType,
145 UserMode,
146 (PVOID*)&Process,
147 NULL);
148 if (!NT_SUCCESS(Status))
149 {
150 return(Status);
151 }
152 *Token = PsReferencePrimaryToken(Process);
153 ObDereferenceObject(Process);
154 return(STATUS_SUCCESS);
155 }
156
157
158 VOID
159 PiKillMostProcesses(VOID)
160 {
161 KIRQL oldIrql;
162 PLIST_ENTRY current_entry;
163 PEPROCESS current;
164
165 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
166
167 current_entry = PsProcessListHead.Flink;
168 while (current_entry != &PsProcessListHead)
169 {
170 current = CONTAINING_RECORD(current_entry, EPROCESS,
171 ProcessListEntry);
172 current_entry = current_entry->Flink;
173
174 if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
175 current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
176 {
177 PiTerminateProcessThreads(current, STATUS_SUCCESS);
178 }
179 }
180
181 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
182 }
183
184
185 VOID
186 PsInitProcessManagment(VOID)
187 {
188
189 PKPROCESS KProcess;
190 KIRQL oldIrql;
191 NTSTATUS Status;
192
193 /*
194 * Register the process object type
195 */
196
197 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
198
199 PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
200 PsProcessType->TotalObjects = 0;
201 PsProcessType->TotalHandles = 0;
202 PsProcessType->MaxObjects = ULONG_MAX;
203 PsProcessType->MaxHandles = ULONG_MAX;
204 PsProcessType->PagedPoolCharge = 0;
205 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
206 PsProcessType->Mapping = &PiProcessMapping;
207 PsProcessType->Dump = NULL;
208 PsProcessType->Open = NULL;
209 PsProcessType->Close = NULL;
210 PsProcessType->Delete = PiDeleteProcess;
211 PsProcessType->Parse = NULL;
212 PsProcessType->Security = NULL;
213 PsProcessType->QueryName = NULL;
214 PsProcessType->OkayToClose = NULL;
215 PsProcessType->Create = NULL;
216 PsProcessType->DuplicationNotify = NULL;
217
218 RtlInitUnicodeString(&PsProcessType->TypeName, L"Process");
219
220 InitializeListHead(&PsProcessListHead);
221 KeInitializeSpinLock(&PsProcessListLock);
222
223 /*
224 * Initialize the system process
225 */
226 Status = ObCreateObject(NULL,
227 PROCESS_ALL_ACCESS,
228 NULL,
229 PsProcessType,
230 (PVOID*)&PsInitialSystemProcess);
231 if (!NT_SUCCESS(Status))
232 {
233 return;
234 }
235
236 /* System threads may run on any processor. */
237 PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
238 PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
239 KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
240 InternalProcessType,
241 sizeof(EPROCESS),
242 FALSE);
243 KProcess = &PsInitialSystemProcess->Pcb;
244
245 MmInitializeAddressSpace(PsInitialSystemProcess,
246 &PsInitialSystemProcess->AddressSpace);
247 ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess);
248 KProcess->DirectoryTableBase[0] = MmGetPageDirectory();
249 PsInitialSystemProcess->UniqueProcessId =
250 InterlockedIncrement(&PiNextProcessUniqueId);
251
252 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
253 InsertHeadList(&PsProcessListHead,
254 &PsInitialSystemProcess->ProcessListEntry);
255 InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
256 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
257
258 strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM");
259
260 ObCreateHandle(PsInitialSystemProcess,
261 PsInitialSystemProcess,
262 PROCESS_ALL_ACCESS,
263 FALSE,
264 &SystemProcessHandle);
265 }
266
267 #ifdef KDBG
268
269 VOID
270 PiFreeSymbols(PPEB Peb)
271 {
272 PLIST_ENTRY CurrentEntry;
273 PLDR_MODULE Current;
274 PSYMBOL NextSymbol;
275 PSYMBOL Symbol;
276
277 assert (Peb);
278 assert (Peb->Ldr);
279
280 CurrentEntry = Peb->Ldr->InLoadOrderModuleList.Flink;
281 while ((CurrentEntry != &Peb->Ldr->InLoadOrderModuleList) && (CurrentEntry != NULL))
282 {
283 Current = CONTAINING_RECORD (CurrentEntry, LDR_MODULE, InLoadOrderModuleList);
284 Symbol = Current->Symbols.Symbols;
285 while (Symbol != NULL)
286 {
287 NextSymbol = Symbol->Next;
288 RtlFreeUnicodeString (&Symbol->Name);
289 ExFreePool (Symbol);
290 Symbol = NextSymbol;
291 }
292 Current->Symbols.SymbolCount = 0;
293 Current->Symbols.Symbols = NULL;
294 CurrentEntry = CurrentEntry->Flink;
295 }
296 }
297
298 #endif /* KDBG */
299
300 VOID STDCALL
301 PiDeleteProcess(PVOID ObjectBody)
302 {
303 KIRQL oldIrql;
304
305 DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody);
306
307 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
308 RemoveEntryList(&((PEPROCESS)ObjectBody)->ProcessListEntry);
309 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
310
311 #ifdef KDBG
312 PiFreeSymbols(((PEPROCESS)ObjectBody)->Peb);
313 #endif /* KDBG */
314
315 (VOID)MmReleaseMmInfo((PEPROCESS)ObjectBody);
316 ObDeleteHandleTable((PEPROCESS)ObjectBody);
317 }
318
319
320 static NTSTATUS
321 PsCreatePeb(HANDLE ProcessHandle,
322 PVOID ImageBase,
323 PVOID* RPeb)
324 {
325 NTSTATUS Status;
326 PVOID PebBase;
327 ULONG PebSize;
328 PEB Peb;
329 ULONG BytesWritten;
330
331 memset(&Peb, 0, sizeof(Peb));
332 Peb.ImageBaseAddress = ImageBase;
333
334 PebBase = (PVOID)PEB_BASE;
335 PebSize = 0x1000;
336 Status = NtAllocateVirtualMemory(ProcessHandle,
337 &PebBase,
338 0,
339 &PebSize,
340 MEM_RESERVE | MEM_COMMIT,
341 PAGE_READWRITE);
342 if (!NT_SUCCESS(Status))
343 {
344 return(Status);
345 }
346
347 NtWriteVirtualMemory(ProcessHandle,
348 (PVOID)PEB_BASE,
349 &Peb,
350 sizeof(Peb),
351 &BytesWritten);
352
353 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase);
354
355 *RPeb = PebBase;
356
357 return(STATUS_SUCCESS);
358 }
359
360
361 PKPROCESS
362 KeGetCurrentProcess(VOID)
363 /*
364 * FUNCTION: Returns a pointer to the current process
365 */
366 {
367 return(&(PsGetCurrentProcess()->Pcb));
368 }
369
370 HANDLE STDCALL
371 PsGetCurrentProcessId(VOID)
372 {
373 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
374 }
375
376 /*
377 * FUNCTION: Returns a pointer to the current process
378 */
379 PEPROCESS STDCALL
380 PsGetCurrentProcess(VOID)
381 {
382 if (PsGetCurrentThread() == NULL ||
383 PsGetCurrentThread()->ThreadsProcess == NULL)
384 {
385 return(PsInitialSystemProcess);
386 }
387 else
388 {
389 return(PsGetCurrentThread()->ThreadsProcess);
390 }
391 }
392
393 PEPROCESS STDCALL
394 IoGetCurrentProcess(VOID)
395 {
396 return(PsGetCurrentProcess());
397 }
398
399 NTSTATUS STDCALL
400 PsCreateSystemProcess(PHANDLE ProcessHandle,
401 ACCESS_MASK DesiredAccess,
402 POBJECT_ATTRIBUTES ObjectAttributes)
403 {
404 return NtCreateProcess(ProcessHandle,
405 DesiredAccess,
406 ObjectAttributes,
407 SystemProcessHandle,
408 FALSE,
409 NULL,
410 NULL,
411 NULL);
412 }
413
414 NTSTATUS STDCALL
415 NtCreateProcess(OUT PHANDLE ProcessHandle,
416 IN ACCESS_MASK DesiredAccess,
417 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
418 IN HANDLE ParentProcessHandle,
419 IN BOOLEAN InheritObjectTable,
420 IN HANDLE SectionHandle OPTIONAL,
421 IN HANDLE DebugPortHandle OPTIONAL,
422 IN HANDLE ExceptionPortHandle OPTIONAL)
423 /*
424 * FUNCTION: Creates a process.
425 * ARGUMENTS:
426 * ProcessHandle (OUT) = Caller supplied storage for the resulting
427 * handle
428 * DesiredAccess = Specifies the allowed or desired access to the
429 * process can be a combination of
430 * STANDARD_RIGHTS_REQUIRED| ..
431 * ObjectAttribute = Initialized attributes for the object, contains
432 * the rootdirectory and the filename
433 * ParentProcess = Handle to the parent process.
434 * InheritObjectTable = Specifies to inherit the objects of the parent
435 * process if true.
436 * SectionHandle = Handle to a section object to back the image file
437 * DebugPort = Handle to a DebugPort if NULL the system default debug
438 * port will be used.
439 * ExceptionPort = Handle to a exception port.
440 * REMARKS:
441 * This function maps to the win32 CreateProcess.
442 * RETURNS: Status
443 */
444 {
445 PEPROCESS Process;
446 PEPROCESS ParentProcess;
447 PKPROCESS KProcess;
448 NTSTATUS Status;
449 KIRQL oldIrql;
450 PVOID LdrStartupAddr;
451 PVOID ImageBase;
452 PVOID Peb;
453 PEPORT DebugPort;
454 PEPORT ExceptionPort;
455 PVOID BaseAddress;
456 PMEMORY_AREA MemoryArea;
457
458 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
459
460 Status = ObReferenceObjectByHandle(ParentProcessHandle,
461 PROCESS_CREATE_PROCESS,
462 PsProcessType,
463 UserMode,
464 (PVOID*)&ParentProcess,
465 NULL);
466 if (!NT_SUCCESS(Status))
467 {
468 DPRINT("NtCreateProcess() = %x\n",Status);
469 return(Status);
470 }
471
472 Status = ObCreateObject(ProcessHandle,
473 DesiredAccess,
474 ObjectAttributes,
475 PsProcessType,
476 (PVOID*)&Process);
477 if (!NT_SUCCESS(Status))
478 {
479 ObDereferenceObject(ParentProcess);
480 DPRINT("ObCreateObject() = %x\n",Status);
481 return(Status);
482 }
483
484 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
485 InternalProcessType,
486 sizeof(EPROCESS),
487 FALSE);
488 KProcess = &Process->Pcb;
489 /* Inherit parent process's affinity. */
490 KProcess->Affinity = ParentProcess->Pcb.Affinity;
491 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
492 MmInitializeAddressSpace(Process,
493 &Process->AddressSpace);
494 Process->UniqueProcessId = InterlockedIncrement(&PiNextProcessUniqueId);
495 Process->InheritedFromUniqueProcessId =
496 (HANDLE)ParentProcess->UniqueProcessId;
497 ObCreateHandleTable(ParentProcess,
498 InheritObjectTable,
499 Process);
500 MmCopyMmInfo(ParentProcess, Process);
501
502 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
503 InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
504 InitializeListHead(&Process->ThreadListHead);
505 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
506
507 Process->Pcb.State = PROCESS_STATE_ACTIVE;
508
509 /*
510 * Add the debug port
511 */
512 if (DebugPortHandle != NULL)
513 {
514 Status = ObReferenceObjectByHandle(DebugPortHandle,
515 PORT_ALL_ACCESS,
516 ExPortType,
517 UserMode,
518 (PVOID*)&DebugPort,
519 NULL);
520 if (!NT_SUCCESS(Status))
521 {
522 ObDereferenceObject(Process);
523 ObDereferenceObject(ParentProcess);
524 ZwClose(*ProcessHandle);
525 *ProcessHandle = NULL;
526 return(Status);
527 }
528 Process->DebugPort = DebugPort;
529 }
530
531 /*
532 * Add the exception port
533 */
534 if (ExceptionPortHandle != NULL)
535 {
536 Status = ObReferenceObjectByHandle(ExceptionPortHandle,
537 PORT_ALL_ACCESS,
538 ExPortType,
539 UserMode,
540 (PVOID*)&ExceptionPort,
541 NULL);
542 if (!NT_SUCCESS(Status))
543 {
544 ObDereferenceObject(Process);
545 ObDereferenceObject(ParentProcess);
546 ZwClose(*ProcessHandle);
547 *ProcessHandle = NULL;
548 return(Status);
549 }
550 Process->ExceptionPort = ExceptionPort;
551 }
552
553 /*
554 * Now we have created the process proper
555 */
556
557 /*
558 * Create the shared data page
559 */
560 MmLockAddressSpace(&Process->AddressSpace);
561 BaseAddress = (PVOID)USER_SHARED_DATA_BASE;
562 Status = MmCreateMemoryArea(Process,
563 &Process->AddressSpace,
564 MEMORY_AREA_SHARED_DATA,
565 &BaseAddress,
566 PAGESIZE,
567 PAGE_READONLY,
568 &MemoryArea,
569 FALSE);
570 MmUnlockAddressSpace(&Process->AddressSpace);
571 if (!NT_SUCCESS(Status))
572 {
573 DPRINT1("Failed to create shared data page\n");
574 KeBugCheck(0);
575 }
576
577 /*
578 * Map ntdll
579 */
580 Status = LdrpMapSystemDll(*ProcessHandle,
581 &LdrStartupAddr);
582 if (!NT_SUCCESS(Status))
583 {
584 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
585 ObDereferenceObject(Process);
586 ObDereferenceObject(ParentProcess);
587 return(Status);
588 }
589
590 /*
591 * Map the process image
592 */
593 if (SectionHandle != NULL)
594 {
595 DPRINT("Mapping process image\n");
596 Status = LdrpMapImage(*ProcessHandle,
597 SectionHandle,
598 &ImageBase);
599 if (!NT_SUCCESS(Status))
600 {
601 DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
602 ObDereferenceObject(Process);
603 ObDereferenceObject(ParentProcess);
604 return(Status);
605 }
606 }
607 else
608 {
609 ImageBase = NULL;
610 }
611
612 /*
613 *
614 */
615 DPRINT("Creating PEB\n");
616 Status = PsCreatePeb(*ProcessHandle,
617 ImageBase,
618 &Peb);
619 if (!NT_SUCCESS(Status))
620 {
621 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
622 ObDereferenceObject(Process);
623 ObDereferenceObject(ParentProcess);
624 ZwClose(*ProcessHandle);
625 *ProcessHandle = NULL;
626 return(Status);
627 }
628 Process->Peb = Peb;
629
630 /*
631 * Maybe send a message to the creator process's debugger
632 */
633 #if 0
634 if (ParentProcess->DebugPort != NULL)
635 {
636 LPC_DBG_MESSAGE Message;
637 HANDLE FileHandle;
638
639 ObCreateHandle(NULL, // Debugger Process
640 NULL, // SectionHandle
641 FILE_ALL_ACCESS,
642 FALSE,
643 &FileHandle);
644
645 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
646 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
647 sizeof(LPC_MESSAGE_HEADER);
648 Message.Type = DBG_EVENT_CREATE_PROCESS;
649 Message.Data.CreateProcess.FileHandle = FileHandle;
650 Message.Data.CreateProcess.Base = ImageBase;
651 Message.Data.CreateProcess.EntryPoint = NULL; //
652
653 Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
654 &Message);
655 }
656 #endif
657
658 ObDereferenceObject(Process);
659 ObDereferenceObject(ParentProcess);
660 return(STATUS_SUCCESS);
661 }
662
663
664 NTSTATUS STDCALL
665 NtOpenProcess(OUT PHANDLE ProcessHandle,
666 IN ACCESS_MASK DesiredAccess,
667 IN POBJECT_ATTRIBUTES ObjectAttributes,
668 IN PCLIENT_ID ClientId)
669 {
670 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
671 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
672 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
673 ClientId->UniqueProcess, ClientId->UniqueThread);
674
675
676 /*
677 * Not sure of the exact semantics
678 */
679 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
680 ObjectAttributes->ObjectName->Buffer != NULL)
681 {
682 NTSTATUS Status;
683 PEPROCESS Process;
684
685 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
686 ObjectAttributes->Attributes,
687 NULL,
688 DesiredAccess,
689 PsProcessType,
690 UserMode,
691 NULL,
692 (PVOID*)&Process);
693 if (Status != STATUS_SUCCESS)
694 {
695 return(Status);
696 }
697
698 Status = ObCreateHandle(PsGetCurrentProcess(),
699 Process,
700 DesiredAccess,
701 FALSE,
702 ProcessHandle);
703 ObDereferenceObject(Process);
704
705 return(Status);
706 }
707 else
708 {
709 KIRQL oldIrql;
710 PLIST_ENTRY current_entry;
711 PEPROCESS current;
712 NTSTATUS Status;
713
714 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
715 current_entry = PsProcessListHead.Flink;
716 while (current_entry != &PsProcessListHead)
717 {
718 current = CONTAINING_RECORD(current_entry, EPROCESS,
719 ProcessListEntry);
720 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
721 {
722 ObReferenceObjectByPointer(current,
723 DesiredAccess,
724 PsProcessType,
725 UserMode);
726 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
727 Status = ObCreateHandle(PsGetCurrentProcess(),
728 current,
729 DesiredAccess,
730 FALSE,
731 ProcessHandle);
732 ObDereferenceObject(current);
733 DPRINT("*ProcessHandle %x\n", ProcessHandle);
734 DPRINT("NtOpenProcess() = %x\n", Status);
735 return(Status);
736 }
737 current_entry = current_entry->Flink;
738 }
739 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
740 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
741 return(STATUS_UNSUCCESSFUL);
742 }
743 return(STATUS_UNSUCCESSFUL);
744 }
745
746
747 NTSTATUS STDCALL
748 NtQueryInformationProcess(IN HANDLE ProcessHandle,
749 IN CINT ProcessInformationClass,
750 OUT PVOID ProcessInformation,
751 IN ULONG ProcessInformationLength,
752 OUT PULONG ReturnLength)
753 {
754 PEPROCESS Process;
755 NTSTATUS Status;
756 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
757
758 Status = ObReferenceObjectByHandle(ProcessHandle,
759 PROCESS_SET_INFORMATION,
760 PsProcessType,
761 UserMode,
762 (PVOID*)&Process,
763 NULL);
764 if (Status != STATUS_SUCCESS)
765 {
766 return(Status);
767 }
768
769 switch (ProcessInformationClass)
770 {
771 case ProcessBasicInformation:
772 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
773 ProcessInformation;
774 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
775 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
776 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
777 ProcessBasicInformationP->UniqueProcessId =
778 Process->UniqueProcessId;
779 ProcessBasicInformationP->InheritedFromUniqueProcessId =
780 (ULONG)Process->InheritedFromUniqueProcessId;
781 Status = STATUS_SUCCESS;
782 break;
783
784 case ProcessQuotaLimits:
785 case ProcessIoCounters:
786 case ProcessVmCounters:
787 case ProcessTimes:
788 case ProcessBasePriority:
789 case ProcessRaisePriority:
790 case ProcessDebugPort:
791 case ProcessExceptionPort:
792 case ProcessAccessToken:
793 case ProcessLdtInformation:
794 case ProcessLdtSize:
795 Status = STATUS_NOT_IMPLEMENTED;
796 break;
797
798 case ProcessDefaultHardErrorMode:
799 *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
800 break;
801
802 case ProcessIoPortHandlers:
803 case ProcessWorkingSetWatch:
804 case ProcessUserModeIOPL:
805 case ProcessEnableAlignmentFaultFixup:
806 Status = STATUS_NOT_IMPLEMENTED;
807 break;
808
809 case ProcessForegroundInformation:
810 ((PPROCESS_PRIORITY_CLASS)ProcessInformation)->Foreground =
811 FALSE; /*FIXME: how to compute it? */
812 case ProcessPriorityClass:
813 ((PPROCESS_PRIORITY_CLASS)ProcessInformation)->PriorityClass =
814 Process->PriorityClass;
815 break;
816
817 case ProcessWx86Information:
818 case ProcessHandleCount:
819 case ProcessAffinityMask:
820 case ProcessPriorityBoost:
821 case ProcessDeviceMap:
822 case ProcessSessionInformation:
823 case ProcessWow64Information:
824 Status = STATUS_NOT_IMPLEMENTED;
825 break;
826
827 default:
828 Status = STATUS_INVALID_INFO_CLASS;
829 }
830 ObDereferenceObject(Process);
831 return(Status);
832 }
833
834 NTSTATUS
835 PspAssignPrimaryToken(PEPROCESS Process,
836 HANDLE TokenHandle)
837 {
838 PACCESS_TOKEN Token;
839 PACCESS_TOKEN OldToken;
840 NTSTATUS Status;
841
842 Status = ObReferenceObjectByHandle(TokenHandle,
843 0,
844 SeTokenType,
845 UserMode,
846 (PVOID*)&Token,
847 NULL);
848 if (!NT_SUCCESS(Status))
849 {
850 return(Status);
851 }
852 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
853 if (!NT_SUCCESS(Status))
854 {
855 ObDereferenceObject(OldToken);
856 }
857 ObDereferenceObject(Token);
858 return(Status);
859 }
860
861 NTSTATUS STDCALL
862 NtSetInformationProcess(IN HANDLE ProcessHandle,
863 IN CINT ProcessInformationClass,
864 IN PVOID ProcessInformation,
865 IN ULONG ProcessInformationLength)
866 {
867 PEPROCESS Process;
868 NTSTATUS Status;
869 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
870 PHANDLE ProcessAccessTokenP;
871
872 Status = ObReferenceObjectByHandle(ProcessHandle,
873 PROCESS_SET_INFORMATION,
874 PsProcessType,
875 UserMode,
876 (PVOID*)&Process,
877 NULL);
878 if (!NT_SUCCESS(Status))
879 {
880 return(Status);
881 }
882
883 switch (ProcessInformationClass)
884 {
885 case ProcessBasicInformation:
886 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
887 ProcessInformation;
888 memset(ProcessBasicInformationP, 0, sizeof(PROCESS_BASIC_INFORMATION));
889 Process->Pcb.Affinity = ProcessBasicInformationP->AffinityMask;
890 Status = STATUS_SUCCESS;
891 break;
892
893 case ProcessQuotaLimits:
894 case ProcessIoCounters:
895 case ProcessVmCounters:
896 case ProcessTimes:
897 case ProcessBasePriority:
898 case ProcessRaisePriority:
899 case ProcessDebugPort:
900 case ProcessExceptionPort:
901 case ProcessAccessToken:
902 ProcessAccessTokenP = (PHANDLE)ProcessInformation;
903 Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
904 break;
905
906 case ProcessImageFileName:
907 memcpy(Process->ImageFileName, ProcessInformation, 8);
908 // DPRINT1("Process->ImageFileName %.8s\n", Process->ImageFileName);
909 Status = STATUS_SUCCESS;
910 break;
911
912 case ProcessLdtInformation:
913 case ProcessLdtSize:
914 case ProcessDefaultHardErrorMode:
915 case ProcessIoPortHandlers:
916 case ProcessWorkingSetWatch:
917 case ProcessUserModeIOPL:
918 case ProcessEnableAlignmentFaultFixup:
919 case ProcessPriorityClass:
920 case ProcessWx86Information:
921 case ProcessHandleCount:
922 case ProcessAffinityMask:
923 default:
924 Status = STATUS_NOT_IMPLEMENTED;
925 }
926 ObDereferenceObject(Process);
927 return(Status);
928 }
929
930
931 /**********************************************************************
932 * NAME INTERNAL
933 * PiQuerySystemProcessInformation
934 *
935 * DESCRIPTION
936 * Compute the size of a process+thread snapshot as
937 * expected by NtQuerySystemInformation.
938 *
939 * RETURN VALUE
940 * 0 on error; otherwise the size, in bytes of the buffer
941 * required to write a full snapshot.
942 *
943 * NOTE
944 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
945 */
946 NTSTATUS
947 PiQuerySystemProcessInformation(PVOID Buffer,
948 ULONG Size,
949 PULONG ReqSize)
950 {
951 return STATUS_NOT_IMPLEMENTED;
952
953 #if 0
954 KIRQL OldIrql;
955 PLIST_ENTRY CurrentEntryP;
956 PEPROCESS CurrentP;
957 PLIST_ENTRY CurrentEntryT;
958 PETHREAD CurrentT;
959
960 ULONG RequiredSize = 0L;
961 BOOLEAN SizeOnly = FALSE;
962
963 ULONG SpiSize = 0L;
964
965 PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
966 PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
967 PSYSTEM_THREAD_INFO pInfoT = NULL;
968
969
970 /* Lock the process list. */
971 KeAcquireSpinLock(&PsProcessListLock,
972 &OldIrql);
973
974 /*
975 * Scan the process list. Since the
976 * list is circular, the guard is false
977 * after the last process.
978 */
979 for ( CurrentEntryP = PsProcessListHead.Flink;
980 (CurrentEntryP != & PsProcessListHead);
981 CurrentEntryP = CurrentEntryP->Flink
982 )
983 {
984 /*
985 * Compute how much space is
986 * occupied in the snapshot
987 * by adding this process info.
988 * (at least one thread).
989 */
990 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
991 RequiredSize += SpiSizeCurrent;
992 /*
993 * Do not write process data in the
994 * buffer if it is too small.
995 */
996 if (TRUE == SizeOnly) continue;
997 /*
998 * Check if the buffer can contain
999 * the full snapshot.
1000 */
1001 if (Size < RequiredSize)
1002 {
1003 SizeOnly = TRUE;
1004 continue;
1005 }
1006 /*
1007 * Get a reference to the
1008 * process descriptor we are
1009 * handling.
1010 */
1011 CurrentP = CONTAINING_RECORD(
1012 CurrentEntryP,
1013 EPROCESS,
1014 ProcessListEntry
1015 );
1016 /*
1017 * Write process data in the buffer.
1018 */
1019 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
1020 /* PROCESS */
1021 pInfoP->ThreadCount = 0L;
1022 pInfoP->ProcessId = CurrentP->UniqueProcessId;
1023 RtlInitUnicodeString (
1024 & pInfoP->Name,
1025 CurrentP->ImageFileName
1026 );
1027 /* THREAD */
1028 for ( pInfoT = & CurrentP->ThreadSysInfo [0],
1029 CurrentEntryT = CurrentP->ThreadListHead.Flink;
1030
1031 (CurrentEntryT != & CurrentP->ThreadListHead);
1032
1033 pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
1034 CurrentEntryT = CurrentEntryT->Flink
1035 )
1036 {
1037 /*
1038 * Recalculate the size of the
1039 * information block.
1040 */
1041 if (0 < pInfoP->ThreadCount)
1042 {
1043 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
1044 }
1045 /*
1046 * Do not write thread data in the
1047 * buffer if it is too small.
1048 */
1049 if (TRUE == SizeOnly) continue;
1050 /*
1051 * Check if the buffer can contain
1052 * the full snapshot.
1053 */
1054 if (Size < RequiredSize)
1055 {
1056 SizeOnly = TRUE;
1057 continue;
1058 }
1059 /*
1060 * Get a reference to the
1061 * thread descriptor we are
1062 * handling.
1063 */
1064 CurrentT = CONTAINING_RECORD(
1065 CurrentEntryT,
1066 KTHREAD,
1067 Tcb.ThreadListEntry
1068 );
1069 /*
1070 * Write thread data.
1071 */
1072 RtlZeroMemory (
1073 pInfoT,
1074 sizeof (SYSTEM_THREAD_INFORMATION)
1075 );
1076 pInfoT->KernelTime = CurrentT-> ; /* TIME */
1077 pInfoT->UserTime = CurrentT-> ; /* TIME */
1078 pInfoT->CreateTime = CurrentT-> ; /* TIME */
1079 pInfoT->TickCount = CurrentT-> ; /* ULONG */
1080 pInfoT->StartEIP = CurrentT-> ; /* ULONG */
1081 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1082 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
1083 pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
1084 pInfoT->BasePriority = CurrentT-> ; /* ULONG */
1085 pInfoT->nSwitches = CurrentT-> ; /* ULONG */
1086 pInfoT->State = CurrentT-> ; /* DWORD */
1087 pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
1088 /*
1089 * Count the number of threads
1090 * this process has.
1091 */
1092 ++ pInfoP->ThreadCount;
1093 }
1094 /*
1095 * Save the size of information
1096 * stored in the buffer for the
1097 * current process.
1098 */
1099 pInfoP->RelativeOffset = SpiSize;
1100 /*
1101 * Save a reference to the last
1102 * valid information block.
1103 */
1104 pInfoPLast = pInfoP;
1105 /*
1106 * Compute the offset of the
1107 * SYSTEM_PROCESS_INFORMATION
1108 * descriptor in the snapshot
1109 * buffer for the next process.
1110 */
1111 (ULONG) pInfoP += SpiSize;
1112 }
1113 /*
1114 * Unlock the process list.
1115 */
1116 KeReleaseSpinLock (
1117 & PsProcessListLock,
1118 OldIrql
1119 );
1120 /*
1121 * Return the proper error status code,
1122 * if the buffer was too small.
1123 */
1124 if (TRUE == SizeOnly)
1125 {
1126 if (NULL != RequiredSize)
1127 {
1128 *pRequiredSize = RequiredSize;
1129 }
1130 return STATUS_INFO_LENGTH_MISMATCH;
1131 }
1132 /*
1133 * Mark the end of the snapshot.
1134 */
1135 pInfoP->RelativeOffset = 0L;
1136 /* OK */
1137 return STATUS_SUCCESS;
1138 #endif
1139 }
1140
1141 LARGE_INTEGER STDCALL
1142 PsGetProcessExitTime(VOID)
1143 {
1144 LARGE_INTEGER Li;
1145 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1146 return Li;
1147 }
1148
1149 BOOLEAN STDCALL
1150 PsIsThreadTerminating(IN PETHREAD Thread)
1151 {
1152 return(Thread->DeadThread);
1153 }
1154
1155 /* EOF */