Remove all non-official LPC structures/defines/hardcoded hacks, and use actual correc...
[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 NTSTATUS Status;
196
197 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
198 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
199
200 NewProcessData = CsrCreateProcessData(Request->Data.CreateProcessRequest.NewProcessId);
201 if (NewProcessData == NULL)
202 {
203 Request->Status = STATUS_NO_MEMORY;
204 return(STATUS_NO_MEMORY);
205 }
206
207 if (!(Request->Data.CreateProcessRequest.Flags & (CREATE_NEW_CONSOLE|DETACHED_PROCESS)))
208 {
209 NewProcessData->ParentConsole = ProcessData->Console;
210 NewProcessData->bInheritHandles = Request->Data.CreateProcessRequest.bInheritHandles;
211 if (Request->Data.CreateProcessRequest.bInheritHandles)
212 {
213 Status = CsrDuplicateHandleTable(ProcessData, NewProcessData);
214 }
215 }
216
217 /* Set default shutdown parameters */
218 NewProcessData->ShutdownLevel = 0x280;
219 NewProcessData->ShutdownFlags = 0;
220
221 Request->Status = STATUS_SUCCESS;
222 return(STATUS_SUCCESS);
223 }
224
225 CSR_API(CsrTerminateProcess)
226 {
227 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
228 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE);
229
230 if (ProcessData == NULL)
231 {
232 return(Request->Status = STATUS_INVALID_PARAMETER);
233 }
234
235 Request->Status = STATUS_SUCCESS;
236 return STATUS_SUCCESS;
237 }
238
239 CSR_API(CsrConnectProcess)
240 {
241 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
242 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
243
244 Request->Status = STATUS_SUCCESS;
245
246 return(STATUS_SUCCESS);
247 }
248
249 CSR_API(CsrGetShutdownParameters)
250 {
251 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
252 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
253
254 if (ProcessData == NULL)
255 {
256 return(Request->Status = STATUS_INVALID_PARAMETER);
257 }
258
259 Request->Data.GetShutdownParametersRequest.Level = ProcessData->ShutdownLevel;
260 Request->Data.GetShutdownParametersRequest.Flags = ProcessData->ShutdownFlags;
261
262 Request->Status = STATUS_SUCCESS;
263
264 return(STATUS_SUCCESS);
265 }
266
267 CSR_API(CsrSetShutdownParameters)
268 {
269 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
270 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
271
272 if (ProcessData == NULL)
273 {
274 return(Request->Status = STATUS_INVALID_PARAMETER);
275 }
276
277 ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level;
278 ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags;
279
280 Request->Status = STATUS_SUCCESS;
281
282 return(STATUS_SUCCESS);
283 }
284
285 CSR_API(CsrGetInputHandle)
286 {
287 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
288 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
289
290 if (ProcessData == NULL)
291 {
292 Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
293 Request->Status = STATUS_INVALID_PARAMETER;
294 }
295 else if (ProcessData->Console)
296 {
297 Request->Status = CsrInsertObject(ProcessData,
298 &Request->Data.GetInputHandleRequest.InputHandle,
299 (Object_t *)ProcessData->Console);
300 }
301 else
302 {
303 Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
304 Request->Status = STATUS_SUCCESS;
305 }
306
307 return Request->Status;
308 }
309
310 CSR_API(CsrGetOutputHandle)
311 {
312 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
313 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
314
315 if (ProcessData == NULL)
316 {
317 Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
318 Request->Status = STATUS_INVALID_PARAMETER;
319 }
320 else if (ProcessData->Console)
321 {
322 RtlEnterCriticalSection(&ProcessDataLock);
323 Request->Status = CsrInsertObject(ProcessData,
324 &Request->Data.GetOutputHandleRequest.OutputHandle,
325 &(ProcessData->Console->ActiveBuffer->Header));
326 RtlLeaveCriticalSection(&ProcessDataLock);
327 }
328 else
329 {
330 Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
331 Request->Status = STATUS_SUCCESS;
332 }
333
334 return Request->Status;
335 }
336
337 CSR_API(CsrCloseHandle)
338 {
339 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
340 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
341
342 if (ProcessData == NULL)
343 {
344 Request->Status = STATUS_INVALID_PARAMETER;
345 }
346 else
347 {
348 Request->Status = CsrReleaseObject(ProcessData, Request->Data.CloseHandleRequest.Handle);
349 }
350 return Request->Status;
351 }
352
353 CSR_API(CsrVerifyHandle)
354 {
355 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
356 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
357
358 Request->Status = CsrVerifyObject(ProcessData, Request->Data.VerifyHandleRequest.Handle);
359 if (!NT_SUCCESS(Request->Status))
360 {
361 DPRINT("CsrVerifyObject failed, status=%x\n", Request->Status);
362 }
363
364 return Request->Status;
365 }
366
367 CSR_API(CsrDuplicateHandle)
368 {
369 Object_t *Object;
370
371 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
372 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
373
374 ProcessData = CsrGetProcessData(Request->Data.DuplicateHandleRequest.ProcessId);
375 Request->Status = CsrGetObject(ProcessData, Request->Data.DuplicateHandleRequest.Handle, &Object);
376 if (! NT_SUCCESS(Request->Status))
377 {
378 DPRINT("CsrGetObject failed, status=%x\n", Request->Status);
379 }
380 else
381 {
382 Request->Status = CsrInsertObject(ProcessData,
383 &Request->Data.DuplicateHandleRequest.Handle,
384 Object);
385 }
386 return Request->Status;
387 }
388
389 CSR_API(CsrGetInputWaitHandle)
390 {
391 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
392 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
393
394 if (ProcessData == NULL)
395 {
396
397 Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = INVALID_HANDLE_VALUE;
398 Request->Status = STATUS_INVALID_PARAMETER;
399 }
400 else
401 {
402 Request->Data.GetConsoleInputWaitHandle.InputWaitHandle = ProcessData->ConsoleEvent;
403 Request->Status = STATUS_SUCCESS;
404 }
405 return Request->Status;
406 }
407
408 /* EOF */