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