c3f692b7214bfe65dad7d2d2b5f2d9cc2551fe1c
[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 #include <debug.h>
17
18 /* GLOBALS *******************************************************************/
19
20 HANDLE CsrssApiHeap = (HANDLE) 0;
21
22 static unsigned ApiDefinitionsCount = 0;
23 static PCSRSS_API_DEFINITION ApiDefinitions = NULL;
24
25 /* FUNCTIONS *****************************************************************/
26
27 NTSTATUS FASTCALL
28 CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions)
29 {
30 unsigned NewCount;
31 PCSRSS_API_DEFINITION Scan;
32 PCSRSS_API_DEFINITION New;
33
34 DPRINT("CSR: %s called", __FUNCTION__);
35
36 NewCount = 0;
37 for (Scan = NewDefinitions; 0 != Scan->Handler; Scan++)
38 {
39 NewCount++;
40 }
41
42 New = RtlAllocateHeap(CsrssApiHeap, 0,
43 (ApiDefinitionsCount + NewCount)
44 * sizeof(CSRSS_API_DEFINITION));
45 if (NULL == New)
46 {
47 DPRINT1("Unable to allocate memory\n");
48 return STATUS_NO_MEMORY;
49 }
50 if (0 != ApiDefinitionsCount)
51 {
52 RtlCopyMemory(New, ApiDefinitions,
53 ApiDefinitionsCount * sizeof(CSRSS_API_DEFINITION));
54 RtlFreeHeap(CsrssApiHeap, 0, ApiDefinitions);
55 }
56 RtlCopyMemory(New + ApiDefinitionsCount, NewDefinitions,
57 NewCount * sizeof(CSRSS_API_DEFINITION));
58 ApiDefinitions = New;
59 ApiDefinitionsCount += NewCount;
60
61 return STATUS_SUCCESS;
62 }
63
64 VOID
65 FASTCALL
66 CsrApiCallHandler(PCSRSS_PROCESS_DATA ProcessData,
67 PCSR_API_MESSAGE Request)
68 {
69 BOOL Found = FALSE;
70 unsigned DefIndex;
71 ULONG Type;
72
73 DPRINT("CSR: Calling handler for type: %x.\n", Request->Type);
74 Type = Request->Type & 0xFFFF; /* FIXME: USE MACRO */
75 DPRINT("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >> 16);
76
77 /* FIXME: Extract DefIndex instead of looping */
78 for (DefIndex = 0; ! Found && DefIndex < ApiDefinitionsCount; DefIndex++)
79 {
80 if (ApiDefinitions[DefIndex].Type == Type)
81 {
82 if (Request->Header.DataSize < ApiDefinitions[DefIndex].MinRequestSize)
83 {
84 DPRINT1("Request type %d min request size %d actual %d\n",
85 Type, ApiDefinitions[DefIndex].MinRequestSize,
86 Request->Header.DataSize);
87 Request->Status = STATUS_INVALID_PARAMETER;
88 }
89 else
90 {
91 (ApiDefinitions[DefIndex].Handler)(ProcessData, Request);
92 Found = TRUE;
93 }
94 }
95 }
96 if (! Found)
97 {
98 DPRINT1("CSR: Unknown request type 0x%x\n", Request->Type);
99 Request->Header.MessageSize = sizeof(CSR_API_MESSAGE);
100 Request->Header.DataSize = sizeof(CSR_API_MESSAGE) - LPC_MESSAGE_BASE_SIZE;
101 Request->Status = STATUS_INVALID_SYSTEM_SERVICE;
102 }
103 }
104
105 STATIC
106 VOID
107 STDCALL
108 ClientConnectionThread(HANDLE ServerPort)
109 {
110 NTSTATUS Status;
111 LPC_MAX_MESSAGE LpcRequest;
112 PCSR_API_MESSAGE Request;
113 PCSR_API_MESSAGE Reply;
114 PCSRSS_PROCESS_DATA ProcessData;
115
116 DPRINT("CSR: %s called", __FUNCTION__);
117
118 /* Reply must be NULL at the first call to NtReplyWaitReceivePort */
119 Reply = NULL;
120
121 /* Loop and reply/wait for a new message */
122 for (;;)
123 {
124 /* Send the reply and wait for a new request */
125 Status = NtReplyWaitReceivePort(ServerPort,
126 0,
127 &Reply->Header,
128 &LpcRequest.Header);
129 if (!NT_SUCCESS(Status))
130 {
131 DPRINT1("CSR: NtReplyWaitReceivePort failed\n");
132 break;
133 }
134
135 /* If the connection was closed, handle that */
136 if (LpcRequest.Header.MessageType == LPC_PORT_CLOSED)
137 {
138 CsrFreeProcessData( LpcRequest.Header.ClientId.UniqueProcess );
139 break;
140 }
141
142 /* Get the CSR Message */
143 Request = (PCSR_API_MESSAGE)&LpcRequest;
144
145 DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
146 Request->Type,
147 Request->Header.ClientId.UniqueProcess);
148
149 /* Get the Process Data */
150 ProcessData = CsrGetProcessData(LpcRequest.Header.ClientId.UniqueProcess);
151 if (ProcessData == NULL)
152 {
153 DPRINT1("CSR: Message %d: Unable to find data for process 0x%x\n",
154 LpcRequest.Header.MessageType,
155 LpcRequest.Header.ClientId.UniqueProcess);
156 break;
157 }
158
159 /* Call the Handler */
160 CsrApiCallHandler(ProcessData, Request);
161
162 /* Send back the reply */
163 Reply = Request;
164 }
165
166 /* Close the port and exit the thread */
167 NtClose(ServerPort);
168 RtlExitUserThread(STATUS_SUCCESS);
169 }
170
171 /**********************************************************************
172 * NAME
173 * ServerApiPortThread/1
174 *
175 * DESCRIPTION
176 * Handle connection requests from clients to the port
177 * "\Windows\ApiPort".
178 */
179 DWORD STDCALL
180 ServerApiPortThread (PVOID PortHandle)
181 {
182 NTSTATUS Status = STATUS_SUCCESS;
183 LPC_MAX_MESSAGE Request;
184 HANDLE hApiListenPort = * (PHANDLE) PortHandle;
185 HANDLE ServerPort = (HANDLE) 0;
186 HANDLE ServerThread = (HANDLE) 0;
187 PCSRSS_PROCESS_DATA ProcessData = NULL;
188
189 CsrInitProcessData();
190
191 DPRINT("CSR: %s called", __FUNCTION__);
192
193 for (;;)
194 {
195 LPC_SECTION_READ LpcRead;
196 ServerPort = NULL;
197
198 Status = NtListenPort (hApiListenPort, & Request.Header);
199 if (!NT_SUCCESS(Status))
200 {
201 DPRINT1("CSR: NtListenPort() failed\n");
202 break;
203 }
204 Status = NtAcceptConnectPort(& ServerPort,
205 hApiListenPort,
206 NULL,
207 TRUE,
208 0,
209 & LpcRead);
210 if (!NT_SUCCESS(Status))
211 {
212 DPRINT1("CSR: NtAcceptConnectPort() failed\n");
213 break;
214 }
215
216 ProcessData = CsrCreateProcessData(Request.Header.ClientId.UniqueProcess);
217 if (ProcessData == NULL)
218 {
219 DPRINT1("Unable to allocate or find data for process 0x%x\n",
220 Request.Header.ClientId.UniqueProcess);
221 Status = STATUS_UNSUCCESSFUL;
222 break;
223 }
224
225
226 ProcessData->CsrSectionViewBase = LpcRead.ViewBase;
227 ProcessData->CsrSectionViewSize = LpcRead.ViewSize;
228
229 Status = NtCompleteConnectPort(ServerPort);
230 if (!NT_SUCCESS(Status))
231 {
232 DPRINT1("CSR: NtCompleteConnectPort() failed\n");
233 break;
234 }
235
236 Status = RtlCreateUserThread(NtCurrentProcess(),
237 NULL,
238 FALSE,
239 0,
240 NULL,
241 NULL,
242 (PTHREAD_START_ROUTINE)ClientConnectionThread,
243 ServerPort,
244 & ServerThread,
245 NULL);
246 if (!NT_SUCCESS(Status))
247 {
248 DPRINT1("CSR: Unable to create server thread\n");
249 break;
250 }
251 NtClose(ServerThread);
252 }
253 if (ServerPort)
254 {
255 NtClose(ServerPort);
256 }
257 NtClose(PortHandle);
258 NtTerminateThread(NtCurrentThread(), Status);
259 return 0;
260 }
261
262 /**********************************************************************
263 * NAME
264 * ServerSbApiPortThread/1
265 *
266 * DESCRIPTION
267 * Handle connection requests from SM to the port
268 * "\Windows\SbApiPort". We will accept only one
269 * connection request (from the SM).
270 */
271 DWORD STDCALL
272 ServerSbApiPortThread (PVOID PortHandle)
273 {
274 HANDLE hSbApiPortListen = * (PHANDLE) PortHandle;
275 HANDLE hConnectedPort = (HANDLE) 0;
276 LPC_MAX_MESSAGE Request = {{0}};
277 PVOID Context = NULL;
278 NTSTATUS Status = STATUS_SUCCESS;
279
280 DPRINT("CSR: %s called\n", __FUNCTION__);
281
282 Status = NtListenPort (hSbApiPortListen, & Request.Header);
283 if (!NT_SUCCESS(Status))
284 {
285 DPRINT1("CSR: %s: NtListenPort(SB) failed (Status=0x%08lx)\n",
286 __FUNCTION__, Status);
287 } else {
288 DPRINT("-- 1\n");
289 Status = NtAcceptConnectPort (& hConnectedPort,
290 hSbApiPortListen,
291 NULL,
292 TRUE,
293 NULL,
294 NULL);
295 if(!NT_SUCCESS(Status))
296 {
297 DPRINT1("CSR: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n",
298 __FUNCTION__, Status);
299 } else {
300 DPRINT("-- 2\n");
301 Status = NtCompleteConnectPort (hConnectedPort);
302 if(!NT_SUCCESS(Status))
303 {
304 DPRINT1("CSR: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n",
305 __FUNCTION__, Status);
306 } else {
307 DPRINT("-- 3\n");
308 PLPC_MESSAGE Reply = NULL;
309 /*
310 * Tell the init thread the SM gave the
311 * green light for boostrapping.
312 */
313 Status = NtSetEvent (hBootstrapOk, NULL);
314 if(!NT_SUCCESS(Status))
315 {
316 DPRINT1("CSR: %s: NtSetEvent failed (Status=0x%08lx)\n",
317 __FUNCTION__, Status);
318 }
319 /* Wait for messages from the SM */
320 DPRINT("-- 4\n");
321 while (TRUE)
322 {
323 Status = NtReplyWaitReceivePort(hConnectedPort,
324 Context,
325 Reply,
326 & Request.Header);
327 if(!NT_SUCCESS(Status))
328 {
329 DPRINT1("CSR: %s: NtReplyWaitReceivePort failed (Status=0x%08lx)\n",
330 __FUNCTION__, Status);
331 break;
332 }
333 switch (Request.Header.MessageType)//fix .h PORT_MESSAGE_TYPE(Request))
334 {
335 /* TODO */
336 default:
337 DPRINT1("CSR: %s received message (type=%d)\n",
338 __FUNCTION__, Request.Header.MessageType);
339 }
340 DPRINT("-- 5\n");
341 }
342 }
343 }
344 }
345 DPRINT1("CSR: %s: terminating!\n", __FUNCTION__);
346 if(hConnectedPort) NtClose (hConnectedPort);
347 NtClose (hSbApiPortListen);
348 NtTerminateThread (NtCurrentThread(), Status);
349 return 0;
350 }
351
352 /* EOF */