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