Files forgotten in r19815
[reactos.git] / reactos / subsys / csrss / api / process.c
1 /*
2 * reactos/subsys/csrss/api/process.c
3 *
4 * "\windows\ApiPort" port process management functions
5 *
6 * ReactOS Operating System
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <csrss.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 #define LOCK RtlEnterCriticalSection(&ProcessDataLock)
17 #define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
18
19 /* GLOBALS *******************************************************************/
20
21 static ULONG NrProcess;
22 static PCSRSS_PROCESS_DATA ProcessData[256];
23 RTL_CRITICAL_SECTION ProcessDataLock;
24
25 /* FUNCTIONS *****************************************************************/
26
27 VOID STDCALL CsrInitProcessData(VOID)
28 {
29 RtlZeroMemory (ProcessData, sizeof ProcessData);
30 NrProcess = sizeof ProcessData / sizeof ProcessData[0];
31 RtlInitializeCriticalSection( &ProcessDataLock );
32 }
33
34 PCSRSS_PROCESS_DATA STDCALL CsrGetProcessData(HANDLE ProcessId)
35 {
36 ULONG hash;
37 PCSRSS_PROCESS_DATA pProcessData;
38
39 hash = ((ULONG_PTR)ProcessId >> 2) % (sizeof(ProcessData) / sizeof(*ProcessData));
40
41 LOCK;
42
43 pProcessData = ProcessData[hash];
44
45 while (pProcessData && pProcessData->ProcessId != ProcessId)
46 {
47 pProcessData = pProcessData->next;
48 }
49 UNLOCK;
50 return pProcessData;
51 }
52
53 PCSRSS_PROCESS_DATA STDCALL CsrCreateProcessData(HANDLE ProcessId)
54 {
55 ULONG hash;
56 PCSRSS_PROCESS_DATA pProcessData;
57 OBJECT_ATTRIBUTES ObjectAttributes;
58 CLIENT_ID ClientId;
59 NTSTATUS Status;
60
61 hash = ((ULONG_PTR)ProcessId >> 2) % (sizeof(ProcessData) / sizeof(*ProcessData));
62
63 LOCK;
64
65 pProcessData = ProcessData[hash];
66
67 while (pProcessData && pProcessData->ProcessId != ProcessId)
68 {
69 pProcessData = pProcessData->next;
70 }
71 if (pProcessData == NULL)
72 {
73 pProcessData = RtlAllocateHeap(CsrssApiHeap,
74 HEAP_ZERO_MEMORY,
75 sizeof(CSRSS_PROCESS_DATA));
76 if (pProcessData)
77 {
78 pProcessData->ProcessId = ProcessId;
79 pProcessData->next = ProcessData[hash];
80 ProcessData[hash] = pProcessData;
81
82 ClientId.UniqueThread = NULL;
83 ClientId.UniqueProcess = pProcessData->ProcessId;
84 InitializeObjectAttributes(&ObjectAttributes,
85 NULL,
86 0,
87 NULL,
88 NULL);
89
90 /* using OpenProcess is not optimal due to HANDLE vs. DWORD PIDs... */
91 Status = NtOpenProcess(&pProcessData->Process,
92 PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION |
93 PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | SYNCHRONIZE,
94 &ObjectAttributes,
95 &ClientId);
96 if (!NT_SUCCESS(Status))
97 {
98 ProcessData[hash] = pProcessData->next;
99 RtlFreeHeap(CsrssApiHeap, 0, pProcessData);
100 pProcessData = NULL;
101 }
102 else
103 {
104 RtlInitializeCriticalSection(&pProcessData->HandleTableLock);
105 }
106 }
107 }
108 else
109 {
110 DPRINT("Process data for pid %d already exist\n", ProcessId);
111 }
112 UNLOCK;
113 if (pProcessData == NULL)
114 {
115 DPRINT1("CsrCreateProcessData() failed\n");
116 }
117 else
118 {
119 pProcessData->Terminated = FALSE;
120
121 /* Set default shutdown parameters */
122 pProcessData->ShutdownLevel = 0x280;
123 pProcessData->ShutdownFlags = 0;
124 }
125 return pProcessData;
126 }
127
128 NTSTATUS STDCALL CsrFreeProcessData(HANDLE Pid)
129 {
130 ULONG hash;
131 UINT c;
132 PCSRSS_PROCESS_DATA pProcessData, pPrevProcessData = NULL;
133
134 hash = ((ULONG_PTR)Pid >> 2) % (sizeof(ProcessData) / sizeof(*ProcessData));
135
136 LOCK;
137
138 pProcessData = ProcessData[hash];
139
140 while (pProcessData && pProcessData->ProcessId != Pid)
141 {
142 pPrevProcessData = pProcessData;
143 pProcessData = pProcessData->next;
144 }
145
146 if (pProcessData)
147 {
148 DPRINT("CsrFreeProcessData pid: %d\n", Pid);
149 if (pProcessData->Process)
150 {
151 NtClose(pProcessData->Process);
152 }
153 if (pProcessData->Console)
154 {
155 RemoveEntryList(&pProcessData->ProcessEntry);
156 }
157 if (pProcessData->HandleTable)
158 {
159 for (c = 0; c < pProcessData->HandleTableSize; c++)
160 {
161 if (pProcessData->HandleTable[c])
162 {
163 CsrReleaseObject(pProcessData, (HANDLE)(((c + 1) << 2)|0x3));
164 }
165 }
166 RtlFreeHeap(CsrssApiHeap, 0, pProcessData->HandleTable);
167 }
168 RtlDeleteCriticalSection(&pProcessData->HandleTableLock);
169 if (pProcessData->Console)
170 {
171 CsrReleaseObjectByPointer((Object_t *) pProcessData->Console);
172 }
173 if (pProcessData->CsrSectionViewBase)
174 {
175 NtUnmapViewOfSection(NtCurrentProcess(), pProcessData->CsrSectionViewBase);
176 }
177 if (pPrevProcessData)
178 {
179 pPrevProcessData->next = pProcessData->next;
180 }
181 else
182 {
183 ProcessData[hash] = pProcessData->next;
184 }
185
186 RtlFreeHeap(CsrssApiHeap, 0, pProcessData);
187 UNLOCK;
188 return STATUS_SUCCESS;
189 }
190
191 UNLOCK;
192 return STATUS_INVALID_PARAMETER;
193 }
194
195 NTSTATUS STDCALL
196 CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc, PVOID Context)
197 {
198 UINT Hash;
199 PCSRSS_PROCESS_DATA pProcessData;
200 NTSTATUS Status = STATUS_SUCCESS;
201
202 LOCK;
203
204 for (Hash = 0; Hash < (sizeof(ProcessData) / sizeof(*ProcessData)); Hash++)
205 {
206 pProcessData = ProcessData[Hash];
207 while (NULL != pProcessData)
208 {
209 Status = EnumProc(pProcessData, Context);
210 if (STATUS_SUCCESS != Status)
211 {
212 UNLOCK;
213 return Status;
214 }
215 pProcessData = pProcessData->next;
216 }
217 }
218
219 UNLOCK;
220
221 return Status;
222 }
223
224 /**********************************************************************
225 * CSRSS API
226 *********************************************************************/
227
228 CSR_API(CsrCreateProcess)
229 {
230 PCSRSS_PROCESS_DATA NewProcessData;
231 NTSTATUS Status;
232
233 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
234 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
235
236 NewProcessData = CsrCreateProcessData(Request->Data.CreateProcessRequest.NewProcessId);
237 if (NewProcessData == NULL)
238 {
239 Request->Status = STATUS_NO_MEMORY;
240 return(STATUS_NO_MEMORY);
241 }
242
243 if (!(Request->Data.CreateProcessRequest.Flags & (CREATE_NEW_CONSOLE|DETACHED_PROCESS)))
244 {
245 NewProcessData->ParentConsole = ProcessData->Console;
246 NewProcessData->bInheritHandles = Request->Data.CreateProcessRequest.bInheritHandles;
247 if (Request->Data.CreateProcessRequest.bInheritHandles)
248 {
249 Status = CsrDuplicateHandleTable(ProcessData, NewProcessData);
250 }
251 }
252
253 /* Set default shutdown parameters */
254 NewProcessData->ShutdownLevel = 0x280;
255 NewProcessData->ShutdownFlags = 0;
256
257 Request->Status = STATUS_SUCCESS;
258 return(STATUS_SUCCESS);
259 }
260
261 CSR_API(CsrTerminateProcess)
262 {
263 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
264 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE);
265
266 if (ProcessData == NULL)
267 {
268 return(Request->Status = STATUS_INVALID_PARAMETER);
269 }
270
271 ProcessData->Terminated = TRUE;
272 Request->Status = STATUS_SUCCESS;
273 return STATUS_SUCCESS;
274 }
275
276 CSR_API(CsrConnectProcess)
277 {
278 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
279 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
280
281 Request->Status = STATUS_SUCCESS;
282
283 return(STATUS_SUCCESS);
284 }
285
286 CSR_API(CsrGetShutdownParameters)
287 {
288 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
289 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
290
291 if (ProcessData == NULL)
292 {
293 return(Request->Status = STATUS_INVALID_PARAMETER);
294 }
295
296 Request->Data.GetShutdownParametersRequest.Level = ProcessData->ShutdownLevel;
297 Request->Data.GetShutdownParametersRequest.Flags = ProcessData->ShutdownFlags;
298
299 Request->Status = STATUS_SUCCESS;
300
301 return(STATUS_SUCCESS);
302 }
303
304 CSR_API(CsrSetShutdownParameters)
305 {
306 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
307 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
308
309 if (ProcessData == NULL)
310 {
311 return(Request->Status = STATUS_INVALID_PARAMETER);
312 }
313
314 ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level;
315 ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags;
316
317 Request->Status = STATUS_SUCCESS;
318
319 return(STATUS_SUCCESS);
320 }
321
322 CSR_API(CsrGetInputHandle)
323 {
324 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
325 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
326
327 if (ProcessData == NULL)
328 {
329 Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
330 Request->Status = STATUS_INVALID_PARAMETER;
331 }
332 else if (ProcessData->Console)
333 {
334 Request->Status = CsrInsertObject(ProcessData,
335 &Request->Data.GetInputHandleRequest.InputHandle,
336 (Object_t *)ProcessData->Console);
337 }
338 else
339 {
340 Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
341 Request->Status = STATUS_SUCCESS;
342 }
343
344 return Request->Status;
345 }
346
347 CSR_API(CsrGetOutputHandle)
348 {
349 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
350 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
351
352 if (ProcessData == NULL)
353 {
354 Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
355 Request->Status = STATUS_INVALID_PARAMETER;
356 }
357 else if (ProcessData->Console)
358 {
359 RtlEnterCriticalSection(&ProcessDataLock);
360 Request->Status = CsrInsertObject(ProcessData,
361 &Request->Data.GetOutputHandleRequest.OutputHandle,
362 &(ProcessData->Console->ActiveBuffer->Header));
363 RtlLeaveCriticalSection(&ProcessDataLock);
364 }
365 else
366 {
367 Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
368 Request->Status = STATUS_SUCCESS;
369 }
370
371 return Request->Status;
372 }
373
374 CSR_API(CsrCloseHandle)
375 {
376 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
377 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
378
379 if (ProcessData == NULL)
380 {
381 Request->Status = STATUS_INVALID_PARAMETER;
382 }
383 else
384 {
385 Request->Status = CsrReleaseObject(ProcessData, Request->Data.CloseHandleRequest.Handle);
386 }
387 return Request->Status;
388 }
389
390 CSR_API(CsrVerifyHandle)
391 {
392 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
393 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
394
395 Request->Status = CsrVerifyObject(ProcessData, Request->Data.VerifyHandleRequest.Handle);
396 if (!NT_SUCCESS(Request->Status))
397 {
398 DPRINT("CsrVerifyObject failed, status=%x\n", Request->Status);
399 }
400
401 return Request->Status;
402 }
403
404 CSR_API(CsrDuplicateHandle)
405 {
406 Object_t *Object;
407
408 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
409 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
410
411 ProcessData = CsrGetProcessData(Request->Data.DuplicateHandleRequest.ProcessId);
412 if (NULL == ProcessData || ProcessData->Terminated)
413 {
414 DPRINT1("Invalid source process %d\n", Request->Data.DuplicateHandleRequest.ProcessId);
415 Request->Status = STATUS_INVALID_PARAMETER;
416 return Request->Status;
417 }
418
419 Request->Status = CsrGetObject(ProcessData, Request->Data.DuplicateHandleRequest.Handle, &Object);
420 if (! NT_SUCCESS(Request->Status))
421 {
422 DPRINT("CsrGetObject failed, status=%x\n", Request->Status);
423 }
424 else
425 {
426 Request->Status = CsrInsertObject(ProcessData,
427 &Request->Data.DuplicateHandleRequest.Handle,
428 Object);
429 }
430 return Request->Status;
431 }
432
433 CSR_API(CsrGetInputWaitHandle)
434 {
435 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
436 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
437
438 if (ProcessData == NULL)
439 {
440
441 Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = INVALID_HANDLE_VALUE;
442 Request->Status = STATUS_INVALID_PARAMETER;
443 }
444 else
445 {
446 Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = ProcessData->ConsoleEvent;
447 Request->Status = STATUS_SUCCESS;
448 }
449 return Request->Status;
450 }
451
452 /* EOF */