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(IN OUT PCSR_API_MESSAGE ApiMessage
,
49 IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL
,
50 IN CSR_API_NUMBER ApiNumber
,
56 /* Fill out the Port Message Header. */
57 ApiMessage
->Header
.u2
.ZeroInit
= 0;
58 ApiMessage
->Header
.u1
.s1
.TotalLength
=
59 FIELD_OFFSET(CSR_API_MESSAGE
, Data
) + DataLength
;
60 ApiMessage
->Header
.u1
.s1
.DataLength
=
61 ApiMessage
->Header
.u1
.s1
.TotalLength
- sizeof(PORT_MESSAGE
);
63 /* Fill out the CSR Header. */
64 ApiMessage
->ApiNumber
= ApiNumber
;
65 ApiMessage
->CsrCaptureData
= NULL
;
67 DPRINT("API: %lx, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n",
69 ApiMessage
->Header
.u1
.s1
.DataLength
,
70 ApiMessage
->Header
.u1
.s1
.TotalLength
);
72 /* Check if we are already inside a CSR Server. */
73 if (!InsideCsrProcess
)
75 /* Check if we got a Capture Buffer. */
79 * We have to convert from our local (client) view
80 * to the remote (server) view.
82 ApiMessage
->CsrCaptureData
= (PCSR_CAPTURE_BUFFER
)
83 ((ULONG_PTR
)CaptureBuffer
+ CsrPortMemoryDelta
);
85 /* Lock the buffer. */
86 CaptureBuffer
->BufferEnd
= NULL
;
89 * Each client pointer inside the CSR message is converted into
90 * a server pointer, and each pointer to these message pointers
91 * is converted into an offset.
93 for (i
= 0 ; i
< CaptureBuffer
->PointerCount
; ++i
)
95 if (CaptureBuffer
->PointerOffsetsArray
[i
] != 0)
97 *(PULONG_PTR
)CaptureBuffer
->PointerOffsetsArray
[i
] += CsrPortMemoryDelta
;
98 CaptureBuffer
->PointerOffsetsArray
[i
] -= (ULONG_PTR
)ApiMessage
;
103 /* Send the LPC Message. */
104 Status
= NtRequestWaitReplyPort(CsrApiPort
,
106 &ApiMessage
->Header
);
108 /* Check if we got a Capture Buffer. */
112 * We have to convert back from the remote (server) view
113 * to our local (client) view.
115 ApiMessage
->CsrCaptureData
= (PCSR_CAPTURE_BUFFER
)
116 ((ULONG_PTR
)ApiMessage
->CsrCaptureData
- CsrPortMemoryDelta
);
119 * Convert back the offsets into pointers to CSR message
120 * pointers, and convert back these message server pointers
121 * into client pointers.
123 for (i
= 0 ; i
< CaptureBuffer
->PointerCount
; ++i
)
125 if (CaptureBuffer
->PointerOffsetsArray
[i
] != 0)
127 CaptureBuffer
->PointerOffsetsArray
[i
] += (ULONG_PTR
)ApiMessage
;
128 *(PULONG_PTR
)CaptureBuffer
->PointerOffsetsArray
[i
] -= CsrPortMemoryDelta
;
133 /* Check for success. */
134 if (!NT_SUCCESS(Status
))
136 /* We failed. Overwrite the return value with the failure. */
137 DPRINT1("LPC Failed: %lx\n", Status
);
138 ApiMessage
->Status
= Status
;
143 /* This is a server-to-server call. Save our CID and do a direct call. */
144 DPRINT1("Next gen server-to-server call\n");
146 /* We check this equality inside CsrValidateMessageBuffer. */
147 ApiMessage
->Header
.ClientId
= NtCurrentTeb()->ClientId
;
149 Status
= CsrServerApiRoutine(&ApiMessage
->Header
,
150 &ApiMessage
->Header
);
152 /* Check for success. */
153 if (!NT_SUCCESS(Status
))
155 /* We failed. Overwrite the return value with the failure. */
156 ApiMessage
->Status
= Status
;
160 /* Return the CSR Result. */
161 DPRINT("Got back: 0x%lx\n", ApiMessage
->Status
);
162 return ApiMessage
->Status
;
167 CsrpConnectToServer(IN PWSTR ObjectDirectory
)
169 ULONG PortNameLength
;
170 UNICODE_STRING PortName
;
171 LARGE_INTEGER CsrSectionViewSize
;
173 HANDLE CsrSectionHandle
;
175 REMOTE_PORT_VIEW LpcRead
;
176 SECURITY_QUALITY_OF_SERVICE SecurityQos
;
177 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
178 PSID SystemSid
= NULL
;
179 CSR_CONNECTION_INFO ConnectionInfo
;
180 ULONG ConnectionInfoLength
= sizeof(CSR_CONNECTION_INFO
);
182 DPRINT("%s(%S)\n", __FUNCTION__
, ObjectDirectory
);
184 /* Binary compatibility with MS KERNEL32 */
185 if (NULL
== ObjectDirectory
)
187 ObjectDirectory
= L
"\\Windows";
190 /* Calculate the total port name size */
191 PortNameLength
= ((wcslen(ObjectDirectory
) + 1) * sizeof(WCHAR
)) +
192 sizeof(CSR_PORT_NAME
);
194 /* Set the port name */
196 PortName
.MaximumLength
= PortNameLength
;
198 /* Allocate a buffer for it */
199 PortName
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, PortNameLength
);
200 if (PortName
.Buffer
== NULL
)
202 return STATUS_INSUFFICIENT_RESOURCES
;
205 /* Create the name */
206 RtlAppendUnicodeToString(&PortName
, ObjectDirectory
);
207 RtlAppendUnicodeToString(&PortName
, UNICODE_PATH_SEP
);
208 RtlAppendUnicodeToString(&PortName
, CSR_PORT_NAME
);
210 /* Create a section for the port memory */
211 CsrSectionViewSize
.QuadPart
= CSR_CSRSS_SECTION_SIZE
;
212 Status
= NtCreateSection(&CsrSectionHandle
,
219 if (!NT_SUCCESS(Status
))
221 DPRINT1("Failure allocating CSR Section\n");
225 /* Set up the port view structures to match them with the section */
226 LpcWrite
.Length
= sizeof(PORT_VIEW
);
227 LpcWrite
.SectionHandle
= CsrSectionHandle
;
228 LpcWrite
.SectionOffset
= 0;
229 LpcWrite
.ViewSize
= CsrSectionViewSize
.u
.LowPart
;
230 LpcWrite
.ViewBase
= 0;
231 LpcWrite
.ViewRemoteBase
= 0;
232 LpcRead
.Length
= sizeof(REMOTE_PORT_VIEW
);
233 LpcRead
.ViewSize
= 0;
234 LpcRead
.ViewBase
= 0;
237 SecurityQos
.ImpersonationLevel
= SecurityImpersonation
;
238 SecurityQos
.ContextTrackingMode
= SECURITY_DYNAMIC_TRACKING
;
239 SecurityQos
.EffectiveOnly
= TRUE
;
241 /* Setup the connection info */
242 ConnectionInfo
.Version
= 0x10000;
244 /* Create a SID for us */
245 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
,
247 SECURITY_LOCAL_SYSTEM_RID
,
256 if (!NT_SUCCESS(Status
))
259 DPRINT1("Couldn't allocate SID\n");
260 NtClose(CsrSectionHandle
);
264 /* Connect to the port */
265 Status
= NtSecureConnectPort(&CsrApiPort
,
273 &ConnectionInfoLength
);
274 NtClose(CsrSectionHandle
);
275 if (!NT_SUCCESS(Status
))
278 DPRINT1("Couldn't connect to CSR port\n");
282 /* Save the delta between the sections, for capture usage later */
283 CsrPortMemoryDelta
= (ULONG_PTR
)LpcWrite
.ViewRemoteBase
-
284 (ULONG_PTR
)LpcWrite
.ViewBase
;
286 /* Save the Process */
287 CsrProcessId
= ConnectionInfo
.ProcessId
;
289 /* Save CSR Section data */
290 NtCurrentPeb()->ReadOnlySharedMemoryBase
= ConnectionInfo
.SharedSectionBase
;
291 NtCurrentPeb()->ReadOnlySharedMemoryHeap
= ConnectionInfo
.SharedSectionHeap
;
292 NtCurrentPeb()->ReadOnlyStaticServerData
= ConnectionInfo
.SharedSectionData
;
294 /* Create the port heap */
295 CsrPortHeap
= RtlCreateHeap(0,
301 if (CsrPortHeap
== NULL
)
304 DPRINT1("Couldn't create heap for CSR port\n");
307 return STATUS_INSUFFICIENT_RESOURCES
;
311 return STATUS_SUCCESS
;
319 CsrClientConnectToServer(IN PWSTR ObjectDirectory
,
321 IN PVOID ConnectionInfo
,
322 IN OUT PULONG ConnectionInfoSize
,
323 OUT PBOOLEAN ServerToServerCall
)
326 PIMAGE_NT_HEADERS NtHeader
;
327 UNICODE_STRING CsrSrvName
;
329 ANSI_STRING CsrServerRoutineName
;
330 CSR_API_MESSAGE ApiMessage
;
331 PCSR_CLIENT_CONNECT ClientConnect
= &ApiMessage
.Data
.CsrClientConnect
;
332 PCSR_CAPTURE_BUFFER CaptureBuffer
;
334 /* Validate the Connection Info */
335 DPRINT("CsrClientConnectToServer: %lx %p\n", ServerId
, ConnectionInfo
);
336 if (ConnectionInfo
&& (!ConnectionInfoSize
|| !*ConnectionInfoSize
))
338 DPRINT1("Connection info given, but no length\n");
339 return STATUS_INVALID_PARAMETER
;
342 /* Check if we're inside a CSR Process */
343 if (InsideCsrProcess
)
345 /* Tell the client that we're already inside CSR */
346 if (ServerToServerCall
) *ServerToServerCall
= TRUE
;
347 return STATUS_SUCCESS
;
351 * We might be in a CSR Process but not know it, if this is the first call.
354 if (!(NtHeader
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
)))
356 /* The image isn't valid */
357 DPRINT1("Invalid image\n");
358 return STATUS_INVALID_IMAGE_FORMAT
;
360 InsideCsrProcess
= (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
);
362 /* Now we can check if we are inside or not */
363 if (InsideCsrProcess
)
365 /* We're inside, so let's find csrsrv */
366 DPRINT1("Next-GEN CSRSS support\n");
367 RtlInitUnicodeString(&CsrSrvName
, L
"csrsrv");
368 Status
= LdrGetDllHandle(NULL
,
373 /* Now get the Server to Server routine */
374 RtlInitAnsiString(&CsrServerRoutineName
, "CsrCallServerFromServer");
375 Status
= LdrGetProcedureAddress(hCsrSrv
,
376 &CsrServerRoutineName
,
378 (PVOID
*)&CsrServerApiRoutine
);
380 /* Use the local heap as port heap */
381 CsrPortHeap
= RtlGetProcessHeap();
383 /* Tell the caller we're inside the server */
384 *ServerToServerCall
= InsideCsrProcess
;
385 return STATUS_SUCCESS
;
388 /* Now check if connection info is given */
391 /* Well, we're defintely in a client now */
392 InsideCsrProcess
= FALSE
;
394 /* Do we have a connection to CSR yet? */
397 /* No, set it up now */
398 if (!NT_SUCCESS(Status
= CsrpConnectToServer(ObjectDirectory
)))
401 DPRINT1("Failure to connect to CSR\n");
406 /* Setup the connect message header */
407 ClientConnect
->ServerId
= ServerId
;
408 ClientConnect
->ConnectionInfoSize
= *ConnectionInfoSize
;
410 /* Setup a buffer for the connection info */
411 CaptureBuffer
= CsrAllocateCaptureBuffer(1, ClientConnect
->ConnectionInfoSize
);
412 if (CaptureBuffer
== NULL
)
414 return STATUS_INSUFFICIENT_RESOURCES
;
417 /* Capture the connection info data */
418 CsrCaptureMessageBuffer(CaptureBuffer
,
420 ClientConnect
->ConnectionInfoSize
,
421 &ClientConnect
->ConnectionInfo
);
423 /* Return the allocated length */
424 *ConnectionInfoSize
= ClientConnect
->ConnectionInfoSize
;
427 Status
= CsrClientCallServer(&ApiMessage
,
429 CSR_CREATE_API_NUMBER(CSRSRV_SERVERDLL_INDEX
, CsrpClientConnect
),
430 sizeof(CSR_CLIENT_CONNECT
));
434 /* No connection info, just return */
435 Status
= STATUS_SUCCESS
;
438 /* Let the caller know if this was server to server */
439 DPRINT("Status was: 0x%lx. Are we in server: 0x%x\n", Status
, InsideCsrProcess
);
440 if (ServerToServerCall
) *ServerToServerCall
= InsideCsrProcess
;