- Merge a couple of small bugfixes from 25461 (smss and csrss related)
[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 HANDLE CsrssApiHeap = (HANDLE) 0;
23
24 static unsigned ApiDefinitionsCount = 0;
25 static PCSRSS_API_DEFINITION ApiDefinitions = NULL;
26
27 /* FUNCTIONS *****************************************************************/
28
29 NTSTATUS FASTCALL
30 CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions)
31 {
32 unsigned NewCount;
33 PCSRSS_API_DEFINITION Scan;
34 PCSRSS_API_DEFINITION New;
35
36 DPRINT("CSR: %s called", __FUNCTION__);
37
38 NewCount = 0;
39 for (Scan = NewDefinitions; 0 != Scan->Handler; Scan++)
40 {
41 NewCount++;
42 }
43
44 New = RtlAllocateHeap(CsrssApiHeap, 0,
45 (ApiDefinitionsCount + NewCount)
46 * sizeof(CSRSS_API_DEFINITION));
47 if (NULL == New)
48 {
49 DPRINT1("Unable to allocate memory\n");
50 return STATUS_NO_MEMORY;
51 }
52 if (0 != ApiDefinitionsCount)
53 {
54 RtlCopyMemory(New, ApiDefinitions,
55 ApiDefinitionsCount * sizeof(CSRSS_API_DEFINITION));
56 RtlFreeHeap(CsrssApiHeap, 0, ApiDefinitions);
57 }
58 RtlCopyMemory(New + ApiDefinitionsCount, NewDefinitions,
59 NewCount * sizeof(CSRSS_API_DEFINITION));
60 ApiDefinitions = New;
61 ApiDefinitionsCount += NewCount;
62
63 return STATUS_SUCCESS;
64 }
65
66 VOID
67 FASTCALL
68 CsrApiCallHandler(PCSRSS_PROCESS_DATA ProcessData,
69 PCSR_API_MESSAGE Request)
70 {
71 BOOL Found = FALSE;
72 unsigned DefIndex;
73 ULONG Type;
74
75 DPRINT("CSR: Calling handler for type: %x.\n", Request->Type);
76 Type = Request->Type & 0xFFFF; /* FIXME: USE MACRO */
77 DPRINT("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >> 16);
78
79 /* FIXME: Extract DefIndex instead of looping */
80 for (DefIndex = 0; ! Found && DefIndex < ApiDefinitionsCount; DefIndex++)
81 {
82 if (ApiDefinitions[DefIndex].Type == Type)
83 {
84 if (Request->Header.u1.s1.DataLength < ApiDefinitions[DefIndex].MinRequestSize)
85 {
86 DPRINT1("Request type %d min request size %d actual %d\n",
87 Type, ApiDefinitions[DefIndex].MinRequestSize,
88 Request->Header.u1.s1.DataLength);
89 Request->Status = STATUS_INVALID_PARAMETER;
90 }
91 else
92 {
93 (ApiDefinitions[DefIndex].Handler)(ProcessData, Request);
94 Found = TRUE;
95 }
96 }
97 }
98 if (! Found)
99 {
100 DPRINT1("CSR: Unknown request type 0x%x\n", Request->Type);
101 Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
102 Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
103 Request->Status = STATUS_INVALID_SYSTEM_SERVICE;
104 }
105 }
106
107 BOOL FASTCALL CallHardError(void);
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 CallHardError();
119 }
120
121 NTSTATUS STDCALL
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 #ifdef NTLPC
136 NULL,
137 Request,
138 #else
139 hApiListenPort,
140 NULL,
141 #endif
142 TRUE,
143 0,
144 & LpcRead);
145 if (!NT_SUCCESS(Status))
146 {
147 DPRINT1("CSR: NtAcceptConnectPort() failed\n");
148 return Status;
149 }
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 ProcessData->CsrSectionViewBase = LpcRead.ViewBase;
161 ProcessData->CsrSectionViewSize = LpcRead.ViewSize;
162
163 Status = NtCompleteConnectPort(ServerPort);
164 if (!NT_SUCCESS(Status))
165 {
166 DPRINT1("CSR: NtCompleteConnectPort() failed\n");
167 return Status;
168 }
169
170 #if !defined(NTLPC) /* ReactOS LPC */
171 HANDLE ServerThread = (HANDLE) 0;
172 Status = RtlCreateUserThread(NtCurrentProcess(),
173 NULL,
174 FALSE,
175 0,
176 0,
177 0,
178 (PTHREAD_START_ROUTINE)ClientConnectionThread,
179 ServerPort,
180 & ServerThread,
181 NULL);
182 if (!NT_SUCCESS(Status))
183 {
184 DPRINT1("CSR: Unable to create server thread\n");
185 return Status;
186 }
187
188 NtClose(ServerThread);
189 #endif
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", __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(ServerPort,
216 0,
217 &Reply->Header,
218 &Request->Header);
219 if (!NT_SUCCESS(Status))
220 {
221 DPRINT1("NtReplyWaitReceivePort failed: %lx\n", Status);
222 break;
223 }
224
225 /* If the connection was closed, handle that */
226 if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED)
227 {
228 DPRINT("Port died, oh well\n");
229 CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
230 //NtClose();
231 Reply = NULL;
232 continue;
233 //break;
234 }
235
236 if (Request->Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
237 {
238 CsrpHandleConnectionRequest((PPORT_MESSAGE)Request, ServerPort);
239 Reply = NULL;
240 continue;
241 }
242
243 if (Request->Header.u2.s2.Type == LPC_CLIENT_DIED)
244 {
245 DPRINT("Client died, oh well\n");
246 Reply = NULL;
247 continue;
248 }
249
250 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
251 Request->Type,
252 Request->Header.ClientId.UniqueThread);
253
254 /* Get the Process Data */
255 ProcessData = CsrGetProcessData(Request->Header.ClientId.UniqueProcess);
256 if (ProcessData == NULL)
257 {
258 DPRINT1("Message %d: Unable to find data for process 0x%x\n",
259 Request->Header.u2.s2.Type,
260 Request->Header.ClientId.UniqueProcess);
261 break;
262 }
263 if (ProcessData->Terminated)
264 {
265 DPRINT1("Message %d: process %d already terminated\n",
266 Request->Type, (ULONG)Request->Header.ClientId.UniqueProcess);
267 continue;
268 }
269
270 /* Check if we got a hard error */
271 if (Request->Header.u2.s2.Type == LPC_ERROR_EVENT)
272 {
273 /* Call the Handler */
274 CsrHandleHardError(ProcessData, (PHARDERROR_MSG)Request);
275 }
276 else
277 {
278 /* Call the Handler */
279 CsrApiCallHandler(ProcessData, Request);
280 }
281
282 /* Send back the reply */
283 Reply = Request;
284 }
285
286 /* Close the port and exit the thread */
287 NtClose(ServerPort);
288 RtlExitUserThread(STATUS_SUCCESS);
289 }
290
291 /**********************************************************************
292 * NAME
293 * ServerApiPortThread/1
294 *
295 * DESCRIPTION
296 * Handle connection requests from clients to the port
297 * "\Windows\ApiPort".
298 */
299 DWORD STDCALL
300 ServerApiPortThread (HANDLE hApiListenPort)
301 {
302 NTSTATUS Status = STATUS_SUCCESS;
303 BYTE RawRequest[sizeof(PORT_MESSAGE) + sizeof(CSR_CONNECTION_INFO)];
304 PPORT_MESSAGE Request = (PPORT_MESSAGE)RawRequest;
305
306 DPRINT("CSR: %s called", __FUNCTION__);
307
308 for (;;)
309 {
310 REMOTE_PORT_VIEW LpcRead;
311 LpcRead.Length = sizeof(LpcRead);
312
313 Status = NtListenPort (hApiListenPort, Request);
314 if (!NT_SUCCESS(Status))
315 {
316 DPRINT1("CSR: NtListenPort() failed, status=%x\n", Status);
317 break;
318 }
319
320 Status = CsrpHandleConnectionRequest(Request, hApiListenPort);
321 if(!NT_SUCCESS(Status))
322 {
323 DPRINT1("CSR: %s: SmpHandleConnectionRequest failed (Status=0x%08lx)\n",
324 __FUNCTION__, Status);
325 break;
326 }
327 }
328
329 NtClose(hApiListenPort);
330 NtTerminateThread(NtCurrentThread(), Status);
331 return 0;
332 }
333
334 /**********************************************************************
335 * NAME
336 * ServerSbApiPortThread/1
337 *
338 * DESCRIPTION
339 * Handle connection requests from SM to the port
340 * "\Windows\SbApiPort". We will accept only one
341 * connection request (from the SM).
342 */
343 DWORD STDCALL
344 ServerSbApiPortThread (HANDLE hSbApiPortListen)
345 {
346 HANDLE hConnectedPort = (HANDLE) 0;
347 PORT_MESSAGE Request;
348 PVOID Context = NULL;
349 NTSTATUS Status = STATUS_SUCCESS;
350 PPORT_MESSAGE Reply = NULL;
351
352 DPRINT("CSR: %s called\n", __FUNCTION__);
353
354 RtlZeroMemory(&Request, sizeof(PORT_MESSAGE));
355 Status = NtListenPort (hSbApiPortListen, & Request);
356 if (!NT_SUCCESS(Status))
357 {
358 DPRINT1("CSR: %s: NtListenPort(SB) failed (Status=0x%08lx)\n",
359 __FUNCTION__, Status);
360 } else {
361 DPRINT("-- 1\n");
362 Status = NtAcceptConnectPort (& hConnectedPort,
363 #ifdef NTLPC
364 NULL,
365 &Request,
366 #else
367 hSbApiPortListen,
368 NULL,
369 #endif
370 TRUE,
371 NULL,
372 NULL);
373 if(!NT_SUCCESS(Status))
374 {
375 DPRINT1("CSR: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
376 __FUNCTION__, Status);
377 } else {
378 DPRINT("-- 2\n");
379 Status = NtCompleteConnectPort (hConnectedPort);
380 if(!NT_SUCCESS(Status))
381 {
382 DPRINT1("CSR: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
383 __FUNCTION__, Status);
384 } else {
385 DPRINT("-- 3\n");
386
387 /*
388 * Tell the init thread the SM gave the
389 * green light for boostrapping.
390 */
391 Status = NtSetEvent (hBootstrapOk, NULL);
392 if(!NT_SUCCESS(Status))
393 {
394 DPRINT1("CSR: %s: NtSetEvent failed (Status=0x%08lx)\n",
395 __FUNCTION__, Status);
396 }
397 /* Wait for messages from the SM */
398 DPRINT("-- 4\n");
399 while (TRUE)
400 {
401 Status = NtReplyWaitReceivePort(hConnectedPort,
402 Context,
403 Reply,
404 & Request);
405 if(!NT_SUCCESS(Status))
406 {
407 DPRINT1("CSR: %s: NtReplyWaitReceivePort failed (Status=0x%08lx)\n",
408 __FUNCTION__, Status);
409 break;
410 }
411 switch (Request.u2.s2.Type)//fix .h PORT_MESSAGE_TYPE(Request))
412 {
413 /* TODO */
414 default:
415 DPRINT1("CSR: %s received message (type=%d)\n",
416 __FUNCTION__, Request.u2.s2.Type);
417 }
418 DPRINT("-- 5\n");
419 }
420 }
421 }
422 }
423 DPRINT("CSR: %s: terminating!\n", __FUNCTION__);
424 if(hConnectedPort) NtClose (hConnectedPort);
425 NtClose (hSbApiPortListen);
426 NtTerminateThread (NtCurrentThread(), Status);
427 return 0;
428 }
429
430 /* EOF */