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