Updated the minix driver
[reactos.git] / reactos / ntoskrnl / ps / process.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/process.c
5 * PURPOSE: Process managment
6 * PROGRAMMER: David Welch (welch@cwcom.net)
7 * REVISION HISTORY:
8 * 21/07/98: Created
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <internal/ob.h>
15 #include <internal/mm.h>
16 #include <internal/ke.h>
17 #include <internal/ps.h>
18 #include <string.h>
19 #include <internal/string.h>
20 #include <internal/id.h>
21 #include <internal/teb.h>
22 #include <internal/ldr.h>
23
24 #define NDEBUG
25 #include <internal/debug.h>
26
27 /* GLOBALS ******************************************************************/
28
29 PEPROCESS SystemProcess = NULL;
30 HANDLE SystemProcessHandle = NULL;
31
32 POBJECT_TYPE PsProcessType = NULL;
33
34 static LIST_ENTRY PsProcessListHead;
35 static KSPIN_LOCK PsProcessListLock;
36 static ULONG PiNextProcessUniqueId = 0;
37
38 /* FUNCTIONS *****************************************************************/
39
40 NTSTATUS STDCALL NtOpenProcessToken(IN HANDLE ProcessHandle,
41 IN ACCESS_MASK DesiredAccess,
42 OUT PHANDLE TokenHandle)
43 {
44 PACCESS_TOKEN Token;
45 NTSTATUS Status;
46
47 Status = PsOpenTokenOfProcess(ProcessHandle,
48 &Token);
49 if (!NT_SUCCESS(Status))
50 {
51 return(Status);
52 }
53 Status = ObCreateHandle(PsGetCurrentProcess(),
54 Token,
55 DesiredAccess,
56 FALSE,
57 ProcessHandle);
58 ObDereferenceObject(Token);
59 return(Status);
60 }
61
62 PACCESS_TOKEN PsReferencePrimaryToken(PEPROCESS Process)
63 {
64 ObReferenceObjectByPointer(Process->Token,
65 GENERIC_ALL,
66 SeTokenType,
67 UserMode);
68 return(Process->Token);
69 }
70
71 NTSTATUS PsOpenTokenOfProcess(HANDLE ProcessHandle,
72 PACCESS_TOKEN* Token)
73 {
74 PEPROCESS Process;
75 NTSTATUS Status;
76
77 Status = ObReferenceObjectByHandle(ProcessHandle,
78 PROCESS_QUERY_INFORMATION,
79 PsProcessType,
80 UserMode,
81 (PVOID*)&Process,
82 NULL);
83 if (!NT_SUCCESS(Status))
84 {
85 return(Status);
86 }
87 *Token = PsReferencePrimaryToken(Process);
88 ObDereferenceObject(Process);
89 return(STATUS_SUCCESS);
90 }
91
92 VOID PiKillMostProcesses(VOID)
93 {
94 KIRQL oldIrql;
95 PLIST_ENTRY current_entry;
96 PEPROCESS current;
97
98 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
99
100 current_entry = PsProcessListHead.Flink;
101 while (current_entry != &PsProcessListHead)
102 {
103 current = CONTAINING_RECORD(current_entry, EPROCESS,
104 Pcb.ProcessListEntry);
105 current_entry = current_entry->Flink;
106
107 if (current->UniqueProcessId != SystemProcess->UniqueProcessId &&
108 current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
109 {
110 PiTerminateProcess(current, STATUS_SUCCESS);
111 }
112 }
113
114 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
115 }
116
117 VOID PsInitProcessManagment(VOID)
118 {
119 ANSI_STRING AnsiString;
120 PKPROCESS KProcess;
121 KIRQL oldIrql;
122
123 /*
124 * Register the process object type
125 */
126
127 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
128
129 PsProcessType->TotalObjects = 0;
130 PsProcessType->TotalHandles = 0;
131 PsProcessType->MaxObjects = ULONG_MAX;
132 PsProcessType->MaxHandles = ULONG_MAX;
133 PsProcessType->PagedPoolCharge = 0;
134 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
135 PsProcessType->Dump = NULL;
136 PsProcessType->Open = NULL;
137 PsProcessType->Close = NULL;
138 PsProcessType->Delete = PiDeleteProcess;
139 PsProcessType->Parse = NULL;
140 PsProcessType->Security = NULL;
141 PsProcessType->QueryName = NULL;
142 PsProcessType->OkayToClose = NULL;
143 PsProcessType->Create = NULL;
144
145 RtlInitAnsiString(&AnsiString,"Process");
146 RtlAnsiStringToUnicodeString(&PsProcessType->TypeName,&AnsiString,TRUE);
147
148 InitializeListHead(&PsProcessListHead);
149 KeInitializeSpinLock(&PsProcessListLock);
150
151 /*
152 * Initialize the system process
153 */
154 SystemProcess = ObCreateObject(NULL,
155 PROCESS_ALL_ACCESS,
156 NULL,
157 PsProcessType);
158 SystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
159 KeInitializeDispatcherHeader(&SystemProcess->Pcb.DispatcherHeader,
160 InternalProcessType,
161 sizeof(EPROCESS),
162 FALSE);
163 KProcess = &SystemProcess->Pcb;
164
165 InitializeListHead(&(KProcess->MemoryAreaList));
166 ObCreateHandleTable(NULL,FALSE,SystemProcess);
167 KProcess->PageTableDirectory = get_page_directory();
168 SystemProcess->UniqueProcessId =
169 InterlockedIncrement(&PiNextProcessUniqueId);
170
171 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
172 InsertHeadList(&PsProcessListHead, &KProcess->ProcessListEntry);
173 InitializeListHead( &KProcess->ThreadListHead );
174 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
175
176 strcpy(SystemProcess->ImageFileName, "SYSTEM");
177
178 ObCreateHandle(SystemProcess,
179 SystemProcess,
180 PROCESS_ALL_ACCESS,
181 FALSE,
182 &SystemProcessHandle);
183 }
184
185 VOID PiDeleteProcess(PVOID ObjectBody)
186 {
187 KIRQL oldIrql;
188
189 DPRINT("PiDeleteProcess(ObjectBody %x)\n",ObjectBody);
190
191 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
192 RemoveEntryList(&((PEPROCESS)ObjectBody)->Pcb.ProcessListEntry);
193 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
194 (VOID)MmReleaseMmInfo((PEPROCESS)ObjectBody);
195 ObDeleteHandleTable((PEPROCESS)ObjectBody);
196 }
197
198
199 static NTSTATUS PsCreatePeb(HANDLE ProcessHandle,
200 PVOID ImageBase,
201 PVOID* RPeb)
202 {
203 NTSTATUS Status;
204 PVOID PebBase;
205 ULONG PebSize;
206 PEB Peb;
207 ULONG BytesWritten;
208
209 memset(&Peb, 0, sizeof(Peb));
210 Peb.ImageBaseAddress = ImageBase;
211
212 PebBase = (PVOID)PEB_BASE;
213 PebSize = 0x1000;
214 Status = NtAllocateVirtualMemory(ProcessHandle,
215 &PebBase,
216 0,
217 &PebSize,
218 MEM_COMMIT,
219 PAGE_READWRITE);
220 if (!NT_SUCCESS(Status))
221 {
222 return(Status);
223 }
224
225 ZwWriteVirtualMemory(ProcessHandle,
226 (PVOID)PEB_BASE,
227 &Peb,
228 sizeof(Peb),
229 &BytesWritten);
230
231 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase);
232
233 *RPeb = PebBase;
234
235 return(STATUS_SUCCESS);
236 }
237
238
239 PKPROCESS KeGetCurrentProcess(VOID)
240 /*
241 * FUNCTION: Returns a pointer to the current process
242 */
243 {
244 return(&(PsGetCurrentProcess()->Pcb));
245 }
246
247 HANDLE PsGetCurrentProcessId(VOID)
248 {
249 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
250 }
251
252 struct _EPROCESS* PsGetCurrentProcess(VOID)
253 /*
254 * FUNCTION: Returns a pointer to the current process
255 */
256 {
257 if (PsGetCurrentThread() == NULL ||
258 PsGetCurrentThread()->ThreadsProcess == NULL)
259 {
260 return(SystemProcess);
261 }
262 else
263 {
264 return(PsGetCurrentThread()->ThreadsProcess);
265 }
266 }
267
268 NTSTATUS STDCALL NtCreateProcess (OUT PHANDLE ProcessHandle,
269 IN ACCESS_MASK DesiredAccess,
270 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
271 IN HANDLE ParentProcessHandle,
272 IN BOOLEAN InheritObjectTable,
273 IN HANDLE SectionHandle OPTIONAL,
274 IN HANDLE DebugPort OPTIONAL,
275 IN HANDLE ExceptionPort OPTIONAL)
276 /*
277 * FUNCTION: Creates a process.
278 * ARGUMENTS:
279 * ProcessHandle (OUT) = Caller supplied storage for the resulting
280 * handle
281 * DesiredAccess = Specifies the allowed or desired access to the
282 * process can be a combination of
283 * STANDARD_RIGHTS_REQUIRED| ..
284 * ObjectAttribute = Initialized attributes for the object, contains
285 * the rootdirectory and the filename
286 * ParentProcess = Handle to the parent process.
287 * InheritObjectTable = Specifies to inherit the objects of the parent
288 * process if true.
289 * SectionHandle = Handle to a section object to back the image file
290 * DebugPort = Handle to a DebugPort if NULL the system default debug
291 * port will be used.
292 * ExceptionPort = Handle to a exception port.
293 * REMARKS:
294 * This function maps to the win32 CreateProcess.
295 * RETURNS: Status
296 */
297 {
298 PEPROCESS Process;
299 PEPROCESS ParentProcess;
300 PKPROCESS KProcess;
301 NTSTATUS Status;
302 KIRQL oldIrql;
303 PVOID LdrStartupAddr;
304 PVOID ImageBase;
305 PVOID Peb;
306
307 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
308
309 Status = ObReferenceObjectByHandle(ParentProcessHandle,
310 PROCESS_CREATE_PROCESS,
311 PsProcessType,
312 UserMode,
313 (PVOID*)&ParentProcess,
314 NULL);
315
316 if (Status != STATUS_SUCCESS)
317 {
318 DPRINT("NtCreateProcess() = %x\n",Status);
319 return(Status);
320 }
321
322 Process = ObCreateObject(ProcessHandle,
323 DesiredAccess,
324 ObjectAttributes,
325 PsProcessType);
326 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
327 InternalProcessType,
328 sizeof(EPROCESS),
329 FALSE);
330 KProcess = &Process->Pcb;
331
332 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
333 InitializeListHead(&(KProcess->MemoryAreaList));
334 Process->UniqueProcessId = InterlockedIncrement(&PiNextProcessUniqueId);
335 Process->InheritedFromUniqueProcessId = ParentProcess->UniqueProcessId;
336 ObCreateHandleTable(ParentProcess,
337 InheritObjectTable,
338 Process);
339 MmCopyMmInfo(ParentProcess, Process);
340
341 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
342 InsertHeadList(&PsProcessListHead, &KProcess->ProcessListEntry);
343 InitializeListHead( &KProcess->ThreadListHead );
344 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
345
346 Process->Pcb.ProcessState = PROCESS_STATE_ACTIVE;
347
348 /*
349 * Now we have created the process proper
350 */
351
352 /*
353 * Map ntdll
354 */
355 Status = LdrpMapSystemDll(*ProcessHandle,
356 &LdrStartupAddr);
357 if (!NT_SUCCESS(Status))
358 {
359 DbgPrint("LdrpMapSystemDll failed (Status %x)\n", Status);
360 ObDereferenceObject(Process);
361 ObDereferenceObject(ParentProcess);
362 return(Status);
363 }
364
365 /*
366 * Map the process image
367 */
368 if (SectionHandle != NULL)
369 {
370 DPRINT("Mapping process image\n");
371 Status = LdrpMapImage(*ProcessHandle,
372 SectionHandle,
373 &ImageBase);
374 if (!NT_SUCCESS(Status))
375 {
376 DbgPrint("LdrpMapImage failed (Status %x)\n", Status);
377 ObDereferenceObject(Process);
378 ObDereferenceObject(ParentProcess);
379 return(Status);
380 }
381 }
382 else
383 {
384 ImageBase = NULL;
385 }
386
387 /*
388 *
389 */
390 DPRINT("Creating PEB\n");
391 Status = PsCreatePeb(*ProcessHandle,
392 ImageBase,
393 &Peb);
394 if (!NT_SUCCESS(Status))
395 {
396 DbgPrint("NtCreateProcess() Peb creation failed: Status %x\n",Status);
397 return(Status);
398 }
399 Process->Peb = Peb;
400
401 ObDereferenceObject(Process);
402 ObDereferenceObject(ParentProcess);
403 return(STATUS_SUCCESS);
404 }
405
406
407 NTSTATUS STDCALL NtOpenProcess (OUT PHANDLE ProcessHandle,
408 IN ACCESS_MASK DesiredAccess,
409 IN POBJECT_ATTRIBUTES ObjectAttributes,
410 IN PCLIENT_ID ClientId)
411 {
412 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
413 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
414 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
415 ClientId->UniqueProcess, ClientId->UniqueThread);
416
417
418 /*
419 * Not sure of the exact semantics
420 */
421 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
422 ObjectAttributes->ObjectName->Buffer != NULL)
423 {
424 NTSTATUS Status;
425 PEPROCESS Process;
426
427 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
428 ObjectAttributes->Attributes,
429 NULL,
430 DesiredAccess,
431 PsProcessType,
432 UserMode,
433 NULL,
434 (PVOID*)&Process);
435 if (Status != STATUS_SUCCESS)
436 {
437 return(Status);
438 }
439
440 Status = ObCreateHandle(PsGetCurrentProcess(),
441 Process,
442 DesiredAccess,
443 FALSE,
444 ProcessHandle);
445 ObDereferenceObject(Process);
446
447 return(Status);
448 }
449 else
450 {
451 KIRQL oldIrql;
452 PLIST_ENTRY current_entry;
453 PEPROCESS current;
454 NTSTATUS Status;
455
456 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
457 current_entry = PsProcessListHead.Flink;
458 while (current_entry != &PsProcessListHead)
459 {
460 current = CONTAINING_RECORD(current_entry, EPROCESS,
461 Pcb.ProcessListEntry);
462 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
463 {
464 ObReferenceObjectByPointer(current,
465 DesiredAccess,
466 PsProcessType,
467 UserMode);
468 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
469 Status = ObCreateHandle(PsGetCurrentProcess(),
470 current,
471 DesiredAccess,
472 FALSE,
473 ProcessHandle);
474 ObDereferenceObject(current);
475 DPRINT("*ProcessHandle %x\n", ProcessHandle);
476 DPRINT("NtOpenProcess() = %x\n", Status);
477 return(Status);
478 }
479 current_entry = current_entry->Flink;
480 }
481 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
482 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
483 return(STATUS_UNSUCCESSFUL);
484 }
485 return(STATUS_UNSUCCESSFUL);
486 }
487
488
489 NTSTATUS STDCALL NtQueryInformationProcess (IN HANDLE ProcessHandle,
490 IN CINT ProcessInformationClass,
491 OUT PVOID ProcessInformation,
492 IN ULONG ProcessInformationLength,
493 OUT PULONG ReturnLength)
494 {
495 PEPROCESS Process;
496 NTSTATUS Status;
497 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
498
499 Status = ObReferenceObjectByHandle(ProcessHandle,
500 PROCESS_SET_INFORMATION,
501 PsProcessType,
502 UserMode,
503 (PVOID*)&Process,
504 NULL);
505 if (Status != STATUS_SUCCESS)
506 {
507 return(Status);
508 }
509
510 switch (ProcessInformationClass)
511 {
512 case ProcessBasicInformation:
513 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
514 ProcessInformation;
515 ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
516 ProcessBasicInformationP->PebBaseAddress = Process->Peb;
517 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
518 ProcessBasicInformationP->UniqueProcessId =
519 Process->UniqueProcessId;
520 ProcessBasicInformationP->InheritedFromUniqueProcessId =
521 Process->InheritedFromUniqueProcessId;
522 Status = STATUS_SUCCESS;
523 break;
524
525 case ProcessQuotaLimits:
526 case ProcessIoCounters:
527 case ProcessVmCounters:
528 case ProcessTimes:
529 case ProcessBasePriority:
530 case ProcessRaisePriority:
531 case ProcessDebugPort:
532 case ProcessExceptionPort:
533 case ProcessAccessToken:
534 case ProcessLdtInformation:
535 case ProcessLdtSize:
536 Status = STATUS_NOT_IMPLEMENTED;
537 break;
538
539 case ProcessDefaultHardErrorMode:
540 *((PULONG)ProcessInformation) = Process->DefaultHardErrorProcessing;
541 break;
542
543 case ProcessIoPortHandlers:
544 case ProcessWorkingSetWatch:
545 case ProcessUserModeIOPL:
546 case ProcessEnableAlignmentFaultFixup:
547 case ProcessPriorityClass:
548 case ProcessWx86Information:
549 case ProcessHandleCount:
550 case ProcessAffinityMask:
551 default:
552 Status = STATUS_NOT_IMPLEMENTED;
553 }
554 ObDereferenceObject(Process);
555 return(Status);
556 }
557
558 NTSTATUS PspAssignPrimaryToken(PEPROCESS Process,
559 HANDLE TokenHandle)
560 {
561 PACCESS_TOKEN Token;
562 PACCESS_TOKEN OldToken;
563 NTSTATUS Status;
564
565 Status = ObReferenceObjectByHandle(TokenHandle,
566 0,
567 SeTokenType,
568 UserMode,
569 (PVOID*)&Token,
570 NULL);
571 if (!NT_SUCCESS(Status))
572 {
573 return(Status);
574 }
575 Status = SeExchangePrimaryToken(Process, Token, &OldToken);
576 if (!NT_SUCCESS(Status))
577 {
578 ObDereferenceObject(OldToken);
579 }
580 ObDereferenceObject(Token);
581 return(Status);
582 }
583
584 NTSTATUS STDCALL NtSetInformationProcess(IN HANDLE ProcessHandle,
585 IN CINT ProcessInformationClass,
586 IN PVOID ProcessInformation,
587 IN ULONG ProcessInformationLength)
588 {
589 PEPROCESS Process;
590 NTSTATUS Status;
591 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
592 PHANDLE ProcessAccessTokenP;
593
594 Status = ObReferenceObjectByHandle(ProcessHandle,
595 PROCESS_SET_INFORMATION,
596 PsProcessType,
597 UserMode,
598 (PVOID*)&Process,
599 NULL);
600 if (!NT_SUCCESS(Status))
601 {
602 return(Status);
603 }
604
605 switch (ProcessInformationClass)
606 {
607 case ProcessBasicInformation:
608 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
609 ProcessInformation;
610 memset(ProcessBasicInformationP, 0, sizeof(PROCESS_BASIC_INFORMATION));
611 Process->Pcb.Affinity = ProcessBasicInformationP->AffinityMask;
612 Status = STATUS_SUCCESS;
613 break;
614
615 case ProcessQuotaLimits:
616 case ProcessIoCounters:
617 case ProcessVmCounters:
618 case ProcessTimes:
619 case ProcessBasePriority:
620 case ProcessRaisePriority:
621 case ProcessDebugPort:
622 case ProcessExceptionPort:
623 case ProcessAccessToken:
624 ProcessAccessTokenP = (PHANDLE)ProcessInformation;
625 Status = PspAssignPrimaryToken(Process, *ProcessAccessTokenP);
626 break;
627
628 case ProcessImageFileName:
629 memcpy(Process->ImageFileName, ProcessInformation, 8);
630 // DPRINT1("Process->ImageFileName %.8s\n", Process->ImageFileName);
631 Status = STATUS_SUCCESS;
632 break;
633
634 case ProcessLdtInformation:
635 case ProcessLdtSize:
636 case ProcessDefaultHardErrorMode:
637 case ProcessIoPortHandlers:
638 case ProcessWorkingSetWatch:
639 case ProcessUserModeIOPL:
640 case ProcessEnableAlignmentFaultFixup:
641 case ProcessPriorityClass:
642 case ProcessWx86Information:
643 case ProcessHandleCount:
644 case ProcessAffinityMask:
645 default:
646 Status = STATUS_NOT_IMPLEMENTED;
647 }
648 ObDereferenceObject(Process);
649 return(Status);
650 }
651