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