+PsReferencePrimaryToken()
[reactos.git] / ntoskrnl / ps / process.c
1 /* $Id$
2  *
3  * COPYRIGHT:         See COPYING in the top level directory
4  * PROJECT:           ReactOS kernel
5  * FILE:              ntoskrnl/ps/process.c
6  * PURPOSE:           Process managment
7  * PROGRAMMER:        David Welch (welch@cwcom.net)
8  * REVISION HISTORY:
9  *              21/07/98: Created
10  */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <limits.h>
15 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
17 #include <internal/mm.h>
18 #include <internal/ke.h>
19 #include <internal/ps.h>
20 #include <internal/se.h>
21 #include <internal/id.h>
22 #include <napi/teb.h>
23 #include <internal/ldr.h>
24 #include <internal/port.h>
25 #include <napi/dbg.h>
26 #include <internal/dbg.h>
27 #include <internal/pool.h>
28 #include <roscfg.h>
29 #include <internal/se.h>
30 #include <internal/kd.h>
31
32 #define NDEBUG
33 #include <internal/debug.h>
34
35 /* GLOBALS ******************************************************************/
36
37 PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
38 HANDLE SystemProcessHandle = NULL;
39
40 POBJECT_TYPE EXPORTED PsProcessType = NULL;
41
42 LIST_ENTRY PsProcessListHead;
43 static KSPIN_LOCK PsProcessListLock;
44 static ULONG PiNextProcessUniqueId = 0;
45
46 static GENERIC_MAPPING PiProcessMapping = {PROCESS_READ,
47                                            PROCESS_WRITE,
48                                            PROCESS_EXECUTE,
49                                            PROCESS_ALL_ACCESS};
50
51 #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT    8
52
53 #ifndef LIBCAPTIVE
54 static ULONG PiProcessNotifyRoutineCount = 0;
55 static PCREATE_PROCESS_NOTIFY_ROUTINE
56 PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
57 #endif /* LIBCAPTIVE */
58
59 /* FUNCTIONS *****************************************************************/
60
61 #ifndef LIBCAPTIVE
62
63 PEPROCESS 
64 PsGetNextProcess(PEPROCESS OldProcess)
65 {
66    KIRQL oldIrql;
67    PEPROCESS NextProcess;
68    NTSTATUS Status;
69    
70    if (OldProcess == NULL)
71      {
72         return(PsInitialSystemProcess);
73      }
74    
75    KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
76    if (OldProcess->ProcessListEntry.Flink == &PsProcessListHead)
77      {
78         NextProcess = CONTAINING_RECORD(PsProcessListHead.Flink,
79                                         EPROCESS,
80                                         ProcessListEntry);
81      }
82    else
83      {
84         NextProcess = CONTAINING_RECORD(OldProcess->ProcessListEntry.Flink,
85                                         EPROCESS,
86                                         ProcessListEntry);
87      }
88    KeReleaseSpinLock(&PsProcessListLock, oldIrql);
89    Status = ObReferenceObjectByPointer(NextProcess,
90                                        PROCESS_ALL_ACCESS,
91                                        PsProcessType,
92                                        KernelMode);   
93    if (!NT_SUCCESS(Status))
94      {
95         CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
96         KeBugCheck(0);
97      }
98    ObDereferenceObject(OldProcess);
99    
100    return(NextProcess);
101 }
102
103
104 NTSTATUS STDCALL 
105 _NtOpenProcessToken(IN  HANDLE          ProcessHandle,
106                    IN   ACCESS_MASK     DesiredAccess,
107                    OUT  PHANDLE         TokenHandle)
108 {
109    PACCESS_TOKEN Token;
110    NTSTATUS Status;
111   
112    Status = PsOpenTokenOfProcess(ProcessHandle,
113                                  &Token);
114    if (!NT_SUCCESS(Status))
115      {
116         return(Status);
117      }
118    Status = ObCreateHandle(PsGetCurrentProcess(),
119                            Token,
120                            DesiredAccess,
121                            FALSE,
122                            TokenHandle);
123    ObDereferenceObject(Token);
124    return(Status);
125 }
126
127
128 NTSTATUS STDCALL 
129 NtOpenProcessToken(IN   HANDLE          ProcessHandle,
130                    IN   ACCESS_MASK     DesiredAccess,
131                    OUT  PHANDLE         TokenHandle)
132 {
133   return _NtOpenProcessToken(ProcessHandle, DesiredAccess, TokenHandle);
134 }
135
136 #endif /* LIBCAPTIVE */
137
138 PACCESS_TOKEN STDCALL
139 PsReferencePrimaryToken(PEPROCESS Process)
140 {
141    ObReferenceObjectByPointer(Process->Token,
142                               TOKEN_ALL_ACCESS,
143                               SepTokenObjectType,
144                               UserMode);
145    return(Process->Token);
146 }
147
148 #ifndef LIBCAPTIVE
149
150 NTSTATUS
151 PsOpenTokenOfProcess(HANDLE ProcessHandle,
152                      PACCESS_TOKEN* Token)
153 {
154    PEPROCESS Process;
155    NTSTATUS Status;
156    
157    Status = ObReferenceObjectByHandle(ProcessHandle,
158                                       PROCESS_QUERY_INFORMATION,
159                                       PsProcessType,
160                                       UserMode,
161                                       (PVOID*)&Process,
162                                       NULL);
163    if (!NT_SUCCESS(Status))
164      {
165         return(Status);
166      }
167    *Token = PsReferencePrimaryToken(Process);
168    ObDereferenceObject(Process);
169    return(STATUS_SUCCESS);
170 }
171
172
173 VOID 
174 PiKillMostProcesses(VOID)
175 {
176    KIRQL oldIrql;
177    PLIST_ENTRY current_entry;
178    PEPROCESS current;
179    
180    KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
181    
182    current_entry = PsProcessListHead.Flink;
183    while (current_entry != &PsProcessListHead)
184      {
185         current = CONTAINING_RECORD(current_entry, EPROCESS, 
186                                     ProcessListEntry);
187         current_entry = current_entry->Flink;
188         
189         if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
190             current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
191           {
192              PiTerminateProcessThreads(current, STATUS_SUCCESS);
193           }
194      }
195    
196    KeReleaseSpinLock(&PsProcessListLock, oldIrql);
197 }
198
199 #endif /* LIBCAPTIVE */
200
201 VOID
202 PsInitProcessManagment(VOID)
203 {
204    PKPROCESS KProcess;
205    KIRQL oldIrql;
206    NTSTATUS Status;
207    
208    /*
209     * Register the process object type
210     */
211    
212    PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
213
214    PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
215    PsProcessType->TotalObjects = 0;
216    PsProcessType->TotalHandles = 0;
217    PsProcessType->MaxObjects = ULONG_MAX;
218    PsProcessType->MaxHandles = ULONG_MAX;
219    PsProcessType->PagedPoolCharge = 0;
220    PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS)
221 #ifdef LIBCAPTIVE
222          /* Need to present 0-terminated string "System"
223           * from KPROCESS up to PAGE_SIZE offset
224           * for ext2fsd.sys V0.10A debug.c/Ext2GetProcessNameOffset()
225           */
226          +strlen("System")+1/* 0-terminator */;
227 #endif /* LIBCAPTIVE */
228          ;
229    PsProcessType->Mapping = &PiProcessMapping;
230    PsProcessType->Dump = NULL;
231    PsProcessType->Open = NULL;
232    PsProcessType->Close = NULL;
233 #ifndef LIBCAPTIVE
234    PsProcessType->Delete = PiDeleteProcess;
235 #else
236    PsProcessType->Delete = NULL;        /* never Delete PsInitialSystemProcess */
237 #endif /* LIBCAPTIVE */
238    PsProcessType->Parse = NULL;
239    PsProcessType->Security = NULL;
240    PsProcessType->QueryName = NULL;
241    PsProcessType->OkayToClose = NULL;
242    PsProcessType->Create = NULL;
243    PsProcessType->DuplicationNotify = NULL;
244    
245    RtlInitUnicodeStringFromLiteral(&PsProcessType->TypeName, REACTOS_UCS2(L"Process"));
246    
247    InitializeListHead(&PsProcessListHead);
248    KeInitializeSpinLock(&PsProcessListLock);
249    
250    /*
251     * Initialize the system process
252     */
253    Status = ObCreateObject(NULL,
254                            PROCESS_ALL_ACCESS,
255                            NULL,
256                            PsProcessType,
257                            (PVOID*)&PsInitialSystemProcess);
258    if (!NT_SUCCESS(Status))
259      {
260         return;
261      }
262    
263 #ifdef LIBCAPTIVE
264    /* Need to present 0-terminated string "System"
265     * from KPROCESS up to PAGE_SIZE offset
266     * for ext2fsd.sys V0.10A debug.c/Ext2GetProcessNameOffset()
267     */
268    strcpy(((char *)PsInitialSystemProcess) +strlen("System")+1/* 0-terminator */,"System");
269 #endif /* LIBCAPTIVE */
270
271    /* System threads may run on any processor. */
272    PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
273    PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
274 #ifndef LIBCAPTIVE
275    KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
276                                 InternalProcessType,
277                                 sizeof(EPROCESS),
278                                 FALSE);
279 #endif /* LIBCAPTIVE */
280    KProcess = &PsInitialSystemProcess->Pcb;
281    
282 #ifndef LIBCAPTIVE
283    MmInitializeAddressSpace(PsInitialSystemProcess,
284                             &PsInitialSystemProcess->AddressSpace);
285 #endif /* LIBCAPTIVE */
286    ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess);
287 #ifndef LIBCAPTIVE
288    KProcess->DirectoryTableBase = 
289      (LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
290 #endif /* LIBCAPTIVE */
291    PsInitialSystemProcess->UniqueProcessId = 
292      InterlockedIncrement(&PiNextProcessUniqueId);
293    PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
294    PsInitialSystemProcess->Win32Desktop = (HANDLE)0;
295    
296    KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
297    InsertHeadList(&PsProcessListHead, 
298                   &PsInitialSystemProcess->ProcessListEntry);
299    InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
300    KeReleaseSpinLock(&PsProcessListLock, oldIrql);
301    
302    strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM");
303
304    SepCreateSystemProcessToken(PsInitialSystemProcess);
305
306    ObCreateHandle(PsInitialSystemProcess,
307                   PsInitialSystemProcess,
308                   PROCESS_ALL_ACCESS,
309                   FALSE,
310                   &SystemProcessHandle);
311 }
312
313 #ifndef LIBCAPTIVE
314
315 VOID STDCALL
316 PiDeleteProcess(PVOID ObjectBody)
317 {
318   KIRQL oldIrql;
319   PEPROCESS Process;
320   ULONG i;
321
322   DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody);
323
324   Process = (PEPROCESS)ObjectBody;
325   KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
326   for (i = 0; i < PiProcessNotifyRoutineCount; i++)
327     {
328       PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
329                                 (HANDLE)Process->UniqueProcessId,
330                                 FALSE);
331     }
332    RemoveEntryList(&Process->ProcessListEntry);
333    KeReleaseSpinLock(&PsProcessListLock, oldIrql);
334
335    /* KDB hook */
336    KDB_DELETEPROCESS_HOOK(Process);
337
338    ObDereferenceObject(Process->Token);
339    ObDeleteHandleTable(Process);
340
341    (VOID)MmReleaseMmInfo(Process);
342 }
343
344
345 static NTSTATUS
346 PsCreatePeb(HANDLE ProcessHandle,
347             PVOID ImageBase,
348             PVOID* RPeb)
349 {
350    NTSTATUS Status;
351    PVOID PebBase;
352    ULONG PebSize;
353    PEB Peb;
354    ULONG BytesWritten;
355    
356    memset(&Peb, 0, sizeof(Peb));
357    Peb.ImageBaseAddress = ImageBase;
358    
359    PebBase = (PVOID)PEB_BASE;
360    PebSize = 0x1000;
361    Status = NtAllocateVirtualMemory(ProcessHandle,
362                                     &PebBase,
363                                     0,
364                                     &PebSize,
365                                     MEM_RESERVE | MEM_COMMIT,
366                                     PAGE_READWRITE);
367    if (!NT_SUCCESS(Status))
368      {
369         return(Status);
370      }
371    
372    NtWriteVirtualMemory(ProcessHandle,
373                         (PVOID)PEB_BASE,
374                         &Peb,
375                         sizeof(Peb),
376                         &BytesWritten);
377
378    DPRINT("PsCreatePeb: Peb created at %x\n", PebBase);
379    
380    *RPeb = PebBase;
381    
382    return(STATUS_SUCCESS);
383 }
384
385
386 PKPROCESS
387 KeGetCurrentProcess(VOID)
388 /*
389  * FUNCTION: Returns a pointer to the current process
390  */
391 {
392    return(&(PsGetCurrentProcess()->Pcb));
393 }
394
395 HANDLE STDCALL
396 PsGetCurrentProcessId(VOID)
397 {
398    return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
399 }
400
401 #endif /* LIBCAPTIVE */
402
403 /*
404  * FUNCTION: Returns a pointer to the current process
405  */
406 PEPROCESS STDCALL
407 PsGetCurrentProcess(VOID)
408 {
409 #ifndef LIBCAPTIVE
410    if (PsGetCurrentThread() == NULL || 
411        PsGetCurrentThread()->ThreadsProcess == NULL)
412      {
413 #endif /* LIBCAPTIVE */
414         return(PsInitialSystemProcess);
415 #ifndef LIBCAPTIVE
416      }
417    else
418      {
419         return(PsGetCurrentThread()->ThreadsProcess);
420      }
421 #endif /* LIBCAPTIVE */
422 }
423
424 PEPROCESS STDCALL
425 IoGetCurrentProcess(VOID)
426 {
427   return(PsGetCurrentProcess());
428 }
429
430 #ifndef LIBCAPTIVE
431
432 NTSTATUS STDCALL
433 PsCreateSystemProcess(PHANDLE ProcessHandle,
434                       ACCESS_MASK DesiredAccess,
435                       POBJECT_ATTRIBUTES ObjectAttributes)
436 {
437    return NtCreateProcess(ProcessHandle,
438                           DesiredAccess,
439                           ObjectAttributes,
440                           SystemProcessHandle,
441                           FALSE,
442                           NULL,
443                           NULL,
444                           NULL);
445 }
446
447 NTSTATUS STDCALL
448 NtCreateProcess(OUT PHANDLE ProcessHandle,
449                 IN ACCESS_MASK DesiredAccess,
450                 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
451                 IN HANDLE ParentProcessHandle,
452                 IN BOOLEAN InheritObjectTable,
453                 IN HANDLE SectionHandle OPTIONAL,
454                 IN HANDLE DebugPortHandle OPTIONAL,
455                 IN HANDLE ExceptionPortHandle OPTIONAL)
456 /*
457  * FUNCTION: Creates a process.
458  * ARGUMENTS:
459  *        ProcessHandle (OUT) = Caller supplied storage for the resulting 
460  *                              handle
461  *        DesiredAccess = Specifies the allowed or desired access to the 
462  *                        process can be a combination of 
463  *                        STANDARD_RIGHTS_REQUIRED| ..  
464  *        ObjectAttribute = Initialized attributes for the object, contains 
465  *                          the rootdirectory and the filename
466  *        ParentProcess = Handle to the parent process.
467  *        InheritObjectTable = Specifies to inherit the objects of the parent 
468  *                             process if true.
469  *        SectionHandle = Handle to a section object to back the image file
470  *        DebugPort = Handle to a DebugPort if NULL the system default debug 
471  *                    port will be used.
472  *        ExceptionPort = Handle to a exception port. 
473  * REMARKS:
474  *        This function maps to the win32 CreateProcess. 
475  * RETURNS: Status
476  */
477 {
478    PEPROCESS Process;
479    PEPROCESS ParentProcess;
480    PKPROCESS KProcess;
481    NTSTATUS Status;
482    KIRQL oldIrql;
483    PVOID LdrStartupAddr;
484    PVOID ImageBase;
485    PVOID Peb;
486    PEPORT DebugPort;
487    PEPORT ExceptionPort;
488    PVOID BaseAddress;
489    PMEMORY_AREA MemoryArea;
490    ULONG i;
491    
492    DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
493
494    Status = ObReferenceObjectByHandle(ParentProcessHandle,
495                                       PROCESS_CREATE_PROCESS,
496                                       PsProcessType,
497                                       ExGetPreviousMode(),
498                                       (PVOID*)&ParentProcess,
499                                       NULL);
500    if (!NT_SUCCESS(Status))
501      {
502         DPRINT("NtCreateProcess() = %x\n",Status);
503         return(Status);
504      }
505
506    Status = ObCreateObject(ProcessHandle,
507                            DesiredAccess,
508                            ObjectAttributes,
509                            PsProcessType,
510                            (PVOID*)&Process);
511    if (!NT_SUCCESS(Status))
512      {
513         ObDereferenceObject(ParentProcess);
514         DPRINT("ObCreateObject() = %x\n",Status);
515         return(Status);
516      }
517
518    KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
519                                 InternalProcessType,
520                                 sizeof(EPROCESS),
521                                 FALSE);
522    KProcess = &Process->Pcb;
523    /* Inherit parent process's affinity. */
524    KProcess->Affinity = ParentProcess->Pcb.Affinity;
525    KProcess->BasePriority = PROCESS_PRIO_NORMAL;
526    MmInitializeAddressSpace(Process,
527                             &Process->AddressSpace);
528    Process->UniqueProcessId = InterlockedIncrement(&PiNextProcessUniqueId);
529    Process->InheritedFromUniqueProcessId = 
530      (HANDLE)ParentProcess->UniqueProcessId;
531    ObCreateHandleTable(ParentProcess,
532                        InheritObjectTable,
533                        Process);
534    MmCopyMmInfo(ParentProcess, Process);
535    if (ParentProcess->Win32WindowStation != (HANDLE)0)
536      {
537        /* Always duplicate the process window station. */
538        Process->Win32WindowStation = 0;
539        Status = ObDuplicateObject(ParentProcess,
540                                   Process,
541                                   ParentProcess->Win32WindowStation,
542                                   &Process->Win32WindowStation,
543                                   0,
544                                   FALSE,
545                                   DUPLICATE_SAME_ACCESS);
546        if (!NT_SUCCESS(Status))
547          {
548            KeBugCheck(0);
549          }
550      }
551    else
552      {
553        Process->Win32WindowStation = (HANDLE)0;
554      }
555    if (ParentProcess->Win32Desktop != (HANDLE)0)
556      {
557        /* Always duplicate the process window station. */
558        Process->Win32Desktop = 0;
559        Status = ObDuplicateObject(ParentProcess,
560                                   Process,
561                                   ParentProcess->Win32Desktop,
562                                   &Process->Win32Desktop,
563                                   0,
564                                   FALSE,
565                                   DUPLICATE_SAME_ACCESS);
566        if (!NT_SUCCESS(Status))
567          {
568            KeBugCheck(0);
569          }
570      }
571    else
572      {
573        Process->Win32Desktop = (HANDLE)0;
574      }
575
576    KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
577    for (i = 0; i < PiProcessNotifyRoutineCount; i++)
578     {
579       PiProcessNotifyRoutine[i](Process->InheritedFromUniqueProcessId,
580                                 (HANDLE)Process->UniqueProcessId,
581                                 TRUE);
582     }
583    InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
584    InitializeListHead(&Process->ThreadListHead);
585    KeReleaseSpinLock(&PsProcessListLock, oldIrql);
586    
587    Process->Pcb.State = PROCESS_STATE_ACTIVE;
588    
589    /*
590     * Add the debug port
591     */
592    if (DebugPortHandle != NULL)
593      {
594         Status = ObReferenceObjectByHandle(DebugPortHandle,
595                                            PORT_ALL_ACCESS,
596                                            ExPortType,
597                                            UserMode,
598                                            (PVOID*)&DebugPort,
599                                            NULL);   
600         if (!NT_SUCCESS(Status))
601           {
602              ObDereferenceObject(Process);
603              ObDereferenceObject(ParentProcess);
604              ZwClose(*ProcessHandle);
605              *ProcessHandle = NULL;
606              return(Status);
607           }
608         Process->DebugPort = DebugPort;
609      }
610         
611    /*
612     * Add the exception port
613     */
614    if (ExceptionPortHandle != NULL)
615      {
616         Status = ObReferenceObjectByHandle(ExceptionPortHandle,
617                                            PORT_ALL_ACCESS,
618                                            ExPortType,
619                                            UserMode,
620                                            (PVOID*)&ExceptionPort,
621                                            NULL);   
622         if (!NT_SUCCESS(Status))
623           {
624              ObDereferenceObject(Process);
625              ObDereferenceObject(ParentProcess);
626              ZwClose(*ProcessHandle);
627              *ProcessHandle = NULL;
628              return(Status);
629           }
630         Process->ExceptionPort = ExceptionPort;
631      }
632    
633    /*
634     * Now we have created the process proper
635     */
636    
637    /*
638     * Create the shared data page
639     */
640    MmLockAddressSpace(&Process->AddressSpace);
641    BaseAddress = (PVOID)USER_SHARED_DATA;
642    Status = MmCreateMemoryArea(Process,
643                                &Process->AddressSpace,
644                                MEMORY_AREA_SHARED_DATA,
645                                &BaseAddress,
646                                PAGE_SIZE,
647                                PAGE_READONLY,
648                                &MemoryArea,
649                                FALSE);
650    MmUnlockAddressSpace(&Process->AddressSpace);
651    if (!NT_SUCCESS(Status))
652      {
653         DPRINT1("Failed to create shared data page\n");
654         KeBugCheck(0);
655      }
656    
657    /*
658     * Map ntdll
659     */
660    Status = LdrpMapSystemDll(*ProcessHandle,
661                              &LdrStartupAddr);
662    if (!NT_SUCCESS(Status))
663      {
664         DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
665         ObDereferenceObject(Process);
666         ObDereferenceObject(ParentProcess);
667         return(Status);
668      }
669    
670    /*
671     * Map the process image
672     */
673    if (SectionHandle != NULL)
674      {
675         DPRINT("Mapping process image\n");
676         Status = LdrpMapImage(*ProcessHandle,
677                               SectionHandle,
678                               &ImageBase);
679         if (!NT_SUCCESS(Status))
680           {
681              DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
682              ObDereferenceObject(Process);
683              ObDereferenceObject(ParentProcess);
684              return(Status);
685           }
686      }
687    else
688      {
689         ImageBase = NULL;
690      }
691    
692   /*
693    * Duplicate the token
694    */
695   Status = SepInitializeNewProcess(Process, ParentProcess);
696   if (!NT_SUCCESS(Status))
697     {
698        DbgPrint("SepInitializeNewProcess failed (Status %x)\n", Status);
699        ObDereferenceObject(Process);
700        ObDereferenceObject(ParentProcess);
701        return(Status);
702     }
703
704    /*
705     * 
706     */
707    DPRINT("Creating PEB\n");
708    Status = PsCreatePeb(*ProcessHandle,
709                         ImageBase,
710                         &Peb);
711    if (!NT_SUCCESS(Status))
712      {
713         DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
714         ObDereferenceObject(Process);
715         ObDereferenceObject(ParentProcess);
716         ZwClose(*ProcessHandle);
717         *ProcessHandle = NULL;
718         return(Status);
719      }
720    Process->Peb = Peb;
721    
722    /*
723     * Maybe send a message to the creator process's debugger
724     */
725 #if 0
726    if (ParentProcess->DebugPort != NULL)
727      {
728         LPC_DBG_MESSAGE Message;
729         HANDLE FileHandle;
730         
731         ObCreateHandle(NULL, // Debugger Process
732                        NULL, // SectionHandle
733                        FILE_ALL_ACCESS,
734                        FALSE,
735                        &FileHandle);
736         
737         Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
738         Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
739           sizeof(LPC_MESSAGE);
740         Message.Type = DBG_EVENT_CREATE_PROCESS;
741         Message.Data.CreateProcess.FileHandle = FileHandle;
742         Message.Data.CreateProcess.Base = ImageBase;
743         Message.Data.CreateProcess.EntryPoint = NULL; //
744         
745         Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
746                                          &Message);
747      }
748 #endif
749    
750    ObDereferenceObject(Process);
751    ObDereferenceObject(ParentProcess);
752    return(STATUS_SUCCESS);
753 }
754
755
756 NTSTATUS STDCALL
757 NtOpenProcess(OUT PHANDLE           ProcessHandle,
758               IN  ACCESS_MASK       DesiredAccess,
759               IN  POBJECT_ATTRIBUTES  ObjectAttributes,
760               IN  PCLIENT_ID        ClientId)
761 {
762    DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
763           "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
764           ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
765           ClientId->UniqueProcess, ClientId->UniqueThread);
766           
767    
768    /*
769     * Not sure of the exact semantics 
770     */
771    if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
772        ObjectAttributes->ObjectName->Buffer != NULL)
773      {
774         NTSTATUS Status;
775         PEPROCESS Process;
776                 
777         Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
778                                          ObjectAttributes->Attributes,
779                                          NULL,
780                                          DesiredAccess,
781                                          PsProcessType,
782                                          UserMode,
783                                          NULL,
784                                          (PVOID*)&Process);
785         if (Status != STATUS_SUCCESS)
786           {
787              return(Status);
788           }
789         
790         Status = ObCreateHandle(PsGetCurrentProcess(),
791                                 Process,
792                                 DesiredAccess,
793                                 FALSE,
794                                 ProcessHandle);
795         ObDereferenceObject(Process);
796    
797         return(Status);
798      }
799    else
800      {
801         KIRQL oldIrql;
802         PLIST_ENTRY current_entry;
803         PEPROCESS current;
804         NTSTATUS Status;
805         
806         KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
807         current_entry = PsProcessListHead.Flink;
808         while (current_entry != &PsProcessListHead)
809           {
810              current = CONTAINING_RECORD(current_entry, EPROCESS, 
811                                          ProcessListEntry);
812              if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
813                {
814                   ObReferenceObjectByPointer(current,
815                                              DesiredAccess,
816                                              PsProcessType,
817                                              UserMode);
818                   KeReleaseSpinLock(&PsProcessListLock, oldIrql);
819                   Status = ObCreateHandle(PsGetCurrentProcess(),
820                                           current,
821                                           DesiredAccess,
822                                           FALSE,
823                                           ProcessHandle);
824                   ObDereferenceObject(current);
825                   DPRINT("*ProcessHandle %x\n", ProcessHandle);
826                   DPRINT("NtOpenProcess() = %x\n", Status);
827                   return(Status);
828                }
829              current_entry = current_entry->Flink;
830           }
831         KeReleaseSpinLock(&PsProcessListLock, oldIrql);
832         DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
833         return(STATUS_UNSUCCESSFUL);
834      }
835    return(STATUS_UNSUCCESSFUL);
836 }
837
838
839 NTSTATUS STDCALL
840 NtQueryInformationProcess(IN  HANDLE ProcessHandle,
841                           IN  CINT ProcessInformationClass,
842                           OUT PVOID ProcessInformation,
843                           IN  ULONG ProcessInformationLength,
844                           OUT PULONG ReturnLength)
845 {
846    PEPROCESS Process;
847    NTSTATUS Status;
848    PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
849    
850    Status = ObReferenceObjectByHandle(ProcessHandle,
851                                       PROCESS_SET_INFORMATION,
852                                       PsProcessType,
853                                       UserMode,
854                                       (PVOID*)&Process,
855                                       NULL);
856    if (Status != STATUS_SUCCESS)
857      {
858         return(Status);
859      }
860    
861    switch (ProcessInformationClass)
862      {
863       case ProcessBasicInformation:
864         ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
865           ProcessInformation;
866         ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
867         ProcessBasicInformationP->PebBaseAddress = Process->Peb;
868         ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
869         ProcessBasicInformationP->UniqueProcessId =
870           Process->UniqueProcessId;
871         ProcessBasicInformationP->InheritedFromUniqueProcessId =
872           (ULONG)Process->InheritedFromUniqueProcessId;
873         Status = STATUS_SUCCESS;
874         break;
875         
876       case ProcessQuotaLimits:
877       case ProcessIoCounters:
878       case ProcessVmCounters:
879       case ProcessTimes:
880       case ProcessDebugPort:
881       case ProcessLdtInformation:
882         Status = STATUS_NOT_IMPLEMENTED;
883         break;
884         
885       case ProcessDefaultHardErrorMode:
886         *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
887         break;
888         
889       case ProcessWorkingSetWatch:
890         Status = STATUS_NOT_IMPLEMENTED;
891         break;
892
893       case ProcessWx86Information:
894       case ProcessHandleCount:
895       case ProcessPriorityBoost:
896       case ProcessDeviceMap:
897       case ProcessSessionInformation:
898       case ProcessWow64Information:
899         Status = STATUS_NOT_IMPLEMENTED;
900         break;
901         
902       case ProcessBasePriority:
903       case ProcessRaisePriority:
904       case ProcessExceptionPort:
905       case ProcessAccessToken:
906       case ProcessLdtSize:
907       case ProcessIoPortHandlers:
908       case ProcessUserModeIOPL:
909       case ProcessEnableAlignmentFaultFixup:
910       case ProcessPriorityClass:
911       case ProcessAffinityMask:
912       case ProcessForegroundInformation:
913       default:
914         Status = STATUS_INVALID_INFO_CLASS;
915      }
916    ObDereferenceObject(Process);
917    return(Status);
918 }
919
920 NTSTATUS
921 PspAssignPrimaryToken(PEPROCESS Process,
922                       HANDLE TokenHandle)
923 {
924    PACCESS_TOKEN Token;
925    PACCESS_TOKEN OldToken;
926    NTSTATUS Status;
927    
928    Status = ObReferenceObjectByHandle(TokenHandle,
929                                       0,
930                                       SepTokenObjectType,
931                                       UserMode,
932                                       (PVOID*)&Token,
933                                       NULL);
934    if (!NT_SUCCESS(Status))
935      {
936         return(Status);
937      }
938    Status = SeExchangePrimaryToken(Process, Token, &OldToken);
939    if (NT_SUCCESS(Status))
940      {
941         ObDereferenceObject(OldToken);
942      }
943    ObDereferenceObject(Token);
944    return(Status);
945 }
946
947 NTSTATUS STDCALL
948 NtSetInformationProcess(IN HANDLE ProcessHandle,
949                         IN CINT ProcessInformationClass,
950                         IN PVOID ProcessInformation,
951                         IN ULONG ProcessInformationLength)
952 {
953    PEPROCESS Process;
954    NTSTATUS Status;
955    PHANDLE ProcessAccessTokenP;
956    
957    Status = ObReferenceObjectByHandle(ProcessHandle,
958                                       PROCESS_SET_INFORMATION,
959                                       PsProcessType,
960                                       UserMode,
961                                       (PVOID*)&Process,
962                                       NULL);
963    if (!NT_SUCCESS(Status))
964      {
965         return(Status);
966      }
967
968    switch (ProcessInformationClass)
969      {
970       case ProcessQuotaLimits:
971       case ProcessBasePriority:
972       case ProcessRaisePriority:
973       case ProcessDebugPort:
974       case ProcessExceptionPort:
975         Status = STATUS_NOT_IMPLEMENTED;
976         break;
977
978       case ProcessAccessToken:
979         ProcessAccessTokenP = (PHANDLE)ProcessInformation;
980         Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
981         break;
982         
983       case ProcessImageFileName:
984         memcpy(Process->ImageFileName, ProcessInformation, 8);
985         Status = STATUS_SUCCESS;
986         break;
987         
988       case ProcessLdtInformation:
989       case ProcessLdtSize:
990       case ProcessDefaultHardErrorMode:
991       case ProcessIoPortHandlers:
992       case ProcessWorkingSetWatch:
993       case ProcessUserModeIOPL:
994       case ProcessEnableAlignmentFaultFixup:
995       case ProcessPriorityClass:
996       case ProcessAffinityMask:
997         Status = STATUS_NOT_IMPLEMENTED;
998         break;
999
1000       case ProcessBasicInformation:
1001       case ProcessIoCounters:
1002       case ProcessVmCounters:
1003       case ProcessTimes:
1004       case ProcessPooledUsageAndLimits:
1005       case ProcessWx86Information:
1006       case ProcessHandleCount:
1007       case ProcessWow64Information:
1008       default:
1009         Status = STATUS_INVALID_INFO_CLASS;
1010
1011      case ProcessDesktop:
1012        Process->Win32Desktop = *(PHANDLE)ProcessInformation;
1013        Status = STATUS_SUCCESS;
1014        break;
1015      }
1016    ObDereferenceObject(Process);
1017    return(Status);
1018 }
1019
1020
1021 /**********************************************************************
1022  * NAME                                                 INTERNAL
1023  *      PiQuerySystemProcessInformation
1024  *
1025  * DESCRIPTION
1026  *      Compute the size of a process+thread snapshot as 
1027  *      expected by NtQuerySystemInformation.
1028  *
1029  * RETURN VALUE
1030  *      0 on error; otherwise the size, in bytes of the buffer
1031  *      required to write a full snapshot.
1032  *
1033  * NOTE
1034  *      We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
1035  */
1036 NTSTATUS
1037 PiQuerySystemProcessInformation(PVOID Buffer,
1038                                 ULONG Size,
1039                                 PULONG ReqSize)
1040 {
1041    return STATUS_NOT_IMPLEMENTED;
1042
1043 #if 0
1044         KIRQL           OldIrql;
1045         PLIST_ENTRY     CurrentEntryP;
1046         PEPROCESS       CurrentP;
1047         PLIST_ENTRY     CurrentEntryT;
1048         PETHREAD        CurrentT;
1049         
1050         ULONG           RequiredSize = 0L;
1051         BOOLEAN         SizeOnly = FALSE;
1052
1053         ULONG           SpiSize = 0L;
1054         
1055         PSYSTEM_PROCESS_INFORMATION     pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
1056         PSYSTEM_PROCESS_INFORMATION     pInfoPLast = NULL;
1057         PSYSTEM_THREAD_INFO             pInfoT = NULL;
1058         
1059
1060    /* Lock the process list. */
1061    KeAcquireSpinLock(&PsProcessListLock,
1062                      &OldIrql);
1063
1064         /*
1065          * Scan the process list. Since the
1066          * list is circular, the guard is false
1067          * after the last process.
1068          */
1069         for (   CurrentEntryP = PsProcessListHead.Flink;
1070                 (CurrentEntryP != & PsProcessListHead);
1071                 CurrentEntryP = CurrentEntryP->Flink
1072                 )
1073         {
1074                 /*
1075                  * Compute how much space is
1076                  * occupied in the snapshot
1077                  * by adding this process info.
1078                  * (at least one thread).
1079                  */
1080                 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
1081                 RequiredSize += SpiSizeCurrent;
1082                 /*
1083                  * Do not write process data in the
1084                  * buffer if it is too small.
1085                  */
1086                 if (TRUE == SizeOnly) continue;
1087                 /*
1088                  * Check if the buffer can contain
1089                  * the full snapshot.
1090                  */
1091                 if (Size < RequiredSize)
1092                 {
1093                         SizeOnly = TRUE;
1094                         continue;
1095                 }
1096                 /* 
1097                  * Get a reference to the 
1098                  * process descriptor we are
1099                  * handling.
1100                  */
1101                 CurrentP = CONTAINING_RECORD(
1102                                 CurrentEntryP,
1103                                 EPROCESS, 
1104                                 ProcessListEntry
1105                                 );
1106                 /*
1107                  * Write process data in the buffer.
1108                  */
1109                 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
1110                 /* PROCESS */
1111                 pInfoP->ThreadCount = 0L;
1112                 pInfoP->ProcessId = CurrentP->UniqueProcessId;
1113                 RtlInitUnicodeString (
1114                         & pInfoP->Name,
1115                         CurrentP->ImageFileName
1116                         );
1117                 /* THREAD */
1118                 for (   pInfoT = & CurrentP->ThreadSysInfo [0],
1119                         CurrentEntryT = CurrentP->ThreadListHead.Flink;
1120                         
1121                         (CurrentEntryT != & CurrentP->ThreadListHead);
1122                         
1123                         pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
1124                         CurrentEntryT = CurrentEntryT->Flink
1125                         )
1126                 {
1127                         /*
1128                          * Recalculate the size of the
1129                          * information block.
1130                          */
1131                         if (0 < pInfoP->ThreadCount)
1132                         {
1133                                 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
1134                         }
1135                         /*
1136                          * Do not write thread data in the
1137                          * buffer if it is too small.
1138                          */
1139                         if (TRUE == SizeOnly) continue;
1140                         /*
1141                          * Check if the buffer can contain
1142                          * the full snapshot.
1143                          */
1144                         if (Size < RequiredSize)
1145                         {
1146                                 SizeOnly = TRUE;
1147                                 continue;
1148                         }
1149                         /* 
1150                          * Get a reference to the 
1151                          * thread descriptor we are
1152                          * handling.
1153                          */
1154                         CurrentT = CONTAINING_RECORD(
1155                                         CurrentEntryT,
1156                                         KTHREAD, 
1157                                         Tcb.ThreadListEntry
1158                                         );
1159                         /*
1160                          * Write thread data.
1161                          */
1162                         RtlZeroMemory (
1163                                 pInfoT,
1164                                 sizeof (SYSTEM_THREAD_INFORMATION)
1165                                 );
1166                         pInfoT->KernelTime      = CurrentT-> ;  /* TIME */
1167                         pInfoT->UserTime        = CurrentT-> ;  /* TIME */
1168                         pInfoT->CreateTime      = CurrentT-> ;  /* TIME */
1169                         pInfoT->TickCount       = CurrentT-> ;  /* ULONG */
1170                         pInfoT->StartEIP        = CurrentT-> ;  /* ULONG */
1171                         pInfoT->ClientId        = CurrentT-> ;  /* CLIENT_ID */
1172                         pInfoT->ClientId        = CurrentT-> ;  /* CLIENT_ID */
1173                         pInfoT->DynamicPriority = CurrentT-> ;  /* ULONG */
1174                         pInfoT->BasePriority    = CurrentT-> ;  /* ULONG */
1175                         pInfoT->nSwitches       = CurrentT-> ;  /* ULONG */
1176                         pInfoT->State           = CurrentT-> ;  /* DWORD */
1177                         pInfoT->WaitReason      = CurrentT-> ;  /* KWAIT_REASON */
1178                         /*
1179                          * Count the number of threads 
1180                          * this process has.
1181                          */
1182                         ++ pInfoP->ThreadCount;
1183                 }
1184                 /*
1185                  * Save the size of information
1186                  * stored in the buffer for the
1187                  * current process.
1188                  */
1189                 pInfoP->RelativeOffset = SpiSize;
1190                 /*
1191                  * Save a reference to the last
1192                  * valid information block.
1193                  */
1194                 pInfoPLast = pInfoP;
1195                 /*
1196                  * Compute the offset of the 
1197                  * SYSTEM_PROCESS_INFORMATION
1198                  * descriptor in the snapshot 
1199                  * buffer for the next process.
1200                  */
1201                 (ULONG) pInfoP += SpiSize;
1202         }
1203         /*
1204          * Unlock the process list.
1205          */
1206         KeReleaseSpinLock (
1207                 & PsProcessListLock,
1208                 OldIrql
1209                 );
1210         /*
1211          * Return the proper error status code,
1212          * if the buffer was too small.
1213          */
1214         if (TRUE == SizeOnly)
1215         {
1216                 if (NULL != RequiredSize)
1217                 {
1218                         *pRequiredSize = RequiredSize;
1219                 }
1220                 return STATUS_INFO_LENGTH_MISMATCH;
1221         }
1222         /*
1223          * Mark the end of the snapshot.
1224          */
1225         pInfoP->RelativeOffset = 0L;
1226         /* OK */        
1227         return STATUS_SUCCESS;
1228 #endif
1229 }
1230
1231 LARGE_INTEGER STDCALL
1232 PsGetProcessExitTime(VOID)
1233 {
1234   LARGE_INTEGER Li;
1235   Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart;
1236   return Li;
1237 }
1238
1239 BOOLEAN STDCALL
1240 PsIsThreadTerminating(IN PETHREAD Thread)
1241 {
1242   return(Thread->DeadThread);
1243 }
1244
1245
1246 NTSTATUS STDCALL
1247 PsLookupProcessByProcessId(IN PVOID ProcessId,
1248                            OUT PEPROCESS *Process)
1249 {
1250   KIRQL oldIrql;
1251   PLIST_ENTRY current_entry;
1252   PEPROCESS current;
1253
1254   KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
1255
1256   current_entry = PsProcessListHead.Flink;
1257   while (current_entry != &PsProcessListHead)
1258     {
1259       current = CONTAINING_RECORD(current_entry,
1260                                   EPROCESS,
1261                                   ProcessListEntry);
1262       if (current->UniqueProcessId == (ULONG)ProcessId)
1263         {
1264           *Process = current;
1265           KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1266           return(STATUS_SUCCESS);
1267         }
1268       current_entry = current_entry->Flink;
1269     }
1270
1271   KeReleaseSpinLock(&PsProcessListLock, oldIrql);
1272
1273   return(STATUS_INVALID_PARAMETER);
1274 }
1275
1276
1277 NTSTATUS STDCALL
1278 PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
1279                                 IN BOOLEAN Remove)
1280 {
1281   if (PiProcessNotifyRoutineCount >= MAX_PROCESS_NOTIFY_ROUTINE_COUNT)
1282     return(STATUS_INSUFFICIENT_RESOURCES);
1283
1284   PiProcessNotifyRoutine[PiProcessNotifyRoutineCount] = NotifyRoutine;
1285   PiProcessNotifyRoutineCount++;
1286
1287   return(STATUS_SUCCESS);
1288 }
1289
1290 #endif /* LIBCAPTIVE */
1291
1292 /* EOF */