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: %x, 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 DPRINT1("Converting CaptureBuffer\n");
83 ApiMessage
->CsrCaptureData
= (PVOID
)((ULONG_PTR
)CaptureBuffer
+
87 CaptureBuffer
->BufferEnd
= 0;
89 /* Get the pointer information */
90 PointerCount
= CaptureBuffer
->PointerCount
;
91 Pointers
= CaptureBuffer
->PointerArray
;
93 /* Loop through every pointer and convert it */
94 while (PointerCount
--)
96 /* Get this pointer and check if it's valid */
97 if ((CurrentPointer
= *Pointers
++))
100 *(PULONG_PTR
)CurrentPointer
+= CsrPortMemoryDelta
;
101 Pointers
[-1] = CurrentPointer
- (ULONG_PTR
)ApiMessage
;
106 /* Send the LPC Message */
107 Status
= NtRequestWaitReplyPort(CsrApiPort
,
109 &ApiMessage
->Header
);
111 /* Check if we got a a Capture Buffer */
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
-
120 /* Get the pointer information */
121 PointerCount
= CaptureBuffer
->PointerCount
;
122 Pointers
= CaptureBuffer
->PointerArray
;
124 /* Loop through every pointer and convert it */
125 while (PointerCount
--)
127 /* Get this pointer and check if it's valid */
128 if ((CurrentPointer
= *Pointers
++))
131 CurrentPointer
+= (ULONG_PTR
)ApiMessage
;
132 Pointers
[-1] = CurrentPointer
;
133 *(PULONG_PTR
)CurrentPointer
-= CsrPortMemoryDelta
;
138 /* Check for success */
139 if (!NT_SUCCESS(Status
))
141 /* We failed. Overwrite the return value with the failure */
142 DPRINT1("LPC Failed: %lx\n", Status
);
143 ApiMessage
->Status
= Status
;
148 /* This is a server-to-server call. Save our CID and do a direct call */
150 ApiMessage
->Header
.ClientId
= NtCurrentTeb()->Cid
;
151 Status
= CsrServerApiRoutine(&ApiMessage
->Header
,
152 &ApiMessage
->Header
);
154 /* Check for success */
155 if (!NT_SUCCESS(Status
))
157 /* We failed. Overwrite the return value with the failure */
158 ApiMessage
->Status
= Status
;
162 /* Return the CSR Result */
163 DPRINT("Got back: %x\n", ApiMessage
->Status
);
164 return ApiMessage
->Status
;
169 CsrConnectToServer(IN PWSTR ObjectDirectory
)
171 ULONG PortNameLength
;
172 UNICODE_STRING PortName
;
173 LARGE_INTEGER CsrSectionViewSize
;
175 HANDLE CsrSectionHandle
;
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
);
184 DPRINT("%s(%S)\n", __FUNCTION__
, ObjectDirectory
);
186 /* Binary compatibility with MS KERNEL32 */
187 if (NULL
== ObjectDirectory
)
189 ObjectDirectory
= L
"\\Windows";
192 /* Calculate the total port name size */
193 PortNameLength
= ((wcslen(ObjectDirectory
) + 1) * sizeof(WCHAR
)) +
194 sizeof(CSR_PORT_NAME
);
196 /* Set the port name */
198 PortName
.MaximumLength
= PortNameLength
;
200 /* Allocate a buffer for it */
201 PortName
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, PortNameLength
);
203 /* Create the name */
204 RtlAppendUnicodeToString(&PortName
, ObjectDirectory
);
205 RtlAppendUnicodeToString(&PortName
, UNICODE_PATH_SEP
);
206 RtlAppendUnicodeToString(&PortName
, CSR_PORT_NAME
);
208 /* Create a section for the port memory */
209 CsrSectionViewSize
.QuadPart
= CSR_CSRSS_SECTION_SIZE
;
210 Status
= NtCreateSection(&CsrSectionHandle
,
217 if (!NT_SUCCESS(Status
))
219 DPRINT1("Failure allocating CSR Section\n");
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;
235 SecurityQos
.ImpersonationLevel
= SecurityImpersonation
;
236 SecurityQos
.ContextTrackingMode
= SECURITY_DYNAMIC_TRACKING
;
237 SecurityQos
.EffectiveOnly
= TRUE
;
239 /* Setup the connection info */
240 ConnectionInfo
.Version
= 0x10000;
242 /* Create a SID for us */
243 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
,
245 SECURITY_LOCAL_SYSTEM_RID
,
255 /* Connect to the port */
256 Status
= NtSecureConnectPort(&CsrApiPort
,
264 &ConnectionInfoLength
);
265 NtClose(CsrSectionHandle
);
266 if (!NT_SUCCESS(Status
))
269 DPRINT1("Couldn't connect to CSR port\n");
273 /* Save the delta between the sections, for capture usage later */
274 CsrPortMemoryDelta
= (ULONG_PTR
)LpcWrite
.ViewRemoteBase
-
275 (ULONG_PTR
)LpcWrite
.ViewBase
;
277 /* Save the Process */
278 CsrProcessId
= ConnectionInfo
.ProcessId
;
280 /* Save CSR Section data */
281 NtCurrentPeb()->ReadOnlySharedMemoryBase
= ConnectionInfo
.SharedSectionBase
;
282 NtCurrentPeb()->ReadOnlySharedMemoryHeap
= ConnectionInfo
.SharedSectionHeap
;
283 NtCurrentPeb()->ReadOnlyStaticServerData
= ConnectionInfo
.SharedSectionData
;
285 /* Create the port heap */
286 CsrPortHeap
= RtlCreateHeap(0,
294 return STATUS_SUCCESS
;
302 CsrClientConnectToServer(PWSTR ObjectDirectory
,
304 PVOID ConnectionInfo
,
305 PULONG ConnectionInfoSize
,
306 PBOOLEAN ServerToServerCall
)
309 PIMAGE_NT_HEADERS NtHeader
;
310 UNICODE_STRING CsrSrvName
;
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
;
318 /* Validate the Connection Info */
319 DPRINT("CsrClientConnectToServer: %lx %p\n", ServerId
, ConnectionInfo
);
320 if (ConnectionInfo
&& (!ConnectionInfoSize
|| !*ConnectionInfoSize
))
322 DPRINT1("Connection info given, but no length\n");
323 return STATUS_INVALID_PARAMETER
;
326 /* Check if we're inside a CSR Process */
327 if (InsideCsrProcess
)
329 /* Tell the client that we're already inside CSR */
330 if (ServerToServerCall
) *ServerToServerCall
= TRUE
;
331 return STATUS_SUCCESS
;
335 * We might be in a CSR Process but not know it, if this is the first call.
338 if (!(NtHeader
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
)))
340 /* The image isn't valid */
341 DPRINT1("Invalid image\n");
342 return STATUS_INVALID_IMAGE_FORMAT
;
344 InsideCsrProcess
= (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
);
346 /* Now we can check if we are inside or not */
347 if (InsideCsrProcess
&& !UsingOldCsr
)
349 /* We're inside, so let's find csrsrv */
351 RtlInitUnicodeString(&CsrSrvName
, L
"csrsrv");
352 Status
= LdrGetDllHandle(NULL
,
356 RtlFreeUnicodeString(&CsrSrvName
);
358 /* Now get the Server to Server routine */
359 RtlInitAnsiString(&CsrServerRoutineName
, "CsrCallServerFromServer");
360 Status
= LdrGetProcedureAddress(hCsrSrv
,
361 &CsrServerRoutineName
,
363 (PVOID
*)&CsrServerApiRoutine
);
365 /* Use the local heap as port heap */
366 CsrPortHeap
= RtlGetProcessHeap();
368 /* Tell the caller we're inside the server */
369 *ServerToServerCall
= InsideCsrProcess
;
370 return STATUS_SUCCESS
;
373 /* Now check if connection info is given */
376 /* Well, we're defintely in a client now */
377 InsideCsrProcess
= FALSE
;
379 /* Do we have a connection to CSR yet? */
382 /* No, set it up now */
383 if (!NT_SUCCESS(Status
= CsrConnectToServer(ObjectDirectory
)))
386 DPRINT1("Failure to connect to CSR\n");
391 /* Setup the connect message header */
392 ClientConnect
->ServerId
= ServerId
;
393 ClientConnect
->ConnectionInfoSize
= *ConnectionInfoSize
;
395 /* Setup a buffer for the connection info */
396 CaptureBuffer
= CsrAllocateCaptureBuffer(1,
397 ClientConnect
->ConnectionInfoSize
);
399 /* Allocate a pointer for the connection info*/
400 CsrAllocateMessagePointer(CaptureBuffer
,
401 ClientConnect
->ConnectionInfoSize
,
402 &ClientConnect
->ConnectionInfo
);
404 /* Copy the data into the buffer */
405 RtlMoveMemory(ClientConnect
->ConnectionInfo
,
407 ClientConnect
->ConnectionInfoSize
);
409 /* Return the allocated length */
410 *ConnectionInfoSize
= ClientConnect
->ConnectionInfoSize
;
414 Status
= CsrClientCallServer(&ApiMessage
,
416 CSR_MAKE_OPCODE(CsrSrvClientConnect
,
418 sizeof(CSR_CLIENT_CONNECT
));
420 Status
= CsrClientCallServer(&RosApiMessage
,
422 MAKE_CSR_API(CONNECT_PROCESS
, CSR_NATIVE
),
423 sizeof(CSR_API_MESSAGE
));
427 /* No connection info, just return */
428 Status
= STATUS_SUCCESS
;
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
;