Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenconnect.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: lib/ntdll/csr/connect.c 00005 * PURPOSE: Routines for connecting and calling CSR 00006 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include <ntdll.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS *******************************************************************/ 00016 00017 HANDLE CsrApiPort; 00018 HANDLE CsrProcessId; 00019 HANDLE CsrPortHeap; 00020 ULONG_PTR CsrPortMemoryDelta; 00021 BOOLEAN InsideCsrProcess = FALSE; 00022 00023 typedef NTSTATUS 00024 (NTAPI *PCSR_SERVER_API_ROUTINE)(IN PPORT_MESSAGE Request, 00025 IN PPORT_MESSAGE Reply); 00026 00027 PCSR_SERVER_API_ROUTINE CsrServerApiRoutine; 00028 00029 #define UNICODE_PATH_SEP L"\\" 00030 #define CSR_PORT_NAME L"ApiPort" 00031 00032 /* FUNCTIONS *****************************************************************/ 00033 00034 /* 00035 * @implemented 00036 */ 00037 HANDLE 00038 NTAPI 00039 CsrGetProcessId(VOID) 00040 { 00041 return CsrProcessId; 00042 } 00043 00044 /* 00045 * @implemented 00046 */ 00047 NTSTATUS 00048 NTAPI 00049 CsrClientCallServer(PCSR_API_MESSAGE ApiMessage, 00050 PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL, 00051 CSR_API_NUMBER ApiNumber, 00052 ULONG RequestLength) 00053 { 00054 NTSTATUS Status; 00055 ULONG PointerCount; 00056 PULONG_PTR Pointers; 00057 ULONG_PTR CurrentPointer; 00058 DPRINT("CsrClientCallServer\n"); 00059 00060 /* Fill out the Port Message Header */ 00061 ApiMessage->Header.u2.ZeroInit = 0; 00062 ApiMessage->Header.u1.s1.DataLength = RequestLength - sizeof(PORT_MESSAGE); 00063 ApiMessage->Header.u1.s1.TotalLength = RequestLength; 00064 00065 /* Fill out the CSR Header */ 00066 ApiMessage->Type = ApiNumber; 00067 //ApiMessage->Opcode = ApiNumber; <- Activate with new CSR 00068 ApiMessage->CsrCaptureData = NULL; 00069 00070 DPRINT("API: %lx, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n", 00071 ApiNumber, 00072 ApiMessage->Header.u1.s1.DataLength, 00073 ApiMessage->Header.u1.s1.TotalLength); 00074 00075 /* Check if we are already inside a CSR Server */ 00076 if (!InsideCsrProcess) 00077 { 00078 /* Check if we got a a Capture Buffer */ 00079 if (CaptureBuffer) 00080 { 00081 /* We have to convert from our local view to the remote view */ 00082 ApiMessage->CsrCaptureData = (PVOID)((ULONG_PTR)CaptureBuffer + 00083 CsrPortMemoryDelta); 00084 00085 /* Lock the buffer */ 00086 CaptureBuffer->BufferEnd = 0; 00087 00088 /* Get the pointer information */ 00089 PointerCount = CaptureBuffer->PointerCount; 00090 Pointers = CaptureBuffer->PointerArray; 00091 00092 /* Loop through every pointer and convert it */ 00093 DPRINT("PointerCount: %lx\n", PointerCount); 00094 while (PointerCount--) 00095 { 00096 /* Get this pointer and check if it's valid */ 00097 DPRINT("Array Address: %p. This pointer: %p. Data: %lx\n", 00098 &Pointers, Pointers, *Pointers); 00099 if ((CurrentPointer = *Pointers++)) 00100 { 00101 /* Update it */ 00102 DPRINT("CurrentPointer: %lx.\n", *(PULONG_PTR)CurrentPointer); 00103 *(PULONG_PTR)CurrentPointer += CsrPortMemoryDelta; 00104 Pointers[-1] = CurrentPointer - (ULONG_PTR)ApiMessage; 00105 DPRINT("CurrentPointer: %lx.\n", *(PULONG_PTR)CurrentPointer); 00106 } 00107 } 00108 } 00109 00110 /* Send the LPC Message */ 00111 Status = NtRequestWaitReplyPort(CsrApiPort, 00112 &ApiMessage->Header, 00113 &ApiMessage->Header); 00114 00115 /* Check if we got a a Capture Buffer */ 00116 if (CaptureBuffer) 00117 { 00118 /* We have to convert from the remote view to our remote view */ 00119 DPRINT("Reconverting CaptureBuffer\n"); 00120 ApiMessage->CsrCaptureData = (PVOID)((ULONG_PTR) 00121 ApiMessage->CsrCaptureData - 00122 CsrPortMemoryDelta); 00123 00124 /* Get the pointer information */ 00125 PointerCount = CaptureBuffer->PointerCount; 00126 Pointers = CaptureBuffer->PointerArray; 00127 00128 /* Loop through every pointer and convert it */ 00129 while (PointerCount--) 00130 { 00131 /* Get this pointer and check if it's valid */ 00132 if ((CurrentPointer = *Pointers++)) 00133 { 00134 /* Update it */ 00135 CurrentPointer += (ULONG_PTR)ApiMessage; 00136 Pointers[-1] = CurrentPointer; 00137 *(PULONG_PTR)CurrentPointer -= CsrPortMemoryDelta; 00138 } 00139 } 00140 } 00141 00142 /* Check for success */ 00143 if (!NT_SUCCESS(Status)) 00144 { 00145 /* We failed. Overwrite the return value with the failure */ 00146 DPRINT1("LPC Failed: %lx\n", Status); 00147 ApiMessage->Status = Status; 00148 } 00149 } 00150 else 00151 { 00152 /* This is a server-to-server call. Save our CID and do a direct call */ 00153 DPRINT1("Next gen server-to-server call\n"); 00154 ApiMessage->Header.ClientId = NtCurrentTeb()->ClientId; 00155 Status = CsrServerApiRoutine(&ApiMessage->Header, 00156 &ApiMessage->Header); 00157 00158 /* Check for success */ 00159 if (!NT_SUCCESS(Status)) 00160 { 00161 /* We failed. Overwrite the return value with the failure */ 00162 ApiMessage->Status = Status; 00163 } 00164 } 00165 00166 /* Return the CSR Result */ 00167 DPRINT("Got back: 0x%lx\n", ApiMessage->Status); 00168 return ApiMessage->Status; 00169 } 00170 00171 NTSTATUS 00172 NTAPI 00173 CsrConnectToServer(IN PWSTR ObjectDirectory) 00174 { 00175 ULONG PortNameLength; 00176 UNICODE_STRING PortName; 00177 LARGE_INTEGER CsrSectionViewSize; 00178 NTSTATUS Status; 00179 HANDLE CsrSectionHandle; 00180 PORT_VIEW LpcWrite; 00181 REMOTE_PORT_VIEW LpcRead; 00182 SECURITY_QUALITY_OF_SERVICE SecurityQos; 00183 SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; 00184 PSID SystemSid = NULL; 00185 CSR_CONNECTION_INFO ConnectionInfo; 00186 ULONG ConnectionInfoLength = sizeof(CSR_CONNECTION_INFO); 00187 00188 DPRINT("%s(%S)\n", __FUNCTION__, ObjectDirectory); 00189 00190 /* Binary compatibility with MS KERNEL32 */ 00191 if (NULL == ObjectDirectory) 00192 { 00193 ObjectDirectory = L"\\Windows"; 00194 } 00195 00196 /* Calculate the total port name size */ 00197 PortNameLength = ((wcslen(ObjectDirectory) + 1) * sizeof(WCHAR)) + 00198 sizeof(CSR_PORT_NAME); 00199 00200 /* Set the port name */ 00201 PortName.Length = 0; 00202 PortName.MaximumLength = PortNameLength; 00203 00204 /* Allocate a buffer for it */ 00205 PortName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PortNameLength); 00206 if (PortName.Buffer == NULL) 00207 { 00208 return STATUS_INSUFFICIENT_RESOURCES; 00209 } 00210 00211 /* Create the name */ 00212 RtlAppendUnicodeToString(&PortName, ObjectDirectory ); 00213 RtlAppendUnicodeToString(&PortName, UNICODE_PATH_SEP); 00214 RtlAppendUnicodeToString(&PortName, CSR_PORT_NAME); 00215 00216 /* Create a section for the port memory */ 00217 CsrSectionViewSize.QuadPart = CSR_CSRSS_SECTION_SIZE; 00218 Status = NtCreateSection(&CsrSectionHandle, 00219 SECTION_ALL_ACCESS, 00220 NULL, 00221 &CsrSectionViewSize, 00222 PAGE_READWRITE, 00223 SEC_COMMIT, 00224 NULL); 00225 if (!NT_SUCCESS(Status)) 00226 { 00227 DPRINT1("Failure allocating CSR Section\n"); 00228 return Status; 00229 } 00230 00231 /* Set up the port view structures to match them with the section */ 00232 LpcWrite.Length = sizeof(PORT_VIEW); 00233 LpcWrite.SectionHandle = CsrSectionHandle; 00234 LpcWrite.SectionOffset = 0; 00235 LpcWrite.ViewSize = CsrSectionViewSize.u.LowPart; 00236 LpcWrite.ViewBase = 0; 00237 LpcWrite.ViewRemoteBase = 0; 00238 LpcRead.Length = sizeof(REMOTE_PORT_VIEW); 00239 LpcRead.ViewSize = 0; 00240 LpcRead.ViewBase = 0; 00241 00242 /* Setup the QoS */ 00243 SecurityQos.ImpersonationLevel = SecurityImpersonation; 00244 SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; 00245 SecurityQos.EffectiveOnly = TRUE; 00246 00247 /* Setup the connection info */ 00248 ConnectionInfo.Version = 0x10000; 00249 00250 /* Create a SID for us */ 00251 Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 00252 1, 00253 SECURITY_LOCAL_SYSTEM_RID, 00254 0, 00255 0, 00256 0, 00257 0, 00258 0, 00259 0, 00260 0, 00261 &SystemSid); 00262 if (!NT_SUCCESS(Status)) 00263 { 00264 /* Failure */ 00265 DPRINT1("Couldn't allocate SID\n"); 00266 NtClose(CsrSectionHandle); 00267 return Status; 00268 } 00269 00270 /* Connect to the port */ 00271 Status = NtSecureConnectPort(&CsrApiPort, 00272 &PortName, 00273 &SecurityQos, 00274 &LpcWrite, 00275 SystemSid, 00276 &LpcRead, 00277 NULL, 00278 &ConnectionInfo, 00279 &ConnectionInfoLength); 00280 NtClose(CsrSectionHandle); 00281 if (!NT_SUCCESS(Status)) 00282 { 00283 /* Failure */ 00284 DPRINT1("Couldn't connect to CSR port\n"); 00285 return Status; 00286 } 00287 00288 /* Save the delta between the sections, for capture usage later */ 00289 CsrPortMemoryDelta = (ULONG_PTR)LpcWrite.ViewRemoteBase - 00290 (ULONG_PTR)LpcWrite.ViewBase; 00291 00292 /* Save the Process */ 00293 CsrProcessId = ConnectionInfo.ProcessId; 00294 00295 /* Save CSR Section data */ 00296 NtCurrentPeb()->ReadOnlySharedMemoryBase = ConnectionInfo.SharedSectionBase; 00297 NtCurrentPeb()->ReadOnlySharedMemoryHeap = ConnectionInfo.SharedSectionHeap; 00298 NtCurrentPeb()->ReadOnlyStaticServerData = ConnectionInfo.SharedSectionData; 00299 00300 /* Create the port heap */ 00301 CsrPortHeap = RtlCreateHeap(0, 00302 LpcWrite.ViewBase, 00303 LpcWrite.ViewSize, 00304 PAGE_SIZE, 00305 0, 00306 0); 00307 if (CsrPortHeap == NULL) 00308 { 00309 NtClose(CsrApiPort); 00310 CsrApiPort = NULL; 00311 return STATUS_INSUFFICIENT_RESOURCES; 00312 } 00313 00314 /* Return success */ 00315 return STATUS_SUCCESS; 00316 } 00317 00318 /* 00319 * @implemented 00320 */ 00321 NTSTATUS 00322 NTAPI 00323 CsrClientConnectToServer(PWSTR ObjectDirectory, 00324 ULONG ServerId, 00325 PVOID ConnectionInfo, 00326 PULONG ConnectionInfoSize, 00327 PBOOLEAN ServerToServerCall) 00328 { 00329 NTSTATUS Status; 00330 PIMAGE_NT_HEADERS NtHeader; 00331 UNICODE_STRING CsrSrvName; 00332 HANDLE hCsrSrv; 00333 ANSI_STRING CsrServerRoutineName; 00334 PCSR_CAPTURE_BUFFER CaptureBuffer; 00335 CSR_API_MESSAGE RosApiMessage; 00336 CSR_API_MESSAGE2 ApiMessage; 00337 PCSR_CLIENT_CONNECT ClientConnect = &ApiMessage.ClientConnect; 00338 00339 /* Validate the Connection Info */ 00340 DPRINT("CsrClientConnectToServer: %lx %p\n", ServerId, ConnectionInfo); 00341 if (ConnectionInfo && (!ConnectionInfoSize || !*ConnectionInfoSize)) 00342 { 00343 DPRINT1("Connection info given, but no length\n"); 00344 return STATUS_INVALID_PARAMETER; 00345 } 00346 00347 /* Check if we're inside a CSR Process */ 00348 if (InsideCsrProcess) 00349 { 00350 /* Tell the client that we're already inside CSR */ 00351 if (ServerToServerCall) *ServerToServerCall = TRUE; 00352 return STATUS_SUCCESS; 00353 } 00354 00355 /* 00356 * We might be in a CSR Process but not know it, if this is the first call. 00357 * So let's find out. 00358 */ 00359 if (!(NtHeader = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress))) 00360 { 00361 /* The image isn't valid */ 00362 DPRINT1("Invalid image\n"); 00363 return STATUS_INVALID_IMAGE_FORMAT; 00364 } 00365 InsideCsrProcess = (NtHeader->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE); 00366 00367 /* Now we can check if we are inside or not */ 00368 if (InsideCsrProcess) 00369 { 00370 /* We're inside, so let's find csrsrv */ 00371 DPRINT1("Next-GEN CSRSS support\n"); 00372 RtlInitUnicodeString(&CsrSrvName, L"csrsrv"); 00373 Status = LdrGetDllHandle(NULL, 00374 NULL, 00375 &CsrSrvName, 00376 &hCsrSrv); 00377 00378 /* Now get the Server to Server routine */ 00379 RtlInitAnsiString(&CsrServerRoutineName, "CsrCallServerFromServer"); 00380 Status = LdrGetProcedureAddress(hCsrSrv, 00381 &CsrServerRoutineName, 00382 0L, 00383 (PVOID*)&CsrServerApiRoutine); 00384 00385 /* Use the local heap as port heap */ 00386 CsrPortHeap = RtlGetProcessHeap(); 00387 00388 /* Tell the caller we're inside the server */ 00389 *ServerToServerCall = InsideCsrProcess; 00390 return STATUS_SUCCESS; 00391 } 00392 00393 /* Now check if connection info is given */ 00394 if (ConnectionInfo) 00395 { 00396 /* Well, we're defintely in a client now */ 00397 InsideCsrProcess = FALSE; 00398 00399 /* Do we have a connection to CSR yet? */ 00400 if (!CsrApiPort) 00401 { 00402 /* No, set it up now */ 00403 if (!NT_SUCCESS(Status = CsrConnectToServer(ObjectDirectory))) 00404 { 00405 /* Failed */ 00406 DPRINT1("Failure to connect to CSR\n"); 00407 return Status; 00408 } 00409 } 00410 00411 /* Setup the connect message header */ 00412 ClientConnect->ServerId = ServerId; 00413 ClientConnect->ConnectionInfoSize = *ConnectionInfoSize; 00414 00415 /* Setup a buffer for the connection info */ 00416 CaptureBuffer = CsrAllocateCaptureBuffer(1, 00417 ClientConnect->ConnectionInfoSize); 00418 if (CaptureBuffer == NULL) 00419 { 00420 return STATUS_INSUFFICIENT_RESOURCES; 00421 } 00422 00423 /* Allocate a pointer for the connection info*/ 00424 CsrAllocateMessagePointer(CaptureBuffer, 00425 ClientConnect->ConnectionInfoSize, 00426 &ClientConnect->ConnectionInfo); 00427 00428 /* Copy the data into the buffer */ 00429 RtlMoveMemory(ClientConnect->ConnectionInfo, 00430 ConnectionInfo, 00431 ClientConnect->ConnectionInfoSize); 00432 00433 /* Return the allocated length */ 00434 *ConnectionInfoSize = ClientConnect->ConnectionInfoSize; 00435 00436 /* Call CSR */ 00437 #if 0 00438 Status = CsrClientCallServer(&ApiMessage, 00439 CaptureBuffer, 00440 CSR_MAKE_OPCODE(CsrpClientConnect, 00441 CSR_SRV_DLL), 00442 sizeof(CSR_CLIENT_CONNECT)); 00443 #endif 00444 Status = CsrClientCallServer(&RosApiMessage, 00445 NULL, 00446 MAKE_CSR_API(CONNECT_PROCESS, CSR_NATIVE), 00447 sizeof(CSR_API_MESSAGE)); 00448 } 00449 else 00450 { 00451 /* No connection info, just return */ 00452 Status = STATUS_SUCCESS; 00453 } 00454 00455 /* Let the caller know if this was server to server */ 00456 DPRINT("Status was: 0x%lx. Are we in server: 0x%x\n", Status, InsideCsrProcess); 00457 if (ServerToServerCall) *ServerToServerCall = InsideCsrProcess; 00458 return Status; 00459 } 00460 00461 /* EOF */ Generated on Sat May 26 2012 04:21:02 for ReactOS by
1.7.6.1
|