Fix Process/Thread information structures to match Windows 2000 and have proper struc...
[reactos.git] / reactos / ntoskrnl / ps / process.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/process.c
5 * PURPOSE: Process managment
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
20 PEPROCESS PsIdleProcess = NULL;
21 POBJECT_TYPE EXPORTED PsProcessType = NULL;
22
23 LIST_ENTRY PsActiveProcessHead;
24 FAST_MUTEX PspActiveProcessMutex;
25 LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
26
27 /* INTERNAL FUNCTIONS *****************************************************************/
28
29 NTSTATUS
30 PsLockProcess(PEPROCESS Process, BOOLEAN Timeout)
31 {
32 ULONG Attempts = 0;
33 PKTHREAD PrevLockOwner;
34 NTSTATUS Status = STATUS_UNSUCCESSFUL;
35 PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL);
36 PKTHREAD CallingThread = KeGetCurrentThread();
37
38 PAGED_CODE();
39
40 KeEnterCriticalRegion();
41
42 for(;;)
43 {
44 PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer(
45 &Process->LockOwner, CallingThread, NULL);
46 if(PrevLockOwner == NULL || PrevLockOwner == CallingThread)
47 {
48 /* we got the lock or already locked it */
49 if(InterlockedIncrementUL(&Process->LockCount) == 1)
50 {
51 KeClearEvent(&Process->LockEvent);
52 }
53
54 return STATUS_SUCCESS;
55 }
56 else
57 {
58 if(++Attempts > 2)
59 {
60 Status = KeWaitForSingleObject(&Process->LockEvent,
61 Executive,
62 KernelMode,
63 FALSE,
64 Delay);
65 if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT)
66 {
67 #ifndef NDEBUG
68 if(Status == STATUS_TIMEOUT)
69 {
70 DPRINT1("PsLockProcess(0x%x) timed out!\n", Process);
71 }
72 #endif
73 KeLeaveCriticalRegion();
74 break;
75 }
76 }
77 else
78 {
79 KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
80 }
81 }
82 }
83
84 return Status;
85 }
86
87 VOID
88 PsUnlockProcess(PEPROCESS Process)
89 {
90 PAGED_CODE();
91
92 ASSERT(Process->LockOwner == KeGetCurrentThread());
93
94 if(InterlockedDecrementUL(&Process->LockCount) == 0)
95 {
96 InterlockedExchangePointer(&Process->LockOwner, NULL);
97 KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE);
98 }
99
100 KeLeaveCriticalRegion();
101 }
102
103 PEPROCESS
104 STDCALL
105 PsGetNextProcess(PEPROCESS OldProcess)
106 {
107 PEPROCESS NextProcess;
108 NTSTATUS Status;
109
110 /* Check if we have a previous process */
111 if (OldProcess == NULL)
112 {
113 /* We don't, start with the Idle Process */
114 Status = ObReferenceObjectByPointer(PsIdleProcess,
115 PROCESS_ALL_ACCESS,
116 PsProcessType,
117 KernelMode);
118 if (!NT_SUCCESS(Status))
119 {
120 DPRINT1("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsIdleProcess\n");
121 KEBUGCHECK(0);
122 }
123
124 return PsIdleProcess;
125 }
126
127 /* Acquire the Active Process Lock */
128 ExAcquireFastMutex(&PspActiveProcessMutex);
129
130 /* Start at the previous process */
131 NextProcess = OldProcess;
132
133 /* Loop until we fail */
134 while (1)
135 {
136 /* Get the Process Link */
137 PLIST_ENTRY Flink = (NextProcess == PsIdleProcess ? PsActiveProcessHead.Flink :
138 NextProcess->ProcessListEntry.Flink);
139
140 /* Move to the next Process if we're not back at the beginning */
141 if (Flink != &PsActiveProcessHead)
142 {
143 NextProcess = CONTAINING_RECORD(Flink, EPROCESS, ProcessListEntry);
144 }
145 else
146 {
147 NextProcess = NULL;
148 break;
149 }
150
151 /* Reference the Process */
152 Status = ObReferenceObjectByPointer(NextProcess,
153 PROCESS_ALL_ACCESS,
154 PsProcessType,
155 KernelMode);
156
157 /* Exit the loop if the reference worked, keep going if there's an error */
158 if (NT_SUCCESS(Status)) break;
159 }
160
161 /* Release the lock */
162 ExReleaseFastMutex(&PspActiveProcessMutex);
163
164 /* Reference the Process we had referenced earlier */
165 ObDereferenceObject(OldProcess);
166 return(NextProcess);
167 }
168
169 NTSTATUS
170 STDCALL
171 PspCreateProcess(OUT PHANDLE ProcessHandle,
172 IN ACCESS_MASK DesiredAccess,
173 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
174 IN HANDLE ParentProcess OPTIONAL,
175 IN BOOLEAN InheritObjectTable,
176 IN HANDLE SectionHandle OPTIONAL,
177 IN HANDLE DebugPort OPTIONAL,
178 IN HANDLE ExceptionPort OPTIONAL)
179 {
180 HANDLE hProcess;
181 PEPROCESS Process;
182 PEPROCESS pParentProcess;
183 PEPORT pDebugPort = NULL;
184 PEPORT pExceptionPort = NULL;
185 PSECTION_OBJECT SectionObject = NULL;
186 NTSTATUS Status = STATUS_SUCCESS;
187 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
188 PHYSICAL_ADDRESS DirectoryTableBase;
189 KAFFINITY Affinity;
190 DirectoryTableBase.QuadPart = (ULONGLONG)0;
191
192 DPRINT("PspCreateProcess(ObjectAttributes %x)\n", ObjectAttributes);
193
194 /* Reference the Parent if there is one */
195 if(ParentProcess != NULL)
196 {
197 Status = ObReferenceObjectByHandle(ParentProcess,
198 PROCESS_CREATE_PROCESS,
199 PsProcessType,
200 PreviousMode,
201 (PVOID*)&pParentProcess,
202 NULL);
203
204 if (!NT_SUCCESS(Status))
205 {
206 DPRINT1("Failed to reference the parent process: Status: 0x%x\n", Status);
207 return(Status);
208 }
209
210 /* Inherit Parent process's Affinity. */
211 Affinity = pParentProcess->Pcb.Affinity;
212
213 }
214 else
215 {
216 pParentProcess = NULL;
217 Affinity = KeActiveProcessors;
218 }
219
220 /* Add the debug port */
221 if (DebugPort != NULL)
222 {
223 Status = ObReferenceObjectByHandle(DebugPort,
224 PORT_ALL_ACCESS,
225 LpcPortObjectType,
226 PreviousMode,
227 (PVOID*)&pDebugPort,
228 NULL);
229 if (!NT_SUCCESS(Status))
230 {
231 DPRINT1("Failed to reference the debug port: Status: 0x%x\n", Status);
232 goto exitdereferenceobjects;
233 }
234 }
235
236 /* Add the exception port */
237 if (ExceptionPort != NULL)
238 {
239 Status = ObReferenceObjectByHandle(ExceptionPort,
240 PORT_ALL_ACCESS,
241 LpcPortObjectType,
242 PreviousMode,
243 (PVOID*)&pExceptionPort,
244 NULL);
245
246 if (!NT_SUCCESS(Status))
247 {
248 DPRINT1("Failed to reference the exception port: Status: 0x%x\n", Status);
249 goto exitdereferenceobjects;
250 }
251 }
252
253 /* Add the Section */
254 if (SectionHandle != NULL)
255 {
256 Status = ObReferenceObjectByHandle(SectionHandle,
257 0,
258 MmSectionObjectType,
259 PreviousMode,
260 (PVOID*)&SectionObject,
261 NULL);
262 if (!NT_SUCCESS(Status))
263 {
264 DPRINT1("Failed to reference process image section: Status: 0x%x\n", Status);
265 goto exitdereferenceobjects;
266 }
267 }
268
269 /* Create the Object */
270 DPRINT("Creating Process Object\n");
271 Status = ObCreateObject(PreviousMode,
272 PsProcessType,
273 ObjectAttributes,
274 PreviousMode,
275 NULL,
276 sizeof(EPROCESS),
277 0,
278 0,
279 (PVOID*)&Process);
280
281 if (!NT_SUCCESS(Status))
282 {
283 DPRINT1("Failed to create process object, Status: 0x%x\n", Status);
284 goto exitdereferenceobjects;
285 }
286
287 /* Clean up the Object */
288 DPRINT("Cleaning Process Object\n");
289 RtlZeroMemory(Process, sizeof(EPROCESS));
290
291 /* Inherit stuff from the Parent since we now have the object created */
292 if (pParentProcess)
293 {
294 Process->InheritedFromUniqueProcessId = pParentProcess->UniqueProcessId;
295 Process->SessionId = pParentProcess->SessionId;
296 }
297
298 /* FIXME: Set up the Quota Block from the Parent
299 PspInheritQuota(Parent, Process); */
300
301 /* FIXME: Set up Dos Device Map from the Parent
302 ObInheritDeviceMap(Parent, Process) */
303
304 /* Set the Process' LPC Ports */
305 Process->DebugPort = pDebugPort;
306 Process->ExceptionPort = pExceptionPort;
307
308 /* Setup the Lock Event */
309 DPRINT("Initialzing Process Lock\n");
310 KeInitializeEvent(&Process->LockEvent, SynchronizationEvent, FALSE);
311
312 /* Setup the Thread List Head */
313 DPRINT("Initialzing Process ThreadListHead\n");
314 InitializeListHead(&Process->ThreadListHead);
315
316 /* Create or Clone the Handle Table */
317 DPRINT("Initialzing Process Handle Table\n");
318 ObCreateHandleTable(pParentProcess, InheritObjectTable, Process);
319 DPRINT("Handle Table: %x\n", Process->ObjectTable);
320
321 /* Set Process's Directory Base */
322 DPRINT("Initialzing Process Directory Base\n");
323 MmCopyMmInfo(pParentProcess ? pParentProcess : PsInitialSystemProcess,
324 Process,
325 &DirectoryTableBase);
326
327 /* Now initialize the Kernel Process */
328 DPRINT("Initialzing Kernel Process\n");
329 KeInitializeProcess(&Process->Pcb,
330 PROCESS_PRIO_NORMAL,
331 Affinity,
332 DirectoryTableBase);
333
334 /* Duplicate Parent Token */
335 DPRINT("Initialzing Process Token\n");
336 Status = PspInitializeProcessSecurity(Process, pParentProcess);
337 if (!NT_SUCCESS(Status))
338 {
339 DbgPrint("PspInitializeProcessSecurity failed (Status %x)\n", Status);
340 ObDereferenceObject(Process);
341 goto exitdereferenceobjects;
342 }
343
344 /* Create the Process' Address Space */
345 DPRINT("Initialzing Process Address Space\n");
346 Status = MmCreateProcessAddressSpace(Process, SectionObject);
347 if (!NT_SUCCESS(Status))
348 {
349 DPRINT1("Failed to create Address Space\n");
350 ObDereferenceObject(Process);
351 goto exitdereferenceobjects;
352 }
353
354 if (SectionObject)
355 {
356 /* Map the System Dll */
357 DPRINT("Mapping System DLL\n");
358 LdrpMapSystemDll(Process, NULL);
359 }
360
361 /* Create a handle for the Process */
362 DPRINT("Initialzing Process CID Handle\n");
363 Status = PsCreateCidHandle(Process,
364 PsProcessType,
365 &Process->UniqueProcessId);
366 DPRINT("Created CID: %d\n", Process->UniqueProcessId);
367 if(!NT_SUCCESS(Status))
368 {
369 DPRINT1("Failed to create CID handle (unique process ID)! Status: 0x%x\n", Status);
370 ObDereferenceObject(Process);
371 goto exitdereferenceobjects;
372 }
373
374 /* FIXME: Insert into Job Object */
375
376 /* Create PEB only for User-Mode Processes */
377 if (pParentProcess)
378 {
379 DPRINT("Creating PEB\n");
380 Status = MmCreatePeb(Process);
381 if (!NT_SUCCESS(Status))
382 {
383 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
384 ObDereferenceObject(Process);
385 goto exitdereferenceobjects;
386 }
387
388 /* Let's take advantage of this time to kill the reference too */
389 ObDereferenceObject(pParentProcess);
390 }
391
392 /* W00T! The process can now be activated */
393 DPRINT("Inserting into Active Process List\n");
394 ExAcquireFastMutex(&PspActiveProcessMutex);
395 InsertTailList(&PsActiveProcessHead, &Process->ProcessListEntry);
396 ExReleaseFastMutex(&PspActiveProcessMutex);
397
398 /* FIXME: SeCreateAccessStateEx */
399
400 /* Insert the Process into the Object Directory */
401 DPRINT("Inserting Process Object\n");
402 Status = ObInsertObject(Process,
403 NULL,
404 DesiredAccess,
405 0,
406 NULL,
407 &hProcess);
408 if (!NT_SUCCESS(Status))
409 {
410 DPRINT1("Could not get a handle to the Process Object\n");
411 ObDereferenceObject(Process);
412 goto exitdereferenceobjects;
413 }
414
415 DPRINT("Done. Returning handle: %x\n", hProcess);
416 if (NT_SUCCESS(Status))
417 {
418 _SEH_TRY
419 {
420 *ProcessHandle = hProcess;
421 }
422 _SEH_HANDLE
423 {
424 Status = _SEH_GetExceptionCode();
425 } _SEH_END;
426 }
427
428 /* FIXME: ObGetObjectSecurity(Process, &SecurityDescriptor)
429 SeAccessCheck
430 */
431 ObDereferenceObject(Process);
432 return Status;
433
434 exitdereferenceobjects:
435 if(SectionObject != NULL) ObDereferenceObject(SectionObject);
436 if(pExceptionPort != NULL) ObDereferenceObject(pExceptionPort);
437 if(pDebugPort != NULL) ObDereferenceObject(pDebugPort);
438 if(pParentProcess != NULL) ObDereferenceObject(pParentProcess);
439 return Status;
440 }
441
442 /* PUBLIC FUNCTIONS *****************************************************************/
443
444 /*
445 * @implemented
446 */
447 NTSTATUS
448 STDCALL
449 PsCreateSystemProcess(PHANDLE ProcessHandle,
450 ACCESS_MASK DesiredAccess,
451 POBJECT_ATTRIBUTES ObjectAttributes)
452 {
453 return PspCreateProcess(ProcessHandle,
454 DesiredAccess,
455 ObjectAttributes,
456 NULL, /* no parent process */
457 FALSE,
458 NULL,
459 NULL,
460 NULL);
461 }
462
463 /*
464 * @implemented
465 */
466 NTSTATUS
467 STDCALL
468 PsLookupProcessByProcessId(IN HANDLE ProcessId,
469 OUT PEPROCESS *Process)
470 {
471 PHANDLE_TABLE_ENTRY CidEntry;
472 PEPROCESS FoundProcess;
473
474 PAGED_CODE();
475
476 ASSERT(Process);
477
478 CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess);
479 if(CidEntry != NULL)
480 {
481 ObReferenceObject(FoundProcess);
482
483 PsUnlockCidHandle(CidEntry);
484
485 *Process = FoundProcess;
486 return STATUS_SUCCESS;
487 }
488
489 return STATUS_INVALID_PARAMETER;
490 }
491
492 /*
493 * FUNCTION: Returns a pointer to the current process
494 *
495 * @implemented
496 */
497 PEPROCESS STDCALL
498 IoGetCurrentProcess(VOID)
499 {
500 if (PsGetCurrentThread() == NULL ||
501 PsGetCurrentThread()->Tcb.ApcState.Process == NULL)
502 {
503 return(PsInitialSystemProcess);
504 }
505 else
506 {
507 return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process);
508 }
509 }
510
511 /*
512 * @implemented
513 */
514 LARGE_INTEGER STDCALL
515 PsGetProcessExitTime(VOID)
516 {
517 LARGE_INTEGER Li;
518 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
519 return Li;
520 }
521
522 /*
523 * @implemented
524 */
525 LONGLONG
526 STDCALL
527 PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
528 {
529 return Process->CreateTime.QuadPart;
530 }
531
532 /*
533 * @implemented
534 */
535 PVOID
536 STDCALL
537 PsGetProcessDebugPort(PEPROCESS Process)
538 {
539 return Process->DebugPort;
540 }
541
542 /*
543 * @implemented
544 */
545 BOOLEAN
546 STDCALL
547 PsGetProcessExitProcessCalled(PEPROCESS Process)
548 {
549 return Process->ExitProcessCalled;
550 }
551
552 /*
553 * @implemented
554 */
555 NTSTATUS
556 STDCALL
557 PsGetProcessExitStatus(PEPROCESS Process)
558 {
559 return Process->ExitStatus;
560 }
561
562 /*
563 * @implemented
564 */
565 HANDLE
566 STDCALL
567 PsGetProcessId(PEPROCESS Process)
568 {
569 return (HANDLE)Process->UniqueProcessId;
570 }
571
572 /*
573 * @implemented
574 */
575 LPSTR
576 STDCALL
577 PsGetProcessImageFileName(PEPROCESS Process)
578 {
579 return (LPSTR)Process->ImageFileName;
580 }
581
582 /*
583 * @implemented
584 */
585 HANDLE
586 STDCALL
587 PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
588 {
589 return Process->InheritedFromUniqueProcessId;
590 }
591
592 /*
593 * @implemented
594 */
595 PEJOB
596 STDCALL
597 PsGetProcessJob(PEPROCESS Process)
598 {
599 return Process->Job;
600 }
601
602 /*
603 * @implemented
604 */
605 PPEB
606 STDCALL
607 PsGetProcessPeb(PEPROCESS Process)
608 {
609 return Process->Peb;
610 }
611
612 /*
613 * @implemented
614 */
615 ULONG
616 STDCALL
617 PsGetProcessPriorityClass(PEPROCESS Process)
618 {
619 return Process->PriorityClass;
620 }
621
622 /*
623 * @implemented
624 */
625 HANDLE STDCALL
626 PsGetCurrentProcessId(VOID)
627 {
628 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
629 }
630
631 /*
632 * @implemented
633 */
634 ULONG
635 STDCALL
636 PsGetCurrentProcessSessionId(VOID)
637 {
638 return PsGetCurrentProcess()->SessionId;
639 }
640
641 /*
642 * @implemented
643 */
644 PVOID
645 STDCALL
646 PsGetProcessSectionBaseAddress(PEPROCESS Process)
647 {
648 return Process->SectionBaseAddress;
649 }
650
651 /*
652 * @implemented
653 */
654 PVOID
655 STDCALL
656 PsGetProcessSecurityPort(PEPROCESS Process)
657 {
658 return Process->SecurityPort;
659 }
660
661 /*
662 * @implemented
663 */
664 HANDLE
665 STDCALL
666 PsGetProcessSessionId(PEPROCESS Process)
667 {
668 return (HANDLE)Process->SessionId;
669 }
670
671 /*
672 * @implemented
673 */
674 PVOID
675 STDCALL
676 PsGetProcessWin32Process(PEPROCESS Process)
677 {
678 return Process->Win32Process;
679 }
680
681 /*
682 * @implemented
683 */
684 PVOID
685 STDCALL
686 PsGetProcessWin32WindowStation(PEPROCESS Process)
687 {
688 return Process->Win32WindowStation;
689 }
690
691 /*
692 * @implemented
693 */
694 BOOLEAN
695 STDCALL
696 PsIsProcessBeingDebugged(PEPROCESS Process)
697 {
698 return FALSE; //Process->IsProcessBeingDebugged;
699 }
700
701 /*
702 * @implemented
703 */
704 VOID
705 STDCALL
706 PsSetProcessPriorityClass(PEPROCESS Process,
707 ULONG PriorityClass)
708 {
709 Process->PriorityClass = PriorityClass;
710 }
711
712 /*
713 * @implemented
714 */
715 VOID
716 STDCALL
717 PsSetProcessSecurityPort(PEPROCESS Process,
718 PVOID SecurityPort)
719 {
720 Process->SecurityPort = SecurityPort;
721 }
722
723 /*
724 * @implemented
725 */
726 VOID
727 STDCALL
728 PsSetProcessWin32Process(PEPROCESS Process,
729 PVOID Win32Process)
730 {
731 Process->Win32Process = Win32Process;
732 }
733
734 /*
735 * @implemented
736 */
737 VOID
738 STDCALL
739 PsSetProcessWin32WindowStation(PEPROCESS Process,
740 PVOID WindowStation)
741 {
742 Process->Win32WindowStation = WindowStation;
743 }
744
745 /*
746 * FUNCTION: Creates a process.
747 * ARGUMENTS:
748 * ProcessHandle (OUT) = Caller supplied storage for the resulting
749 * handle
750 * DesiredAccess = Specifies the allowed or desired access to the
751 * process can be a combination of
752 * STANDARD_RIGHTS_REQUIRED| ..
753 * ObjectAttribute = Initialized attributes for the object, contains
754 * the rootdirectory and the filename
755 * ParentProcess = Handle to the parent process.
756 * InheritObjectTable = Specifies to inherit the objects of the parent
757 * process if true.
758 * SectionHandle = Handle to a section object to back the image file
759 * DebugPort = Handle to a DebugPort if NULL the system default debug
760 * port will be used.
761 * ExceptionPort = Handle to a exception port.
762 * REMARKS:
763 * This function maps to the win32 CreateProcess.
764 * RETURNS: Status
765 *
766 * @implemented
767 */
768 NTSTATUS
769 STDCALL
770 NtCreateProcess(OUT PHANDLE ProcessHandle,
771 IN ACCESS_MASK DesiredAccess,
772 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
773 IN HANDLE ParentProcess,
774 IN BOOLEAN InheritObjectTable,
775 IN HANDLE SectionHandle OPTIONAL,
776 IN HANDLE DebugPort OPTIONAL,
777 IN HANDLE ExceptionPort OPTIONAL)
778 {
779 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
780 NTSTATUS Status = STATUS_SUCCESS;
781
782 PAGED_CODE();
783
784 /* Check parameters */
785 if(PreviousMode != KernelMode)
786 {
787 _SEH_TRY
788 {
789 ProbeForWrite(ProcessHandle,
790 sizeof(HANDLE),
791 sizeof(ULONG));
792 }
793 _SEH_HANDLE
794 {
795 Status = _SEH_GetExceptionCode();
796 }
797 _SEH_END;
798
799 if(!NT_SUCCESS(Status)) return Status;
800 }
801
802 /* Make sure there's a parent process */
803 if(ParentProcess == NULL)
804 {
805 /* Can't create System Processes like this */
806 Status = STATUS_INVALID_PARAMETER;
807 }
808 else
809 {
810 /* Create a user Process */
811 Status = PspCreateProcess(ProcessHandle,
812 DesiredAccess,
813 ObjectAttributes,
814 ParentProcess,
815 InheritObjectTable,
816 SectionHandle,
817 DebugPort,
818 ExceptionPort);
819 }
820
821 /* Return Status */
822 return Status;
823 }
824
825 /*
826 * @implemented
827 */
828 NTSTATUS
829 STDCALL
830 NtOpenProcess(OUT PHANDLE ProcessHandle,
831 IN ACCESS_MASK DesiredAccess,
832 IN POBJECT_ATTRIBUTES ObjectAttributes,
833 IN PCLIENT_ID ClientId)
834 {
835 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
836 NTSTATUS Status = STATUS_INVALID_PARAMETER;
837 PEPROCESS Process;
838 PETHREAD Thread = NULL;
839
840 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
841 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
842 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
843 ClientId->UniqueProcess, ClientId->UniqueThread);
844
845 PAGED_CODE();
846
847 /* Open by name if one was given */
848 DPRINT("Checking type\n");
849 if (ObjectAttributes->ObjectName)
850 {
851 /* Open it */
852 DPRINT("Opening by name\n");
853 Status = ObOpenObjectByName(ObjectAttributes,
854 PsProcessType,
855 NULL,
856 PreviousMode,
857 DesiredAccess,
858 NULL,
859 ProcessHandle);
860
861 if (Status != STATUS_SUCCESS)
862 {
863 DPRINT1("Could not open object by name\n");
864 }
865
866 /* Return Status */
867 DPRINT("Found: %x\n", ProcessHandle);
868 return(Status);
869 }
870 else if (ClientId)
871 {
872 /* Open by Thread ID */
873 if (ClientId->UniqueThread)
874 {
875 /* Get the Process */
876 if (ClientId->UniqueThread == (HANDLE)-1) KEBUGCHECK(0);
877 DPRINT("Opening by Thread ID: %x\n", ClientId->UniqueThread);
878 Status = PsLookupProcessThreadByCid(ClientId,
879 &Process,
880 &Thread);
881 DPRINT("Found: %x\n", Process);
882 }
883 else
884 {
885 /* Get the Process */
886 DPRINT("Opening by Process ID: %x\n", ClientId->UniqueProcess);
887 Status = PsLookupProcessByProcessId(ClientId->UniqueProcess,
888 &Process);
889 DPRINT("Found: %x\n", Process);
890 }
891
892 if(!NT_SUCCESS(Status))
893 {
894 DPRINT1("Failure to find process\n");
895 return Status;
896 }
897
898 /* Open the Process Object */
899 Status = ObOpenObjectByPointer(Process,
900 ObjectAttributes->Attributes,
901 NULL,
902 DesiredAccess,
903 PsProcessType,
904 PreviousMode,
905 ProcessHandle);
906 if(!NT_SUCCESS(Status))
907 {
908 DPRINT1("Failure to open process\n");
909 }
910
911 /* Dereference the thread if we used it */
912 if (Thread) ObDereferenceObject(Thread);
913
914 /* Dereference the Process */
915 ObDereferenceObject(Process);
916 }
917
918 return Status;
919 }
920 /* EOF */