[CSRSS]
[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 = NULL, ServerThread = NULL;
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 Status = RtlCreateUserThread(NtCurrentProcess(),
171 NULL,
172 FALSE,
173 0,
174 0,
175 0,
176 (PTHREAD_START_ROUTINE)ClientConnectionThread,
177 ServerPort,
178 & ServerThread,
179 NULL);
180 if (!NT_SUCCESS(Status))
181 {
182 DPRINT1("CSR: Unable to create server thread\n");
183 return Status;
184 }
185
186 NtClose(ServerThread);
187
188 Status = STATUS_SUCCESS;
189 DPRINT("CSR: %s done\n", __FUNCTION__);
190 return Status;
191 }
192
193 VOID
194 WINAPI
195 ClientConnectionThread(HANDLE ServerPort)
196 {
197 NTSTATUS Status;
198 BYTE RawRequest[LPC_MAX_DATA_LENGTH];
199 PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
200 PCSR_API_MESSAGE Reply;
201 PCSRSS_PROCESS_DATA ProcessData;
202
203 DPRINT("CSR: %s called\n", __FUNCTION__);
204
205 /* Reply must be NULL at the first call to NtReplyWaitReceivePort */
206 Reply = NULL;
207
208 /* Loop and reply/wait for a new message */
209 for (;;)
210 {
211 /* Send the reply and wait for a new request */
212 Status = NtReplyWaitReceivePort(hApiPort,
213 0,
214 &Reply->Header,
215 &Request->Header);
216 /* Client died, continue */
217 if (Status == STATUS_INVALID_CID)
218 {
219 Reply = NULL;
220 continue;
221 }
222
223 if (!NT_SUCCESS(Status))
224 {
225 DPRINT1("NtReplyWaitReceivePort failed: %lx\n", Status);
226 break;
227 }
228
229 /* If the connection was closed, handle that */
230 if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED)
231 {
232 DPRINT("Port died, oh well\n");
233 CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
234 break;
235 }
236
237 if (Request->Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
238 {
239 CsrpHandleConnectionRequest((PPORT_MESSAGE)Request, ServerPort);
240 Reply = NULL;
241 continue;
242 }
243
244 if (Request->Header.u2.s2.Type == LPC_CLIENT_DIED)
245 {
246 DPRINT("Client died, oh well\n");
247 Reply = NULL;
248 continue;
249 }
250
251 if ((Request->Header.u2.s2.Type != LPC_ERROR_EVENT) &&
252 (Request->Header.u2.s2.Type != LPC_REQUEST))
253 {
254 DPRINT1("CSR: received message %d\n", Request->Header.u2.s2.Type);
255 Reply = NULL;
256 continue;
257 }
258
259 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
260 Request->Type,
261 Request->Header.ClientId.UniqueThread);
262
263 /* Get the Process Data */
264 ProcessData = CsrGetProcessData(Request->Header.ClientId.UniqueProcess);
265 if (ProcessData == NULL)
266 {
267 DPRINT1("Message %d: Unable to find data for process 0x%x\n",
268 Request->Header.u2.s2.Type,
269 Request->Header.ClientId.UniqueProcess);
270 break;
271 }
272 if (ProcessData->Terminated)
273 {
274 DPRINT1("Message %d: process %p already terminated\n",
275 Request->Type, Request->Header.ClientId.UniqueProcess);
276 continue;
277 }
278
279 /* Check if we got a hard error */
280 if (Request->Header.u2.s2.Type == LPC_ERROR_EVENT)
281 {
282 /* Call the Handler */
283 CsrHandleHardError(ProcessData, (PHARDERROR_MSG)Request);
284 }
285 else
286 {
287 /* Call the Handler */
288 CsrApiCallHandler(ProcessData, Request);
289 }
290
291 /* Send back the reply */
292 Reply = Request;
293 }
294
295 /* Close the port and exit the thread */
296 // NtClose(ServerPort);
297
298 DPRINT("CSR: %s done\n", __FUNCTION__);
299 RtlExitUserThread(STATUS_SUCCESS);
300 }
301
302 /**********************************************************************
303 * NAME
304 * ServerSbApiPortThread/1
305 *
306 * DESCRIPTION
307 * Handle connection requests from SM to the port
308 * "\Windows\SbApiPort". We will accept only one
309 * connection request (from the SM).
310 */
311 DWORD WINAPI
312 ServerSbApiPortThread (HANDLE hSbApiPortListen)
313 {
314 HANDLE hConnectedPort = (HANDLE) 0;
315 PORT_MESSAGE Request;
316 PVOID Context = NULL;
317 NTSTATUS Status = STATUS_SUCCESS;
318 PPORT_MESSAGE Reply = NULL;
319
320 DPRINT("CSR: %s called\n", __FUNCTION__);
321
322 RtlZeroMemory(&Request, sizeof(PORT_MESSAGE));
323 Status = NtListenPort (hSbApiPortListen, & Request);
324
325 if (!NT_SUCCESS(Status))
326 {
327 DPRINT1("CSR: %s: NtListenPort(SB) failed (Status=0x%08lx)\n",
328 __FUNCTION__, Status);
329 } else {
330 DPRINT("-- 1\n");
331 Status = NtAcceptConnectPort(&hConnectedPort,
332 NULL,
333 &Request,
334 TRUE,
335 NULL,
336 NULL);
337 if(!NT_SUCCESS(Status))
338 {
339 DPRINT1("CSR: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
340 __FUNCTION__, Status);
341 } else {
342 DPRINT("-- 2\n");
343 Status = NtCompleteConnectPort (hConnectedPort);
344 if(!NT_SUCCESS(Status))
345 {
346 DPRINT1("CSR: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
347 __FUNCTION__, Status);
348 } else {
349 DPRINT("-- 3\n");
350 /*
351 * Tell the init thread the SM gave the
352 * green light for boostrapping.
353 */
354 Status = NtSetEvent (hBootstrapOk, NULL);
355 if(!NT_SUCCESS(Status))
356 {
357 DPRINT1("CSR: %s: NtSetEvent failed (Status=0x%08lx)\n",
358 __FUNCTION__, Status);
359 }
360 /* Wait for messages from the SM */
361 DPRINT("-- 4\n");
362 while (TRUE)
363 {
364 Status = NtReplyWaitReceivePort(hConnectedPort,
365 Context,
366 Reply,
367 &Request);
368 if(!NT_SUCCESS(Status))
369 {
370 DPRINT1("CSR: %s: NtReplyWaitReceivePort failed (Status=0x%08lx)\n",
371 __FUNCTION__, Status);
372 break;
373 }
374
375 switch (Request.u2.s2.Type) //fix .h PORT_MESSAGE_TYPE(Request))
376 {
377 /* TODO */
378 default:
379 DPRINT1("CSR: %s received message (type=%d)\n",
380 __FUNCTION__, Request.u2.s2.Type);
381 }
382 DPRINT("-- 5\n");
383 }
384 }
385 }
386 }
387
388 DPRINT("CSR: %s: terminating!\n", __FUNCTION__);
389 if(hConnectedPort) NtClose (hConnectedPort);
390 NtClose (hSbApiPortListen);
391 NtTerminateThread (NtCurrentThread(), Status);
392 return 0;
393 }
394
395 /* EOF */