- Fix mixed tab/space formatting issues.
[reactos.git] / reactos / lib / ntdll / csr / connect.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: lib/ntdll/csr/connect.c
5 * PURPOSE: Routines for connecting and calling CSR
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntdll.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 HANDLE CsrApiPort;
18 HANDLE CsrProcessId;
19 HANDLE CsrPortHeap;
20 ULONG_PTR CsrPortMemoryDelta;
21 BOOLEAN InsideCsrProcess = FALSE;
22 BOOLEAN UsingOldCsr = TRUE;
23
24 typedef NTSTATUS
25 (NTAPI *PCSR_SERVER_API_ROUTINE)(IN PPORT_MESSAGE Request,
26 IN PPORT_MESSAGE Reply);
27
28 PCSR_SERVER_API_ROUTINE CsrServerApiRoutine;
29
30 #define UNICODE_PATH_SEP L"\\"
31 #define CSR_PORT_NAME L"ApiPort"
32
33 /* FUNCTIONS *****************************************************************/
34
35 /*
36 * @implemented
37 */
38 HANDLE
39 NTAPI
40 CsrGetProcessId(VOID)
41 {
42 return CsrProcessId;
43 }
44
45 /*
46 * @implemented
47 */
48 NTSTATUS
49 NTAPI
50 CsrClientCallServer(PCSR_API_MESSAGE ApiMessage,
51 PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL,
52 CSR_API_NUMBER ApiNumber,
53 ULONG RequestLength)
54 {
55 NTSTATUS Status;
56 ULONG PointerCount;
57 PULONG_PTR Pointers;
58 ULONG_PTR CurrentPointer;
59 DPRINT("CsrClientCallServer\n");
60
61 /* Fill out the Port Message Header */
62 ApiMessage->Header.u1.s1.DataLength = RequestLength - sizeof(PORT_MESSAGE);
63 ApiMessage->Header.u1.s1.TotalLength = RequestLength;
64
65 /* Fill out the CSR Header */
66 ApiMessage->Type = ApiNumber;
67 //ApiMessage->Opcode = ApiNumber; <- Activate with new CSR
68 ApiMessage->CsrCaptureData = NULL;
69
70 DPRINT("API: %x, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n",
71 ApiNumber,
72 ApiMessage->Header.u1.s1.DataLength,
73 ApiMessage->Header.u1.s1.TotalLength);
74
75 /* Check if we are already inside a CSR Server */
76 if (!InsideCsrProcess)
77 {
78 /* Check if we got a a Capture Buffer */
79 if (CaptureBuffer)
80 {
81 /* We have to convert from our local view to the remote view */
82 DPRINT1("Converting CaptureBuffer\n");
83 ApiMessage->CsrCaptureData = (PVOID)((ULONG_PTR)CaptureBuffer +
84 CsrPortMemoryDelta);
85
86 /* Lock the buffer */
87 CaptureBuffer->BufferEnd = 0;
88
89 /* Get the pointer information */
90 PointerCount = CaptureBuffer->PointerCount;
91 Pointers = CaptureBuffer->PointerArray;
92
93 /* Loop through every pointer and convert it */
94 while (PointerCount--)
95 {
96 /* Get this pointer and check if it's valid */
97 if ((CurrentPointer = *Pointers++))
98 {
99 /* Update it */
100 *(PULONG_PTR)CurrentPointer += CsrPortMemoryDelta;
101 Pointers[-1] = CurrentPointer - (ULONG_PTR)ApiMessage;
102 }
103 }
104 }
105
106 /* Send the LPC Message */
107 Status = NtRequestWaitReplyPort(CsrApiPort,
108 &ApiMessage->Header,
109 &ApiMessage->Header);
110
111 /* Check if we got a a Capture Buffer */
112 if (CaptureBuffer)
113 {
114 /* We have to convert from the remote view to our remote view */
115 DPRINT1("Reconverting CaptureBuffer\n");
116 ApiMessage->CsrCaptureData = (PVOID)((ULONG_PTR)
117 ApiMessage->CsrCaptureData -
118 CsrPortMemoryDelta);
119
120 /* Get the pointer information */
121 PointerCount = CaptureBuffer->PointerCount;
122 Pointers = CaptureBuffer->PointerArray;
123
124 /* Loop through every pointer and convert it */
125 while (PointerCount--)
126 {
127 /* Get this pointer and check if it's valid */
128 if ((CurrentPointer = *Pointers++))
129 {
130 /* Update it */
131 CurrentPointer += (ULONG_PTR)ApiMessage;
132 Pointers[-1] = CurrentPointer;
133 *(PULONG_PTR)CurrentPointer -= CsrPortMemoryDelta;
134 }
135 }
136 }
137
138 /* Check for success */
139 if (!NT_SUCCESS(Status))
140 {
141 /* We failed. Overwrite the return value with the failure */
142 DPRINT1("LPC Failed: %lx\n", Status);
143 ApiMessage->Status = Status;
144 }
145 }
146 else
147 {
148 /* This is a server-to-server call. Save our CID and do a direct call */
149 DbgBreakPoint();
150 ApiMessage->Header.ClientId = NtCurrentTeb()->Cid;
151 Status = CsrServerApiRoutine(&ApiMessage->Header,
152 &ApiMessage->Header);
153
154 /* Check for success */
155 if (!NT_SUCCESS(Status))
156 {
157 /* We failed. Overwrite the return value with the failure */
158 ApiMessage->Status = Status;
159 }
160 }
161
162 /* Return the CSR Result */
163 DPRINT("Got back: %x\n", ApiMessage->Status);
164 return ApiMessage->Status;
165 }
166
167 NTSTATUS
168 NTAPI
169 CsrConnectToServer(IN PWSTR ObjectDirectory)
170 {
171 ULONG PortNameLength;
172 UNICODE_STRING PortName;
173 LARGE_INTEGER CsrSectionViewSize;
174 NTSTATUS Status;
175 HANDLE CsrSectionHandle;
176 PORT_VIEW LpcWrite;
177 REMOTE_PORT_VIEW LpcRead;
178 SECURITY_QUALITY_OF_SERVICE SecurityQos;
179 SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
180 PSID SystemSid = NULL;
181 CSR_CONNECTION_INFO ConnectionInfo;
182 ULONG ConnectionInfoLength = sizeof(CSR_CONNECTION_INFO);
183
184 DPRINT("%s(%S)\n", __FUNCTION__, ObjectDirectory);
185
186 /* Binary compatibility with MS KERNEL32 */
187 if (NULL == ObjectDirectory)
188 {
189 ObjectDirectory = L"\\Windows";
190 }
191
192 /* Calculate the total port name size */
193 PortNameLength = ((wcslen(ObjectDirectory) + 1) * sizeof(WCHAR)) +
194 sizeof(CSR_PORT_NAME);
195
196 /* Set the port name */
197 PortName.Length = 0;
198 PortName.MaximumLength = PortNameLength;
199
200 /* Allocate a buffer for it */
201 PortName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PortNameLength);
202
203 /* Create the name */
204 RtlAppendUnicodeToString(&PortName, ObjectDirectory );
205 RtlAppendUnicodeToString(&PortName, UNICODE_PATH_SEP);
206 RtlAppendUnicodeToString(&PortName, CSR_PORT_NAME);
207
208 /* Create a section for the port memory */
209 CsrSectionViewSize.QuadPart = CSR_CSRSS_SECTION_SIZE;
210 Status = NtCreateSection(&CsrSectionHandle,
211 SECTION_ALL_ACCESS,
212 NULL,
213 &CsrSectionViewSize,
214 PAGE_READWRITE,
215 SEC_COMMIT,
216 NULL);
217 if (!NT_SUCCESS(Status))
218 {
219 DPRINT1("Failure allocating CSR Section\n");
220 return Status;
221 }
222
223 /* Set up the port view structures to match them with the section */
224 LpcWrite.Length = sizeof(PORT_VIEW);
225 LpcWrite.SectionHandle = CsrSectionHandle;
226 LpcWrite.SectionOffset = 0;
227 LpcWrite.ViewSize = CsrSectionViewSize.u.LowPart;
228 LpcWrite.ViewBase = 0;
229 LpcWrite.ViewRemoteBase = 0;
230 LpcRead.Length = sizeof(REMOTE_PORT_VIEW);
231 LpcRead.ViewSize = 0;
232 LpcRead.ViewBase = 0;
233
234 /* Setup the QoS */
235 SecurityQos.ImpersonationLevel = SecurityImpersonation;
236 SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
237 SecurityQos.EffectiveOnly = TRUE;
238
239 /* Setup the connection info */
240 ConnectionInfo.Version = 0x10000;
241
242 /* Create a SID for us */
243 Status = RtlAllocateAndInitializeSid(&NtSidAuthority,
244 1,
245 SECURITY_LOCAL_SYSTEM_RID,
246 0,
247 0,
248 0,
249 0,
250 0,
251 0,
252 0,
253 &SystemSid);
254
255 /* Connect to the port */
256 Status = NtSecureConnectPort(&CsrApiPort,
257 &PortName,
258 &SecurityQos,
259 &LpcWrite,
260 SystemSid,
261 &LpcRead,
262 NULL,
263 &ConnectionInfo,
264 &ConnectionInfoLength);
265 NtClose(CsrSectionHandle);
266 if (!NT_SUCCESS(Status))
267 {
268 /* Failure */
269 DPRINT1("Couldn't connect to CSR port\n");
270 return Status;
271 }
272
273 /* Save the delta between the sections, for capture usage later */
274 CsrPortMemoryDelta = (ULONG_PTR)LpcWrite.ViewRemoteBase -
275 (ULONG_PTR)LpcWrite.ViewBase;
276
277 /* Save the Process */
278 CsrProcessId = ConnectionInfo.ProcessId;
279
280 /* Save CSR Section data */
281 NtCurrentPeb()->ReadOnlySharedMemoryBase = ConnectionInfo.SharedSectionBase;
282 NtCurrentPeb()->ReadOnlySharedMemoryHeap = ConnectionInfo.SharedSectionHeap;
283 NtCurrentPeb()->ReadOnlyStaticServerData = ConnectionInfo.SharedSectionData;
284
285 /* Create the port heap */
286 CsrPortHeap = RtlCreateHeap(0,
287 LpcWrite.ViewBase,
288 LpcWrite.ViewSize,
289 PAGE_SIZE,
290 0,
291 0);
292
293 /* Return success */
294 return STATUS_SUCCESS;
295 }
296
297 /*
298 * @implemented
299 */
300 NTSTATUS
301 NTAPI
302 CsrClientConnectToServer(PWSTR ObjectDirectory,
303 ULONG ServerId,
304 PVOID ConnectionInfo,
305 PULONG ConnectionInfoSize,
306 PBOOLEAN ServerToServerCall)
307 {
308 NTSTATUS Status;
309 PIMAGE_NT_HEADERS NtHeader;
310 UNICODE_STRING CsrSrvName;
311 HANDLE hCsrSrv;
312 ANSI_STRING CsrServerRoutineName;
313 PCSR_CAPTURE_BUFFER CaptureBuffer;
314 CSR_API_MESSAGE RosApiMessage;
315 CSR_API_MESSAGE2 ApiMessage;
316 PCSR_CLIENT_CONNECT ClientConnect = &ApiMessage.ClientConnect;
317
318 /* Validate the Connection Info */
319 DPRINT("CsrClientConnectToServer: %lx %p\n", ServerId, ConnectionInfo);
320 if (ConnectionInfo && (!ConnectionInfoSize || !*ConnectionInfoSize))
321 {
322 DPRINT1("Connection info given, but no length\n");
323 return STATUS_INVALID_PARAMETER;
324 }
325
326 /* Check if we're inside a CSR Process */
327 if (InsideCsrProcess)
328 {
329 /* Tell the client that we're already inside CSR */
330 if (ServerToServerCall) *ServerToServerCall = TRUE;
331 return STATUS_SUCCESS;
332 }
333
334 /*
335 * We might be in a CSR Process but not know it, if this is the first call.
336 * So let's find out.
337 */
338 if (!(NtHeader = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress)))
339 {
340 /* The image isn't valid */
341 DPRINT1("Invalid image\n");
342 return STATUS_INVALID_IMAGE_FORMAT;
343 }
344 InsideCsrProcess = (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE);
345
346 /* Now we can check if we are inside or not */
347 if (InsideCsrProcess && !UsingOldCsr)
348 {
349 /* We're inside, so let's find csrsrv */
350 DbgBreakPoint();
351 RtlInitUnicodeString(&CsrSrvName, L"csrsrv");
352 Status = LdrGetDllHandle(NULL,
353 NULL,
354 &CsrSrvName,
355 &hCsrSrv);
356 RtlFreeUnicodeString(&CsrSrvName);
357
358 /* Now get the Server to Server routine */
359 RtlInitAnsiString(&CsrServerRoutineName, "CsrCallServerFromServer");
360 Status = LdrGetProcedureAddress(hCsrSrv,
361 &CsrServerRoutineName,
362 0L,
363 (PVOID*)&CsrServerApiRoutine);
364
365 /* Use the local heap as port heap */
366 CsrPortHeap = RtlGetProcessHeap();
367
368 /* Tell the caller we're inside the server */
369 *ServerToServerCall = InsideCsrProcess;
370 return STATUS_SUCCESS;
371 }
372
373 /* Now check if connection info is given */
374 if (ConnectionInfo)
375 {
376 /* Well, we're defintely in a client now */
377 InsideCsrProcess = FALSE;
378
379 /* Do we have a connection to CSR yet? */
380 if (!CsrApiPort)
381 {
382 /* No, set it up now */
383 if (!NT_SUCCESS(Status = CsrConnectToServer(ObjectDirectory)))
384 {
385 /* Failed */
386 DPRINT1("Failure to connect to CSR\n");
387 return Status;
388 }
389 }
390
391 /* Setup the connect message header */
392 ClientConnect->ServerId = ServerId;
393 ClientConnect->ConnectionInfoSize = *ConnectionInfoSize;
394
395 /* Setup a buffer for the connection info */
396 CaptureBuffer = CsrAllocateCaptureBuffer(1,
397 ClientConnect->ConnectionInfoSize);
398
399 /* Allocate a pointer for the connection info*/
400 CsrAllocateMessagePointer(CaptureBuffer,
401 ClientConnect->ConnectionInfoSize,
402 &ClientConnect->ConnectionInfo);
403
404 /* Copy the data into the buffer */
405 RtlMoveMemory(ClientConnect->ConnectionInfo,
406 ConnectionInfo,
407 ClientConnect->ConnectionInfoSize);
408
409 /* Return the allocated length */
410 *ConnectionInfoSize = ClientConnect->ConnectionInfoSize;
411
412 /* Call CSR */
413 #if 0
414 Status = CsrClientCallServer(&ApiMessage,
415 CaptureBuffer,
416 CSR_MAKE_OPCODE(CsrSrvClientConnect,
417 CSR_SRV_DLL),
418 sizeof(CSR_CLIENT_CONNECT));
419 #endif
420 Status = CsrClientCallServer(&RosApiMessage,
421 NULL,
422 MAKE_CSR_API(CONNECT_PROCESS, CSR_NATIVE),
423 sizeof(CSR_API_MESSAGE));
424 }
425 else
426 {
427 /* No connection info, just return */
428 Status = STATUS_SUCCESS;
429 }
430
431 /* Let the caller know if this was server to server */
432 DPRINT("Status was: %lx. Are we in server: %lx\n", Status, InsideCsrProcess);
433 if (ServerToServerCall) *ServerToServerCall = InsideCsrProcess;
434 return Status;
435 }
436
437 /* EOF */