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