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