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