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)
9 /* INCLUDES *****************************************************************/
15 /* GLOBALS *******************************************************************/
20 ULONG_PTR CsrPortMemoryDelta
;
21 BOOLEAN InsideCsrProcess
= FALSE
;
24 (NTAPI
*PCSR_SERVER_API_ROUTINE
)(IN PPORT_MESSAGE Request
,
25 IN PPORT_MESSAGE Reply
);
27 PCSR_SERVER_API_ROUTINE CsrServerApiRoutine
;
29 #define UNICODE_PATH_SEP L"\\"
31 /* FUNCTIONS *****************************************************************/
48 CsrClientCallServer(PCSR_API_MESSAGE ApiMessage
,
49 PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL
,
50 CSR_API_NUMBER ApiNumber
,
56 ULONG_PTR CurrentPointer
;
57 DPRINT("CsrClientCallServer\n");
59 /* Fill out the Port Message Header */
60 ApiMessage
->Header
.u2
.ZeroInit
= 0;
61 ApiMessage
->Header
.u1
.s1
.DataLength
= RequestLength
- sizeof(PORT_MESSAGE
);
62 ApiMessage
->Header
.u1
.s1
.TotalLength
= RequestLength
;
64 /* Fill out the CSR Header */
65 ApiMessage
->ApiNumber
= ApiNumber
;
66 ApiMessage
->CsrCaptureData
= NULL
;
68 DPRINT("API: %lx, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n",
70 ApiMessage
->Header
.u1
.s1
.DataLength
,
71 ApiMessage
->Header
.u1
.s1
.TotalLength
);
73 /* Check if we are already inside a CSR Server */
74 if (!InsideCsrProcess
)
76 /* Check if we got a a Capture Buffer */
79 /* We have to convert from our local view to the remote view */
80 ApiMessage
->CsrCaptureData
= (PVOID
)((ULONG_PTR
)CaptureBuffer
+
84 CaptureBuffer
->BufferEnd
= 0;
86 /* Get the pointer information */
87 PointerCount
= CaptureBuffer
->PointerCount
;
88 Pointers
= CaptureBuffer
->PointerArray
;
90 /* Loop through every pointer and convert it */
91 DPRINT("PointerCount: %lx\n", PointerCount
);
92 while (PointerCount
--)
94 /* Get this pointer and check if it's valid */
95 DPRINT("Array Address: %p. This pointer: %p. Data: %lx\n",
96 &Pointers
, Pointers
, *Pointers
);
97 if ((CurrentPointer
= *Pointers
++))
100 DPRINT("CurrentPointer: %lx.\n", *(PULONG_PTR
)CurrentPointer
);
101 *(PULONG_PTR
)CurrentPointer
+= CsrPortMemoryDelta
;
102 Pointers
[-1] = CurrentPointer
- (ULONG_PTR
)ApiMessage
;
103 DPRINT("CurrentPointer: %lx.\n", *(PULONG_PTR
)CurrentPointer
);
108 /* Send the LPC Message */
109 Status
= NtRequestWaitReplyPort(CsrApiPort
,
111 &ApiMessage
->Header
);
113 /* Check if we got a a Capture Buffer */
116 /* We have to convert from the remote view to our remote view */
117 DPRINT("Reconverting CaptureBuffer\n");
118 ApiMessage
->CsrCaptureData
= (PVOID
)((ULONG_PTR
)
119 ApiMessage
->CsrCaptureData
-
122 /* Get the pointer information */
123 PointerCount
= CaptureBuffer
->PointerCount
;
124 Pointers
= CaptureBuffer
->PointerArray
;
126 /* Loop through every pointer and convert it */
127 while (PointerCount
--)
129 /* Get this pointer and check if it's valid */
130 if ((CurrentPointer
= *Pointers
++))
133 CurrentPointer
+= (ULONG_PTR
)ApiMessage
;
134 Pointers
[-1] = CurrentPointer
;
135 *(PULONG_PTR
)CurrentPointer
-= CsrPortMemoryDelta
;
140 /* Check for success */
141 if (!NT_SUCCESS(Status
))
143 /* We failed. Overwrite the return value with the failure */
144 DPRINT1("LPC Failed: %lx\n", Status
);
145 ApiMessage
->Status
= Status
;
150 /* This is a server-to-server call. Save our CID and do a direct call */
151 DPRINT1("Next gen server-to-server call\n");
152 ApiMessage
->Header
.ClientId
= NtCurrentTeb()->ClientId
;
153 Status
= CsrServerApiRoutine(&ApiMessage
->Header
,
154 &ApiMessage
->Header
);
156 /* Check for success */
157 if (!NT_SUCCESS(Status
))
159 /* We failed. Overwrite the return value with the failure */
160 ApiMessage
->Status
= Status
;
164 /* Return the CSR Result */
165 DPRINT("Got back: 0x%lx\n", ApiMessage
->Status
);
166 return ApiMessage
->Status
;
171 CsrConnectToServer(IN PWSTR ObjectDirectory
)
173 ULONG PortNameLength
;
174 UNICODE_STRING PortName
;
175 LARGE_INTEGER CsrSectionViewSize
;
177 HANDLE CsrSectionHandle
;
179 REMOTE_PORT_VIEW LpcRead
;
180 SECURITY_QUALITY_OF_SERVICE SecurityQos
;
181 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
182 PSID SystemSid
= NULL
;
183 CSR_CONNECTION_INFO ConnectionInfo
;
184 ULONG ConnectionInfoLength
= sizeof(CSR_CONNECTION_INFO
);
186 DPRINT("%s(%S)\n", __FUNCTION__
, ObjectDirectory
);
188 /* Binary compatibility with MS KERNEL32 */
189 if (NULL
== ObjectDirectory
)
191 ObjectDirectory
= L
"\\Windows";
194 /* Calculate the total port name size */
195 PortNameLength
= ((wcslen(ObjectDirectory
) + 1) * sizeof(WCHAR
)) +
196 sizeof(CSR_PORT_NAME
);
198 /* Set the port name */
200 PortName
.MaximumLength
= PortNameLength
;
202 /* Allocate a buffer for it */
203 PortName
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, PortNameLength
);
204 if (PortName
.Buffer
== NULL
)
206 return STATUS_INSUFFICIENT_RESOURCES
;
209 /* Create the name */
210 RtlAppendUnicodeToString(&PortName
, ObjectDirectory
);
211 RtlAppendUnicodeToString(&PortName
, UNICODE_PATH_SEP
);
212 RtlAppendUnicodeToString(&PortName
, CSR_PORT_NAME
);
214 /* Create a section for the port memory */
215 CsrSectionViewSize
.QuadPart
= CSR_CSRSS_SECTION_SIZE
;
216 Status
= NtCreateSection(&CsrSectionHandle
,
223 if (!NT_SUCCESS(Status
))
225 DPRINT1("Failure allocating CSR Section\n");
229 /* Set up the port view structures to match them with the section */
230 LpcWrite
.Length
= sizeof(PORT_VIEW
);
231 LpcWrite
.SectionHandle
= CsrSectionHandle
;
232 LpcWrite
.SectionOffset
= 0;
233 LpcWrite
.ViewSize
= CsrSectionViewSize
.u
.LowPart
;
234 LpcWrite
.ViewBase
= 0;
235 LpcWrite
.ViewRemoteBase
= 0;
236 LpcRead
.Length
= sizeof(REMOTE_PORT_VIEW
);
237 LpcRead
.ViewSize
= 0;
238 LpcRead
.ViewBase
= 0;
241 SecurityQos
.ImpersonationLevel
= SecurityImpersonation
;
242 SecurityQos
.ContextTrackingMode
= SECURITY_DYNAMIC_TRACKING
;
243 SecurityQos
.EffectiveOnly
= TRUE
;
245 /* Setup the connection info */
246 ConnectionInfo
.Version
= 0x10000;
248 /* Create a SID for us */
249 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
,
251 SECURITY_LOCAL_SYSTEM_RID
,
260 if (!NT_SUCCESS(Status
))
263 DPRINT1("Couldn't allocate SID\n");
264 NtClose(CsrSectionHandle
);
268 /* Connect to the port */
269 Status
= NtSecureConnectPort(&CsrApiPort
,
277 &ConnectionInfoLength
);
278 NtClose(CsrSectionHandle
);
279 if (!NT_SUCCESS(Status
))
282 DPRINT1("Couldn't connect to CSR port\n");
286 /* Save the delta between the sections, for capture usage later */
287 CsrPortMemoryDelta
= (ULONG_PTR
)LpcWrite
.ViewRemoteBase
-
288 (ULONG_PTR
)LpcWrite
.ViewBase
;
290 /* Save the Process */
291 CsrProcessId
= ConnectionInfo
.ProcessId
;
293 /* Save CSR Section data */
294 NtCurrentPeb()->ReadOnlySharedMemoryBase
= ConnectionInfo
.SharedSectionBase
;
295 NtCurrentPeb()->ReadOnlySharedMemoryHeap
= ConnectionInfo
.SharedSectionHeap
;
296 NtCurrentPeb()->ReadOnlyStaticServerData
= ConnectionInfo
.SharedSectionData
;
298 /* Create the port heap */
299 CsrPortHeap
= RtlCreateHeap(0,
305 if (CsrPortHeap
== NULL
)
309 return STATUS_INSUFFICIENT_RESOURCES
;
313 return STATUS_SUCCESS
;
321 CsrClientConnectToServer(PWSTR ObjectDirectory
,
323 PVOID ConnectionInfo
,
324 PULONG ConnectionInfoSize
,
325 PBOOLEAN ServerToServerCall
)
328 PIMAGE_NT_HEADERS NtHeader
;
329 UNICODE_STRING CsrSrvName
;
331 ANSI_STRING CsrServerRoutineName
;
332 PCSR_CAPTURE_BUFFER CaptureBuffer
;
333 CSR_API_MESSAGE ApiMessage
;
334 PCSR_CLIENT_CONNECT ClientConnect
= &ApiMessage
.Data
.CsrClientConnect
;
336 /* Validate the Connection Info */
337 DPRINT("CsrClientConnectToServer: %lx %p\n", ServerId
, ConnectionInfo
);
338 if (ConnectionInfo
&& (!ConnectionInfoSize
|| !*ConnectionInfoSize
))
340 DPRINT1("Connection info given, but no length\n");
341 return STATUS_INVALID_PARAMETER
;
344 /* Check if we're inside a CSR Process */
345 if (InsideCsrProcess
)
347 /* Tell the client that we're already inside CSR */
348 if (ServerToServerCall
) *ServerToServerCall
= TRUE
;
349 return STATUS_SUCCESS
;
353 * We might be in a CSR Process but not know it, if this is the first call.
356 if (!(NtHeader
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
)))
358 /* The image isn't valid */
359 DPRINT1("Invalid image\n");
360 return STATUS_INVALID_IMAGE_FORMAT
;
362 InsideCsrProcess
= (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
);
364 /* Now we can check if we are inside or not */
365 if (InsideCsrProcess
)
367 /* We're inside, so let's find csrsrv */
368 DPRINT1("Next-GEN CSRSS support\n");
369 RtlInitUnicodeString(&CsrSrvName
, L
"csrsrv");
370 Status
= LdrGetDllHandle(NULL
,
375 /* Now get the Server to Server routine */
376 RtlInitAnsiString(&CsrServerRoutineName
, "CsrCallServerFromServer");
377 Status
= LdrGetProcedureAddress(hCsrSrv
,
378 &CsrServerRoutineName
,
380 (PVOID
*)&CsrServerApiRoutine
);
382 /* Use the local heap as port heap */
383 CsrPortHeap
= RtlGetProcessHeap();
385 /* Tell the caller we're inside the server */
386 *ServerToServerCall
= InsideCsrProcess
;
387 return STATUS_SUCCESS
;
390 /* Now check if connection info is given */
393 /* Well, we're defintely in a client now */
394 InsideCsrProcess
= FALSE
;
396 /* Do we have a connection to CSR yet? */
399 /* No, set it up now */
400 if (!NT_SUCCESS(Status
= CsrConnectToServer(ObjectDirectory
)))
403 DPRINT1("Failure to connect to CSR\n");
408 /* Setup the connect message header */
409 ClientConnect
->ServerId
= ServerId
;
410 ClientConnect
->ConnectionInfoSize
= *ConnectionInfoSize
;
412 /* Setup a buffer for the connection info */
413 CaptureBuffer
= CsrAllocateCaptureBuffer(1,
414 ClientConnect
->ConnectionInfoSize
);
415 if (CaptureBuffer
== NULL
)
417 return STATUS_INSUFFICIENT_RESOURCES
;
420 /* Allocate a pointer for the connection info*/
421 CsrAllocateMessagePointer(CaptureBuffer
,
422 ClientConnect
->ConnectionInfoSize
,
423 &ClientConnect
->ConnectionInfo
);
425 /* Copy the data into the buffer */
426 RtlMoveMemory(ClientConnect
->ConnectionInfo
,
428 ClientConnect
->ConnectionInfoSize
);
430 /* Return the allocated length */
431 *ConnectionInfoSize
= ClientConnect
->ConnectionInfoSize
;
434 Status
= CsrClientCallServer(&ApiMessage
,
436 CSR_CREATE_API_NUMBER(CSR_SRV_DLL
, CsrpClientConnect
),
437 sizeof(CSR_CLIENT_CONNECT
));
439 Status = CsrClientCallServer(&ApiMessage,
441 CSR_CREATE_API_NUMBER(CSR_NATIVE, CONNECT_PROCESS),
442 sizeof(CSR_API_MESSAGE));
447 /* No connection info, just return */
448 Status
= STATUS_SUCCESS
;
451 /* Let the caller know if this was server to server */
452 DPRINT("Status was: 0x%lx. Are we in server: 0x%x\n", Status
, InsideCsrProcess
);
453 if (ServerToServerCall
) *ServerToServerCall
= InsideCsrProcess
;