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
;
22 BOOLEAN UsingOldCsr
= TRUE
;
25 (NTAPI
*PCSR_SERVER_API_ROUTINE
)(IN PPORT_MESSAGE Request
,
26 IN PPORT_MESSAGE Reply
);
28 PCSR_SERVER_API_ROUTINE CsrServerApiRoutine
;
30 #define UNICODE_PATH_SEP L"\\"
31 #define CSR_PORT_NAME L"ApiPort"
33 /* FUNCTIONS *****************************************************************/
50 CsrClientCallServer(PCSR_API_MESSAGE ApiMessage
,
51 PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL
,
52 CSR_API_NUMBER ApiNumber
,
58 ULONG_PTR CurrentPointer
;
59 DPRINT("CsrClientCallServer\n");
61 /* Fill out the Port Message Header */
62 ApiMessage
->Header
.u1
.s1
.DataLength
= RequestLength
- sizeof(PORT_MESSAGE
);
63 ApiMessage
->Header
.u1
.s1
.TotalLength
= RequestLength
;
65 /* Fill out the CSR Header */
66 ApiMessage
->Type
= ApiNumber
;
67 //ApiMessage->Opcode = ApiNumber; <- Activate with new CSR
68 ApiMessage
->CsrCaptureData
= NULL
;
70 DPRINT("API: %lx, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n",
72 ApiMessage
->Header
.u1
.s1
.DataLength
,
73 ApiMessage
->Header
.u1
.s1
.TotalLength
);
75 /* Check if we are already inside a CSR Server */
76 if (!InsideCsrProcess
)
78 /* Check if we got a a Capture Buffer */
81 /* We have to convert from our local view to the remote view */
82 ApiMessage
->CsrCaptureData
= (PVOID
)((ULONG_PTR
)CaptureBuffer
+
86 CaptureBuffer
->BufferEnd
= 0;
88 /* Get the pointer information */
89 PointerCount
= CaptureBuffer
->PointerCount
;
90 Pointers
= CaptureBuffer
->PointerArray
;
92 /* Loop through every pointer and convert it */
93 DPRINT("PointerCount: %lx\n", PointerCount
);
94 while (PointerCount
--)
96 /* Get this pointer and check if it's valid */
97 DPRINT("Array Address: %p. This pointer: %p. Data: %lx\n",
98 &Pointers
, Pointers
, *Pointers
);
99 if ((CurrentPointer
= *Pointers
++))
102 DPRINT("CurrentPointer: %lx.\n", *(PULONG_PTR
)CurrentPointer
);
103 *(PULONG_PTR
)CurrentPointer
+= CsrPortMemoryDelta
;
104 Pointers
[-1] = CurrentPointer
- (ULONG_PTR
)ApiMessage
;
105 DPRINT("CurrentPointer: %lx.\n", *(PULONG_PTR
)CurrentPointer
);
110 /* Send the LPC Message */
111 Status
= NtRequestWaitReplyPort(CsrApiPort
,
113 &ApiMessage
->Header
);
115 /* Check if we got a a Capture Buffer */
118 /* We have to convert from the remote view to our remote view */
119 DPRINT("Reconverting CaptureBuffer\n");
120 ApiMessage
->CsrCaptureData
= (PVOID
)((ULONG_PTR
)
121 ApiMessage
->CsrCaptureData
-
124 /* Get the pointer information */
125 PointerCount
= CaptureBuffer
->PointerCount
;
126 Pointers
= CaptureBuffer
->PointerArray
;
128 /* Loop through every pointer and convert it */
129 while (PointerCount
--)
131 /* Get this pointer and check if it's valid */
132 if ((CurrentPointer
= *Pointers
++))
135 CurrentPointer
+= (ULONG_PTR
)ApiMessage
;
136 Pointers
[-1] = CurrentPointer
;
137 *(PULONG_PTR
)CurrentPointer
-= CsrPortMemoryDelta
;
142 /* Check for success */
143 if (!NT_SUCCESS(Status
))
145 /* We failed. Overwrite the return value with the failure */
146 DPRINT1("LPC Failed: %lx\n", Status
);
147 ApiMessage
->Status
= Status
;
152 /* This is a server-to-server call. Save our CID and do a direct call */
154 ApiMessage
->Header
.ClientId
= NtCurrentTeb()->Cid
;
155 Status
= CsrServerApiRoutine(&ApiMessage
->Header
,
156 &ApiMessage
->Header
);
158 /* Check for success */
159 if (!NT_SUCCESS(Status
))
161 /* We failed. Overwrite the return value with the failure */
162 ApiMessage
->Status
= Status
;
166 /* Return the CSR Result */
167 DPRINT("Got back: 0x%lx\n", ApiMessage
->Status
);
168 return ApiMessage
->Status
;
173 CsrConnectToServer(IN PWSTR ObjectDirectory
)
175 ULONG PortNameLength
;
176 UNICODE_STRING PortName
;
177 LARGE_INTEGER CsrSectionViewSize
;
179 HANDLE CsrSectionHandle
;
181 REMOTE_PORT_VIEW LpcRead
;
182 SECURITY_QUALITY_OF_SERVICE SecurityQos
;
183 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
184 PSID SystemSid
= NULL
;
185 CSR_CONNECTION_INFO ConnectionInfo
;
186 ULONG ConnectionInfoLength
= sizeof(CSR_CONNECTION_INFO
);
188 DPRINT("%s(%S)\n", __FUNCTION__
, ObjectDirectory
);
190 /* Binary compatibility with MS KERNEL32 */
191 if (NULL
== ObjectDirectory
)
193 ObjectDirectory
= L
"\\Windows";
196 /* Calculate the total port name size */
197 PortNameLength
= ((wcslen(ObjectDirectory
) + 1) * sizeof(WCHAR
)) +
198 sizeof(CSR_PORT_NAME
);
200 /* Set the port name */
202 PortName
.MaximumLength
= PortNameLength
;
204 /* Allocate a buffer for it */
205 PortName
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, PortNameLength
);
207 /* Create the name */
208 RtlAppendUnicodeToString(&PortName
, ObjectDirectory
);
209 RtlAppendUnicodeToString(&PortName
, UNICODE_PATH_SEP
);
210 RtlAppendUnicodeToString(&PortName
, CSR_PORT_NAME
);
212 /* Create a section for the port memory */
213 CsrSectionViewSize
.QuadPart
= CSR_CSRSS_SECTION_SIZE
;
214 Status
= NtCreateSection(&CsrSectionHandle
,
221 if (!NT_SUCCESS(Status
))
223 DPRINT1("Failure allocating CSR Section\n");
227 /* Set up the port view structures to match them with the section */
228 LpcWrite
.Length
= sizeof(PORT_VIEW
);
229 LpcWrite
.SectionHandle
= CsrSectionHandle
;
230 LpcWrite
.SectionOffset
= 0;
231 LpcWrite
.ViewSize
= CsrSectionViewSize
.u
.LowPart
;
232 LpcWrite
.ViewBase
= 0;
233 LpcWrite
.ViewRemoteBase
= 0;
234 LpcRead
.Length
= sizeof(REMOTE_PORT_VIEW
);
235 LpcRead
.ViewSize
= 0;
236 LpcRead
.ViewBase
= 0;
239 SecurityQos
.ImpersonationLevel
= SecurityImpersonation
;
240 SecurityQos
.ContextTrackingMode
= SECURITY_DYNAMIC_TRACKING
;
241 SecurityQos
.EffectiveOnly
= TRUE
;
243 /* Setup the connection info */
244 ConnectionInfo
.Version
= 0x10000;
246 /* Create a SID for us */
247 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
,
249 SECURITY_LOCAL_SYSTEM_RID
,
259 /* Connect to the port */
260 Status
= NtSecureConnectPort(&CsrApiPort
,
268 &ConnectionInfoLength
);
269 NtClose(CsrSectionHandle
);
270 if (!NT_SUCCESS(Status
))
273 DPRINT1("Couldn't connect to CSR port\n");
277 /* Save the delta between the sections, for capture usage later */
278 CsrPortMemoryDelta
= (ULONG_PTR
)LpcWrite
.ViewRemoteBase
-
279 (ULONG_PTR
)LpcWrite
.ViewBase
;
281 /* Save the Process */
282 CsrProcessId
= ConnectionInfo
.ProcessId
;
284 /* Save CSR Section data */
285 NtCurrentPeb()->ReadOnlySharedMemoryBase
= ConnectionInfo
.SharedSectionBase
;
286 NtCurrentPeb()->ReadOnlySharedMemoryHeap
= ConnectionInfo
.SharedSectionHeap
;
287 NtCurrentPeb()->ReadOnlyStaticServerData
= ConnectionInfo
.SharedSectionData
;
289 /* Create the port heap */
290 CsrPortHeap
= RtlCreateHeap(0,
298 return STATUS_SUCCESS
;
306 CsrClientConnectToServer(PWSTR ObjectDirectory
,
308 PVOID ConnectionInfo
,
309 PULONG ConnectionInfoSize
,
310 PBOOLEAN ServerToServerCall
)
313 PIMAGE_NT_HEADERS NtHeader
;
314 UNICODE_STRING CsrSrvName
;
316 ANSI_STRING CsrServerRoutineName
;
317 PCSR_CAPTURE_BUFFER CaptureBuffer
;
318 CSR_API_MESSAGE RosApiMessage
;
319 CSR_API_MESSAGE2 ApiMessage
;
320 PCSR_CLIENT_CONNECT ClientConnect
= &ApiMessage
.ClientConnect
;
322 /* Validate the Connection Info */
323 DPRINT("CsrClientConnectToServer: %lx %p\n", ServerId
, ConnectionInfo
);
324 if (ConnectionInfo
&& (!ConnectionInfoSize
|| !*ConnectionInfoSize
))
326 DPRINT1("Connection info given, but no length\n");
327 return STATUS_INVALID_PARAMETER
;
330 /* Check if we're inside a CSR Process */
331 if (InsideCsrProcess
)
333 /* Tell the client that we're already inside CSR */
334 if (ServerToServerCall
) *ServerToServerCall
= TRUE
;
335 return STATUS_SUCCESS
;
339 * We might be in a CSR Process but not know it, if this is the first call.
342 if (!(NtHeader
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
)))
344 /* The image isn't valid */
345 DPRINT1("Invalid image\n");
346 return STATUS_INVALID_IMAGE_FORMAT
;
348 InsideCsrProcess
= (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
);
350 /* Now we can check if we are inside or not */
351 if (InsideCsrProcess
&& !UsingOldCsr
)
353 /* We're inside, so let's find csrsrv */
355 RtlInitUnicodeString(&CsrSrvName
, L
"csrsrv");
356 Status
= LdrGetDllHandle(NULL
,
360 RtlFreeUnicodeString(&CsrSrvName
);
362 /* Now get the Server to Server routine */
363 RtlInitAnsiString(&CsrServerRoutineName
, "CsrCallServerFromServer");
364 Status
= LdrGetProcedureAddress(hCsrSrv
,
365 &CsrServerRoutineName
,
367 (PVOID
*)&CsrServerApiRoutine
);
369 /* Use the local heap as port heap */
370 CsrPortHeap
= RtlGetProcessHeap();
372 /* Tell the caller we're inside the server */
373 *ServerToServerCall
= InsideCsrProcess
;
374 return STATUS_SUCCESS
;
377 /* Now check if connection info is given */
380 /* Well, we're defintely in a client now */
381 InsideCsrProcess
= FALSE
;
383 /* Do we have a connection to CSR yet? */
386 /* No, set it up now */
387 if (!NT_SUCCESS(Status
= CsrConnectToServer(ObjectDirectory
)))
390 DPRINT1("Failure to connect to CSR\n");
395 /* Setup the connect message header */
396 ClientConnect
->ServerId
= ServerId
;
397 ClientConnect
->ConnectionInfoSize
= *ConnectionInfoSize
;
399 /* Setup a buffer for the connection info */
400 CaptureBuffer
= CsrAllocateCaptureBuffer(1,
401 ClientConnect
->ConnectionInfoSize
);
403 /* Allocate a pointer for the connection info*/
404 CsrAllocateMessagePointer(CaptureBuffer
,
405 ClientConnect
->ConnectionInfoSize
,
406 &ClientConnect
->ConnectionInfo
);
408 /* Copy the data into the buffer */
409 RtlMoveMemory(ClientConnect
->ConnectionInfo
,
411 ClientConnect
->ConnectionInfoSize
);
413 /* Return the allocated length */
414 *ConnectionInfoSize
= ClientConnect
->ConnectionInfoSize
;
418 Status
= CsrClientCallServer(&ApiMessage
,
420 CSR_MAKE_OPCODE(CsrSrvClientConnect
,
422 sizeof(CSR_CLIENT_CONNECT
));
424 Status
= CsrClientCallServer(&RosApiMessage
,
426 MAKE_CSR_API(CONNECT_PROCESS
, CSR_NATIVE
),
427 sizeof(CSR_API_MESSAGE
));
431 /* No connection info, just return */
432 Status
= STATUS_SUCCESS
;
435 /* Let the caller know if this was server to server */
436 DPRINT("Status was: 0x%lx. Are we in server: 0x%x\n", Status
, InsideCsrProcess
);
437 if (ServerToServerCall
) *ServerToServerCall
= InsideCsrProcess
;