Bring back ext2 code from branch
[reactos.git] / reactos / subsystems / win32 / csrss / api / wapi.c
1 /* $Id$
2 *
3 * reactos/subsys/csrss/api/wapi.c
4 *
5 * CSRSS port message processing
6 *
7 * ReactOS Operating System
8 *
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <csrss.h>
14
15 #define NDEBUG
16
17 #define NDEBUG
18 #include <debug.h>
19
20 /* GLOBALS *******************************************************************/
21
22 extern HANDLE hApiPort;
23
24 HANDLE CsrssApiHeap = (HANDLE) 0;
25
26 static unsigned ApiDefinitionsCount = 0;
27 static PCSRSS_API_DEFINITION ApiDefinitions = NULL;
28
29 /* FUNCTIONS *****************************************************************/
30
31 NTSTATUS FASTCALL
32 CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions)
33 {
34 unsigned NewCount;
35 PCSRSS_API_DEFINITION Scan;
36 PCSRSS_API_DEFINITION New;
37
38 DPRINT("CSR: %s called\n", __FUNCTION__);
39
40 NewCount = 0;
41 for (Scan = NewDefinitions; 0 != Scan->Handler; Scan++)
42 {
43 NewCount++;
44 }
45
46 New = RtlAllocateHeap(CsrssApiHeap, 0,
47 (ApiDefinitionsCount + NewCount)
48 * sizeof(CSRSS_API_DEFINITION));
49 if (NULL == New)
50 {
51 DPRINT1("Unable to allocate memory\n");
52 return STATUS_NO_MEMORY;
53 }
54 if (0 != ApiDefinitionsCount)
55 {
56 RtlCopyMemory(New, ApiDefinitions,
57 ApiDefinitionsCount * sizeof(CSRSS_API_DEFINITION));
58 RtlFreeHeap(CsrssApiHeap, 0, ApiDefinitions);
59 }
60 RtlCopyMemory(New + ApiDefinitionsCount, NewDefinitions,
61 NewCount * sizeof(CSRSS_API_DEFINITION));
62 ApiDefinitions = New;
63 ApiDefinitionsCount += NewCount;
64
65 return STATUS_SUCCESS;
66 }
67
68 VOID
69 FASTCALL
70 CsrApiCallHandler(PCSRSS_PROCESS_DATA ProcessData,
71 PCSR_API_MESSAGE Request)
72 {
73 BOOL Found = FALSE;
74 unsigned DefIndex;
75 ULONG Type;
76
77 DPRINT("CSR: Calling handler for type: %x.\n", Request->Type);
78 Type = Request->Type & 0xFFFF; /* FIXME: USE MACRO */
79 DPRINT("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >> 16);
80
81 /* FIXME: Extract DefIndex instead of looping */
82 for (DefIndex = 0; ! Found && DefIndex < ApiDefinitionsCount; DefIndex++)
83 {
84 if (ApiDefinitions[DefIndex].Type == Type)
85 {
86 if (Request->Header.u1.s1.DataLength < ApiDefinitions[DefIndex].MinRequestSize)
87 {
88 DPRINT1("Request type %d min request size %d actual %d\n",
89 Type, ApiDefinitions[DefIndex].MinRequestSize,
90 Request->Header.u1.s1.DataLength);
91 Request->Status = STATUS_INVALID_PARAMETER;
92 }
93 else
94 {
95 (ApiDefinitions[DefIndex].Handler)(ProcessData, Request);
96 Found = TRUE;
97 }
98 }
99 }
100 if (! Found)
101 {
102 DPRINT1("CSR: Unknown request type 0x%x\n", Request->Type);
103 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
104 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
105 Request->Status = STATUS_INVALID_SYSTEM_SERVICE;
106 }
107 }
108
109 BOOL
110 CallHardError(IN PCSRSS_PROCESS_DATA ProcessData,
111 IN PHARDERROR_MSG HardErrorMessage);
112
113 static
114 VOID
115 NTAPI
116 CsrHandleHardError(IN PCSRSS_PROCESS_DATA ProcessData,
117 IN OUT PHARDERROR_MSG Message)
118 {
119 DPRINT1("CSR: received hard error %lx\n", Message->Status);
120
121 /* Call the hard error handler in win32csr */
122 (VOID)CallHardError(ProcessData, Message);
123 }
124
125 NTSTATUS STDCALL
126 CsrpHandleConnectionRequest (PPORT_MESSAGE Request,
127 IN HANDLE hApiListenPort)
128 {
129 NTSTATUS Status;
130 HANDLE ServerPort = (HANDLE) 0;
131 PCSRSS_PROCESS_DATA ProcessData = NULL;
132 REMOTE_PORT_VIEW LpcRead;
133 LpcRead.Length = sizeof(LpcRead);
134 ServerPort = NULL;
135
136 DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__, Request);
137
138 Status = NtAcceptConnectPort(&ServerPort,
139 NULL,
140 Request,
141 TRUE,
142 0,
143 & LpcRead);
144 if (!NT_SUCCESS(Status))
145 {
146 DPRINT1("CSR: NtAcceptConnectPort() failed\n");
147 return Status;
148 }
149
150 ProcessData = CsrGetProcessData(Request->ClientId.UniqueProcess);
151 if (ProcessData == NULL)
152 {
153 ProcessData = CsrCreateProcessData(Request->ClientId.UniqueProcess);
154 if (ProcessData == NULL)
155 {
156 DPRINT1("Unable to allocate or find data for process 0x%x\n",
157 Request->ClientId.UniqueProcess);
158 Status = STATUS_UNSUCCESSFUL;
159 return Status;
160 }
161 }
162
163 ProcessData->CsrSectionViewBase = LpcRead.ViewBase;
164 ProcessData->CsrSectionViewSize = LpcRead.ViewSize;
165 ProcessData->ServerCommunicationPort = ServerPort;
166
167 Status = NtCompleteConnectPort(ServerPort);
168 if (!NT_SUCCESS(Status))
169 {
170 DPRINT1("CSR: NtCompleteConnectPort() failed\n");
171 return Status;
172 }
173
174 HANDLE ServerThread = (HANDLE) 0;
175 Status = RtlCreateUserThread(NtCurrentProcess(),
176 NULL,
177 FALSE,
178 0,
179 0,
180 0,
181 (PTHREAD_START_ROUTINE)ClientConnectionThread,
182 ServerPort,
183 & ServerThread,
184 NULL);
185 if (!NT_SUCCESS(Status))
186 {
187 DPRINT1("CSR: Unable to create server thread\n");
188 return Status;
189 }
190
191 NtClose(ServerThread);
192
193 Status = STATUS_SUCCESS;
194 DPRINT("CSR: %s done\n", __FUNCTION__);
195 return Status;
196 }
197
198 VOID
199 STDCALL
200 ClientConnectionThread(HANDLE ServerPort)
201 {
202 NTSTATUS Status;
203 BYTE RawRequest[LPC_MAX_DATA_LENGTH];
204 PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
205 PCSR_API_MESSAGE Reply;
206 PCSRSS_PROCESS_DATA ProcessData;
207
208 DPRINT("CSR: %s called\n", __FUNCTION__);
209
210 /* Reply must be NULL at the first call to NtReplyWaitReceivePort */
211 Reply = NULL;
212
213 /* Loop and reply/wait for a new message */
214 for (;;)
215 {
216 /* Send the reply and wait for a new request */
217 Status = NtReplyWaitReceivePort(hApiPort,
218 0,
219 &Reply->Header,
220 &Request->Header);
221 /* Client died, continue */
222 if (Status == STATUS_INVALID_CID)
223 {
224 Reply = NULL;
225 continue;
226 }
227
228 if (!NT_SUCCESS(Status))
229 {
230 DPRINT1("NtReplyWaitReceivePort failed: %lx\n", Status);
231 break;
232 }
233
234 /* If the connection was closed, handle that */
235 if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED)
236 {
237 DPRINT("Port died, oh well\n");
238 CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
239 break;
240 }
241
242 if (Request->Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
243 {
244 CsrpHandleConnectionRequest((PPORT_MESSAGE)Request, ServerPort);
245 Reply = NULL;
246 continue;
247 }
248
249 if (Request->Header.u2.s2.Type == LPC_CLIENT_DIED)
250 {
251 DPRINT("Client died, oh well\n");
252 Reply = NULL;
253 continue;
254 }
255
256 if ((Request->Header.u2.s2.Type != LPC_ERROR_EVENT) &&
257 (Request->Header.u2.s2.Type != LPC_REQUEST))
258 {
259 DPRINT1("CSR: received message %d\n", Request->Header.u2.s2.Type);
260 Reply = NULL;
261 continue;
262 }
263
264 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
265 Request->Type,
266 Request->Header.ClientId.UniqueThread);
267
268 /* Get the Process Data */
269 ProcessData = CsrGetProcessData(Request->Header.ClientId.UniqueProcess);
270 if (ProcessData == NULL)
271 {
272 DPRINT1("Message %d: Unable to find data for process 0x%x\n",
273 Request->Header.u2.s2.Type,
274 Request->Header.ClientId.UniqueProcess);
275 break;
276 }
277 if (ProcessData->Terminated)
278 {
279 DPRINT1("Message %d: process %d already terminated\n",
280 Request->Type, (ULONG)Request->Header.ClientId.UniqueProcess);
281 continue;
282 }
283
284 /* Check if we got a hard error */
285 if (Request->Header.u2.s2.Type == LPC_ERROR_EVENT)
286 {
287 /* Call the Handler */
288 CsrHandleHardError(ProcessData, (PHARDERROR_MSG)Request);
289 }
290 else
291 {
292 /* Call the Handler */
293 CsrApiCallHandler(ProcessData, Request);
294 }
295
296 /* Send back the reply */
297 Reply = Request;
298 }
299
300 /* Close the port and exit the thread */
301 // NtClose(ServerPort);
302
303 DPRINT("CSR: %s done\n", __FUNCTION__);
304 RtlExitUserThread(STATUS_SUCCESS);
305 }
306
307 /**********************************************************************
308 * NAME
309 * ServerApiPortThread/1
310 *
311 * DESCRIPTION
312 * Handle connection requests from clients to the port
313 * "\Windows\ApiPort".
314 */
315 #if 0
316 DWORD STDCALL
317 ServerApiPortThread (HANDLE hApiListenPort)
318 {
319 NTSTATUS Status = STATUS_SUCCESS;
320 BYTE RawRequest[sizeof(PORT_MESSAGE) + sizeof(CSR_CONNECTION_INFO)];
321 PPORT_MESSAGE Request = (PPORT_MESSAGE)RawRequest;
322
323 DPRINT("CSR: %s called", __FUNCTION__);
324
325 for (;;)
326 {
327 REMOTE_PORT_VIEW LpcRead;
328 LpcRead.Length = sizeof(LpcRead);
329
330 Status = NtListenPort (hApiListenPort, Request);
331 if (!NT_SUCCESS(Status))
332 {
333 DPRINT1("CSR: NtListenPort() failed, status=%x\n", Status);
334 break;
335 }
336
337 Status = CsrpHandleConnectionRequest(Request, hApiListenPort);
338 if(!NT_SUCCESS(Status))
339 {
340 DPRINT1("CSR: %s: SmpHandleConnectionRequest failed (Status=0x%08lx)\n",
341 __FUNCTION__, Status);
342 break;
343 }
344 }
345
346 NtClose(hApiListenPort);
347 NtTerminateThread(NtCurrentThread(), Status);
348 return 0;
349 }
350 #endif
351
352 /**********************************************************************
353 * NAME
354 * ServerSbApiPortThread/1
355 *
356 * DESCRIPTION
357 * Handle connection requests from SM to the port
358 * "\Windows\SbApiPort". We will accept only one
359 * connection request (from the SM).
360 */
361 DWORD STDCALL
362 ServerSbApiPortThread (HANDLE hSbApiPortListen)
363 {
364 HANDLE hConnectedPort = (HANDLE) 0;
365 PORT_MESSAGE Request;
366 PVOID Context = NULL;
367 NTSTATUS Status = STATUS_SUCCESS;
368 PPORT_MESSAGE Reply = NULL;
369
370 DPRINT("CSR: %s called\n", __FUNCTION__);
371
372 RtlZeroMemory(&Request, sizeof(PORT_MESSAGE));
373 Status = NtListenPort (hSbApiPortListen, & Request);
374
375 if (!NT_SUCCESS(Status))
376 {
377 DPRINT1("CSR: %s: NtListenPort(SB) failed (Status=0x%08lx)\n",
378 __FUNCTION__, Status);
379 } else {
380 DPRINT("-- 1\n");
381 Status = NtAcceptConnectPort(&hConnectedPort,
382 NULL,
383 &Request,
384 TRUE,
385 NULL,
386 NULL);
387 if(!NT_SUCCESS(Status))
388 {
389 DPRINT1("CSR: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
390 __FUNCTION__, Status);
391 } else {
392 DPRINT("-- 2\n");
393 Status = NtCompleteConnectPort (hConnectedPort);
394 if(!NT_SUCCESS(Status))
395 {
396 DPRINT1("CSR: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
397 __FUNCTION__, Status);
398 } else {
399 DPRINT("-- 3\n");
400 /*
401 * Tell the init thread the SM gave the
402 * green light for boostrapping.
403 */
404 Status = NtSetEvent (hBootstrapOk, NULL);
405 if(!NT_SUCCESS(Status))
406 {
407 DPRINT1("CSR: %s: NtSetEvent failed (Status=0x%08lx)\n",
408 __FUNCTION__, Status);
409 }
410 /* Wait for messages from the SM */
411 DPRINT("-- 4\n");
412 while (TRUE)
413 {
414 Status = NtReplyWaitReceivePort(hConnectedPort,
415 Context,
416 Reply,
417 &Request);
418 if(!NT_SUCCESS(Status))
419 {
420 DPRINT1("CSR: %s: NtReplyWaitReceivePort failed (Status=0x%08lx)\n",
421 __FUNCTION__, Status);
422 break;
423 }
424
425 switch (Request.u2.s2.Type) //fix .h PORT_MESSAGE_TYPE(Request))
426 {
427 /* TODO */
428 default:
429 DPRINT1("CSR: %s received message (type=%d)\n",
430 __FUNCTION__, Request.u2.s2.Type);
431 }
432 DPRINT("-- 5\n");
433 }
434 }
435 }
436 }
437
438 DPRINT("CSR: %s: terminating!\n", __FUNCTION__);
439 if(hConnectedPort) NtClose (hConnectedPort);
440 NtClose (hSbApiPortListen);
441 NtTerminateThread (NtCurrentThread(), Status);
442 return 0;
443 }
444
445 /* EOF */