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

smloop.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Windows-Compatible Session Manager
00003  * LICENSE:         BSD 2-Clause License
00004  * FILE:            base/system/smss/smss.c
00005  * PURPOSE:         Main SMSS Code
00006  * PROGRAMMERS:     Alex Ionescu
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include "smss.h"
00012 #define NDEBUG
00013 #include "debug.h"
00014 
00015 /* GLOBALS ********************************************************************/
00016 
00017 typedef struct _SMP_CLIENT_CONTEXT
00018 {
00019     PVOID Subsystem;
00020     HANDLE ProcessHandle;
00021     HANDLE PortHandle;
00022     ULONG dword10;
00023 } SMP_CLIENT_CONTEXT, *PSMP_CLIENT_CONTEXT;
00024 
00025 typedef
00026 NTSTATUS
00027 (NTAPI *PSM_API_HANDLER)(
00028      IN PSM_API_MSG SmApiMsg,
00029      IN PSMP_CLIENT_CONTEXT ClientContext,
00030      IN HANDLE SmApiPort
00031 );
00032 
00033 volatile LONG SmTotalApiThreads;
00034 HANDLE SmUniqueProcessId;
00035 
00036 /* API HANDLERS ***************************************************************/
00037 
00038 NTSTATUS
00039 NTAPI
00040 SmpCreateForeignSession(IN PSM_API_MSG SmApiMsg,
00041                         IN PSMP_CLIENT_CONTEXT ClientContext,
00042                         IN HANDLE SmApiPort)
00043 {
00044     DPRINT1("%s is not yet implemented\n", __FUNCTION__);
00045     return STATUS_NOT_IMPLEMENTED;
00046 }
00047 
00048 NTSTATUS
00049 NTAPI
00050 SmpSessionComplete(IN PSM_API_MSG SmApiMsg,
00051                    IN PSMP_CLIENT_CONTEXT ClientContext,
00052                    IN HANDLE SmApiPort)
00053 {
00054     DPRINT1("%s is not yet implemented\n", __FUNCTION__);
00055     return STATUS_NOT_IMPLEMENTED;
00056 }
00057 
00058 NTSTATUS
00059 NTAPI
00060 SmpTerminateForeignSession(IN PSM_API_MSG SmApiMsg,
00061                            IN PSMP_CLIENT_CONTEXT ClientContext,
00062                            IN HANDLE SmApiPort)
00063 {
00064     DPRINT1("%s is not yet implemented\n", __FUNCTION__);
00065     return STATUS_NOT_IMPLEMENTED;
00066 }
00067 
00068 NTSTATUS
00069 NTAPI
00070 SmpExecPgm(IN PSM_API_MSG SmApiMsg,
00071            IN PSMP_CLIENT_CONTEXT ClientContext,
00072            IN HANDLE SmApiPort)
00073 {
00074     HANDLE ProcessHandle;
00075     NTSTATUS Status;
00076     PSM_EXEC_PGM_MSG SmExecPgm;
00077     RTL_USER_PROCESS_INFORMATION ProcessInformation;
00078     OBJECT_ATTRIBUTES ObjectAttributes;
00079 
00080     /* Open the client process */
00081     InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
00082     Status = NtOpenProcess(&ProcessHandle,
00083                            PROCESS_DUP_HANDLE,
00084                            &ObjectAttributes,
00085                            &SmApiMsg->h.ClientId);
00086     if (!NT_SUCCESS(Status))
00087     {
00088         /* Fail */
00089         DPRINT1("SmExecPgm: NtOpenProcess Failed %lx\n", Status);
00090         return Status;
00091     }
00092 
00093     /* Copy the process information out of the message */
00094     SmExecPgm = &SmApiMsg->u.ExecPgm;
00095     ProcessInformation = SmExecPgm->ProcessInformation;
00096 
00097     /* Duplicate the process handle */
00098     Status = NtDuplicateObject(ProcessHandle,
00099                                SmExecPgm->ProcessInformation.ProcessHandle,
00100                                NtCurrentProcess(),
00101                                &ProcessInformation.ProcessHandle,
00102                                PROCESS_ALL_ACCESS,
00103                                0,
00104                                0);
00105     if (!NT_SUCCESS(Status))
00106     {
00107         /* Close the handle and fail */
00108         NtClose(ProcessHandle);
00109         DPRINT1("SmExecPgm: NtDuplicateObject (Process) Failed %lx\n", Status);
00110         return Status;
00111     }
00112 
00113     /* Duplicate the thread handle */
00114     Status = NtDuplicateObject(ProcessHandle,
00115                                SmExecPgm->ProcessInformation.ThreadHandle,
00116                                NtCurrentProcess(),
00117                                &ProcessInformation.ThreadHandle,
00118                                THREAD_ALL_ACCESS,
00119                                0,
00120                                0);
00121     if (!NT_SUCCESS(Status))
00122     {
00123         /* Close both handles and fail */
00124         NtClose(ProcessInformation.ProcessHandle);
00125         NtClose(ProcessHandle);
00126         DPRINT1("SmExecPgm: NtDuplicateObject (Thread) Failed %lx\n", Status);
00127         return Status;
00128     }
00129 
00130     /* Close the process handle and call the internal client API */
00131     NtClose(ProcessHandle);
00132     return SmpSbCreateSession(NULL,
00133                               NULL,
00134                               &ProcessInformation,
00135                               0,
00136                               SmExecPgm->DebugFlag ? &SmApiMsg->h.ClientId : NULL);
00137 }
00138 
00139 NTSTATUS
00140 NTAPI
00141 SmpLoadDeferedSubsystem(IN PSM_API_MSG SmApiMsg,
00142                         IN PSMP_CLIENT_CONTEXT ClientContext,
00143                         IN HANDLE SmApiPort)
00144 {
00145     DPRINT1("%s is not yet implemented\n", __FUNCTION__);
00146     return STATUS_NOT_IMPLEMENTED;
00147 }
00148 
00149 NTSTATUS
00150 NTAPI
00151 SmpStartCsr(IN PSM_API_MSG SmApiMsg,
00152             IN PSMP_CLIENT_CONTEXT ClientContext,
00153             IN HANDLE SmApiPort)
00154 {
00155     DPRINT1("%s is not yet implemented\n", __FUNCTION__);
00156     return STATUS_NOT_IMPLEMENTED;
00157 }
00158 
00159 NTSTATUS
00160 NTAPI
00161 SmpStopCsr(IN PSM_API_MSG SmApiMsg,
00162            IN PSMP_CLIENT_CONTEXT ClientContext,
00163            IN HANDLE SmApiPort)
00164 {
00165     DPRINT1("%s is not yet implemented\n", __FUNCTION__);
00166     return STATUS_NOT_IMPLEMENTED;
00167 }
00168 
00169 PSM_API_HANDLER SmpApiDispatch[SmMaxApiNumber] =
00170 {
00171     SmpCreateForeignSession,
00172     SmpSessionComplete,
00173     SmpTerminateForeignSession,
00174     SmpExecPgm,
00175     SmpLoadDeferedSubsystem,
00176     SmpStartCsr,
00177     SmpStopCsr
00178 };
00179 
00180 /* FUNCTIONS ******************************************************************/
00181 
00182 NTSTATUS
00183 NTAPI
00184 SmpHandleConnectionRequest(IN HANDLE SmApiPort,
00185                            IN PSB_API_MSG SbApiMsg)
00186 {
00187     BOOLEAN Accept = TRUE;
00188     HANDLE PortHandle, ProcessHandle;
00189     ULONG SessionId;
00190     UNICODE_STRING SubsystemPort;
00191     SMP_CLIENT_CONTEXT *ClientContext;
00192     NTSTATUS Status;
00193     OBJECT_ATTRIBUTES ObjectAttributes;
00194     REMOTE_PORT_VIEW PortView;
00195     SECURITY_QUALITY_OF_SERVICE SecurityQos;
00196     PSMP_SUBSYSTEM CidSubsystem, TypeSubsystem;
00197 
00198     /* Initialize QoS data */
00199     SecurityQos.ImpersonationLevel = SecurityIdentification;
00200     SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
00201     SecurityQos.EffectiveOnly = TRUE;
00202 
00203     /* Check if this is SM connecting to itself */
00204     if (SbApiMsg->h.ClientId.UniqueProcess == SmUniqueProcessId)
00205     {
00206         /* No need to get any handle -- assume session 0 */
00207         ProcessHandle = NULL;
00208         SessionId = 0;
00209     }
00210     else
00211     {
00212         /* Reference the foreign process */
00213         InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
00214         Status = NtOpenProcess(&ProcessHandle,
00215                                PROCESS_QUERY_INFORMATION,
00216                                &ObjectAttributes,
00217                                &SbApiMsg->h.ClientId);
00218         if (!NT_SUCCESS(Status)) Accept = FALSE;
00219 
00220         /* Get its session ID */
00221         SmpGetProcessMuSessionId(ProcessHandle, &SessionId);
00222     }
00223 
00224     /* See if we already know about the caller's subystem */
00225     CidSubsystem = SmpLocateKnownSubSysByCid(&SbApiMsg->h.ClientId);
00226     if ((CidSubsystem) && (Accept))
00227     {
00228         /* Check if we already have a subsystem for this kind of image */
00229         TypeSubsystem = SmpLocateKnownSubSysByType(SessionId,
00230                                                    SbApiMsg->ConnectionInfo.SubsystemType);
00231         if (TypeSubsystem == CidSubsystem)
00232         {
00233             /* Someone is trying to take control of an existing subsystem, fail */
00234             Accept = FALSE;
00235             DPRINT1("SMSS: Connection from SubSystem rejected\n");
00236             DPRINT1("SMSS: Image type already being served\n");
00237         }
00238         else
00239         {
00240             /* Set this image type as the type for this subsystem */
00241             CidSubsystem->ImageType = SbApiMsg->ConnectionInfo.SubsystemType;
00242         }
00243 
00244         /* Drop the reference we had acquired */
00245         if (TypeSubsystem) SmpDereferenceSubsystem(TypeSubsystem);
00246     }
00247 
00248     /* Check if we'll be accepting the connection */
00249     if (Accept)
00250     {
00251         /* We will, so create a client context for it */
00252         ClientContext = RtlAllocateHeap(SmpHeap, 0, sizeof(SMP_CLIENT_CONTEXT));
00253         if (ClientContext)
00254         {
00255             ClientContext->ProcessHandle = ProcessHandle;
00256             ClientContext->Subsystem = CidSubsystem;
00257             ClientContext->dword10 = 0;
00258             ClientContext->PortHandle = NULL;
00259         }
00260         else
00261         {
00262             /* Failed to allocate a client context, so reject the connection */
00263             DPRINT1("Rejecting connectiond due to lack of memory\n");
00264             Accept = FALSE;
00265         }
00266     }
00267     else
00268     {
00269         /* Use a bogus context since we're going to reject the message */
00270         ClientContext = (PSMP_CLIENT_CONTEXT)SbApiMsg;
00271     }
00272 
00273     /* Now send the actual accept reply (which could be a rejection) */
00274     PortView.Length = sizeof(PortView);
00275     Status = NtAcceptConnectPort(&PortHandle,
00276                                  ClientContext,
00277                                  &SbApiMsg->h,
00278                                  Accept,
00279                                  NULL,
00280                                  &PortView);
00281     if (!(Accept) || !(NT_SUCCESS(Status)))
00282     {
00283         /* Close the process handle, reference the subsystem, and exit */
00284         DPRINT1("Accept failed or rejected: %lx\n", Status);
00285         if (ClientContext != (PVOID)SbApiMsg) RtlFreeHeap(SmpHeap, 0, ClientContext);
00286         if (ProcessHandle) NtClose(ProcessHandle);
00287         if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
00288         return Status;
00289     }
00290 
00291     /* Save the port handle now that we've accepted it */
00292     if (ClientContext) ClientContext->PortHandle = PortHandle;
00293     if (CidSubsystem) CidSubsystem->PortHandle = PortHandle;
00294 
00295     /* Complete the port connection */
00296     Status = NtCompleteConnectPort(PortHandle);
00297     if ((NT_SUCCESS(Status)) && (CidSubsystem))
00298     {
00299         /* This was an actual subsystem, so connect back to it */
00300         SbApiMsg->ConnectionInfo.SbApiPortName[119] = UNICODE_NULL;
00301         RtlCreateUnicodeString(&SubsystemPort,
00302                                SbApiMsg->ConnectionInfo.SbApiPortName);
00303         Status = NtConnectPort(&CidSubsystem->SbApiPort,
00304                                &SubsystemPort,
00305                                &SecurityQos,
00306                                NULL,
00307                                NULL,
00308                                NULL,
00309                                NULL,
00310                                NULL);
00311         if (!NT_SUCCESS(Status))
00312         {
00313             DPRINT1("SMSS: Connect back to Sb %wZ failed %lx\n", &SubsystemPort, Status);
00314         }
00315         RtlFreeUnicodeString(&SubsystemPort);
00316 
00317         /* Now that we're connected, signal the event handle */
00318         NtSetEvent(CidSubsystem->Event, NULL);
00319     }
00320     else if (CidSubsystem)
00321     {
00322         /* We failed to complete the connection, so clear the port handle */
00323         DPRINT1("Completing the connection failed: %lx\n", Status);
00324         CidSubsystem->PortHandle = NULL;
00325     }
00326 
00327     /* Dereference the subsystem and return the result */
00328     if (CidSubsystem) SmpDereferenceSubsystem(CidSubsystem);
00329     return Status;
00330 }
00331 
00332 ULONG
00333 NTAPI
00334 SmpApiLoop(IN PVOID Parameter)
00335 {
00336     HANDLE SmApiPort = (HANDLE)Parameter;
00337     NTSTATUS Status;
00338     PSMP_CLIENT_CONTEXT ClientContext;
00339     PSM_API_MSG ReplyMsg = NULL;
00340     SM_API_MSG RequestMsg;
00341     PROCESS_BASIC_INFORMATION ProcessInformation;
00342     LARGE_INTEGER Timeout;
00343 
00344     /* Increase the number of API threads for throttling code for later */
00345     _InterlockedExchangeAdd(&SmTotalApiThreads, 1);
00346 
00347     /* Mark us critical */
00348     RtlSetThreadIsCritical(TRUE, NULL, TRUE);
00349 
00350     /* Set the PID of the SM process itself for later checking */
00351     NtQueryInformationProcess(NtCurrentProcess(),
00352                               ProcessBasicInformation,
00353                               &ProcessInformation,
00354                               sizeof(ProcessInformation),
00355                               NULL);
00356     SmUniqueProcessId = (HANDLE)ProcessInformation.UniqueProcessId;
00357 
00358     /* Now process incoming messages */
00359     while (TRUE)
00360     {
00361         /* Begin waiting on a request */
00362         Status = NtReplyWaitReceivePort(SmApiPort,
00363                                         (PVOID*)&ClientContext,
00364                                         &ReplyMsg->h,
00365                                         &RequestMsg.h);
00366         if (Status == STATUS_NO_MEMORY)
00367         {
00368             /* Ran out of memory, so do a little timeout and try again */
00369             if (ReplyMsg) DPRINT1("SMSS: Failed to reply to calling thread, retrying.\n");
00370             Timeout.QuadPart = -50000000;
00371             NtDelayExecution(FALSE, &Timeout);
00372             continue;
00373         }
00374 
00375         /* Check what kind of request we received */
00376         switch (RequestMsg.h.u2.s2.Type)
00377         {
00378             /* A new connection */
00379             case LPC_CONNECTION_REQUEST:
00380                 /* Create the right structures for it */
00381                 SmpHandleConnectionRequest(SmApiPort, (PSB_API_MSG)&RequestMsg);
00382                 ReplyMsg =  NULL;
00383                 break;
00384 
00385             /* A closed connection */
00386             case LPC_PORT_CLOSED:
00387                 /* Destroy any state we had for this client */
00388                 DPRINT1("Port closed\n");
00389                 //if (ClientContext) SmpPushDeferredClientContext(ClientContext);
00390                 ReplyMsg = NULL;
00391                 break;
00392 
00393             /* An actual API message */
00394             default:
00395                 if (!ClientContext)
00396                 {
00397                     ReplyMsg = NULL;
00398                     break;
00399                 }
00400 
00401                 RequestMsg.ReturnValue = STATUS_PENDING;
00402 
00403                 /* Check if the API is valid */
00404                 if (RequestMsg.ApiNumber >= SmMaxApiNumber)
00405                 {
00406                     /* It isn't, fail */
00407                     DPRINT1("Invalid API: %lx\n", RequestMsg.ApiNumber);
00408                     Status = STATUS_NOT_IMPLEMENTED;
00409                 }
00410                 else if ((RequestMsg.ApiNumber <= SmTerminateForeignSessionApi) &&
00411                          !(ClientContext->Subsystem))
00412                 {
00413                     /* It's valid, but doesn't have a subsystem with it */
00414                     DPRINT1("Invalid session API\n");
00415                     Status = STATUS_INVALID_PARAMETER;
00416                 }
00417                 else
00418                 {
00419                     /* It's totally okay, so call the dispatcher for it */
00420                     Status = SmpApiDispatch[RequestMsg.ApiNumber](&RequestMsg,
00421                                                                   ClientContext,
00422                                                                   SmApiPort);
00423                 }
00424 
00425                 /* Write the result valud and return the message back */
00426                 RequestMsg.ReturnValue = Status;
00427                 ReplyMsg = &RequestMsg;
00428                 break;
00429         }
00430     }
00431     return STATUS_SUCCESS;
00432 }

Generated on Sat May 26 2012 04:17:44 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.