0f98864af27aa6120aac8e27d14310459387b9b9
[reactos.git] / reactos / ntoskrnl / ps / process.c
1 /* $Id: process.c,v 1.51 2000/07/07 00:49:02 phreak 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 #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 <string.h>
21 #include <internal/string.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
29 #define NDEBUG
30 #include <internal/debug.h>
31
32 /* GLOBALS ******************************************************************/
33
34 PEPROCESS EXPORTED PsInitialSystemProcess = NULL;
35 HANDLE SystemProcessHandle = NULL;
36
37 POBJECT_TYPE EXPORTED PsProcessType = NULL;
38
39 static LIST_ENTRY PsProcessListHead;
40 static KSPIN_LOCK PsProcessListLock;
41 static ULONG PiNextProcessUniqueId = 0;
42
43 /* FUNCTIONS *****************************************************************/
44
45
46 PEPROCESS PsGetNextProcess(PEPROCESS OldProcess)
47 {
48 KIRQL oldIrql;
49 PEPROCESS NextProcess;
50 NTSTATUS Status;
51
52 if (OldProcess == NULL)
53 {
54 return(PsInitialSystemProcess);
55 }
56
57 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
58 if (OldProcess->ProcessListEntry.Flink == &PsProcessListHead)
59 {
60 NextProcess = CONTAINING_RECORD(PsProcessListHead.Flink,
61 EPROCESS,
62 ProcessListEntry);
63 }
64 else
65 {
66 NextProcess = CONTAINING_RECORD(OldProcess->ProcessListEntry.Flink,
67 EPROCESS,
68 ProcessListEntry);
69 }
70 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
71 Status = ObReferenceObjectByPointer(NextProcess,
72 PROCESS_ALL_ACCESS,
73 PsProcessType,
74 KernelMode);
75 if (!NT_SUCCESS(Status))
76 {
77 DbgPrint("PsGetNextProcess(): ObReferenceObjectByPointer failed\n");
78 KeBugCheck(0);
79 }
80 ObDereferenceObject(OldProcess);
81
82 return(NextProcess);
83 }
84
85 NTSTATUS STDCALL NtOpenProcessToken(IN HANDLE ProcessHandle,
86 IN ACCESS_MASK DesiredAccess,
87 OUT PHANDLE TokenHandle)
88 {
89 PACCESS_TOKEN Token;
90 NTSTATUS Status;
91
92 Status = PsOpenTokenOfProcess(ProcessHandle,
93 &Token);
94 if (!NT_SUCCESS(Status))
95 {
96 return(Status);
97 }
98 Status = ObCreateHandle(PsGetCurrentProcess(),
99 Token,
100 DesiredAccess,
101 FALSE,
102 ProcessHandle);
103 ObDereferenceObject(Token);
104 return(Status);
105 }
106
107 PACCESS_TOKEN STDCALL PsReferencePrimaryToken(PEPROCESS Process)
108 {
109 ObReferenceObjectByPointer(Process->Token,
110 GENERIC_ALL,
111 SeTokenType,
112 UserMode);
113 return(Process->Token);
114 }
115
116 NTSTATUS PsOpenTokenOfProcess(HANDLE ProcessHandle,
117 PACCESS_TOKEN* Token)
118 {
119 PEPROCESS Process;
120 NTSTATUS Status;
121
122 Status = ObReferenceObjectByHandle(ProcessHandle,
123 PROCESS_QUERY_INFORMATION,
124 PsProcessType,
125 UserMode,
126 (PVOID*)&Process,
127 NULL);
128 if (!NT_SUCCESS(Status))
129 {
130 return(Status);
131 }
132 *Token = PsReferencePrimaryToken(Process);
133 ObDereferenceObject(Process);
134 return(STATUS_SUCCESS);
135 }
136
137 VOID PiKillMostProcesses(VOID)
138 {
139 KIRQL oldIrql;
140 PLIST_ENTRY current_entry;
141 PEPROCESS current;
142
143 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
144
145 current_entry = PsProcessListHead.Flink;
146 while (current_entry != &PsProcessListHead)
147 {
148 current = CONTAINING_RECORD(current_entry, EPROCESS,
149 ProcessListEntry);
150 current_entry = current_entry->Flink;
151
152 if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
153 current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
154 {
155 PiTerminateProcessThreads(current, STATUS_SUCCESS);
156 }
157 }
158
159 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
160 }
161
162 VOID PsInitProcessManagment(VOID)
163 {
164
165 PKPROCESS KProcess;
166 KIRQL oldIrql;
167
168 /*
169 * Register the process object type
170 */
171
172 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
173
174 PsProcessType->TotalObjects = 0;
175 PsProcessType->TotalHandles = 0;
176 PsProcessType->MaxObjects = ULONG_MAX;
177 PsProcessType->MaxHandles = ULONG_MAX;
178 PsProcessType->PagedPoolCharge = 0;
179 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
180 PsProcessType->Dump = NULL;
181 PsProcessType->Open = NULL;
182 PsProcessType->Close = NULL;
183 PsProcessType->Delete = PiDeleteProcess;
184 PsProcessType->Parse = NULL;
185 PsProcessType->Security = NULL;
186 PsProcessType->QueryName = NULL;
187 PsProcessType->OkayToClose = NULL;
188 PsProcessType->Create = NULL;
189
190 RtlInitUnicodeString(&PsProcessType->TypeName, L"Process");
191
192 InitializeListHead(&PsProcessListHead);
193 KeInitializeSpinLock(&PsProcessListLock);
194
195 /*
196 * Initialize the system process
197 */
198 PsInitialSystemProcess = ObCreateObject(NULL,
199 PROCESS_ALL_ACCESS,
200 NULL,
201 PsProcessType);
202 PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
203 KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
204 InternalProcessType,
205 sizeof(EPROCESS),
206 FALSE);
207 KProcess = &PsInitialSystemProcess->Pcb;
208
209 MmInitializeAddressSpace(PsInitialSystemProcess,
210 &PsInitialSystemProcess->AddressSpace);
211 ObCreateHandleTable(NULL,FALSE,PsInitialSystemProcess);
212 KProcess->PageTableDirectory = get_page_directory();
213 PsInitialSystemProcess->UniqueProcessId =
214 InterlockedIncrement(&PiNextProcessUniqueId);
215
216 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
217 InsertHeadList(&PsProcessListHead,
218 &PsInitialSystemProcess->ProcessListEntry);
219 InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
220 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
221
222 strcpy(PsInitialSystemProcess->ImageFileName, "SYSTEM");
223
224 ObCreateHandle(PsInitialSystemProcess,
225 PsInitialSystemProcess,
226 PROCESS_ALL_ACCESS,
227 FALSE,
228 &SystemProcessHandle);
229 }
230
231 VOID PiDeleteProcess(PVOID ObjectBody)
232 {
233 KIRQL oldIrql;
234
235 DPRINT1("PiDeleteProcess(ObjectBody %x)\n",ObjectBody);
236
237 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
238 RemoveEntryList(&((PEPROCESS)ObjectBody)->ProcessListEntry);
239 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
240 (VOID)MmReleaseMmInfo((PEPROCESS)ObjectBody);
241 ObDeleteHandleTable((PEPROCESS)ObjectBody);
242 }
243
244
245 static NTSTATUS PsCreatePeb(HANDLE ProcessHandle,
246 PVOID ImageBase,
247 PVOID* RPeb)
248 {
249 NTSTATUS Status;
250 PVOID PebBase;
251 ULONG PebSize;
252 PEB Peb;
253 ULONG BytesWritten;
254
255 memset(&Peb, 0, sizeof(Peb));
256 Peb.ImageBaseAddress = ImageBase;
257
258 PebBase = (PVOID)PEB_BASE;
259 PebSize = 0x1000;
260 Status = NtAllocateVirtualMemory(ProcessHandle,
261 &PebBase,
262 0,
263 &PebSize,
264 MEM_COMMIT,
265 PAGE_READWRITE);
266 if (!NT_SUCCESS(Status))
267 {
268 return(Status);
269 }
270
271 ZwWriteVirtualMemory(ProcessHandle,
272 (PVOID)PEB_BASE,
273 &Peb,
274 sizeof(Peb),
275 &BytesWritten);
276
277 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase);
278
279 *RPeb = PebBase;
280
281 return(STATUS_SUCCESS);
282 }
283
284
285 PKPROCESS KeGetCurrentProcess(VOID)
286 /*
287 * FUNCTION: Returns a pointer to the current process
288 */
289 {
290 return(&(PsGetCurrentProcess()->Pcb));
291 }
292
293 HANDLE STDCALL PsGetCurrentProcessId(VOID)
294 {
295 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
296 }
297
298 /*
299 * FUNCTION: Returns a pointer to the current process
300 */
301 PEPROCESS STDCALL PsGetCurrentProcess(VOID)
302 {
303 if (PsGetCurrentThread() == NULL ||
304 PsGetCurrentThread()->ThreadsProcess == NULL)
305 {
306 return(PsInitialSystemProcess);
307 }
308 else
309 {
310 return(PsGetCurrentThread()->ThreadsProcess);
311 }
312 }
313
314 PEPROCESS STDCALL IoGetCurrentProcess(VOID)
315 {
316 return(PsGetCurrentProcess());
317 }
318
319 NTSTATUS STDCALL NtCreateProcess (OUT PHANDLE ProcessHandle,
320 IN ACCESS_MASK DesiredAccess,
321 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
322 IN HANDLE ParentProcessHandle,
323 IN BOOLEAN InheritObjectTable,
324 IN HANDLE SectionHandle OPTIONAL,
325 IN HANDLE DebugPortHandle OPTIONAL,
326 IN HANDLE ExceptionPortHandle OPTIONAL)
327 /*
328 * FUNCTION: Creates a process.
329 * ARGUMENTS:
330 * ProcessHandle (OUT) = Caller supplied storage for the resulting
331 * handle
332 * DesiredAccess = Specifies the allowed or desired access to the
333 * process can be a combination of
334 * STANDARD_RIGHTS_REQUIRED| ..
335 * ObjectAttribute = Initialized attributes for the object, contains
336 * the rootdirectory and the filename
337 * ParentProcess = Handle to the parent process.
338 * InheritObjectTable = Specifies to inherit the objects of the parent
339 * process if true.
340 * SectionHandle = Handle to a section object to back the image file
341 * DebugPort = Handle to a DebugPort if NULL the system default debug
342 * port will be used.
343 * ExceptionPort = Handle to a exception port.
344 * REMARKS:
345 * This function maps to the win32 CreateProcess.
346 * RETURNS: Status
347 */
348 {
349 PEPROCESS Process;
350 PEPROCESS ParentProcess;
351 PKPROCESS KProcess;
352 NTSTATUS Status;
353 KIRQL oldIrql;
354 PVOID LdrStartupAddr;
355 PVOID ImageBase;
356 PVOID Peb;
357 PEPORT DebugPort;
358 PEPORT ExceptionPort;
359
360 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
361
362 Status = ObReferenceObjectByHandle(ParentProcessHandle,
363 PROCESS_CREATE_PROCESS,
364 PsProcessType,
365 UserMode,
366 (PVOID*)&ParentProcess,
367 NULL);
368
369 if (Status != STATUS_SUCCESS)
370 {
371 DPRINT("NtCreateProcess() = %x\n",Status);
372 return(Status);
373 }
374
375 Process = ObCreateObject(ProcessHandle,
376 DesiredAccess,
377 ObjectAttributes,
378 PsProcessType);
379 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
380 InternalProcessType,
381 sizeof(EPROCESS),
382 FALSE);
383 KProcess = &Process->Pcb;
384
385 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
386 MmInitializeAddressSpace(Process,
387 &Process->AddressSpace);
388 Process->UniqueProcessId = InterlockedIncrement(&PiNextProcessUniqueId);
389 Process->InheritedFromUniqueProcessId = ParentProcess->UniqueProcessId;
390 ObCreateHandleTable(ParentProcess,
391 InheritObjectTable,
392 Process);
393 MmCopyMmInfo(ParentProcess, Process);
394
395 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
396 InsertHeadList(&PsProcessListHead, &Process->ProcessListEntry);
397 InitializeListHead(&Process->ThreadListHead);
398 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
399
400 Process->Pcb.ProcessState = PROCESS_STATE_ACTIVE;
401
402 /*
403 * Add the debug port
404 */
405 if (DebugPortHandle != NULL)
406 {
407 Status = ObReferenceObjectByHandle(DebugPortHandle,
408 PORT_ALL_ACCESS,
409 ExPortType,
410 UserMode,
411 (PVOID*)&DebugPort,
412 NULL);
413 if (!NT_SUCCESS(Status))
414 {
415 ObDereferenceObject(Process);
416 ObDereferenceObject(ParentProcess);
417 ZwClose(*ProcessHandle);
418 *ProcessHandle = NULL;
419 return(Status);
420 }
421 Process->DebugPort = DebugPort;
422 }
423
424 /*
425 * Add the exception port
426 */
427 if (ExceptionPortHandle != NULL)
428 {
429 Status = ObReferenceObjectByHandle(ExceptionPortHandle,
430 PORT_ALL_ACCESS,
431 ExPortType,
432 UserMode,
433 (PVOID*)&ExceptionPort,
434 NULL);
435 if (!NT_SUCCESS(Status))
436 {
437 ObDereferenceObject(Process);
438 ObDereferenceObject(ParentProcess);
439 ZwClose(*ProcessHandle);
440 *ProcessHandle = NULL;
441 return(Status);
442 }
443 Process->ExceptionPort = ExceptionPort;
444 }
445
446 /*
447 * Now we have created the process proper
448 */
449
450 /*
451 * Map ntdll
452 */
453 Status = LdrpMapSystemDll(*ProcessHandle,
454 &LdrStartupAddr);
455 if (!NT_SUCCESS(Status))
456 {
457 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
458 ObDereferenceObject(Process);
459 ObDereferenceObject(ParentProcess);
460 return(Status);
461 }
462
463 /*
464 * Map the process image
465 */
466 if (SectionHandle != NULL)
467 {
468 DPRINT("Mapping process image\n");
469 Status = LdrpMapImage(*ProcessHandle,
470 SectionHandle,
471 &ImageBase);
472 if (!NT_SUCCESS(Status))
473 {
474 DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
475 ObDereferenceObject(Process);
476 ObDereferenceObject(ParentProcess);
477 return(Status);
478 }
479 }
480 else
481 {
482 ImageBase = NULL;
483 }
484
485 /*
486 *
487 */
488 DPRINT("Creating PEB\n");
489 Status = PsCreatePeb(*ProcessHandle,
490 ImageBase,
491 &Peb);
492 if (!NT_SUCCESS(Status))
493 {
494 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
495 ObDereferenceObject(Process);
496 ObDereferenceObject(ParentProcess);
497 ZwClose(*ProcessHandle);
498 *ProcessHandle = NULL;
499 return(Status);
500 }
501 Process->Peb = Peb;
502
503 /*
504 * Maybe send a message to the creator process's debugger
505 */
506 if (ParentProcess->DebugPort != NULL)
507 {
508 LPC_DBG_MESSAGE Message;
509 HANDLE FileHandle;
510
511 ObCreateHandle(NULL, // Debugger Process
512 NULL, // SectionHandle
513 FILE_ALL_ACCESS,
514 FALSE,
515 &FileHandle);
516
517 Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
518 Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
519 sizeof(LPC_MESSAGE_HEADER);
520 Message.Type = DBG_EVENT_CREATE_PROCESS;
521 Message.Data.CreateProcess.FileHandle = FileHandle;
522 Message.Data.CreateProcess.Base = ImageBase;
523 Message.Data.CreateProcess.EntryPoint = NULL; //
524
525 Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
526 &Message);
527 }
528
529 ObDereferenceObject(Process);
530 ObDereferenceObject(ParentProcess);
531 return(STATUS_SUCCESS);
532 }
533
534
535 NTSTATUS STDCALL NtOpenProcess (OUT PHANDLE ProcessHandle,
536 IN ACCESS_MASK DesiredAccess,
537 IN POBJECT_ATTRIBUTES ObjectAttributes,
538 IN PCLIENT_ID ClientId)
539 {
540 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
541 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
542 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
543 ClientId->UniqueProcess, ClientId->UniqueThread);
544
545
546 /*
547 * Not sure of the exact semantics
548 */
549 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
550 ObjectAttributes->ObjectName->Buffer != NULL)
551 {
552 NTSTATUS Status;
553 PEPROCESS Process;
554
555 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
556 ObjectAttributes->Attributes,
557 NULL,
558 DesiredAccess,
559 PsProcessType,
560 UserMode,
561 NULL,
562 (PVOID*)&Process);
563 if (Status != STATUS_SUCCESS)
564 {
565 return(Status);
566 }
567
568 Status = ObCreateHandle(PsGetCurrentProcess(),
569 Process,
570 DesiredAccess,
571 FALSE,
572 ProcessHandle);
573 ObDereferenceObject(Process);
574
575 return(Status);
576 }
577 else
578 {
579 KIRQL oldIrql;
580 PLIST_ENTRY current_entry;
581 PEPROCESS current;
582 NTSTATUS Status;
583
584 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
585 current_entry = PsProcessListHead.Flink;
586 while (current_entry != &PsProcessListHead)
587 {
588 current = CONTAINING_RECORD(current_entry, EPROCESS,
589 ProcessListEntry);
590 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
591 {
592 ObReferenceObjectByPointer(current,
593 DesiredAccess,
594 PsProcessType,
595 UserMode);
596 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
597 Status = ObCreateHandle(PsGetCurrentProcess(),
598 current,
599 DesiredAccess,
600 FALSE,
601 ProcessHandle);
602 ObDereferenceObject(current);
603 DPRINT("*ProcessHandle %x\n", ProcessHandle);
604 DPRINT("NtOpenProcess() = %x\n", Status);
605 return(Status);
606 }
607 current_entry = current_entry->Flink;
608 }
609 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
610 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
611 return(STATUS_UNSUCCESSFUL);
612 }
613 return(STATUS_UNSUCCESSFUL);
614 }
615
616
617 NTSTATUS STDCALL NtQueryInformationProcess (IN HANDLE ProcessHandle,
618 IN CINT ProcessInformationClass,
619 OUT PVOID ProcessInformation,
620 IN ULONG ProcessInformationLength,
621 OUT PULONG ReturnLength)
622 {
623 PEPROCESS Process;
624 NTSTATUS Status;
625 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
626
627 Status = ObReferenceObjectByHandle(ProcessHandle,
628 PROCESS_SET_INFORMATION,
629 PsProcessType,
630 UserMode,
631 (PVOID*)&Process,
632 NULL);
633 if (Status != STATUS_SUCCESS)
634 {
635 return(Status);
636 }
637
638 switch (ProcessInformationClass)
639 {
640 case ProcessBasicInformation:
641 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
642 ProcessInformation;
643 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
644 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
645 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
646 ProcessBasicInformationP->UniqueProcessId =
647 Process->UniqueProcessId;
648 ProcessBasicInformationP->InheritedFromUniqueProcessId =
649 Process->InheritedFromUniqueProcessId;
650 Status = STATUS_SUCCESS;
651 break;
652
653 case ProcessQuotaLimits:
654 case ProcessIoCounters:
655 case ProcessVmCounters:
656 case ProcessTimes:
657 case ProcessBasePriority:
658 case ProcessRaisePriority:
659 case ProcessDebugPort:
660 case ProcessExceptionPort:
661 case ProcessAccessToken:
662 case ProcessLdtInformation:
663 case ProcessLdtSize:
664 Status = STATUS_NOT_IMPLEMENTED;
665 break;
666
667 case ProcessDefaultHardErrorMode:
668 *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
669 break;
670
671 case ProcessIoPortHandlers:
672 case ProcessWorkingSetWatch:
673 case ProcessUserModeIOPL:
674 case ProcessEnableAlignmentFaultFixup:
675 case ProcessPriorityClass:
676 case ProcessWx86Information:
677 case ProcessHandleCount:
678 case ProcessAffinityMask:
679 default:
680 Status = STATUS_NOT_IMPLEMENTED;
681 }
682 ObDereferenceObject(Process);
683 return(Status);
684 }
685
686 NTSTATUS PspAssignPrimaryToken(PEPROCESS Process,
687 HANDLE TokenHandle)
688 {
689 PACCESS_TOKEN Token;
690 PACCESS_TOKEN OldToken;
691 NTSTATUS Status;
692
693 Status = ObReferenceObjectByHandle(TokenHandle,
694 0,
695 SeTokenType,
696 UserMode,
697 (PVOID*)&Token,
698 NULL);
699 if (!NT_SUCCESS(Status))
700 {
701 return(Status);
702 }
703 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
704 if (!NT_SUCCESS(Status))
705 {
706 ObDereferenceObject(OldToken);
707 }
708 ObDereferenceObject(Token);
709 return(Status);
710 }
711
712 NTSTATUS STDCALL NtSetInformationProcess(IN HANDLE ProcessHandle,
713 IN CINT ProcessInformationClass,
714 IN PVOID ProcessInformation,
715 IN ULONG ProcessInformationLength)
716 {
717 PEPROCESS Process;
718 NTSTATUS Status;
719 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
720 PHANDLE ProcessAccessTokenP;
721
722 Status = ObReferenceObjectByHandle(ProcessHandle,
723 PROCESS_SET_INFORMATION,
724 PsProcessType,
725 UserMode,
726 (PVOID*)&Process,
727 NULL);
728 if (!NT_SUCCESS(Status))
729 {
730 return(Status);
731 }
732
733 switch (ProcessInformationClass)
734 {
735 case ProcessBasicInformation:
736 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
737 ProcessInformation;
738 memset(ProcessBasicInformationP, 0, sizeof(PROCESS_BASIC_INFORMATION));
739 Process->Pcb.Affinity = ProcessBasicInformationP->AffinityMask;
740 Status = STATUS_SUCCESS;
741 break;
742
743 case ProcessQuotaLimits:
744 case ProcessIoCounters:
745 case ProcessVmCounters:
746 case ProcessTimes:
747 case ProcessBasePriority:
748 case ProcessRaisePriority:
749 case ProcessDebugPort:
750 case ProcessExceptionPort:
751 case ProcessAccessToken:
752 ProcessAccessTokenP = (PHANDLE)ProcessInformation;
753 Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
754 break;
755
756 case ProcessImageFileName:
757 memcpy(Process->ImageFileName, ProcessInformation, 8);
758 // DPRINT1("Process->ImageFileName %.8s\n", Process->ImageFileName);
759 Status = STATUS_SUCCESS;
760 break;
761
762 case ProcessLdtInformation:
763 case ProcessLdtSize:
764 case ProcessDefaultHardErrorMode:
765 case ProcessIoPortHandlers:
766 case ProcessWorkingSetWatch:
767 case ProcessUserModeIOPL:
768 case ProcessEnableAlignmentFaultFixup:
769 case ProcessPriorityClass:
770 case ProcessWx86Information:
771 case ProcessHandleCount:
772 case ProcessAffinityMask:
773 default:
774 Status = STATUS_NOT_IMPLEMENTED;
775 }
776 ObDereferenceObject(Process);
777 return(Status);
778 }
779
780
781 #if 0
782 /**********************************************************************
783 * NAME INTERNAL
784 * PiSnapshotProcessTable
785 *
786 * DESCRIPTION
787 * Compute the size of a process+thread snapshot as
788 * expected by NtQuerySystemInformation.
789 *
790 * RETURN VALUE
791 * 0 on error; otherwise the size, in bytes of the buffer
792 * required to write a full snapshot.
793 *
794 * NOTE
795 * We assume (sizeof (PVOID) == sizeof (ULONG)) holds.
796 */
797 NTSTATUS
798 STDCALL
799 PiSnapshotProcessTable (
800 IN PVOID SnapshotBuffer,
801 IN ULONG Size,
802 IN PULONG pRequiredSize
803 )
804 {
805 KIRQL OldIrql;
806 PLIST_ENTRY CurrentEntryP;
807 PEPROCESS CurrentP;
808 PLIST_ENTRY CurrentEntryT;
809 PETHREAD CurrentT;
810
811 ULONG RequiredSize = 0L;
812 BOOLEAN SizeOnly = FALSE;
813
814 ULONG SpiSize = 0L;
815
816 PSYSTEM_PROCESS_INFORMATION pInfoP = (PSYSTEM_PROCESS_INFORMATION) SnapshotBuffer;
817 PSYSTEM_PROCESS_INFORMATION pInfoPLast = NULL;
818 PSYSTEM_THREAD_INFO pInfoT = NULL;
819
820
821 /*
822 * Lock the process list.
823 */
824 KeAcquireSpinLock (
825 & PsProcessListLock,
826 & OldIrql
827 );
828 /*
829 * Scan the process list. Since the
830 * list is circular, the guard is false
831 * after the last process.
832 */
833 for ( CurrentEntryP = PsProcessListHead.Flink;
834 (CurrentEntryP != & PsProcessListHead);
835 CurrentEntryP = CurrentEntryP->Flink
836 )
837 {
838 /*
839 * Compute how much space is
840 * occupied in the snapshot
841 * by adding this process info.
842 * (at least one thread).
843 */
844 SpiSizeCurrent = sizeof (SYSTEM_PROCESS_INFORMATION);
845 RequiredSize += SpiSizeCurrent;
846 /*
847 * Do not write process data in the
848 * buffer if it is too small.
849 */
850 if (TRUE == SizeOnly) continue;
851 /*
852 * Check if the buffer can contain
853 * the full snapshot.
854 */
855 if (Size < RequiredSize)
856 {
857 SizeOnly = TRUE;
858 continue;
859 }
860 /*
861 * Get a reference to the
862 * process descriptor we are
863 * handling.
864 */
865 CurrentP = CONTAINING_RECORD(
866 CurrentEntryP,
867 EPROCESS,
868 ProcessListEntry
869 );
870 /*
871 * Write process data in the buffer.
872 */
873 RtlZeroMemory (pInfoP, sizeof (SYSTEM_PROCESS_INFORMATION));
874 /* PROCESS */
875 pInfoP->ThreadCount = 0L;
876 pInfoP->ProcessId = CurrentP->UniqueProcessId;
877 RtlInitUnicodeString (
878 & pInfoP->Name,
879 CurrentP->ImageFileName
880 );
881 /* THREAD */
882 for ( pInfoT = & CurrentP->ThreadSysInfo [0],
883 CurrentEntryT = CurrentP->ThreadListHead.Flink;
884
885 (CurrentEntryT != & CurrentP->ThreadListHead);
886
887 pInfoT = & CurrentP->ThreadSysInfo [pInfoP->ThreadCount],
888 CurrentEntryT = CurrentEntryT->Flink
889 )
890 {
891 /*
892 * Recalculate the size of the
893 * information block.
894 */
895 if (0 < pInfoP->ThreadCount)
896 {
897 RequiredSize += sizeof (SYSTEM_THREAD_INFORMATION);
898 }
899 /*
900 * Do not write thread data in the
901 * buffer if it is too small.
902 */
903 if (TRUE == SizeOnly) continue;
904 /*
905 * Check if the buffer can contain
906 * the full snapshot.
907 */
908 if (Size < RequiredSize)
909 {
910 SizeOnly = TRUE;
911 continue;
912 }
913 /*
914 * Get a reference to the
915 * thread descriptor we are
916 * handling.
917 */
918 CurrentT = CONTAINING_RECORD(
919 CurrentEntryT,
920 KTHREAD,
921 Tcb.ThreadListEntry
922 );
923 /*
924 * Write thread data.
925 */
926 RtlZeroMemory (
927 pInfoT,
928 sizeof (SYSTEM_THREAD_INFORMATION)
929 );
930 pInfoT->KernelTime = CurrentT-> ; /* TIME */
931 pInfoT->UserTime = CurrentT-> ; /* TIME */
932 pInfoT->CreateTime = CurrentT-> ; /* TIME */
933 pInfoT->TickCount = CurrentT-> ; /* ULONG */
934 pInfoT->StartEIP = CurrentT-> ; /* ULONG */
935 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
936 pInfoT->ClientId = CurrentT-> ; /* CLIENT_ID */
937 pInfoT->DynamicPriority = CurrentT-> ; /* ULONG */
938 pInfoT->BasePriority = CurrentT-> ; /* ULONG */
939 pInfoT->nSwitches = CurrentT-> ; /* ULONG */
940 pInfoT->State = CurrentT-> ; /* DWORD */
941 pInfoT->WaitReason = CurrentT-> ; /* KWAIT_REASON */
942 /*
943 * Count the number of threads
944 * this process has.
945 */
946 ++ pInfoP->ThreadCount;
947 }
948 /*
949 * Save the size of information
950 * stored in the buffer for the
951 * current process.
952 */
953 pInfoP->RelativeOffset = SpiSize;
954 /*
955 * Save a reference to the last
956 * valid information block.
957 */
958 pInfoPLast = pInfoP;
959 /*
960 * Compute the offset of the
961 * SYSTEM_PROCESS_INFORMATION
962 * descriptor in the snapshot
963 * buffer for the next process.
964 */
965 (ULONG) pInfoP += SpiSize;
966 }
967 /*
968 * Unlock the process list.
969 */
970 KeReleaseSpinLock (
971 & PsProcessListLock,
972 OldIrql
973 );
974 /*
975 * Return the proper error status code,
976 * if the buffer was too small.
977 */
978 if (TRUE == SizeOnly)
979 {
980 if (NULL != RequiredSize)
981 {
982 *pRequiredSize = RequiredSize;
983 }
984 return STATUS_INFO_LENGTH_MISMATCH;
985 }
986 /*
987 * Mark the end of the snapshot.
988 */
989 pInfoP->RelativeOffset = 0L;
990 /* OK */
991 return STATUS_SUCCESS;
992 }
993 #endif
994
995 /* EOF */