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