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