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

smsubsys.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 RTL_CRITICAL_SECTION SmpKnownSubSysLock;
00018 LIST_ENTRY SmpKnownSubSysHead;
00019 HANDLE SmpWindowsSubSysProcess;
00020 HANDLE SmpWindowsSubSysProcessId;
00021 BOOLEAN RegPosixSingleInstance;
00022 WCHAR InitialCommandBuffer[256];
00023 
00024 /* FUNCTIONS ******************************************************************/
00025 
00026 NTSTATUS
00027 NTAPI
00028 SmpCallCsrCreateProcess(IN PSB_API_MSG SbApiMsg,
00029                         IN USHORT MessageLength,
00030                         IN HANDLE PortHandle)
00031 {
00032     NTSTATUS Status;
00033 
00034     /* Initialize the header and send the message to CSRSS */
00035     SbApiMsg->h.u2.ZeroInit = 0;
00036     SbApiMsg->h.u1.s1.DataLength = MessageLength + 8;
00037     SbApiMsg->h.u1.s1.TotalLength = sizeof(SB_API_MSG);
00038     SbApiMsg->ApiNumber = SbpCreateProcess;
00039     Status = NtRequestWaitReplyPort(PortHandle, &SbApiMsg->h, &SbApiMsg->h);
00040     if (NT_SUCCESS(Status)) Status = SbApiMsg->ReturnValue;
00041     return Status;
00042 }
00043 
00044 VOID
00045 NTAPI
00046 SmpDereferenceSubsystem(IN PSMP_SUBSYSTEM SubSystem)
00047 {
00048     /* Acquire the database lock while we (potentially) destroy this subsystem */
00049     RtlEnterCriticalSection(&SmpKnownSubSysLock);
00050 
00051     /* Drop the reference and see if it's terminating */
00052     if (!(--SubSystem->ReferenceCount) && (SubSystem->Terminating))
00053     {
00054         /* Close all handles and free it */
00055         if (SubSystem->Event) NtClose(SubSystem->Event);
00056         if (SubSystem->ProcessHandle) NtClose(SubSystem->ProcessHandle);
00057         if (SubSystem->SbApiPort) NtClose(SubSystem->SbApiPort);
00058         RtlFreeHeap(SmpHeap, 0, SubSystem);
00059     }
00060 
00061     /* Release the database lock */
00062     RtlLeaveCriticalSection(&SmpKnownSubSysLock);
00063 }
00064 
00065 PSMP_SUBSYSTEM
00066 NTAPI
00067 SmpLocateKnownSubSysByCid(IN PCLIENT_ID ClientId)
00068 {
00069     PSMP_SUBSYSTEM Subsystem = NULL;
00070     PLIST_ENTRY NextEntry;
00071 
00072     /* Lock the subsystem database */
00073     RtlEnterCriticalSection(&SmpKnownSubSysLock);
00074 
00075     /* Loop each subsystem in the database */
00076     NextEntry = SmpKnownSubSysHead.Flink;
00077     while (NextEntry != &SmpKnownSubSysHead)
00078     {
00079         /* Check if this one matches the client ID and is still valid */
00080         Subsystem = CONTAINING_RECORD(NextEntry, SMP_SUBSYSTEM, Entry);
00081         if ((*(PULONGLONG)&Subsystem->ClientId == *(PULONGLONG)ClientId) &&
00082             !(Subsystem->Terminating))
00083         {
00084             /* Add a reference and return it */
00085             Subsystem->ReferenceCount++;
00086             break;
00087         }
00088 
00089         /* Reset the current pointer and keep earching */
00090         Subsystem = NULL;
00091         NextEntry = NextEntry->Flink;
00092     }
00093 
00094     /* Release the lock and return the subsystem we found */
00095     RtlLeaveCriticalSection(&SmpKnownSubSysLock);
00096     return Subsystem;
00097 }
00098 
00099 PSMP_SUBSYSTEM
00100 NTAPI
00101 SmpLocateKnownSubSysByType(IN ULONG MuSessionId,
00102                            IN ULONG ImageType)
00103 {
00104     PSMP_SUBSYSTEM Subsystem = NULL;
00105     PLIST_ENTRY NextEntry;
00106 
00107     /* Lock the subsystem database */
00108     RtlEnterCriticalSection(&SmpKnownSubSysLock);
00109 
00110     /* Loop each subsystem in the database */
00111     NextEntry = SmpKnownSubSysHead.Flink;
00112     while (NextEntry != &SmpKnownSubSysHead)
00113     {
00114         /* Check if this one matches the image and uID, and is still valid */
00115         Subsystem = CONTAINING_RECORD(NextEntry, SMP_SUBSYSTEM, Entry);
00116         if ((Subsystem->ImageType == ImageType) &&
00117             !(Subsystem->Terminating) &&
00118             (Subsystem->MuSessionId == MuSessionId))
00119         {
00120             /* Return it referenced for the caller */
00121             Subsystem->ReferenceCount++;
00122             break;
00123         }
00124 
00125         /* Reset the current pointer and keep earching */
00126         Subsystem = NULL;
00127         NextEntry = NextEntry->Flink;
00128     }
00129 
00130     /* Release the lock and return the subsystem we found */
00131     RtlLeaveCriticalSection(&SmpKnownSubSysLock);
00132     return Subsystem;
00133 }
00134 
00135 NTSTATUS
00136 NTAPI
00137 SmpLoadSubSystem(IN PUNICODE_STRING FileName,
00138                  IN PUNICODE_STRING Directory,
00139                  IN PUNICODE_STRING CommandLine,
00140                  IN ULONG MuSessionId,
00141                  OUT PHANDLE ProcessId,
00142                  IN ULONG Flags)
00143 {
00144     PSMP_SUBSYSTEM Subsystem, NewSubsystem, KnownSubsystem = NULL;
00145     HANDLE SubSysProcessId;
00146     NTSTATUS Status = STATUS_SUCCESS;
00147     SB_API_MSG SbApiMsg, SbApiMsg2;
00148     RTL_USER_PROCESS_INFORMATION ProcessInformation;
00149     LARGE_INTEGER Timeout;
00150     PVOID State;
00151     PSB_CREATE_PROCESS_MSG CreateProcess = &SbApiMsg.CreateProcess;
00152     PSB_CREATE_SESSION_MSG CreateSession = &SbApiMsg.CreateSession;
00153 
00154     /* Make sure this is a found subsystem */
00155     if (Flags & SMP_INVALID_PATH)
00156     {
00157         DPRINT1("SMSS: Unable to find subsystem - %wZ\n", FileName);
00158         return STATUS_OBJECT_NAME_NOT_FOUND;
00159     }
00160 
00161     /* Don't use a session if the flag is set */
00162     if (Flags & 0x80) MuSessionId = 0;
00163 
00164     /* Lock the subsystems while we do a look up */
00165     RtlEnterCriticalSection(&SmpKnownSubSysLock);
00166     while (TRUE)
00167     {
00168         /* Check if we found a subsystem not yet fully iniitalized */
00169         Subsystem = SmpLocateKnownSubSysByType(MuSessionId, -1);
00170         if (!Subsystem) break;
00171         RtlLeaveCriticalSection(&SmpKnownSubSysLock);
00172 
00173         /* Wait on it to initialize */
00174         NtWaitForSingleObject(Subsystem->Event, FALSE, NULL);
00175 
00176         /* Dereference it and try the next one */
00177         RtlEnterCriticalSection(&SmpKnownSubSysLock);
00178         SmpDereferenceSubsystem(Subsystem);
00179     }
00180 
00181     /* Check if this is a POSIX subsystem */
00182     if (Flags & SMP_POSIX_FLAG)
00183     {
00184         /* Do we already have it? */
00185         Subsystem = SmpLocateKnownSubSysByType(MuSessionId, IMAGE_SUBSYSTEM_POSIX_CUI);
00186     }
00187     else if (Flags & SMP_OS2_FLAG)
00188     {
00189         /* This is an OS/2 subsystem, do we we already have it? */
00190         Subsystem = SmpLocateKnownSubSysByType(MuSessionId, IMAGE_SUBSYSTEM_OS2_CUI);
00191     }
00192 
00193     /* Check if we already have one of the optional subsystems for the session */
00194     if (Subsystem)
00195     {
00196         /* Dereference and return, no work to do */
00197         SmpDereferenceSubsystem(Subsystem);
00198         RtlLeaveCriticalSection(&SmpKnownSubSysLock);
00199         return STATUS_SUCCESS;
00200     }
00201 
00202     /* Allocate a new subsystem! */
00203     NewSubsystem = RtlAllocateHeap(SmpHeap, SmBaseTag, sizeof(SMP_SUBSYSTEM));
00204     if (!NewSubsystem)
00205     {
00206         RtlLeaveCriticalSection(&SmpKnownSubSysLock);
00207         return STATUS_NO_MEMORY;
00208     }
00209 
00210     /* Initialize its header and reference count */
00211     NewSubsystem->ReferenceCount = 1;
00212     NewSubsystem->MuSessionId = MuSessionId;
00213     NewSubsystem->ImageType = -1;
00214 
00215     /* Clear out all the other data for now */
00216     NewSubsystem->Terminating = FALSE;
00217     NewSubsystem->ProcessHandle = NULL;
00218     NewSubsystem->Event = NULL;
00219     NewSubsystem->PortHandle = NULL;
00220     NewSubsystem->SbApiPort = NULL;
00221 
00222     /* Create the event we'll be wating on for initialization */
00223     Status = NtCreateEvent(&NewSubsystem->Event,
00224                            EVENT_ALL_ACCESS,
00225                            NULL,
00226                            NotificationEvent,
00227                            FALSE);
00228     if (!NT_SUCCESS(Status))
00229     {
00230         /* This failed, bail out */
00231         RtlFreeHeap(SmpHeap, 0, NewSubsystem);
00232         RtlLeaveCriticalSection(&SmpKnownSubSysLock);
00233         return STATUS_NO_MEMORY;
00234     }
00235 
00236     /* Insert the subsystem and release the lock. It can now be found */
00237     InsertTailList(&SmpKnownSubSysHead, &NewSubsystem->Entry);
00238     RtlLeaveCriticalSection(&SmpKnownSubSysLock);
00239 
00240     /* The OS/2 and POSIX subsystems are actually Windows applications! */
00241     if (Flags & (SMP_POSIX_FLAG | SMP_OS2_FLAG))
00242     {
00243         /* Locate the Windows subsystem for this session */
00244         KnownSubsystem = SmpLocateKnownSubSysByType(MuSessionId,
00245                                                     IMAGE_SUBSYSTEM_WINDOWS_GUI);
00246         if (!KnownSubsystem)
00247         {
00248             DPRINT1("SMSS: SmpLoadSubSystem - SmpLocateKnownSubSysByType Failed\n");
00249             goto Quickie2;
00250         }
00251 
00252         /* Fill out all the process details and call CSRSS to launch it */
00253         CreateProcess->In.ImageName = FileName;
00254         CreateProcess->In.CurrentDirectory = Directory;
00255         CreateProcess->In.CommandLine = CommandLine;
00256         CreateProcess->In.DllPath = SmpDefaultLibPath.Length ?
00257                                     &SmpDefaultLibPath : NULL;
00258         CreateProcess->In.Flags = Flags | SMP_DEFERRED_FLAG;
00259         CreateProcess->In.DebugFlags = SmpDebug;
00260         Status = SmpCallCsrCreateProcess(&SbApiMsg,
00261                                          sizeof(*CreateProcess),
00262                                          KnownSubsystem->SbApiPort);
00263         if (!NT_SUCCESS(Status))
00264         {
00265             /* Handle failures */
00266             DPRINT1("SMSS: SmpLoadSubSystem - SmpCallCsrCreateProcess Failed with  Status %lx\n",
00267                     Status);
00268             goto Quickie2;
00269         }
00270 
00271         /* Save the process information we'll need for the create session */
00272         ProcessInformation.ProcessHandle = CreateProcess->Out.ProcessHandle;
00273         ProcessInformation.ThreadHandle = CreateProcess->Out.ThreadHandle;
00274         ProcessInformation.ClientId = CreateProcess->Out.ClientId;
00275         ProcessInformation.ImageInformation.SubSystemType = CreateProcess->Out.SubsystemType;
00276     }
00277     else
00278     {
00279         /* This must be CSRSS itself, so just launch it and that's it */
00280         Status = SmpExecuteImage(FileName,
00281                                  Directory,
00282                                  CommandLine,
00283                                  MuSessionId,
00284                                  Flags | SMP_DEFERRED_FLAG,
00285                                  &ProcessInformation);
00286         if (!NT_SUCCESS(Status))
00287         {
00288             /* Handle failures */
00289             DPRINT1("SMSS: SmpLoadSubSystem - SmpExecuteImage Failed with  Status %lx\n",
00290                     Status);
00291             goto Quickie2;
00292         }
00293     }
00294 
00295     /* Fill out the handle and client ID in the subsystem structure now */
00296     NewSubsystem->ProcessHandle = ProcessInformation.ProcessHandle;
00297     NewSubsystem->ClientId = ProcessInformation.ClientId;
00298 
00299     /* Check if we launched a native image or a subsystem-backed image */
00300     if (ProcessInformation.ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_NATIVE)
00301     {
00302         /* This must be CSRSS itself, since it's a native subsystem image */
00303         SubSysProcessId = ProcessInformation.ClientId.UniqueProcess;
00304         if ((ProcessId) && !(*ProcessId)) *ProcessId = SubSysProcessId;
00305 
00306         /* Was this the initial CSRSS on Session 0? */
00307         if (!MuSessionId)
00308         {
00309             /* Then save it in the global variables */
00310             SmpWindowsSubSysProcessId = SubSysProcessId;
00311             SmpWindowsSubSysProcess = ProcessInformation.ProcessHandle;
00312         }
00313         ASSERT(NT_SUCCESS(Status));
00314     }
00315     else
00316     {
00317         /* This is the POSIX or OS/2 subsystem process, copy its information */
00318         RtlCopyMemory(&CreateSession->ProcessInfo,
00319                       &ProcessInformation,
00320                       sizeof(CreateSession->ProcessInfo));
00321 
00322         /* Not sure these field mean what I think they do -- but clear them */
00323         *(PULONGLONG)&CreateSession->ClientId = 0;
00324         CreateSession->MuSessionId = 0;
00325 
00326         /* This should find CSRSS because they are POSIX or OS/2 subsystems */
00327         Subsystem = SmpLocateKnownSubSysByType(MuSessionId,
00328                                                ProcessInformation.ImageInformation.SubSystemType);
00329         if (!Subsystem)
00330         {
00331             /* Odd failure -- but handle it anyway */
00332             Status = STATUS_NO_SUCH_PACKAGE;
00333             DPRINT1("SMSS: SmpLoadSubSystem - SmpLocateKnownSubSysByType Failed with  Status %lx for sessionid %ld\n",
00334                     Status,
00335                     MuSessionId);
00336             goto Quickie;
00337         }
00338 
00339         /* Duplicate the parent process handle for the subsystem to have */
00340         Status = NtDuplicateObject(NtCurrentProcess(),
00341                                    ProcessInformation.ProcessHandle,
00342                                    Subsystem->ProcessHandle,
00343                                    &CreateSession->ProcessInfo.ProcessHandle,
00344                                    PROCESS_ALL_ACCESS,
00345                                    0,
00346                                    0);
00347         if (!NT_SUCCESS(Status))
00348         {
00349             /* Fail since this is critical */
00350             DPRINT1("SMSS: SmpLoadSubSystem - NtDuplicateObject Failed with  Status %lx for sessionid %ld\n",
00351                     Status,
00352                     MuSessionId);
00353             goto Quickie;
00354         }
00355 
00356         /* Duplicate the initial thread handle for the subsystem to have */
00357         Status = NtDuplicateObject(NtCurrentProcess(),
00358                                    ProcessInformation.ThreadHandle,
00359                                    Subsystem->ProcessHandle,
00360                                    &CreateSession->ProcessInfo.ThreadHandle,
00361                                    THREAD_ALL_ACCESS,
00362                                    0,
00363                                    0);
00364         if (!NT_SUCCESS(Status))
00365         {
00366             /* Fail since this is critical */
00367             DPRINT1("SMSS: SmpLoadSubSystem - NtDuplicateObject Failed with  Status %lx for sessionid %ld\n",
00368                     Status,
00369                     MuSessionId);
00370             goto Quickie;
00371         }
00372 
00373         /* Allocate an internal Session ID for this subsystem */
00374         MuSessionId = SmpAllocateSessionId(Subsystem, 0);
00375         CreateSession->SessionId = MuSessionId;
00376 
00377         /* Send the create session message to the subsystem */
00378         SbApiMsg2.ReturnValue = STATUS_SUCCESS;
00379         SbApiMsg2.h.u2.ZeroInit = 0;
00380         SbApiMsg2.h.u1.s1.DataLength = sizeof(SB_CREATE_SESSION_MSG) + 8;
00381         SbApiMsg2.h.u1.s1.TotalLength = sizeof(SB_API_MSG);
00382         Status = NtRequestWaitReplyPort(Subsystem->SbApiPort,
00383                                         &SbApiMsg2.h,
00384                                         &SbApiMsg2.h);
00385         if (NT_SUCCESS(Status)) Status = SbApiMsg2.ReturnValue;
00386         if (!NT_SUCCESS(Status))
00387         {
00388             /* Delete the session and handle failure if the LPC call failed */
00389             SmpDeleteSession(CreateSession->SessionId);
00390             DPRINT1("SMSS: SmpLoadSubSystem - NtRequestWaitReplyPort Failed with  Status %lx for sessionid %ld\n",
00391                     Status,
00392                     CreateSession->SessionId);
00393             goto Quickie;
00394         }
00395     }
00396 
00397     /* Okay, everything looks good to go, initialize this subsystem now! */
00398     Status = NtResumeThread(ProcessInformation.ThreadHandle, NULL);
00399     if (!NT_SUCCESS(Status))
00400     {
00401         /* That didn't work -- back out of everything */
00402         DPRINT1("SMSS: SmpLoadSubSystem - NtResumeThread failed Status %lx\n", Status);
00403         goto Quickie;
00404     }
00405 
00406     /* Check if this was the subsystem for a different session */
00407     if (MuSessionId)
00408     {
00409         /* Wait up to 60 seconds for it to initialize */
00410         Timeout.QuadPart = -600000000;
00411         Status = NtWaitForSingleObject(NewSubsystem->Event, FALSE, &Timeout);
00412 
00413         /* Timeout is done -- does this session still exist? */
00414         if (!SmpCheckDuplicateMuSessionId(MuSessionId))
00415         {
00416             /* Nope, it died. Cleanup should've ocurred in a different path. */
00417             DPRINT1("SMSS: SmpLoadSubSystem - session deleted\n");
00418             return STATUS_DELETE_PENDING;
00419         }
00420 
00421         /* Check if we timed our or there was another error with the wait */
00422         if (Status != STATUS_WAIT_0)
00423         {
00424             /* Something is wrong with the subsystem, so back out of everything */
00425             DPRINT1("SMSS: SmpLoadSubSystem - Timeout waiting for subsystem connect with Status %lx for sessionid %ld\n",
00426                     Status,
00427                     MuSessionId);
00428             goto Quickie;
00429         }
00430     }
00431     else
00432     {
00433         /* This a session 0 subsystem, just wait for it to initialize */
00434         NtWaitForSingleObject(NewSubsystem->Event, FALSE, NULL);
00435     }
00436 
00437     /* Subsystem is created, resumed, and initialized. Close handles and exit */
00438     NtClose(ProcessInformation.ThreadHandle);
00439     Status = STATUS_SUCCESS;
00440     goto Quickie2;
00441 
00442 Quickie:
00443     /* This is the failure path. First check if we need to detach from session */
00444     if ((AttachedSessionId == -1) || (Flags & (SMP_POSIX_FLAG | SMP_OS2_FLAG)))
00445     {
00446         /* We were not attached, or did not launch subsystems that required it */
00447         DPRINT1("SMSS: Did not detach from Session Space: SessionId=%x Flags=%x Status=%x\n",
00448                 AttachedSessionId,
00449                 Flags | SMP_DEFERRED_FLAG,
00450                 Status);
00451     }
00452     else
00453     {
00454         /* Get the privilege we need for detachment */
00455         Status = SmpAcquirePrivilege(SE_LOAD_DRIVER_PRIVILEGE, &State);
00456         if (!NT_SUCCESS(Status))
00457         {
00458             /* We can't detach without it */
00459             DPRINT1("SMSS: Did not detach from Session Space: SessionId=%x Flags=%x Status=%x\n",
00460                     AttachedSessionId,
00461                     Flags | SMP_DEFERRED_FLAG,
00462                     Status);
00463         }
00464         else
00465         {
00466             /* Now detach from the session */
00467             Status = NtSetSystemInformation(SystemSessionDetach,
00468                                             &AttachedSessionId,
00469                                             sizeof(AttachedSessionId));
00470             if (!NT_SUCCESS(Status))
00471             {
00472                 /* Failed to detach. Note the DPRINT1 has a typo in Windows */
00473                 DPRINT1("SMSS: SmpStartCsr, Couldn't Detach from Session Space. Status=%x\n", Status);
00474                 ASSERT(NT_SUCCESS(Status));
00475             }
00476             else
00477             {
00478                 /* Detachment worked, reset our attached session ID */
00479                 AttachedSessionId = -1;
00480             }
00481 
00482             /* And release the privilege we acquired */
00483             SmpReleasePrivilege(State);
00484         }
00485     }
00486 
00487     /* Since this is the failure path, terminate the subsystem process */
00488     NtTerminateProcess(ProcessInformation.ProcessHandle, Status);
00489     NtClose(ProcessInformation.ThreadHandle);
00490 
00491 Quickie2:
00492     /* This is the cleanup path -- first dereference our subsystems */
00493     RtlEnterCriticalSection(&SmpKnownSubSysLock);
00494     if (Subsystem) SmpDereferenceSubsystem(Subsystem);
00495     if (KnownSubsystem) SmpDereferenceSubsystem(KnownSubsystem);
00496 
00497     /* In the failure case, destroy the new subsystem we just created */
00498     if (!NT_SUCCESS(Status))
00499     {
00500         RemoveEntryList(&NewSubsystem->Entry);
00501         NtSetEvent(NewSubsystem->Event, 0);
00502         if (NewSubsystem) SmpDereferenceSubsystem(NewSubsystem);
00503     }
00504 
00505     /* Finally, we're all done! */
00506     RtlLeaveCriticalSection(&SmpKnownSubSysLock);
00507     return Status;
00508 }
00509 
00510 NTSTATUS
00511 NTAPI
00512 SmpLoadSubSystemsForMuSession(IN PULONG MuSessionId,
00513                               OUT PHANDLE ProcessId,
00514                               IN PUNICODE_STRING InitialCommand)
00515 {
00516     NTSTATUS Status = STATUS_SUCCESS, Status2;
00517     PSMP_REGISTRY_VALUE RegEntry;
00518     UNICODE_STRING DestinationString, NtPath;
00519     PLIST_ENTRY NextEntry;
00520     LARGE_INTEGER Timeout;
00521     PVOID State;
00522 
00523     /* Write a few last registry keys with the boot partition information */
00524     SmpTranslateSystemPartitionInformation();
00525 
00526     /* Process "SetupExecute" values */
00527     NextEntry = SmpSetupExecuteList.Flink;
00528     while (NextEntry != &SmpSetupExecuteList)
00529     {
00530         /* Execute each one and move on */
00531         RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
00532         SmpExecuteCommand(&RegEntry->Name, 0, NULL, 0);
00533         NextEntry = NextEntry->Flink;
00534     }
00535 
00536     /* Now process the subsystems */
00537     NextEntry = SmpSubSystemList.Flink;
00538     while (NextEntry != &SmpSubSystemList)
00539     {
00540         /* Get the entry and check if this is the special Win32k entry */
00541         RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
00542         if (!_wcsicmp(RegEntry->Name.Buffer, L"Kmode"))
00543         {
00544             /* Translate it */
00545             if (!RtlDosPathNameToNtPathName_U(RegEntry->Value.Buffer,
00546                                               &NtPath,
00547                                               NULL,
00548                                               NULL))
00549             {
00550                 Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
00551                 DPRINT1("Failed: %lx\n", Status);
00552             }
00553             else
00554             {
00555                 /* Get the driver privilege */
00556                 Status = SmpAcquirePrivilege(SE_LOAD_DRIVER_PRIVILEGE, &State);
00557                 if (NT_SUCCESS(Status))
00558                 {
00559                     /* Create the new session */
00560                     ASSERT(AttachedSessionId == -1);
00561                     Status = NtSetSystemInformation(SystemSessionCreate,
00562                                                     MuSessionId,
00563                                                     sizeof(*MuSessionId));
00564                     if (!NT_SUCCESS(Status))
00565                     {
00566                         DPRINT1("SMSS: Session space creation failed\n");
00567                         SmpReleasePrivilege(State);
00568                         RtlFreeHeap(RtlGetProcessHeap(), 0, NtPath.Buffer);
00569                         return Status;
00570                     }
00571                     AttachedSessionId = *MuSessionId;
00572 
00573                     /* Start Win32k.sys on this session */
00574                     RtlInitUnicodeString(&DestinationString,
00575                                          L"\\SystemRoot\\System32\\win32k.sys");
00576                     Status = NtSetSystemInformation(SystemExtendServiceTableInformation,
00577                                                     &DestinationString,
00578                                                     sizeof(DestinationString));
00579                     RtlFreeHeap(RtlGetProcessHeap(), 0, NtPath.Buffer);
00580                     SmpReleasePrivilege(State);
00581                     if (!NT_SUCCESS(Status))
00582                     {
00583                         DPRINT1("SMSS: Load of WIN32K failed.\n");
00584                         return Status;
00585                     }
00586                 }
00587             }
00588         }
00589 
00590         /* Next entry */
00591         NextEntry = NextEntry->Flink;
00592     }
00593 
00594     /* Now parse the required subsystem list */
00595     NextEntry = SmpSubSystemsToLoad.Flink;
00596     while (NextEntry != &SmpSubSystemsToLoad)
00597     {
00598         /* Get each entry and check if it's the internal debug or not */
00599         RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
00600         if (_wcsicmp(RegEntry->Name.Buffer, L"debug"))
00601         {
00602             /* Load the required subsystem */
00603             Status = SmpExecuteCommand(&RegEntry->Value,
00604                                        *MuSessionId,
00605                                        ProcessId,
00606                                        SMP_SUBSYSTEM_FLAG);
00607         }
00608         else
00609         {
00610             /* Load the internal debug system */
00611             Status = SmpExecuteCommand(&RegEntry->Value,
00612                                        *MuSessionId,
00613                                        ProcessId,
00614                                        SMP_DEBUG_FLAG | SMP_SUBSYSTEM_FLAG);
00615         }
00616         if (!NT_SUCCESS(Status))
00617         {
00618             DbgPrint("SMSS: Subsystem execute failed (%WZ)\n", &RegEntry->Value);
00619             return Status;
00620         }
00621 
00622         /* Move to the next entry */
00623         NextEntry = NextEntry->Flink;
00624     }
00625 
00626     /* Process the "Execute" list now */
00627     NextEntry = SmpExecuteList.Blink;
00628     if (NextEntry != &SmpExecuteList)
00629     {
00630         /* Get the custom initial command */
00631         RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
00632 
00633         /* Write the initial command and wait for 5 seconds (why??!) */
00634         *InitialCommand = RegEntry->Name;
00635         Timeout.QuadPart = -50000000;
00636         NtDelayExecution(FALSE, &Timeout);
00637     }
00638     else
00639     {
00640         /* Use the default Winlogon initial command */
00641         RtlInitUnicodeString(InitialCommand, L"winlogon.exe");
00642         InitialCommandBuffer[0] = UNICODE_NULL;
00643 
00644         /* Check if there's a debugger for Winlogon */
00645         Status2 = LdrQueryImageFileExecutionOptions(InitialCommand,
00646                                                     L"Debugger",
00647                                                     REG_SZ,
00648                                                     InitialCommandBuffer,
00649                                                     sizeof(InitialCommandBuffer) -
00650                                                     InitialCommand->Length,
00651                                                     NULL);
00652         if ((NT_SUCCESS(Status2)) && (InitialCommandBuffer[0]))
00653         {
00654             /* Put the debugger string with the Winlogon string */
00655             wcscat(InitialCommandBuffer, L" ");
00656             wcscat(InitialCommandBuffer, InitialCommand->Buffer);
00657             RtlInitUnicodeString(InitialCommand, InitialCommandBuffer);
00658         }
00659     }
00660 
00661     /* Finally check if there was a custom initial command */
00662     NextEntry = SmpExecuteList.Flink;
00663     while (NextEntry != &SmpExecuteList)
00664     {
00665         /* Execute each one */
00666         RegEntry = CONTAINING_RECORD(NextEntry, SMP_REGISTRY_VALUE, Entry);
00667         SmpExecuteCommand(&RegEntry->Name, *MuSessionId, NULL, 0);
00668         NextEntry = NextEntry->Flink;
00669     }
00670 
00671     /* Return status */
00672     return Status;
00673 }
00674 

Generated on Sun May 27 2012 04:18:53 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.