Fixed problem with handles not being released
[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
23 #define NDEBUG
24 #include <internal/debug.h>
25
26 /* GLOBALS ******************************************************************/
27
28 PEPROCESS SystemProcess = NULL;
29 HANDLE SystemProcessHandle = NULL;
30
31 POBJECT_TYPE PsProcessType = NULL;
32
33 static LIST_ENTRY PsProcessListHead;
34 static KSPIN_LOCK PsProcessListLock;
35 static ULONG PiNextProcessUniqueId = 0;
36
37 /* FUNCTIONS *****************************************************************/
38
39 VOID PiKillMostProcesses(VOID)
40 {
41 KIRQL oldIrql;
42 PLIST_ENTRY current_entry;
43 PEPROCESS current;
44
45 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
46
47 current_entry = PsProcessListHead.Flink;
48 while (current_entry != &PsProcessListHead)
49 {
50 current = CONTAINING_RECORD(current_entry, EPROCESS,
51 Pcb.ProcessListEntry);
52 current_entry = current_entry->Flink;
53
54 if (current->UniqueProcessId != SystemProcess->UniqueProcessId &&
55 current->UniqueProcessId != (ULONG)PsGetCurrentProcessId())
56 {
57 PiTerminateProcess(current, STATUS_SUCCESS);
58 }
59 }
60
61 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
62 }
63
64 VOID PsInitProcessManagment(VOID)
65 {
66 ANSI_STRING AnsiString;
67 PKPROCESS KProcess;
68 KIRQL oldIrql;
69
70 /*
71 * Register the process object type
72 */
73
74 PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
75
76 PsProcessType->TotalObjects = 0;
77 PsProcessType->TotalHandles = 0;
78 PsProcessType->MaxObjects = ULONG_MAX;
79 PsProcessType->MaxHandles = ULONG_MAX;
80 PsProcessType->PagedPoolCharge = 0;
81 PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
82 PsProcessType->Dump = NULL;
83 PsProcessType->Open = NULL;
84 PsProcessType->Close = NULL;
85 PsProcessType->Delete = PiDeleteProcess;
86 PsProcessType->Parse = NULL;
87 PsProcessType->Security = NULL;
88 PsProcessType->QueryName = NULL;
89 PsProcessType->OkayToClose = NULL;
90 PsProcessType->Create = NULL;
91
92 RtlInitAnsiString(&AnsiString,"Process");
93 RtlAnsiStringToUnicodeString(&PsProcessType->TypeName,&AnsiString,TRUE);
94
95 InitializeListHead(&PsProcessListHead);
96 KeInitializeSpinLock(&PsProcessListLock);
97
98 /*
99 * Initialize the system process
100 */
101 SystemProcess = ObCreateObject(NULL,
102 PROCESS_ALL_ACCESS,
103 NULL,
104 PsProcessType);
105 SystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
106 KeInitializeDispatcherHeader(&SystemProcess->Pcb.DispatcherHeader,
107 InternalProcessType,
108 sizeof(EPROCESS),
109 FALSE);
110 KProcess = &SystemProcess->Pcb;
111
112 InitializeListHead(&(KProcess->MemoryAreaList));
113 ObCreateHandleTable(NULL,FALSE,SystemProcess);
114 KProcess->PageTableDirectory = get_page_directory();
115 SystemProcess->UniqueProcessId =
116 InterlockedIncrement(&PiNextProcessUniqueId);
117
118 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
119 InsertHeadList(&PsProcessListHead, &KProcess->ProcessListEntry);
120 InitializeListHead( &KProcess->ThreadListHead );
121 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
122
123 ObCreateHandle(SystemProcess,
124 SystemProcess,
125 PROCESS_ALL_ACCESS,
126 FALSE,
127 &SystemProcessHandle);
128 }
129
130 VOID PiDeleteProcess(PVOID ObjectBody)
131 {
132 KIRQL oldIrql;
133
134 DPRINT1("PiDeleteProcess(ObjectBody %x)\n",ObjectBody);
135
136 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
137 RemoveEntryList(&((PEPROCESS)ObjectBody)->Pcb.ProcessListEntry);
138 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
139 (VOID)MmReleaseMmInfo((PEPROCESS)ObjectBody);
140 ObDeleteHandleTable((PEPROCESS)ObjectBody);
141 }
142
143
144 static NTSTATUS PsCreatePeb(HANDLE ProcessHandle)
145 {
146 NTSTATUS Status;
147 PVOID PebBase;
148 ULONG PebSize;
149 PEB Peb;
150 ULONG BytesWritten;
151
152 PebBase = (PVOID)PEB_BASE;
153 PebSize = 0x1000;
154 Status = NtAllocateVirtualMemory(ProcessHandle,
155 &PebBase,
156 0,
157 &PebSize,
158 MEM_COMMIT,
159 PAGE_READWRITE);
160 if (!NT_SUCCESS(Status))
161 {
162 return(Status);
163 }
164
165 memset(&Peb, 0, sizeof(Peb));
166
167 ZwWriteVirtualMemory(ProcessHandle,
168 (PVOID)PEB_BASE,
169 &Peb,
170 sizeof(Peb),
171 &BytesWritten);
172
173 DPRINT("PsCreatePeb: Peb created at %x\n", PebBase);
174
175 return(STATUS_SUCCESS);
176 }
177
178
179 PKPROCESS KeGetCurrentProcess(VOID)
180 /*
181 * FUNCTION: Returns a pointer to the current process
182 */
183 {
184 return(&(PsGetCurrentProcess()->Pcb));
185 }
186
187 HANDLE PsGetCurrentProcessId(VOID)
188 {
189 return((HANDLE)PsGetCurrentProcess()->UniqueProcessId);
190 }
191
192 struct _EPROCESS* PsGetCurrentProcess(VOID)
193 /*
194 * FUNCTION: Returns a pointer to the current process
195 */
196 {
197 if (PsGetCurrentThread() == NULL ||
198 PsGetCurrentThread()->ThreadsProcess == NULL)
199 {
200 return(SystemProcess);
201 }
202 else
203 {
204 return(PsGetCurrentThread()->ThreadsProcess);
205 }
206 }
207
208 NTSTATUS
209 STDCALL
210 NtCreateProcess (
211 OUT PHANDLE ProcessHandle,
212 IN ACCESS_MASK DesiredAccess,
213 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
214 IN HANDLE ParentProcessHandle,
215 IN BOOLEAN InheritObjectTable,
216 IN HANDLE SectionHandle OPTIONAL,
217 IN HANDLE DebugPort OPTIONAL,
218 IN HANDLE ExceptionPort OPTIONAL
219 )
220 /*
221 * FUNCTION: Creates a process.
222 * ARGUMENTS:
223 * ProcessHandle (OUT) = Caller supplied storage for the resulting
224 * handle
225 * DesiredAccess = Specifies the allowed or desired access to the
226 * process can be a combination of
227 * STANDARD_RIGHTS_REQUIRED| ..
228 * ObjectAttribute = Initialized attributes for the object, contains
229 * the rootdirectory and the filename
230 * ParentProcess = Handle to the parent process.
231 * InheritObjectTable = Specifies to inherit the objects of the parent
232 * process if true.
233 * SectionHandle = Handle to a section object to back the image file
234 * DebugPort = Handle to a DebugPort if NULL the system default debug
235 * port will be used.
236 * ExceptionPort = Handle to a exception port.
237 * REMARKS:
238 * This function maps to the win32 CreateProcess.
239 * RETURNS: Status
240 */
241 {
242 PEPROCESS Process;
243 PEPROCESS ParentProcess;
244 PKPROCESS KProcess;
245 NTSTATUS Status;
246 KIRQL oldIrql;
247
248 DPRINT("NtCreateProcess(ObjectAttributes %x)\n",ObjectAttributes);
249
250 Status = ObReferenceObjectByHandle(ParentProcessHandle,
251 PROCESS_CREATE_PROCESS,
252 PsProcessType,
253 UserMode,
254 (PVOID*)&ParentProcess,
255 NULL);
256
257 if (Status != STATUS_SUCCESS)
258 {
259 DPRINT("NtCreateProcess() = %x\n",Status);
260 return(Status);
261 }
262
263 Process = ObCreateObject(ProcessHandle,
264 DesiredAccess,
265 ObjectAttributes,
266 PsProcessType);
267 KeInitializeDispatcherHeader(&Process->Pcb.DispatcherHeader,
268 InternalProcessType,
269 sizeof(EPROCESS),
270 FALSE);
271 KProcess = &(Process->Pcb);
272
273 KProcess->BasePriority = PROCESS_PRIO_NORMAL;
274 InitializeListHead(&(KProcess->MemoryAreaList));
275 Process->UniqueProcessId = InterlockedIncrement(&PiNextProcessUniqueId);
276 Process->InheritedFromUniqueProcessId = ParentProcess->UniqueProcessId;
277 ObCreateHandleTable(ParentProcess,
278 InheritObjectTable,
279 Process);
280 MmCopyMmInfo(ParentProcess, Process);
281
282 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
283 InsertHeadList(&PsProcessListHead, &KProcess->ProcessListEntry);
284 InitializeListHead( &KProcess->ThreadListHead );
285 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
286
287 Status = PsCreatePeb (*ProcessHandle);
288 if (!NT_SUCCESS(Status))
289 {
290 // DPRINT("NtCreateProcess() Peb creation failed: Status %x\n",Status);
291 DbgPrint ("NtCreateProcess() Peb creation failed: Status %x\n",Status);
292 return(Status);
293 }
294
295 /*
296 * FIXME: I don't what I'm supposed to know with a section handle
297 */
298 if (SectionHandle != NULL)
299 {
300 DbgPrint("NtCreateProcess() non-NULL SectionHandle\n");
301 return(STATUS_UNSUCCESSFUL);
302 }
303
304 Process->Pcb.ProcessState = PROCESS_STATE_ACTIVE;
305 ObDereferenceObject(Process);
306 ObDereferenceObject(ParentProcess);
307 return(STATUS_SUCCESS);
308 }
309
310
311 NTSTATUS
312 STDCALL
313 NtOpenProcess (
314 OUT PHANDLE ProcessHandle,
315 IN ACCESS_MASK DesiredAccess,
316 IN POBJECT_ATTRIBUTES ObjectAttributes,
317 IN PCLIENT_ID ClientId
318 )
319 {
320 DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, "
321 "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n",
322 ProcessHandle, DesiredAccess, ObjectAttributes, ClientId,
323 ClientId->UniqueProcess, ClientId->UniqueThread);
324
325
326 /*
327 * Not sure of the exact semantics
328 */
329 if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL &&
330 ObjectAttributes->ObjectName->Buffer != NULL)
331 {
332 NTSTATUS Status;
333 PEPROCESS Process;
334
335 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
336 ObjectAttributes->Attributes,
337 NULL,
338 DesiredAccess,
339 PsProcessType,
340 UserMode,
341 NULL,
342 (PVOID*)&Process);
343 if (Status != STATUS_SUCCESS)
344 {
345 return(Status);
346 }
347
348 Status = ObCreateHandle(PsGetCurrentProcess(),
349 Process,
350 DesiredAccess,
351 FALSE,
352 ProcessHandle);
353 ObDereferenceObject(Process);
354
355 return(Status);
356 }
357 else
358 {
359 KIRQL oldIrql;
360 PLIST_ENTRY current_entry;
361 PEPROCESS current;
362 NTSTATUS Status;
363
364 KeAcquireSpinLock(&PsProcessListLock, &oldIrql);
365 current_entry = PsProcessListHead.Flink;
366 while (current_entry != &PsProcessListHead)
367 {
368 current = CONTAINING_RECORD(current_entry, EPROCESS,
369 Pcb.ProcessListEntry);
370 if (current->UniqueProcessId == (ULONG)ClientId->UniqueProcess)
371 {
372 ObReferenceObjectByPointer(current,
373 DesiredAccess,
374 PsProcessType,
375 UserMode);
376 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
377 Status = ObCreateHandle(PsGetCurrentProcess(),
378 current,
379 DesiredAccess,
380 FALSE,
381 ProcessHandle);
382 ObDereferenceObject(current);
383 DPRINT("*ProcessHandle %x\n", ProcessHandle);
384 DPRINT("NtOpenProcess() = %x\n", Status);
385 return(Status);
386 }
387 current_entry = current_entry->Flink;
388 }
389 KeReleaseSpinLock(&PsProcessListLock, oldIrql);
390 DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n");
391 return(STATUS_UNSUCCESSFUL);
392 }
393 return(STATUS_UNSUCCESSFUL);
394 }
395
396
397 NTSTATUS
398 STDCALL
399 NtQueryInformationProcess (
400 IN HANDLE ProcessHandle,
401 IN CINT ProcessInformationClass,
402 OUT PVOID ProcessInformation,
403 IN ULONG ProcessInformationLength,
404 OUT PULONG ReturnLength
405 )
406 {
407 PEPROCESS Process;
408 NTSTATUS Status;
409 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
410
411 Status = ObReferenceObjectByHandle(ProcessHandle,
412 PROCESS_SET_INFORMATION,
413 PsProcessType,
414 UserMode,
415 (PVOID*)&Process,
416 NULL);
417 if (Status != STATUS_SUCCESS)
418 {
419 return(Status);
420 }
421
422 switch (ProcessInformationClass)
423 {
424 case ProcessBasicInformation:
425 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
426 ProcessInformation;
427 memset(ProcessBasicInformationP, 0, sizeof(PROCESS_BASIC_INFORMATION));
428 ProcessBasicInformationP->AffinityMask = Process->Pcb.Affinity;
429 ProcessBasicInformationP->UniqueProcessId =
430 Process->UniqueProcessId;
431 ProcessBasicInformationP->InheritedFromUniqueProcessId =
432 Process->InheritedFromUniqueProcessId;
433 Status = STATUS_SUCCESS;
434 break;
435
436 case ProcessQuotaLimits:
437 case ProcessIoCounters:
438 case ProcessVmCounters:
439 case ProcessTimes:
440 case ProcessBasePriority:
441 case ProcessRaisePriority:
442 case ProcessDebugPort:
443 case ProcessExceptionPort:
444 case ProcessAccessToken:
445 case ProcessLdtInformation:
446 case ProcessLdtSize:
447 case ProcessDefaultHardErrorMode:
448 case ProcessIoPortHandlers:
449 case ProcessWorkingSetWatch:
450 case ProcessUserModeIOPL:
451 case ProcessEnableAlignmentFaultFixup:
452 case ProcessPriorityClass:
453 case ProcessWx86Information:
454 case ProcessHandleCount:
455 case ProcessAffinityMask:
456 default:
457 Status = STATUS_NOT_IMPLEMENTED;
458 }
459 ObDereferenceObject(Process);
460 return(Status);
461 }
462
463
464 NTSTATUS
465 STDCALL
466 NtSetInformationProcess (
467 IN HANDLE ProcessHandle,
468 IN CINT ProcessInformationClass,
469 IN PVOID ProcessInformation,
470 IN ULONG ProcessInformationLength
471 )
472 {
473 PEPROCESS Process;
474 NTSTATUS Status;
475 PPROCESS_BASIC_INFORMATION ProcessBasicInformationP;
476
477 Status = ObReferenceObjectByHandle(ProcessHandle,
478 PROCESS_SET_INFORMATION,
479 PsProcessType,
480 UserMode,
481 (PVOID*)&Process,
482 NULL);
483 if (Status != STATUS_SUCCESS)
484 {
485 return(Status);
486 }
487
488 switch (ProcessInformationClass)
489 {
490 case ProcessBasicInformation:
491 ProcessBasicInformationP = (PPROCESS_BASIC_INFORMATION)
492 ProcessInformation;
493 memset(ProcessBasicInformationP, 0, sizeof(PROCESS_BASIC_INFORMATION));
494 Process->Pcb.Affinity = ProcessBasicInformationP->AffinityMask;
495 Status = STATUS_SUCCESS;
496 break;
497
498 case ProcessQuotaLimits:
499 case ProcessIoCounters:
500 case ProcessVmCounters:
501 case ProcessTimes:
502 case ProcessBasePriority:
503 case ProcessRaisePriority:
504 case ProcessDebugPort:
505 case ProcessExceptionPort:
506 case ProcessAccessToken:
507 case ProcessLdtInformation:
508 case ProcessLdtSize:
509 case ProcessDefaultHardErrorMode:
510 case ProcessIoPortHandlers:
511 case ProcessWorkingSetWatch:
512 case ProcessUserModeIOPL:
513 case ProcessEnableAlignmentFaultFixup:
514 case ProcessPriorityClass:
515 case ProcessWx86Information:
516 case ProcessHandleCount:
517 case ProcessAffinityMask:
518 default:
519 Status = STATUS_NOT_IMPLEMENTED;
520 }
521 ObDereferenceObject(Process);
522 return(Status);
523 }
524