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