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