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