[CSRSS]: Split off CSRSS into a more Windows-friendly model. CSRSS.EXE is simply...
[reactos.git] / reactos / subsystems / win32 / csrss / csrsrv / 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 <srv.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 = NULL, ServerThread = NULL;
127 PCSRSS_PROCESS_DATA ProcessData = NULL;
128 REMOTE_PORT_VIEW LpcRead;
129 CLIENT_ID ClientId;
130 LpcRead.Length = sizeof(LpcRead);
131 ServerPort = NULL;
132
133 DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__, Request);
134
135 Status = NtAcceptConnectPort(&ServerPort,
136 NULL,
137 Request,
138 TRUE,
139 0,
140 & LpcRead);
141 if (!NT_SUCCESS(Status))
142 {
143 DPRINT1("CSR: NtAcceptConnectPort() failed\n");
144 return Status;
145 }
146
147 ProcessData = CsrGetProcessData(Request->ClientId.UniqueProcess);
148 if (ProcessData == NULL)
149 {
150 ProcessData = CsrCreateProcessData(Request->ClientId.UniqueProcess);
151 if (ProcessData == NULL)
152 {
153 DPRINT1("Unable to allocate or find data for process 0x%x\n",
154 Request->ClientId.UniqueProcess);
155 Status = STATUS_UNSUCCESSFUL;
156 return Status;
157 }
158 }
159
160 ProcessData->CsrSectionViewBase = LpcRead.ViewBase;
161 ProcessData->CsrSectionViewSize = LpcRead.ViewSize;
162 ProcessData->ServerCommunicationPort = ServerPort;
163
164 Status = NtCompleteConnectPort(ServerPort);
165 if (!NT_SUCCESS(Status))
166 {
167 DPRINT1("CSR: NtCompleteConnectPort() failed\n");
168 return Status;
169 }
170
171 Status = RtlCreateUserThread(NtCurrentProcess(),
172 NULL,
173 TRUE,
174 0,
175 0,
176 0,
177 (PTHREAD_START_ROUTINE)ClientConnectionThread,
178 ServerPort,
179 & ServerThread,
180 &ClientId);
181 if (!NT_SUCCESS(Status))
182 {
183 DPRINT1("CSR: Unable to create server thread\n");
184 return Status;
185 }
186
187 CsrAddStaticServerThread(ServerThread, &ClientId, 0);
188
189 NtResumeThread(ServerThread, NULL);
190
191 NtClose(ServerThread);
192
193 Status = STATUS_SUCCESS;
194 DPRINT("CSR: %s done\n", __FUNCTION__);
195 return Status;
196 }
197
198 PCSR_THREAD
199 NTAPI
200 CsrConnectToUser(VOID)
201 {
202 PTEB Teb = NtCurrentTeb();
203 PCSR_THREAD CsrThread;
204 #if 0
205 NTSTATUS Status;
206 ANSI_STRING DllName;
207 UNICODE_STRING TempName;
208 HANDLE hUser32;
209 STRING StartupName;
210
211 /* Check if we didn't already find it */
212 if (!CsrClientThreadSetup)
213 {
214 /* Get the DLL Handle for user32.dll */
215 RtlInitAnsiString(&DllName, "user32");
216 RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);
217 Status = LdrGetDllHandle(NULL,
218 NULL,
219 &TempName,
220 &hUser32);
221 RtlFreeUnicodeString(&TempName);
222
223 /* If we got teh handle, get the Client Thread Startup Entrypoint */
224 if (NT_SUCCESS(Status))
225 {
226 RtlInitAnsiString(&StartupName,"ClientThreadSetup");
227 Status = LdrGetProcedureAddress(hUser32,
228 &StartupName,
229 0,
230 (PVOID)&CsrClientThreadSetup);
231 }
232 }
233
234 /* Connect to user32 */
235 CsrClientThreadSetup();
236 #endif
237 /* Save pointer to this thread in TEB */
238 CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
239 if (CsrThread) Teb->CsrClientThread = CsrThread;
240
241 /* Return it */
242 return CsrThread;
243 }
244
245 VOID
246 WINAPI
247 ClientConnectionThread(HANDLE ServerPort)
248 {
249 NTSTATUS Status;
250 BYTE RawRequest[LPC_MAX_DATA_LENGTH];
251 PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
252 PCSR_API_MESSAGE Reply;
253 PCSRSS_PROCESS_DATA ProcessData;
254 PCSR_THREAD ServerThread;
255
256 DPRINT("CSR: %s called\n", __FUNCTION__);
257
258 /* Connect to user32 */
259 while (!CsrConnectToUser())
260 {
261 /* Keep trying until we get a response */
262 NtCurrentTeb()->Win32ClientInfo[0] = 0;
263 //NtDelayExecution(FALSE, &TimeOut);
264 }
265
266 /* Reply must be NULL at the first call to NtReplyWaitReceivePort */
267 ServerThread = NtCurrentTeb()->CsrClientThread;
268 Reply = NULL;
269
270 /* Loop and reply/wait for a new message */
271 for (;;)
272 {
273 /* Send the reply and wait for a new request */
274 Status = NtReplyWaitReceivePort(hApiPort,
275 0,
276 &Reply->Header,
277 &Request->Header);
278 /* Client died, continue */
279 if (Status == STATUS_INVALID_CID)
280 {
281 Reply = NULL;
282 continue;
283 }
284
285 if (!NT_SUCCESS(Status))
286 {
287 DPRINT1("NtReplyWaitReceivePort failed: %lx\n", Status);
288 break;
289 }
290
291 /* If the connection was closed, handle that */
292 if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED)
293 {
294 DPRINT("Port died, oh well\n");
295 CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
296 break;
297 }
298
299 if (Request->Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
300 {
301 CsrpHandleConnectionRequest((PPORT_MESSAGE)Request, ServerPort);
302 Reply = NULL;
303 continue;
304 }
305
306 if (Request->Header.u2.s2.Type == LPC_CLIENT_DIED)
307 {
308 DPRINT("Client died, oh well\n");
309 Reply = NULL;
310 continue;
311 }
312
313 if ((Request->Header.u2.s2.Type != LPC_ERROR_EVENT) &&
314 (Request->Header.u2.s2.Type != LPC_REQUEST))
315 {
316 DPRINT1("CSR: received message %d\n", Request->Header.u2.s2.Type);
317 Reply = NULL;
318 continue;
319 }
320
321 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
322 Request->Type,
323 Request->Header.ClientId.UniqueThread);
324
325 /* Get the Process Data */
326 ProcessData = CsrGetProcessData(Request->Header.ClientId.UniqueProcess);
327 if (ProcessData == NULL)
328 {
329 DPRINT1("Message %d: Unable to find data for process 0x%x\n",
330 Request->Header.u2.s2.Type,
331 Request->Header.ClientId.UniqueProcess);
332 break;
333 }
334 if (ProcessData->Terminated)
335 {
336 DPRINT1("Message %d: process %d already terminated\n",
337 Request->Type, Request->Header.ClientId.UniqueProcess);
338 continue;
339 }
340
341 /* Check if we got a hard error */
342 if (Request->Header.u2.s2.Type == LPC_ERROR_EVENT)
343 {
344 /* Call the Handler */
345 CsrHandleHardError(ProcessData, (PHARDERROR_MSG)Request);
346 }
347 else
348 {
349 PCSR_THREAD Thread;
350 PCSRSS_PROCESS_DATA Process = NULL;
351
352 //DPRINT1("locate thread %lx/%lx\n", Request->Header.ClientId.UniqueProcess, Request->Header.ClientId.UniqueThread);
353 Thread = CsrLocateThreadByClientId(&Process, &Request->Header.ClientId);
354 //DPRINT1("Thread found: %p %p\n", Thread, Process);
355
356 /* Call the Handler */
357 if (Thread) NtCurrentTeb()->CsrClientThread = Thread;
358 CsrApiCallHandler(ProcessData, Request);
359 if (Thread) NtCurrentTeb()->CsrClientThread = ServerThread;
360 }
361
362 /* Send back the reply */
363 Reply = Request;
364 }
365
366 /* Close the port and exit the thread */
367 // NtClose(ServerPort);
368
369 DPRINT("CSR: %s done\n", __FUNCTION__);
370 RtlExitUserThread(STATUS_SUCCESS);
371 }
372
373 /**********************************************************************
374 * NAME
375 * ServerSbApiPortThread/1
376 *
377 * DESCRIPTION
378 * Handle connection requests from SM to the port
379 * "\Windows\SbApiPort". We will accept only one
380 * connection request (from the SM).
381 */
382 DWORD WINAPI
383 ServerSbApiPortThread (HANDLE hSbApiPortListen)
384 {
385 HANDLE hConnectedPort = (HANDLE) 0;
386 PORT_MESSAGE Request;
387 PVOID Context = NULL;
388 NTSTATUS Status = STATUS_SUCCESS;
389 PPORT_MESSAGE Reply = NULL;
390
391 DPRINT("CSR: %s called\n", __FUNCTION__);
392
393 RtlZeroMemory(&Request, sizeof(PORT_MESSAGE));
394 Status = NtListenPort (hSbApiPortListen, & Request);
395
396 if (!NT_SUCCESS(Status))
397 {
398 DPRINT1("CSR: %s: NtListenPort(SB) failed (Status=0x%08lx)\n",
399 __FUNCTION__, Status);
400 } else {
401 DPRINT("-- 1\n");
402 Status = NtAcceptConnectPort(&hConnectedPort,
403 NULL,
404 &Request,
405 TRUE,
406 NULL,
407 NULL);
408 if(!NT_SUCCESS(Status))
409 {
410 DPRINT1("CSR: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
411 __FUNCTION__, Status);
412 } else {
413 DPRINT("-- 2\n");
414 Status = NtCompleteConnectPort (hConnectedPort);
415 if(!NT_SUCCESS(Status))
416 {
417 DPRINT1("CSR: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
418 __FUNCTION__, Status);
419 } else {
420 DPRINT("-- 3\n");
421 /*
422 * Tell the init thread the SM gave the
423 * green light for boostrapping.
424 */
425 Status = NtSetEvent (hBootstrapOk, NULL);
426 if(!NT_SUCCESS(Status))
427 {
428 DPRINT1("CSR: %s: NtSetEvent failed (Status=0x%08lx)\n",
429 __FUNCTION__, Status);
430 }
431 /* Wait for messages from the SM */
432 DPRINT("-- 4\n");
433 while (TRUE)
434 {
435 Status = NtReplyWaitReceivePort(hConnectedPort,
436 Context,
437 Reply,
438 &Request);
439 if(!NT_SUCCESS(Status))
440 {
441 DPRINT1("CSR: %s: NtReplyWaitReceivePort failed (Status=0x%08lx)\n",
442 __FUNCTION__, Status);
443 break;
444 }
445
446 switch (Request.u2.s2.Type) //fix .h PORT_MESSAGE_TYPE(Request))
447 {
448 /* TODO */
449 default:
450 DPRINT1("CSR: %s received message (type=%d)\n",
451 __FUNCTION__, Request.u2.s2.Type);
452 }
453 DPRINT("-- 5\n");
454 }
455 }
456 }
457 }
458
459 DPRINT("CSR: %s: terminating!\n", __FUNCTION__);
460 if(hConnectedPort) NtClose (hConnectedPort);
461 NtClose (hSbApiPortListen);
462 NtTerminateThread (NtCurrentThread(), Status);
463 return 0;
464 }
465
466 /* EOF */