Do not break away from the loop on every error. It can cause situation when
[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 FASTCALL CallHardError(void);
110
111 static
112 VOID
113 NTAPI
114 CsrHandleHardError(IN PCSRSS_PROCESS_DATA ProcessData,
115 IN OUT PHARDERROR_MSG Message)
116 {
117 DPRINT1("CSR: received hard error %lx\n", Message->Status);
118
119 /* Call the hard error handler in win32csr */
120 CallHardError();
121 }
122
123 NTSTATUS STDCALL
124 CsrpHandleConnectionRequest (PPORT_MESSAGE Request,
125 IN HANDLE hApiListenPort)
126 {
127 NTSTATUS Status;
128 HANDLE ServerPort = (HANDLE) 0;
129 PCSRSS_PROCESS_DATA ProcessData = NULL;
130 REMOTE_PORT_VIEW LpcRead;
131 LpcRead.Length = sizeof(LpcRead);
132 ServerPort = NULL;
133
134 DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__, Request);
135
136 Status = NtAcceptConnectPort(&ServerPort,
137 NULL,
138 Request,
139 TRUE,
140 0,
141 & LpcRead);
142 if (!NT_SUCCESS(Status))
143 {
144 DPRINT1("CSR: NtAcceptConnectPort() failed\n");
145 return Status;
146 }
147
148 ProcessData = CsrGetProcessData(Request->ClientId.UniqueProcess);
149 if (ProcessData == NULL)
150 {
151 ProcessData = CsrCreateProcessData(Request->ClientId.UniqueProcess);
152 if (ProcessData == NULL)
153 {
154 DPRINT1("Unable to allocate or find data for process 0x%x\n",
155 Request->ClientId.UniqueProcess);
156 Status = STATUS_UNSUCCESSFUL;
157 return Status;
158 }
159 }
160
161 ProcessData->CsrSectionViewBase = LpcRead.ViewBase;
162 ProcessData->CsrSectionViewSize = LpcRead.ViewSize;
163 ProcessData->ServerCommunicationPort = ServerPort;
164
165 Status = NtCompleteConnectPort(ServerPort);
166 if (!NT_SUCCESS(Status))
167 {
168 DPRINT1("CSR: NtCompleteConnectPort() failed\n");
169 return Status;
170 }
171
172 HANDLE ServerThread = (HANDLE) 0;
173 Status = RtlCreateUserThread(NtCurrentProcess(),
174 NULL,
175 FALSE,
176 0,
177 0,
178 0,
179 (PTHREAD_START_ROUTINE)ClientConnectionThread,
180 ServerPort,
181 & ServerThread,
182 NULL);
183 if (!NT_SUCCESS(Status))
184 {
185 DPRINT1("CSR: Unable to create server thread\n");
186 return Status;
187 }
188
189 NtClose(ServerThread);
190
191 Status = STATUS_SUCCESS;
192 DPRINT("CSR: %s done\n", __FUNCTION__);
193 return Status;
194 }
195
196 VOID
197 STDCALL
198 ClientConnectionThread(HANDLE ServerPort)
199 {
200 NTSTATUS Status;
201 BYTE RawRequest[LPC_MAX_DATA_LENGTH];
202 PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
203 PCSR_API_MESSAGE Reply;
204 PCSRSS_PROCESS_DATA ProcessData;
205
206 DPRINT("CSR: %s called\n", __FUNCTION__);
207
208 /* Reply must be NULL at the first call to NtReplyWaitReceivePort */
209 Reply = NULL;
210
211 /* Loop and reply/wait for a new message */
212 for (;;)
213 {
214 /* Send the reply and wait for a new request */
215 Status = NtReplyWaitReceivePort(hApiPort,
216 0,
217 &Reply->Header,
218 &Request->Header);
219 /* Client died, continue */
220 if (Status == STATUS_INVALID_CID)
221 {
222 Reply = NULL;
223 continue;
224 }
225
226 if (!NT_SUCCESS(Status))
227 {
228 DPRINT1("NtReplyWaitReceivePort failed: %lx\n", Status);
229 break;
230 }
231
232 /* If the connection was closed, handle that */
233 if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED)
234 {
235 DPRINT("Port died, oh well\n");
236 CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
237 break;
238 }
239
240 if (Request->Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
241 {
242 CsrpHandleConnectionRequest((PPORT_MESSAGE)Request, ServerPort);
243 Reply = NULL;
244 continue;
245 }
246
247 if (Request->Header.u2.s2.Type == LPC_CLIENT_DIED)
248 {
249 DPRINT("Client died, oh well\n");
250 Reply = NULL;
251 continue;
252 }
253
254 if ((Request->Header.u2.s2.Type != LPC_ERROR_EVENT) &&
255 (Request->Header.u2.s2.Type != LPC_REQUEST))
256 {
257 DPRINT1("CSR: received message %d\n", Request->Header.u2.s2.Type);
258 Reply = NULL;
259 continue;
260 }
261
262 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
263 Request->Type,
264 Request->Header.ClientId.UniqueThread);
265
266 /* Get the Process Data */
267 ProcessData = CsrGetProcessData(Request->Header.ClientId.UniqueProcess);
268 if (ProcessData == NULL)
269 {
270 DPRINT1("Message %d: Unable to find data for process 0x%x\n",
271 Request->Header.u2.s2.Type,
272 Request->Header.ClientId.UniqueProcess);
273 break;
274 }
275 if (ProcessData->Terminated)
276 {
277 DPRINT1("Message %d: process %d already terminated\n",
278 Request->Type, (ULONG)Request->Header.ClientId.UniqueProcess);
279 continue;
280 }
281
282 /* Check if we got a hard error */
283 if (Request->Header.u2.s2.Type == LPC_ERROR_EVENT)
284 {
285 /* Call the Handler */
286 CsrHandleHardError(ProcessData, (PHARDERROR_MSG)Request);
287 }
288 else
289 {
290 /* Call the Handler */
291 CsrApiCallHandler(ProcessData, Request);
292 }
293
294 /* Send back the reply */
295 Reply = Request;
296 }
297
298 /* Close the port and exit the thread */
299 // NtClose(ServerPort);
300
301 DPRINT("CSR: %s done\n", __FUNCTION__);
302 RtlExitUserThread(STATUS_SUCCESS);
303 }
304
305 /**********************************************************************
306 * NAME
307 * ServerApiPortThread/1
308 *
309 * DESCRIPTION
310 * Handle connection requests from clients to the port
311 * "\Windows\ApiPort".
312 */
313 #if 0
314 DWORD STDCALL
315 ServerApiPortThread (HANDLE hApiListenPort)
316 {
317 NTSTATUS Status = STATUS_SUCCESS;
318 BYTE RawRequest[sizeof(PORT_MESSAGE) + sizeof(CSR_CONNECTION_INFO)];
319 PPORT_MESSAGE Request = (PPORT_MESSAGE)RawRequest;
320
321 DPRINT("CSR: %s called", __FUNCTION__);
322
323 for (;;)
324 {
325 REMOTE_PORT_VIEW LpcRead;
326 LpcRead.Length = sizeof(LpcRead);
327
328 Status = NtListenPort (hApiListenPort, Request);
329 if (!NT_SUCCESS(Status))
330 {
331 DPRINT1("CSR: NtListenPort() failed, status=%x\n", Status);
332 break;
333 }
334
335 Status = CsrpHandleConnectionRequest(Request, hApiListenPort);
336 if(!NT_SUCCESS(Status))
337 {
338 DPRINT1("CSR: %s: SmpHandleConnectionRequest failed (Status=0x%08lx)\n",
339 __FUNCTION__, Status);
340 break;
341 }
342 }
343
344 NtClose(hApiListenPort);
345 NtTerminateThread(NtCurrentThread(), Status);
346 return 0;
347 }
348 #endif
349
350 /**********************************************************************
351 * NAME
352 * ServerSbApiPortThread/1
353 *
354 * DESCRIPTION
355 * Handle connection requests from SM to the port
356 * "\Windows\SbApiPort". We will accept only one
357 * connection request (from the SM).
358 */
359 DWORD STDCALL
360 ServerSbApiPortThread (HANDLE hSbApiPortListen)
361 {
362 HANDLE hConnectedPort = (HANDLE) 0;
363 PORT_MESSAGE Request;
364 PVOID Context = NULL;
365 NTSTATUS Status = STATUS_SUCCESS;
366 PPORT_MESSAGE Reply = NULL;
367
368 DPRINT("CSR: %s called\n", __FUNCTION__);
369
370 RtlZeroMemory(&Request, sizeof(PORT_MESSAGE));
371 Status = NtListenPort (hSbApiPortListen, & Request);
372
373 if (!NT_SUCCESS(Status))
374 {
375 DPRINT1("CSR: %s: NtListenPort(SB) failed (Status=0x%08lx)\n",
376 __FUNCTION__, Status);
377 } else {
378 DPRINT("-- 1\n");
379 Status = NtAcceptConnectPort(&hConnectedPort,
380 NULL,
381 &Request,
382 TRUE,
383 NULL,
384 NULL);
385 if(!NT_SUCCESS(Status))
386 {
387 DPRINT1("CSR: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
388 __FUNCTION__, Status);
389 } else {
390 DPRINT("-- 2\n");
391 Status = NtCompleteConnectPort (hConnectedPort);
392 if(!NT_SUCCESS(Status))
393 {
394 DPRINT1("CSR: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
395 __FUNCTION__, Status);
396 } else {
397 DPRINT("-- 3\n");
398 /*
399 * Tell the init thread the SM gave the
400 * green light for boostrapping.
401 */
402 Status = NtSetEvent (hBootstrapOk, NULL);
403 if(!NT_SUCCESS(Status))
404 {
405 DPRINT1("CSR: %s: NtSetEvent failed (Status=0x%08lx)\n",
406 __FUNCTION__, Status);
407 }
408 /* Wait for messages from the SM */
409 DPRINT("-- 4\n");
410 while (TRUE)
411 {
412 Status = NtReplyWaitReceivePort(hConnectedPort,
413 Context,
414 Reply,
415 &Request);
416 if(!NT_SUCCESS(Status))
417 {
418 DPRINT1("CSR: %s: NtReplyWaitReceivePort failed (Status=0x%08lx)\n",
419 __FUNCTION__, Status);
420 break;
421 }
422
423 switch (Request.u2.s2.Type) //fix .h PORT_MESSAGE_TYPE(Request))
424 {
425 /* TODO */
426 default:
427 DPRINT1("CSR: %s received message (type=%d)\n",
428 __FUNCTION__, Request.u2.s2.Type);
429 }
430 DPRINT("-- 5\n");
431 }
432 }
433 }
434 }
435
436 DPRINT("CSR: %s: terminating!\n", __FUNCTION__);
437 if(hConnectedPort) NtClose (hConnectedPort);
438 NtClose (hSbApiPortListen);
439 NtTerminateThread (NtCurrentThread(), Status);
440 return 0;
441 }
442
443 /* EOF */