bf4e53fb4813f9a2d5c254cc998d35d52e5f55f1
[reactos.git] / reactos / subsys / 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 static
108 VOID
109 STDCALL
110 ClientConnectionThread(HANDLE ServerPort)
111 {
112 NTSTATUS Status;
113 BYTE RawRequest[LPC_MAX_DATA_LENGTH];
114 PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
115 PCSR_API_MESSAGE Reply;
116 PCSRSS_PROCESS_DATA ProcessData;
117
118 DPRINT("CSR: %s called", __FUNCTION__);
119
120 /* Reply must be NULL at the first call to NtReplyWaitReceivePort */
121 Reply = NULL;
122
123 /* Loop and reply/wait for a new message */
124 for (;;)
125 {
126 /* Send the reply and wait for a new request */
127 Status = NtReplyWaitReceivePort(ServerPort,
128 0,
129 &Reply->Header,
130 &Request->Header);
131 if (!NT_SUCCESS(Status))
132 {
133 DPRINT1("NtReplyWaitReceivePort failed\n");
134 break;
135 }
136
137 /* If the connection was closed, handle that */
138 if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED)
139 {
140 CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
141 break;
142 }
143
144 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
145 Request->Type,
146 Request->Header.ClientId.UniqueProcess);
147
148 /* Get the Process Data */
149 ProcessData = CsrGetProcessData(Request->Header.ClientId.UniqueProcess);
150 if (ProcessData == NULL)
151 {
152 DPRINT1("Message %d: Unable to find data for process 0x%x\n",
153 Request->Header.u2.s2.Type,
154 Request->Header.ClientId.UniqueProcess);
155 break;
156 }
157 if (ProcessData->Terminated)
158 {
159 DPRINT1("Message %d: process %d already terminated\n",
160 Request->Type, (ULONG)Request->Header.ClientId.UniqueProcess);
161 continue;
162 }
163
164 /* Call the Handler */
165 CsrApiCallHandler(ProcessData, Request);
166
167 /* Send back the reply */
168 Reply = Request;
169 }
170
171 /* Close the port and exit the thread */
172 NtClose(ServerPort);
173 RtlExitUserThread(STATUS_SUCCESS);
174 }
175
176 /**********************************************************************
177 * NAME
178 * ServerApiPortThread/1
179 *
180 * DESCRIPTION
181 * Handle connection requests from clients to the port
182 * "\Windows\ApiPort".
183 */
184 DWORD STDCALL
185 ServerApiPortThread (PVOID PortHandle)
186 {
187 NTSTATUS Status = STATUS_SUCCESS;
188 BYTE RawRequest[sizeof(PORT_MESSAGE) + sizeof(CSR_CONNECTION_INFO)];
189 PPORT_MESSAGE Request = (PPORT_MESSAGE)RawRequest;
190 HANDLE hApiListenPort = * (PHANDLE) PortHandle;
191 HANDLE ServerPort = (HANDLE) 0;
192 HANDLE ServerThread = (HANDLE) 0;
193 PCSRSS_PROCESS_DATA ProcessData = NULL;
194
195 CsrInitProcessData();
196
197 DPRINT("CSR: %s called", __FUNCTION__);
198
199 for (;;)
200 {
201 REMOTE_PORT_VIEW LpcRead;
202 ServerPort = NULL;
203
204 Status = NtListenPort (hApiListenPort, Request);
205 if (!NT_SUCCESS(Status))
206 {
207 DPRINT1("CSR: NtListenPort() failed, status=%x\n", Status);
208 break;
209 }
210 Status = NtAcceptConnectPort(& ServerPort,
211 hApiListenPort,
212 NULL,
213 TRUE,
214 0,
215 & LpcRead);
216 if (!NT_SUCCESS(Status))
217 {
218 DPRINT1("CSR: NtAcceptConnectPort() failed\n");
219 break;
220 }
221
222 ProcessData = CsrCreateProcessData(Request->ClientId.UniqueProcess);
223 if (ProcessData == NULL)
224 {
225 DPRINT1("Unable to allocate or find data for process 0x%x\n",
226 Request->ClientId.UniqueProcess);
227 Status = STATUS_UNSUCCESSFUL;
228 break;
229 }
230
231
232 ProcessData->CsrSectionViewBase = LpcRead.ViewBase;
233 ProcessData->CsrSectionViewSize = LpcRead.ViewSize;
234
235 Status = NtCompleteConnectPort(ServerPort);
236 if (!NT_SUCCESS(Status))
237 {
238 DPRINT1("CSR: NtCompleteConnectPort() failed\n");
239 break;
240 }
241
242 Status = RtlCreateUserThread(NtCurrentProcess(),
243 NULL,
244 FALSE,
245 0,
246 0,
247 0,
248 (PTHREAD_START_ROUTINE)ClientConnectionThread,
249 ServerPort,
250 & ServerThread,
251 NULL);
252 if (!NT_SUCCESS(Status))
253 {
254 DPRINT1("CSR: Unable to create server thread\n");
255 break;
256 }
257 NtClose(ServerThread);
258 }
259 if (ServerPort)
260 {
261 NtClose(ServerPort);
262 }
263 NtClose(PortHandle);
264 NtTerminateThread(NtCurrentThread(), Status);
265 return 0;
266 }
267
268 /**********************************************************************
269 * NAME
270 * ServerSbApiPortThread/1
271 *
272 * DESCRIPTION
273 * Handle connection requests from SM to the port
274 * "\Windows\SbApiPort". We will accept only one
275 * connection request (from the SM).
276 */
277 DWORD STDCALL
278 ServerSbApiPortThread (PVOID PortHandle)
279 {
280 HANDLE hSbApiPortListen = * (PHANDLE) PortHandle;
281 HANDLE hConnectedPort = (HANDLE) 0;
282 PORT_MESSAGE Request;
283 PVOID Context = NULL;
284 NTSTATUS Status = STATUS_SUCCESS;
285
286 DPRINT("CSR: %s called\n", __FUNCTION__);
287
288 RtlZeroMemory(&Request, sizeof(PORT_MESSAGE));
289 Status = NtListenPort (hSbApiPortListen, & Request);
290 if (!NT_SUCCESS(Status))
291 {
292 DPRINT1("CSR: %s: NtListenPort(SB) failed (Status=0x%08lx)\n",
293 __FUNCTION__, Status);
294 } else {
295 DPRINT("-- 1\n");
296 Status = NtAcceptConnectPort (& hConnectedPort,
297 hSbApiPortListen,
298 NULL,
299 TRUE,
300 NULL,
301 NULL);
302 if(!NT_SUCCESS(Status))
303 {
304 DPRINT1("CSR: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
305 __FUNCTION__, Status);
306 } else {
307 DPRINT("-- 2\n");
308 Status = NtCompleteConnectPort (hConnectedPort);
309 if(!NT_SUCCESS(Status))
310 {
311 DPRINT1("CSR: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
312 __FUNCTION__, Status);
313 } else {
314 DPRINT("-- 3\n");
315 PPORT_MESSAGE Reply = NULL;
316 /*
317 * Tell the init thread the SM gave the
318 * green light for boostrapping.
319 */
320 Status = NtSetEvent (hBootstrapOk, NULL);
321 if(!NT_SUCCESS(Status))
322 {
323 DPRINT1("CSR: %s: NtSetEvent failed (Status=0x%08lx)\n",
324 __FUNCTION__, Status);
325 }
326 /* Wait for messages from the SM */
327 DPRINT("-- 4\n");
328 while (TRUE)
329 {
330 Status = NtReplyWaitReceivePort(hConnectedPort,
331 Context,
332 Reply,
333 & Request);
334 if(!NT_SUCCESS(Status))
335 {
336 DPRINT1("CSR: %s: NtReplyWaitReceivePort failed (Status=0x%08lx)\n",
337 __FUNCTION__, Status);
338 break;
339 }
340 switch (Request.u2.s2.Type)//fix .h PORT_MESSAGE_TYPE(Request))
341 {
342 /* TODO */
343 default:
344 DPRINT1("CSR: %s received message (type=%d)\n",
345 __FUNCTION__, Request.u2.s2.Type);
346 }
347 DPRINT("-- 5\n");
348 }
349 }
350 }
351 }
352 DPRINT1("CSR: %s: terminating!\n", __FUNCTION__);
353 if(hConnectedPort) NtClose (hConnectedPort);
354 NtClose (hSbApiPortListen);
355 NtTerminateThread (NtCurrentThread(), Status);
356 return 0;
357 }
358
359 /* EOF */