ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

connect.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.