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