merge ROS Shell without integrated explorer part into trunk
[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 pParentProcess = NULL;
391 }
392
393 /* W00T! The process can now be activated */
394 DPRINT("Inserting into Active Process List\n");
395 ExAcquireFastMutex(&PspActiveProcessMutex);
396 InsertTailList(&PsActiveProcessHead, &Process->ProcessListEntry);
397 ExReleaseFastMutex(&PspActiveProcessMutex);
398
399 /* FIXME: SeCreateAccessStateEx */
400
401 /* Insert the Process into the Object Directory */
402 DPRINT("Inserting Process Object\n");
403 Status = ObInsertObject(Process,
404 NULL,
405 DesiredAccess,
406 0,
407 NULL,
408 &hProcess);
409 if (!NT_SUCCESS(Status))
410 {
411 DPRINT1("Could not get a handle to the Process Object\n");
412 ObDereferenceObject(Process);
413 goto exitdereferenceobjects;
414 }
415
416 /* Set the Creation Time */
417 KeQuerySystemTime(&Process->CreateTime);
418
419 DPRINT("Done. Returning handle: %x\n", hProcess);
420 _SEH_TRY
421 {
422 *ProcessHandle = hProcess;
423 }
424 _SEH_HANDLE
425 {
426 Status = _SEH_GetExceptionCode();
427 } _SEH_END;
428
429 /* FIXME: ObGetObjectSecurity(Process, &SecurityDescriptor)
430 SeAccessCheck
431 */
432 ObDereferenceObject(Process);
433 return Status;
434
435 exitdereferenceobjects:
436 if(SectionObject != NULL) ObDereferenceObject(SectionObject);
437 if(pExceptionPort != NULL) ObDereferenceObject(pExceptionPort);
438 if(pDebugPort != NULL) ObDereferenceObject(pDebugPort);
439 if(pParentProcess != NULL) ObDereferenceObject(pParentProcess);
440 return Status;
441 }
442
443 /* PUBLIC FUNCTIONS *****************************************************************/
444
445 /*
446 * @implemented
447 */
448 NTSTATUS
449 STDCALL
450 PsCreateSystemProcess(PHANDLE ProcessHandle,
451 ACCESS_MASK DesiredAccess,
452 POBJECT_ATTRIBUTES ObjectAttributes)
453 {
454 return PspCreateProcess(ProcessHandle,
455 DesiredAccess,
456 ObjectAttributes,
457 NULL, /* no parent process */
458 FALSE,
459 NULL,
460 NULL,
461 NULL);
462 }
463
464 /*
465 * @implemented
466 */
467 NTSTATUS
468 STDCALL
469 PsLookupProcessByProcessId(IN HANDLE ProcessId,
470 OUT PEPROCESS *Process)
471 {
472 PHANDLE_TABLE_ENTRY CidEntry;
473 PEPROCESS FoundProcess;
474
475 PAGED_CODE();
476
477 ASSERT(Process);
478
479 CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess);
480 if(CidEntry != NULL)
481 {
482 ObReferenceObject(FoundProcess);
483
484 PsUnlockCidHandle(CidEntry);
485
486 *Process = FoundProcess;
487 return STATUS_SUCCESS;
488 }
489
490 return STATUS_INVALID_PARAMETER;
491 }
492
493 /*
494 * FUNCTION: Returns a pointer to the current process
495 *
496 * @implemented
497 */
498 PEPROCESS STDCALL
499 IoGetCurrentProcess(VOID)
500 {
501 if (PsGetCurrentThread() == NULL ||
502 PsGetCurrentThread()->Tcb.ApcState.Process == NULL)
503 {
504 return(PsInitialSystemProcess);
505 }
506 else
507 {
508 return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process);
509 }
510 }
511
512 /*
513 * @implemented
514 */
515 LARGE_INTEGER STDCALL
516 PsGetProcessExitTime(VOID)
517 {
518 LARGE_INTEGER Li;
519 Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
520 return Li;
521 }
522
523 /*
524 * @implemented
525 */
526 LONGLONG
527 STDCALL
528 PsGetProcessCreateTimeQuadPart(PEPROCESS Process)
529 {
530 return Process->CreateTime.QuadPart;
531 }
532
533 /*
534 * @implemented
535 */
536 PVOID
537 STDCALL
538 PsGetProcessDebugPort(PEPROCESS Process)
539 {
540 return Process->DebugPort;
541 }
542
543 /*
544 * @implemented
545 */
546 BOOLEAN
547 STDCALL
548 PsGetProcessExitProcessCalled(PEPROCESS Process)
549 {
550 return Process->ExitProcessCalled;
551 }
552
553 /*
554 * @implemented
555 */
556 NTSTATUS
557 STDCALL
558 PsGetProcessExitStatus(PEPROCESS Process)
559 {
560 return Process->ExitStatus;
561 }
562
563 /*
564 * @implemented
565 */
566 HANDLE
567 STDCALL
568 PsGetProcessId(PEPROCESS Process)
569 {
570 return (HANDLE)Process->UniqueProcessId;
571 }
572
573 /*
574 * @implemented
575 */
576 LPSTR
577 STDCALL
578 PsGetProcessImageFileName(PEPROCESS Process)
579 {
580 return (LPSTR)Process->ImageFileName;
581 }
582
583 /*
584 * @implemented
585 */
586 HANDLE
587 STDCALL
588 PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process)
589 {
590 return Process->InheritedFromUniqueProcessId;
591 }
592
593 /*
594 * @implemented
595 */
596 PEJOB
597 STDCALL
598 PsGetProcessJob(PEPROCESS Process)
599 {
600 return Process->Job;
601 }
602
603 /*
604 * @implemented
605 */
606 PPEB
607 STDCALL
608 PsGetProcessPeb(PEPROCESS Process)
609 {
610 return Process->Peb;
611 }
612
613 /*
614 * @implemented
615 */
616 ULONG
617 STDCALL
618 PsGetProcessPriorityClass(PEPROCESS Process)
619 {
620 return Process->PriorityClass;
621 }
622
623 /*
624 * @implemented
625 */
626 HANDLE STDCALL
627 PsGetCurrentProcessId(VOID)
628 {
629 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
630 }
631
632 /*
633 * @implemented
634 */
635 ULONG
636 STDCALL
637 PsGetCurrentProcessSessionId(VOID)
638 {
639 return PsGetCurrentProcess()->SessionId;
640 }
641
642 /*
643 * @implemented
644 */
645 PVOID
646 STDCALL
647 PsGetProcessSectionBaseAddress(PEPROCESS Process)
648 {
649 return Process->SectionBaseAddress;
650 }
651
652 /*
653 * @implemented
654 */
655 PVOID
656 STDCALL
657 PsGetProcessSecurityPort(PEPROCESS Process)
658 {
659 return Process->SecurityPort;
660 }
661
662 /*
663 * @implemented
664 */
665 HANDLE
666 STDCALL
667 PsGetProcessSessionId(PEPROCESS Process)
668 {
669 return (HANDLE)Process->SessionId;
670 }
671
672 /*
673 * @implemented
674 */
675 PVOID
676 STDCALL
677 PsGetProcessWin32Process(PEPROCESS Process)
678 {
679 return Process->Win32Process;
680 }
681
682 /*
683 * @implemented
684 */
685 PVOID
686 STDCALL
687 PsGetProcessWin32WindowStation(PEPROCESS Process)
688 {
689 return Process->Win32WindowStation;
690 }
691
692 /*
693 * @implemented
694 */
695 BOOLEAN
696 STDCALL
697 PsIsProcessBeingDebugged(PEPROCESS Process)
698 {
699 return FALSE; //Process->IsProcessBeingDebugged;
700 }
701
702 /*
703 * @implemented
704 */
705 VOID
706 STDCALL
707 PsSetProcessPriorityClass(PEPROCESS Process,
708 ULONG PriorityClass)
709 {
710 Process->PriorityClass = PriorityClass;
711 }
712
713 /*
714 * @implemented
715 */
716 VOID
717 STDCALL
718 PsSetProcessSecurityPort(PEPROCESS Process,
719 PVOID SecurityPort)
720 {
721 Process->SecurityPort = SecurityPort;
722 }
723
724 /*
725 * @implemented
726 */
727 VOID
728 STDCALL
729 PsSetProcessWin32Process(PEPROCESS Process,
730 PVOID Win32Process)
731 {
732 Process->Win32Process = Win32Process;
733 }
734
735 /*
736 * @implemented
737 */
738 VOID
739 STDCALL
740 PsSetProcessWin32WindowStation(PEPROCESS Process,
741 PVOID WindowStation)
742 {
743 Process->Win32WindowStation = WindowStation;
744 }
745
746 /*
747 * FUNCTION: Creates a process.
748 * ARGUMENTS:
749 * ProcessHandle (OUT) = Caller supplied storage for the resulting
750 * handle
751 * DesiredAccess = Specifies the allowed or desired access to the
752 * process can be a combination of
753 * STANDARD_RIGHTS_REQUIRED| ..
754 * ObjectAttribute = Initialized attributes for the object, contains
755 * the rootdirectory and the filename
756 * ParentProcess = Handle to the parent process.
757 * InheritObjectTable = Specifies to inherit the objects of the parent
758 * process if true.
759 * SectionHandle = Handle to a section object to back the image file
760 * DebugPort = Handle to a DebugPort if NULL the system default debug
761 * port will be used.
762 * ExceptionPort = Handle to a exception port.
763 * REMARKS:
764 * This function maps to the win32 CreateProcess.
765 * RETURNS: Status
766 *
767 * @implemented
768 */
769 NTSTATUS
770 STDCALL
771 NtCreateProcess(OUT PHANDLE ProcessHandle,
772 IN ACCESS_MASK DesiredAccess,
773 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
774 IN HANDLE ParentProcess,
775 IN BOOLEAN InheritObjectTable,
776 IN HANDLE SectionHandle OPTIONAL,
777 IN HANDLE DebugPort OPTIONAL,
778 IN HANDLE ExceptionPort OPTIONAL)
779 {
780 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
781 NTSTATUS Status = STATUS_SUCCESS;
782
783 PAGED_CODE();
784
785 /* Check parameters */
786 if(PreviousMode != KernelMode)
787 {
788 _SEH_TRY
789 {
790 ProbeForWrite(ProcessHandle,
791 sizeof(HANDLE),
792 sizeof(ULONG));
793 }
794 _SEH_HANDLE
795 {
796 Status = _SEH_GetExceptionCode();
797 }
798 _SEH_END;
799
800 if(!NT_SUCCESS(Status)) return Status;
801 }
802
803 /* Make sure there's a parent process */
804 if(ParentProcess == NULL)
805 {
806 /* Can't create System Processes like this */
807 Status = STATUS_INVALID_PARAMETER;
808 }
809 else
810 {
811 /* Create a user Process */
812 Status = PspCreateProcess(ProcessHandle,
813 DesiredAccess,
814 ObjectAttributes,
815 ParentProcess,
816 InheritObjectTable,
817 SectionHandle,
818 DebugPort,
819 ExceptionPort);
820 }
821
822 /* Return Status */
823 return Status;
824 }
825
826 /*
827 * @implemented
828 */
829 NTSTATUS
830 STDCALL
831 NtOpenProcess(OUT PHANDLE ProcessHandle,
832 IN ACCESS_MASK DesiredAccess,
833 IN POBJECT_ATTRIBUTES ObjectAttributes,
834 IN PCLIENT_ID ClientId)
835 {
836 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
837 NTSTATUS Status = STATUS_INVALID_PARAMETER;
838 PEPROCESS Process;
839 PETHREAD Thread = NULL;
840
841 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
842 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
843 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
844 ClientId->UniqueProcess, ClientId->UniqueThread);
845
846 PAGED_CODE();
847
848 /* Open by name if one was given */
849 DPRINT("Checking type\n");
850 if (ObjectAttributes->ObjectName)
851 {
852 /* Open it */
853 DPRINT("Opening by name\n");
854 Status = ObOpenObjectByName(ObjectAttributes,
855 PsProcessType,
856 NULL,
857 PreviousMode,
858 DesiredAccess,
859 NULL,
860 ProcessHandle);
861
862 if (Status != STATUS_SUCCESS)
863 {
864 DPRINT1("Could not open object by name\n");
865 }
866
867 /* Return Status */
868 DPRINT("Found: %x\n", ProcessHandle);
869 return(Status);
870 }
871 else if (ClientId)
872 {
873 /* Open by Thread ID */
874 if (ClientId->UniqueThread)
875 {
876 /* Get the Process */
877 if (ClientId->UniqueThread == (HANDLE)-1) KEBUGCHECK(0);
878 DPRINT("Opening by Thread ID: %x\n", ClientId->UniqueThread);
879 Status = PsLookupProcessThreadByCid(ClientId,
880 &Process,
881 &Thread);
882 DPRINT("Found: %x\n", Process);
883 }
884 else
885 {
886 /* Get the Process */
887 DPRINT("Opening by Process ID: %x\n", ClientId->UniqueProcess);
888 Status = PsLookupProcessByProcessId(ClientId->UniqueProcess,
889 &Process);
890 DPRINT("Found: %x\n", Process);
891 }
892
893 if(!NT_SUCCESS(Status))
894 {
895 DPRINT1("Failure to find process\n");
896 return Status;
897 }
898
899 /* Open the Process Object */
900 Status = ObOpenObjectByPointer(Process,
901 ObjectAttributes->Attributes,
902 NULL,
903 DesiredAccess,
904 PsProcessType,
905 PreviousMode,
906 ProcessHandle);
907 if(!NT_SUCCESS(Status))
908 {
909 DPRINT1("Failure to open process\n");
910 }
911
912 /* Dereference the thread if we used it */
913 if (Thread) ObDereferenceObject(Thread);
914
915 /* Dereference the Process */
916 ObDereferenceObject(Process);
917 }
918
919 return Status;
920 }
921 /* EOF */