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
.u2
.ZeroInit
= 0;
63 ApiMessage
->Header
.u1
.s1
.DataLength
= RequestLength
- sizeof(PORT_MESSAGE
);
64 ApiMessage
->Header
.u1
.s1
.TotalLength
= RequestLength
;
66 /* Fill out the CSR Header */
67 ApiMessage
->Type
= ApiNumber
;
68 //ApiMessage->Opcode = ApiNumber; <- Activate with new CSR
69 ApiMessage
->CsrCaptureData
= NULL
;
71 DPRINT("API: %lx, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n",
73 ApiMessage
->Header
.u1
.s1
.DataLength
,
74 ApiMessage
->Header
.u1
.s1
.TotalLength
);
76 /* Check if we are already inside a CSR Server */
77 if (!InsideCsrProcess
)
79 /* Check if we got a a Capture Buffer */
82 /* We have to convert from our local view to the remote view */
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 DPRINT("PointerCount: %lx\n", PointerCount
);
95 while (PointerCount
--)
97 /* Get this pointer and check if it's valid */
98 DPRINT("Array Address: %p. This pointer: %p. Data: %lx\n",
99 &Pointers
, Pointers
, *Pointers
);
100 if ((CurrentPointer
= *Pointers
++))
103 DPRINT("CurrentPointer: %lx.\n", *(PULONG_PTR
)CurrentPointer
);
104 *(PULONG_PTR
)CurrentPointer
+= CsrPortMemoryDelta
;
105 Pointers
[-1] = CurrentPointer
- (ULONG_PTR
)ApiMessage
;
106 DPRINT("CurrentPointer: %lx.\n", *(PULONG_PTR
)CurrentPointer
);
111 /* Send the LPC Message */
112 Status
= NtRequestWaitReplyPort(CsrApiPort
,
114 &ApiMessage
->Header
);
116 /* Check if we got a a Capture Buffer */
119 /* We have to convert from the remote view to our remote view */
120 DPRINT("Reconverting CaptureBuffer\n");
121 ApiMessage
->CsrCaptureData
= (PVOID
)((ULONG_PTR
)
122 ApiMessage
->CsrCaptureData
-
125 /* Get the pointer information */
126 PointerCount
= CaptureBuffer
->PointerCount
;
127 Pointers
= CaptureBuffer
->PointerArray
;
129 /* Loop through every pointer and convert it */
130 while (PointerCount
--)
132 /* Get this pointer and check if it's valid */
133 if ((CurrentPointer
= *Pointers
++))
136 CurrentPointer
+= (ULONG_PTR
)ApiMessage
;
137 Pointers
[-1] = CurrentPointer
;
138 *(PULONG_PTR
)CurrentPointer
-= CsrPortMemoryDelta
;
143 /* Check for success */
144 if (!NT_SUCCESS(Status
))
146 /* We failed. Overwrite the return value with the failure */
147 DPRINT1("LPC Failed: %lx\n", Status
);
148 ApiMessage
->Status
= Status
;
153 /* This is a server-to-server call. Save our CID and do a direct call */
155 ApiMessage
->Header
.ClientId
= NtCurrentTeb()->ClientId
;
156 Status
= CsrServerApiRoutine(&ApiMessage
->Header
,
157 &ApiMessage
->Header
);
159 /* Check for success */
160 if (!NT_SUCCESS(Status
))
162 /* We failed. Overwrite the return value with the failure */
163 ApiMessage
->Status
= Status
;
167 /* Return the CSR Result */
168 DPRINT("Got back: 0x%lx\n", ApiMessage
->Status
);
169 return ApiMessage
->Status
;
174 CsrConnectToServer(IN PWSTR ObjectDirectory
)
176 ULONG PortNameLength
;
177 UNICODE_STRING PortName
;
178 LARGE_INTEGER CsrSectionViewSize
;
180 HANDLE CsrSectionHandle
;
182 REMOTE_PORT_VIEW LpcRead
;
183 SECURITY_QUALITY_OF_SERVICE SecurityQos
;
184 SID_IDENTIFIER_AUTHORITY NtSidAuthority
= {SECURITY_NT_AUTHORITY
};
185 PSID SystemSid
= NULL
;
186 CSR_CONNECTION_INFO ConnectionInfo
;
187 ULONG ConnectionInfoLength
= sizeof(CSR_CONNECTION_INFO
);
189 DPRINT("%s(%S)\n", __FUNCTION__
, ObjectDirectory
);
191 /* Binary compatibility with MS KERNEL32 */
192 if (NULL
== ObjectDirectory
)
194 ObjectDirectory
= L
"\\Windows";
197 /* Calculate the total port name size */
198 PortNameLength
= ((wcslen(ObjectDirectory
) + 1) * sizeof(WCHAR
)) +
199 sizeof(CSR_PORT_NAME
);
201 /* Set the port name */
203 PortName
.MaximumLength
= PortNameLength
;
205 /* Allocate a buffer for it */
206 PortName
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, PortNameLength
);
207 if (PortName
.Buffer
== NULL
)
209 return STATUS_INSUFFICIENT_RESOURCES
;
212 /* Create the name */
213 RtlAppendUnicodeToString(&PortName
, ObjectDirectory
);
214 RtlAppendUnicodeToString(&PortName
, UNICODE_PATH_SEP
);
215 RtlAppendUnicodeToString(&PortName
, CSR_PORT_NAME
);
217 /* Create a section for the port memory */
218 CsrSectionViewSize
.QuadPart
= CSR_CSRSS_SECTION_SIZE
;
219 Status
= NtCreateSection(&CsrSectionHandle
,
226 if (!NT_SUCCESS(Status
))
228 DPRINT1("Failure allocating CSR Section\n");
232 /* Set up the port view structures to match them with the section */
233 LpcWrite
.Length
= sizeof(PORT_VIEW
);
234 LpcWrite
.SectionHandle
= CsrSectionHandle
;
235 LpcWrite
.SectionOffset
= 0;
236 LpcWrite
.ViewSize
= CsrSectionViewSize
.u
.LowPart
;
237 LpcWrite
.ViewBase
= 0;
238 LpcWrite
.ViewRemoteBase
= 0;
239 LpcRead
.Length
= sizeof(REMOTE_PORT_VIEW
);
240 LpcRead
.ViewSize
= 0;
241 LpcRead
.ViewBase
= 0;
244 SecurityQos
.ImpersonationLevel
= SecurityImpersonation
;
245 SecurityQos
.ContextTrackingMode
= SECURITY_DYNAMIC_TRACKING
;
246 SecurityQos
.EffectiveOnly
= TRUE
;
248 /* Setup the connection info */
249 ConnectionInfo
.Version
= 0x10000;
251 /* Create a SID for us */
252 Status
= RtlAllocateAndInitializeSid(&NtSidAuthority
,
254 SECURITY_LOCAL_SYSTEM_RID
,
263 if (!NT_SUCCESS(Status
))
266 DPRINT1("Couldn't allocate SID\n");
267 NtClose(CsrSectionHandle
);
271 /* Connect to the port */
272 Status
= NtSecureConnectPort(&CsrApiPort
,
280 &ConnectionInfoLength
);
281 NtClose(CsrSectionHandle
);
282 if (!NT_SUCCESS(Status
))
285 DPRINT1("Couldn't connect to CSR port\n");
289 /* Save the delta between the sections, for capture usage later */
290 CsrPortMemoryDelta
= (ULONG_PTR
)LpcWrite
.ViewRemoteBase
-
291 (ULONG_PTR
)LpcWrite
.ViewBase
;
293 /* Save the Process */
294 CsrProcessId
= ConnectionInfo
.ProcessId
;
296 /* Save CSR Section data */
297 NtCurrentPeb()->ReadOnlySharedMemoryBase
= ConnectionInfo
.SharedSectionBase
;
298 NtCurrentPeb()->ReadOnlySharedMemoryHeap
= ConnectionInfo
.SharedSectionHeap
;
299 NtCurrentPeb()->ReadOnlyStaticServerData
= ConnectionInfo
.SharedSectionData
;
301 /* Create the port heap */
302 CsrPortHeap
= RtlCreateHeap(0,
308 if (CsrPortHeap
== NULL
)
312 return STATUS_INSUFFICIENT_RESOURCES
;
316 return STATUS_SUCCESS
;
324 CsrClientConnectToServer(PWSTR ObjectDirectory
,
326 PVOID ConnectionInfo
,
327 PULONG ConnectionInfoSize
,
328 PBOOLEAN ServerToServerCall
)
331 PIMAGE_NT_HEADERS NtHeader
;
332 UNICODE_STRING CsrSrvName
;
334 ANSI_STRING CsrServerRoutineName
;
335 PCSR_CAPTURE_BUFFER CaptureBuffer
;
336 CSR_API_MESSAGE RosApiMessage
;
337 CSR_API_MESSAGE2 ApiMessage
;
338 PCSR_CLIENT_CONNECT ClientConnect
= &ApiMessage
.ClientConnect
;
340 /* Validate the Connection Info */
341 DPRINT("CsrClientConnectToServer: %lx %p\n", ServerId
, ConnectionInfo
);
342 if (ConnectionInfo
&& (!ConnectionInfoSize
|| !*ConnectionInfoSize
))
344 DPRINT1("Connection info given, but no length\n");
345 return STATUS_INVALID_PARAMETER
;
348 /* Check if we're inside a CSR Process */
349 if (InsideCsrProcess
)
351 /* Tell the client that we're already inside CSR */
352 if (ServerToServerCall
) *ServerToServerCall
= TRUE
;
353 return STATUS_SUCCESS
;
357 * We might be in a CSR Process but not know it, if this is the first call.
360 if (!(NtHeader
= RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress
)))
362 /* The image isn't valid */
363 DPRINT1("Invalid image\n");
364 return STATUS_INVALID_IMAGE_FORMAT
;
366 InsideCsrProcess
= (NtHeader
->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_NATIVE
);
368 /* Now we can check if we are inside or not */
369 if (InsideCsrProcess
&& !UsingOldCsr
)
371 /* We're inside, so let's find csrsrv */
373 RtlInitUnicodeString(&CsrSrvName
, L
"csrsrv");
374 Status
= LdrGetDllHandle(NULL
,
379 /* Now get the Server to Server routine */
380 RtlInitAnsiString(&CsrServerRoutineName
, "CsrCallServerFromServer");
381 Status
= LdrGetProcedureAddress(hCsrSrv
,
382 &CsrServerRoutineName
,
384 (PVOID
*)&CsrServerApiRoutine
);
386 /* Use the local heap as port heap */
387 CsrPortHeap
= RtlGetProcessHeap();
389 /* Tell the caller we're inside the server */
390 *ServerToServerCall
= InsideCsrProcess
;
391 return STATUS_SUCCESS
;
394 /* Now check if connection info is given */
397 /* Well, we're defintely in a client now */
398 InsideCsrProcess
= FALSE
;
400 /* Do we have a connection to CSR yet? */
403 /* No, set it up now */
404 if (!NT_SUCCESS(Status
= CsrConnectToServer(ObjectDirectory
)))
407 DPRINT1("Failure to connect to CSR\n");
412 /* Setup the connect message header */
413 ClientConnect
->ServerId
= ServerId
;
414 ClientConnect
->ConnectionInfoSize
= *ConnectionInfoSize
;
416 /* Setup a buffer for the connection info */
417 CaptureBuffer
= CsrAllocateCaptureBuffer(1,
418 ClientConnect
->ConnectionInfoSize
);
419 if (CaptureBuffer
== NULL
)
421 return STATUS_INSUFFICIENT_RESOURCES
;
424 /* Allocate a pointer for the connection info*/
425 CsrAllocateMessagePointer(CaptureBuffer
,
426 ClientConnect
->ConnectionInfoSize
,
427 &ClientConnect
->ConnectionInfo
);
429 /* Copy the data into the buffer */
430 RtlMoveMemory(ClientConnect
->ConnectionInfo
,
432 ClientConnect
->ConnectionInfoSize
);
434 /* Return the allocated length */
435 *ConnectionInfoSize
= ClientConnect
->ConnectionInfoSize
;
439 Status
= CsrClientCallServer(&ApiMessage
,
441 CSR_MAKE_OPCODE(CsrSrvClientConnect
,
443 sizeof(CSR_CLIENT_CONNECT
));
445 Status
= CsrClientCallServer(&RosApiMessage
,
447 MAKE_CSR_API(CONNECT_PROCESS
, CSR_NATIVE
),
448 sizeof(CSR_API_MESSAGE
));
452 /* No connection info, just return */
453 Status
= STATUS_SUCCESS
;
456 /* Let the caller know if this was server to server */
457 DPRINT("Status was: 0x%lx. Are we in server: 0x%x\n", Status
, InsideCsrProcess
);
458 if (ServerToServerCall
) *ServerToServerCall
= InsideCsrProcess
;