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