7bffb18308c6a95babf141dd3fb5f04853748ba1
[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 & ~0x3) % (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 & ~0x3) % (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 RtlInitializeCriticalSection(&pProcessData->HandleTableLock);
104 }
105 }
106 else
107 {
108 DPRINT("Process data for pid %d already exist\n", ProcessId);
109 }
110 UNLOCK;
111 if (pProcessData == NULL)
112 {
113 DbgPrint("CSR: CsrGetProcessData() failed\n");
114 }
115 return pProcessData;
116 }
117
118 NTSTATUS STDCALL CsrFreeProcessData(HANDLE Pid)
119 {
120 ULONG hash;
121 UINT c;
122 PCSRSS_PROCESS_DATA pProcessData, pPrevProcessData = NULL;
123
124 hash = ((ULONG_PTR)Pid & ~0x3) % (sizeof(ProcessData) / sizeof(*ProcessData));
125
126 LOCK;
127
128 pProcessData = ProcessData[hash];
129
130 while (pProcessData && pProcessData->ProcessId != Pid)
131 {
132 pPrevProcessData = pProcessData;
133 pProcessData = pProcessData->next;
134 }
135
136 if (pProcessData)
137 {
138 DPRINT("CsrFreeProcessData pid: %d\n", Pid);
139 if (pProcessData->Process)
140 {
141 NtClose(pProcessData->Process);
142 }
143 if (pProcessData->Console)
144 {
145 RtlEnterCriticalSection(&ProcessDataLock);
146 RemoveEntryList(&pProcessData->ProcessEntry);
147 RtlLeaveCriticalSection(&ProcessDataLock);
148 }
149 if (pProcessData->HandleTable)
150 {
151 for (c = 0; c < pProcessData->HandleTableSize; c++)
152 {
153 if (pProcessData->HandleTable[c])
154 {
155 CsrReleaseObject(pProcessData, (HANDLE)(((c + 1) << 2)|0x3));
156 }
157 }
158 RtlFreeHeap(CsrssApiHeap, 0, pProcessData->HandleTable);
159 }
160 RtlDeleteCriticalSection(&pProcessData->HandleTableLock);
161 if (pProcessData->Console)
162 {
163 CsrReleaseObjectByPointer((Object_t *) pProcessData->Console);
164 }
165 if (pProcessData->CsrSectionViewBase)
166 {
167 NtUnmapViewOfSection(NtCurrentProcess(), pProcessData->CsrSectionViewBase);
168 }
169 if (pPrevProcessData)
170 {
171 pPrevProcessData->next = pProcessData->next;
172 }
173 else
174 {
175 ProcessData[hash] = pProcessData->next;
176 }
177
178 RtlFreeHeap(CsrssApiHeap, 0, pProcessData);
179 UNLOCK;
180 return STATUS_SUCCESS;
181 }
182
183 UNLOCK;
184 return STATUS_INVALID_PARAMETER;
185 }
186
187
188 /**********************************************************************
189 * CSRSS API
190 *********************************************************************/
191
192 CSR_API(CsrCreateProcess)
193 {
194 PCSRSS_PROCESS_DATA NewProcessData;
195
196 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
197 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
198
199 NewProcessData = CsrCreateProcessData(Request->Data.CreateProcessRequest.NewProcessId);
200 if (NewProcessData == NULL)
201 {
202 Request->Status = STATUS_NO_MEMORY;
203 return(STATUS_NO_MEMORY);
204 }
205
206 /* Set default shutdown parameters */
207 NewProcessData->ShutdownLevel = 0x280;
208 NewProcessData->ShutdownFlags = 0;
209
210 Request->Status = STATUS_SUCCESS;
211 return(STATUS_SUCCESS);
212 }
213
214 CSR_API(CsrTerminateProcess)
215 {
216 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
217 Request->Header.DataSize = sizeof(CSR_API_MESSAGE);
218
219 if (ProcessData == NULL)
220 {
221 return(Request->Status = STATUS_INVALID_PARAMETER);
222 }
223
224 Request->Status = STATUS_SUCCESS;
225 return STATUS_SUCCESS;
226 }
227
228 CSR_API(CsrConnectProcess)
229 {
230 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
231 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
232
233 Request->Status = STATUS_SUCCESS;
234
235 return(STATUS_SUCCESS);
236 }
237
238 CSR_API(CsrGetShutdownParameters)
239 {
240 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
241 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
242
243 if (ProcessData == NULL)
244 {
245 return(Request->Status = STATUS_INVALID_PARAMETER);
246 }
247
248 Request->Data.GetShutdownParametersRequest.Level = ProcessData->ShutdownLevel;
249 Request->Data.GetShutdownParametersRequest.Flags = ProcessData->ShutdownFlags;
250
251 Request->Status = STATUS_SUCCESS;
252
253 return(STATUS_SUCCESS);
254 }
255
256 CSR_API(CsrSetShutdownParameters)
257 {
258 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
259 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
260
261 if (ProcessData == NULL)
262 {
263 return(Request->Status = STATUS_INVALID_PARAMETER);
264 }
265
266 ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level;
267 ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags;
268
269 Request->Status = STATUS_SUCCESS;
270
271 return(STATUS_SUCCESS);
272 }
273
274 CSR_API(CsrGetInputHandle)
275 {
276 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
277 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
278
279 if (ProcessData == NULL)
280 {
281 Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
282 Request->Status = STATUS_INVALID_PARAMETER;
283 }
284 else if (ProcessData->Console)
285 {
286 Request->Status = CsrInsertObject(ProcessData,
287 &Request->Data.GetInputHandleRequest.InputHandle,
288 (Object_t *)ProcessData->Console);
289 }
290 else
291 {
292 Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
293 Request->Status = STATUS_SUCCESS;
294 }
295
296 return Request->Status;
297 }
298
299 CSR_API(CsrGetOutputHandle)
300 {
301 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
302 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
303
304 if (ProcessData == NULL)
305 {
306 Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
307 Request->Status = STATUS_INVALID_PARAMETER;
308 }
309 else if (ProcessData->Console)
310 {
311 RtlEnterCriticalSection(&ProcessDataLock);
312 Request->Status = CsrInsertObject(ProcessData,
313 &Request->Data.GetOutputHandleRequest.OutputHandle,
314 &(ProcessData->Console->ActiveBuffer->Header));
315 RtlLeaveCriticalSection(&ProcessDataLock);
316 }
317 else
318 {
319 Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
320 Request->Status = STATUS_SUCCESS;
321 }
322
323 return Request->Status;
324 }
325
326 CSR_API(CsrCloseHandle)
327 {
328 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
329 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
330
331 if (ProcessData == NULL)
332 {
333 Request->Status = STATUS_INVALID_PARAMETER;
334 }
335 else
336 {
337 Request->Status = CsrReleaseObject(ProcessData, Request->Data.CloseHandleRequest.Handle);
338 }
339 return Request->Status;
340 }
341
342 CSR_API(CsrVerifyHandle)
343 {
344 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
345 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
346
347 Request->Status = CsrVerifyObject(ProcessData, Request->Data.VerifyHandleRequest.Handle);
348 if (!NT_SUCCESS(Request->Status))
349 {
350 DPRINT("CsrVerifyObject failed, status=%x\n", Request->Status);
351 }
352
353 return Request->Status;
354 }
355
356 CSR_API(CsrDuplicateHandle)
357 {
358 Object_t *Object;
359
360 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
361 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
362
363 ProcessData = CsrGetProcessData(Request->Data.DuplicateHandleRequest.ProcessId);
364 Request->Status = CsrGetObject(ProcessData, Request->Data.DuplicateHandleRequest.Handle, &Object);
365 if (! NT_SUCCESS(Request->Status))
366 {
367 DPRINT("CsrGetObject failed, status=%x\n", Request->Status);
368 }
369 else
370 {
371 Request->Status = CsrInsertObject(ProcessData,
372 &Request->Data.DuplicateHandleRequest.Handle,
373 Object);
374 }
375 return Request->Status;
376 }
377
378 CSR_API(CsrGetInputWaitHandle)
379 {
380 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
381 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
382
383 if (ProcessData == NULL)
384 {
385
386 Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = INVALID_HANDLE_VALUE;
387 Request->Status = STATUS_INVALID_PARAMETER;
388 }
389 else
390 {
391 Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = ProcessData->ConsoleEvent;
392 Request->Status = STATUS_SUCCESS;
393 }
394 return Request->Status;
395 }
396
397 /* EOF */