SM: change the way sessions are managed.
authorEmanuele Aliberti <ea@iol.it>
Sun, 22 May 2005 15:54:15 +0000 (15:54 +0000)
committerEmanuele Aliberti <ea@iol.it>
Sun, 22 May 2005 15:54:15 +0000 (15:54 +0000)
(it may be buggy)

svn path=/trunk/; revision=15467

reactos/subsys/smss/client.c
reactos/subsys/smss/initmv.c
reactos/subsys/smss/initrun.c
reactos/subsys/smss/initss.c
reactos/subsys/smss/smapi.c
reactos/subsys/smss/smapicomp.c
reactos/subsys/smss/smapiexec.c
reactos/subsys/smss/smss.c
reactos/subsys/smss/smss.h

index 212e333..94e52b7 100644 (file)
@@ -39,9 +39,11 @@ struct _SM_CLIENT_DIRECTORY
        RTL_CRITICAL_SECTION  Lock;\r
        ULONG                 Count;\r
        PSM_CLIENT_DATA       Client;\r
+       PSM_CLIENT_DATA       CandidateClient;\r
 \r
 } SmpClientDirectory;\r
 \r
+\r
 /**********************************************************************\r
  *     SmInitializeClientManagement/0\r
  */\r
@@ -52,56 +54,41 @@ SmInitializeClientManagement (VOID)
        RtlInitializeCriticalSection(& SmpClientDirectory.Lock);\r
        SmpClientDirectory.Count = 0;\r
        SmpClientDirectory.Client = NULL;\r
+       SmpClientDirectory.CandidateClient = NULL;\r
        return STATUS_SUCCESS;\r
 \r
 }\r
-\r
 /**********************************************************************\r
- *     SmCompleteClientInitialization/1\r
- *\r
- * DESCRIPTION\r
- *     Lookup the subsystem server descriptor given the process handle\r
- *     of the subsystem server process.\r
+ * SmpSetClientInitialized/1\r
  */\r
-NTSTATUS STDCALL\r
-SmCompleteClientInitialization (HANDLE hProcess)\r
+VOID FASTCALL\r
+SmpSetClientInitialized (PSM_CLIENT_DATA Client)\r
 {\r
-       NTSTATUS        Status = STATUS_SUCCESS;\r
-       PSM_CLIENT_DATA Client = NULL;\r
-\r
-       DPRINT("SM: %s called\n", __FUNCTION__);\r
-\r
-       RtlEnterCriticalSection (& SmpClientDirectory.Lock);\r
-       if (SmpClientDirectory.Count > 0)\r
-       {\r
-               Client = SmpClientDirectory.Client;\r
-               while (NULL != Client)\r
-               {\r
-                       if (hProcess == Client->ServerProcess)\r
-                       {\r
-                               Client->Initialized = TRUE;\r
-                               break;\r
-                       }\r
-                       Client = Client->Next;\r
-               }\r
-               Status = STATUS_NOT_FOUND;\r
-       }\r
-       RtlLeaveCriticalSection (& SmpClientDirectory.Lock);\r
-       return Status;\r
+       Client->Flags |= SM_CLIENT_FLAG_INITIALIZED;\r
 }\r
-\r
 /**********************************************************************\r
- *     SmpLookupClient/1                                       PRIVATE\r
+ *     SmpLookupClient/2                                       PRIVATE\r
  *\r
  * DESCRIPTION\r
  *     Lookup the subsystem server descriptor given its image ID.\r
  *\r
- * SIDE EFFECTS\r
- *     SmpClientDirectory.Lock is released only on success.\r
+ * ARGUMENTS\r
+ *     SubsystemId: IMAGE_SUBSYSTEM_xxx\r
+ *     Parent: optional: caller provided storage for the\r
+ *             the pointer to the SM_CLIENT_DATA which\r
+ *             Next field contains the value returned by\r
+ *             the function (on success).\r
+ *\r
+ * RETURN VALUES\r
+ *     NULL on error; otherwise a pointer to the SM_CLIENT_DATA\r
+ *     looked up object.\r
+ *\r
+ * WARNING\r
+ *     SmpClientDirectory.Lock must be held by the caller.\r
  */\r
 static PSM_CLIENT_DATA FASTCALL\r
-SmpLookupClientUnsafe (USHORT           SubsystemId,\r
-                      PSM_CLIENT_DATA  * Parent)\r
+SmpLookupClient (USHORT           SubsystemId,\r
+                PSM_CLIENT_DATA  * Parent)\r
 {\r
        PSM_CLIENT_DATA Client = NULL;\r
 \r
@@ -129,72 +116,86 @@ SmpLookupClientUnsafe (USHORT           SubsystemId,
        }\r
        return Client;\r
 }\r
-\r
-static PSM_CLIENT_DATA STDCALL\r
-SmpLookupClient (USHORT SubsystemId)\r
-{\r
-       PSM_CLIENT_DATA Client = NULL;\r
-\r
-       DPRINT("SM: %s called\n", __FUNCTION__);\r
-\r
-       RtlEnterCriticalSection (& SmpClientDirectory.Lock);\r
-       Client = SmpLookupClientUnsafe (SubsystemId, NULL);\r
-       if(NULL != Client)\r
-       {\r
-               RtlLeaveCriticalSection (& SmpClientDirectory.Lock);\r
-       }\r
-       /*\r
-        * Note that we do *not* release SmpClientDirectory.Lock here\r
-        * because SmpLookupClient is called to FAIL when SubsystemId\r
-        * is not registered yet.\r
-        */\r
-       return Client;\r
-}\r
-\r
 /**********************************************************************\r
- *     SmpCreateClient/2\r
+ *     SmBeginClientInitialization/1\r
+ *\r
+ * DESCRIPTION\r
+ *     Check if the candidate client matches the begin session\r
+ *     message from the subsystem process.\r
+ *\r
+ * ARGUMENTS\r
+ *     Request: message received by \SmApiPort\r
+ *     ClientData:\r
+ *             \r
+ * RETURN VALUES\r
+ *     NTSTATUS\r
  */\r
 NTSTATUS STDCALL\r
-SmCreateClient(PSM_PORT_MESSAGE Request, PSM_CLIENT_DATA * ClientData)\r
+SmBeginClientInitialization (IN  PSM_PORT_MESSAGE Request,\r
+                            OUT PSM_CLIENT_DATA  * ClientData)\r
 {\r
-       PSM_CLIENT_DATA pClient = NULL;\r
+       NTSTATUS Status = STATUS_SUCCESS;\r
        PSM_CONNECT_DATA ConnectData = SmpGetConnectData (Request);\r
        ULONG SbApiPortNameSize = SM_CONNECT_DATA_SIZE(*Request);\r
 \r
-       DPRINT("SM: %s called\n", __FUNCTION__);\r
 \r
+       DPRINT("SM: %s called\n", __FUNCTION__);\r
+       \r
+       RtlEnterCriticalSection (& SmpClientDirectory.Lock);\r
+       /*\r
+        * Is there a subsystem bootstrap in progress?\r
+        */\r
+       if (SmpClientDirectory.CandidateClient)\r
+       {\r
+               PROCESS_BASIC_INFORMATION pbi;\r
+               \r
+               RtlZeroMemory (& pbi, sizeof pbi);\r
+               Status = NtQueryInformationProcess (Request->Header.ClientId.UniqueProcess,\r
+                                                   ProcessBasicInformation,\r
+                                                   & pbi,\r
+                                                   sizeof pbi,\r
+                                                   NULL);\r
+               if (NT_SUCCESS(Status))\r
+               {\r
+                       SmpClientDirectory.CandidateClient->ServerProcessId =\r
+                               (ULONG) pbi.UniqueProcessId;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               RtlFreeHeap (SmpHeap, 0, SmpClientDirectory.CandidateClient);\r
+               DPRINT1("SM: %s: subsys booting with no descriptor!\n", __FUNCTION__);\r
+               Status = STATUS_NOT_FOUND;\r
+               RtlLeaveCriticalSection (& SmpClientDirectory.Lock);\r
+               return Status;          \r
+       }\r
        /*\r
         * Check if a client for the ID already exist.\r
         */\r
-       if (SmpLookupClient(ConnectData->SubSystemId))\r
+       if (SmpLookupClient(ConnectData->SubSystemId, NULL))\r
        {\r
                DPRINT("SM: %s: attempt to register again subsystem %d.\n",\r
                        __FUNCTION__,\r
                        ConnectData->SubSystemId);\r
                return STATUS_UNSUCCESSFUL;\r
        }\r
-       DPRINT("SM: %s: registering subsystem ID=%d \n", __FUNCTION__, ConnectData->SubSystemId);\r
-       /*\r
-        * Allocate the storage for client data\r
-        */\r
-       pClient = RtlAllocateHeap (SmpHeap,\r
-                                  HEAP_ZERO_MEMORY,\r
-                                  sizeof (SM_CLIENT_DATA));\r
-       if (NULL == pClient)\r
-       {\r
-               DPRINT("SM: %s: out of memory!\n",__FUNCTION__);\r
-               return STATUS_NO_MEMORY;\r
-       }\r
+       DPRINT("SM: %s: registering subsystem ID=%d \n",\r
+               __FUNCTION__, ConnectData->SubSystemId);\r
+\r
        /*\r
         * Initialize the client data\r
         */\r
-       pClient->SubsystemId = ConnectData->SubSystemId;\r
-       /* SM auto-initializes; other subsystems are required to call\r
+       SmpClientDirectory.CandidateClient->SubsystemId = ConnectData->SubSystemId;\r
+       /* SM && DBG auto-initializes; other subsystems are required to call\r
         * SM_API_COMPLETE_SESSION via SMDLL. */\r
-       pClient->Initialized = (IMAGE_SUBSYSTEM_NATIVE == pClient->SubsystemId);\r
+       if ((IMAGE_SUBSYSTEM_NATIVE == SmpClientDirectory.CandidateClient->SubsystemId) ||\r
+           (IMAGE_SUBSYSTEM_UNKNOWN == SmpClientDirectory.CandidateClient->SubsystemId))\r
+       {\r
+               SmpSetClientInitialized (SmpClientDirectory.CandidateClient);\r
+       }\r
        if (SbApiPortNameSize > 0)\r
        {\r
-               RtlCopyMemory (pClient->SbApiPortName,\r
+               RtlCopyMemory (SmpClientDirectory.CandidateClient->SbApiPortName,\r
                               ConnectData->SbName,\r
                               SbApiPortNameSize);\r
        }\r
@@ -204,28 +205,132 @@ SmCreateClient(PSM_PORT_MESSAGE Request, PSM_CLIENT_DATA * ClientData)
         */\r
        if (NULL == SmpClientDirectory.Client)\r
        {\r
-               SmpClientDirectory.Client = pClient;\r
+               SmpClientDirectory.Client = SmpClientDirectory.CandidateClient;\r
        } else {\r
                PSM_CLIENT_DATA pCD = NULL;\r
 \r
                for (pCD=SmpClientDirectory.Client;\r
                        (NULL != pCD->Next);\r
                        pCD = pCD->Next);\r
-               pCD->Next = pClient;\r
+               pCD->Next = SmpClientDirectory.CandidateClient;\r
        }\r
-       pClient->Next = NULL;\r
+       SmpClientDirectory.CandidateClient->Next = NULL;\r
+       /*\r
+        * Increment the number of active subsystems.\r
+        */\r
        ++ SmpClientDirectory.Count;\r
        /*\r
-        * Note we unlock the client directory here, because\r
-        * it was locked by SmpLookupClient on failure.\r
+        * Notify to the caller the reference to the client data.\r
         */\r
-       RtlLeaveCriticalSection (& SmpClientDirectory.Lock);\r
        if (ClientData) \r
        {\r
-               *ClientData = pClient;\r
+               *ClientData = SmpClientDirectory.CandidateClient;\r
        }\r
+       /*\r
+        * Free the slot for the candidate subsystem.\r
+        */\r
+       SmpClientDirectory.CandidateClient = NULL;\r
+\r
+       RtlLeaveCriticalSection (& SmpClientDirectory.Lock);\r
+       \r
        return STATUS_SUCCESS;\r
 }\r
+/**********************************************************************\r
+ *     SmCompleteClientInitialization/1\r
+ *\r
+ * DESCRIPTION\r
+ *     Lookup the subsystem server descriptor given the process ID\r
+ *     of the subsystem server process.\r
+ */\r
+NTSTATUS STDCALL\r
+SmCompleteClientInitialization (ULONG ProcessId)\r
+{\r
+       NTSTATUS        Status = STATUS_SUCCESS;\r
+       PSM_CLIENT_DATA Client = NULL;\r
+\r
+       DPRINT("SM: %s called\n", __FUNCTION__);\r
+\r
+       RtlEnterCriticalSection (& SmpClientDirectory.Lock);\r
+       if (SmpClientDirectory.Count > 0)\r
+       {\r
+               Client = SmpClientDirectory.Client;\r
+               while (NULL != Client)\r
+               {\r
+                       if (ProcessId == Client->ServerProcessId)\r
+                       {\r
+                               SmpSetClientInitialized (Client);\r
+                               break;\r
+                       }\r
+                       Client = Client->Next;\r
+               }\r
+               Status = STATUS_NOT_FOUND;\r
+       }\r
+       RtlLeaveCriticalSection (& SmpClientDirectory.Lock);\r
+       return Status;\r
+}\r
+\r
+/**********************************************************************\r
+ *     SmpCreateClient/1\r
+ *\r
+ * DESCRIPTION\r
+ *     Create a "candidate" client. Client descriptor will enter the\r
+ *     client directory only at the end of the registration\r
+ *     procedure. Otherwise, we will kill the associated process.\r
+ *\r
+ * ARGUMENTS\r
+ *     ProcessHandle: handle of the subsystem server process.\r
+ *\r
+ * RETURN VALUE\r
+ *     NTSTATUS:\r
+ */\r
+NTSTATUS STDCALL\r
+SmCreateClient (PRTL_PROCESS_INFO ProcessInfo, PWSTR ProgramName)\r
+{\r
+       NTSTATUS Status = STATUS_SUCCESS;\r
+\r
+       \r
+       DPRINT("SM: %s(%lx) called\n", __FUNCTION__, ProcessInfo->ProcessHandle);\r
+       RtlEnterCriticalSection (& SmpClientDirectory.Lock);\r
+       /*\r
+        * Check if the candidate client slot is empty.\r
+        */\r
+       if (NULL != SmpClientDirectory.CandidateClient)\r
+       {\r
+               DPRINT1("SM: %s: CandidateClient pending!\n", __FUNCTION__);\r
+               RtlLeaveCriticalSection (& SmpClientDirectory.Lock);\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+       /*\r
+        * Allocate the storage for client data\r
+        */\r
+       SmpClientDirectory.CandidateClient =\r
+               RtlAllocateHeap (SmpHeap,\r
+                                HEAP_ZERO_MEMORY,\r
+                                sizeof (SM_CLIENT_DATA));\r
+       if (NULL == SmpClientDirectory.CandidateClient)\r
+       {\r
+               DPRINT("SM: %s(%lx): out of memory!\n",\r
+                       __FUNCTION__, ProcessInfo->ProcessHandle);\r
+               Status = STATUS_NO_MEMORY;\r
+       }\r
+       else\r
+       {\r
+               /* Initialize the candidate client. */\r
+               RtlInitializeCriticalSection(& SmpClientDirectory.CandidateClient->Lock);\r
+               SmpClientDirectory.CandidateClient->ServerProcess =\r
+                       (HANDLE) ProcessInfo->ProcessHandle;\r
+               SmpClientDirectory.CandidateClient->ServerProcessId = \r
+                       (ULONG) ProcessInfo->ClientId.UniqueProcess;\r
+       }\r
+       /*\r
+        * Copy the program name\r
+        */\r
+       RtlCopyMemory (SmpClientDirectory.CandidateClient->ProgramName,\r
+                      ProgramName,\r
+                      SM_SB_NAME_MAX_LENGTH);\r
+       RtlLeaveCriticalSection (& SmpClientDirectory.Lock);\r
+       return Status;\r
+}\r
 \r
 /**********************************************************************\r
  *     SmpDestroyClient/1\r
@@ -244,7 +349,7 @@ SmDestroyClient (ULONG SubsystemId)
        DPRINT("SM: %s called\n", __FUNCTION__);\r
 \r
        RtlEnterCriticalSection (& SmpClientDirectory.Lock);\r
-       Client = SmpLookupClientUnsafe (SubsystemId, & Parent);\r
+       Client = SmpLookupClient (SubsystemId, & Parent);\r
        if(NULL == Client)\r
        {\r
                DPRINT1("SM: %s: del req for non existent subsystem (id=%d)\n",\r
@@ -269,6 +374,7 @@ SmDestroyClient (ULONG SubsystemId)
                        }\r
                }\r
                /* TODO: send shutdown or kill */\r
+               NtTerminateProcess (Client->ServerProcess, 0); //FIXME\r
                RtlFreeHeap (SmpHeap, 0, Client);\r
                -- SmpClientDirectory.Count;\r
        }\r
@@ -285,7 +391,7 @@ NTSTATUS FASTCALL
 SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)\r
 {\r
        INT              Index = 0;\r
-       PSM_CLIENT_DATA  Client = NULL;\r
+       PSM_CLIENT_DATA  ClientData = NULL;\r
 \r
        DPRINT("SM: %s called\n", __FUNCTION__);\r
 \r
@@ -296,13 +402,13 @@ SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)
        \r
        if (SmpClientDirectory.Count > 0)\r
        {\r
-               Client = SmpClientDirectory.Client;\r
-               while ((NULL != Client) && (Index < SM_QRYINFO_MAX_SS_COUNT))\r
+               ClientData = SmpClientDirectory.Client;\r
+               while ((NULL != ClientData) && (Index < SM_QRYINFO_MAX_SS_COUNT))\r
                {\r
-                       i->SubSystem[Index].Id        = Client->SubsystemId;\r
-                       i->SubSystem[Index].Flags     = 0; /* TODO */\r
-                       i->SubSystem[Index].ProcessId = 0; /* TODO */\r
-                       Client = Client->Next;\r
+                       i->SubSystem[Index].Id        = ClientData->SubsystemId;\r
+                       i->SubSystem[Index].Flags     = ClientData->Flags;\r
+                       i->SubSystem[Index].ProcessId = ClientData->ServerProcessId;\r
+                       ClientData = ClientData->Next;\r
                }\r
        }\r
 \r
@@ -316,9 +422,27 @@ SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)
 NTSTATUS FASTCALL\r
 SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION i)\r
 {\r
+       NTSTATUS         Status = STATUS_SUCCESS;\r
+       PSM_CLIENT_DATA  ClientData = NULL;\r
+       \r
        DPRINT("SM: %s called\n", __FUNCTION__);\r
 \r
-       return STATUS_NOT_IMPLEMENTED;\r
+       RtlEnterCriticalSection (& SmpClientDirectory.Lock);\r
+       ClientData = SmpLookupClient (i->SubSystemId, NULL);\r
+       if (NULL == ClientData)\r
+       {\r
+               Status = STATUS_NOT_FOUND;\r
+       }\r
+       else\r
+       {\r
+               i->Flags     = ClientData->Flags;\r
+               i->ProcessId = ClientData->ServerProcessId;\r
+               RtlCopyMemory (i->NameSpaceRootNode,\r
+                               ClientData->SbApiPortName,\r
+                               (SM_QRYINFO_MAX_ROOT_NODE * sizeof(i->NameSpaceRootNode[0])));\r
+       }\r
+       RtlLeaveCriticalSection (& SmpClientDirectory.Lock);\r
+       return Status;\r
 }\r
 \r
 /* EOF */\r
index aa78ea5..786a298 100644 (file)
@@ -23,6 +23,7 @@
  *\r
  * --------------------------------------------------------------------\r
  */\r
\r
 \r
 #include "smss.h"\r
 \r
@@ -35,6 +36,13 @@ SmProcessFileRenameList(VOID)
   DPRINT("SmProcessFileRenameList() called\n");\r
 \r
   /* FIXME: implement it! */\r
+/*\r
+ * open HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\FileRenameOperations\r
+ * for each item in its value\r
+ *     clone the old file in the new name,\r
+ *     delete the source.\r
+ *\r
+ */\r
 \r
   DPRINT("SmProcessFileRenameList() done\n");\r
 \r
index 1c0ecdc..e19a172 100644 (file)
@@ -29,7 +29,7 @@
 #define NDEBUG\r
 #include <debug.h>\r
 \r
-HANDLE Children[2] = {0, 0}; /* csrss, winlogon */\r
+//HANDLE Children[2] = {0, 0}; /* csrss, winlogon */\r
 \r
 \r
 /**********************************************************************\r
@@ -99,10 +99,12 @@ SmpRunBootAppsQueryRoutine(PWSTR ValueName,
   Status = SmCreateUserProcess (ImagePath,\r
                                CommandLine,\r
                                TRUE, /* wait */\r
-                               NULL,\r
-                               TRUE, /* terminate */\r
-                               NULL);\r
-\r
+                               NULL, NULL);\r
+  if (!NT_SUCCESS(Status))\r
+  {\r
+               DPRINT1("SM: %s: running '$S' failed (Status=0x%08lx)\n",\r
+                       __FUNCTION__, Status);\r
+  }\r
   return(STATUS_SUCCESS);\r
 }\r
 \r
index 464cfe6..bc8f7fa 100644 (file)
@@ -55,23 +55,40 @@ static NTSTATUS
 SmpRegisterSmss(VOID)\r
 {\r
        NTSTATUS Status = STATUS_SUCCESS;\r
-       UNICODE_STRING SbApiPortName = {0,0,NULL};\r
+       RTL_PROCESS_INFO ProcessInfo;\r
 \r
        \r
        DPRINT("SM: %s called\n",__FUNCTION__);\r
-\r
-       RtlInitUnicodeString (& SbApiPortName, L"");    \r
-       Status = SmConnectApiPort(& SbApiPortName,\r
-                                 (HANDLE) -1, /* SM has no SB port */\r
-                                 IMAGE_SUBSYSTEM_NATIVE,\r
-                                 & hSmApiPort);\r
-       if(!NT_SUCCESS(Status))\r
+       \r
+       RtlZeroMemory (& ProcessInfo, sizeof ProcessInfo);\r
+       ProcessInfo.Size = sizeof ProcessInfo;\r
+       ProcessInfo.ProcessHandle = (HANDLE) SmSsProcessId;\r
+       ProcessInfo.ClientId.UniqueProcess = (HANDLE) SmSsProcessId;\r
+       DPRINT("SM: %s: ProcessInfo.ProcessHandle=%lx\n",\r
+               __FUNCTION__,ProcessInfo.ProcessHandle);\r
+       Status = SmCreateClient (& ProcessInfo, L"Session Manager");\r
+       if (NT_SUCCESS(Status))\r
+       {\r
+               UNICODE_STRING SbApiPortName = {0,0,NULL};\r
+               \r
+               RtlInitUnicodeString (& SbApiPortName, L"");    \r
+               Status = SmConnectApiPort(& SbApiPortName,\r
+                                         (HANDLE) -1, /* SM has no SB port */\r
+                                         IMAGE_SUBSYSTEM_NATIVE,\r
+                                         & hSmApiPort);\r
+               if(!NT_SUCCESS(Status))\r
+               {\r
+                       DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",\r
+                               __FUNCTION__,Status);\r
+                       return Status;\r
+               }\r
+               DPRINT("SM self registered\n");\r
+       }\r
+       else\r
        {\r
-               DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",\r
-                       __FUNCTION__,Status);\r
-               return Status;\r
+               DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",\r
+                       __FUNCTION__, Status);\r
        }\r
-       DPRINT("SM self registered\n");\r
        /*\r
         * Note that you don't need to call complete session\r
         * because connection handling code autocompletes\r
index ed29796..17e169e 100644 (file)
@@ -52,12 +52,13 @@ SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request);
 #endif
 
 /**********************************************************************
- * SmpCallback/2
+ * SmpCallbackServer/2
  *
- * The SM calls back a previously connected subsystem process to
- * authorizes it to bootstrap (initialize). The SM connects to a
- * named LPC port which name was sent in the connection data by the
- * candidate subsystem server process.
+ * DESCRIPTION
+ *     The SM calls back a previously connected subsystem process to
+ *     authorize it to bootstrap (initialize). The SM connects to a
+ *     named LPC port which name was sent in the connection data by
+ *     the candidate subsystem server process.
  */
 static NTSTATUS
 SmpCallbackServer (PSM_PORT_MESSAGE Request,
@@ -72,7 +73,8 @@ SmpCallbackServer (PSM_PORT_MESSAGE Request,
 
        DPRINT("SM: %s called\n", __FUNCTION__);
 
-       if(IMAGE_SUBSYSTEM_NATIVE == ConnectData->SubSystemId)
+       if (    (IMAGE_SUBSYSTEM_UNKNOWN == ConnectData->SubSystemId) ||
+               (IMAGE_SUBSYSTEM_NATIVE  == ConnectData->SubSystemId))
        {
                DPRINT("SM: %s: we do not need calling back SM!\n",
                                __FUNCTION__);
@@ -210,12 +212,10 @@ SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request)
                        {
                                DPRINT("SM: %s: id = %d\n", __FUNCTION__, ConnectData->SubSystemId);
                                /*
-                                * SmCreateClient/2 is called here explicitly to *fail*.
-                                * If it succeeds, there is something wrong in the
-                                * connection request. An environment subsystem *never*
-                                * registers twice. (security issue)
+                                * SmBeginClientInitialization/2 will succeed only if there
+                                * is a candidate client ready.
                                 */
-                               Status = SmCreateClient (Request, & ClientData);
+                               Status = SmBeginClientInitialization (Request, & ClientData);
                                if(STATUS_SUCCESS == Status)
                                {
                                        DPRINT("SM: %s: ClientData = 0x%08lx\n",
@@ -310,7 +310,7 @@ SmpHandleConnectionRequest (PSM_PORT_MESSAGE Request)
  *
  * DECRIPTION
  *     Due to differences in LPC implementation between NT and ROS,
- *     we need a thread to listen for connection request that
+ *     we need a thread to listen to for connection request that
  *     creates a new thread for each connected port. This is not
  *     necessary in NT LPC, because server side connected ports are
  *     never used to receive requests.
index 94abeb9..f4d4222 100644 (file)
  */\r
 SMAPI(SmCompSes)\r
 {\r
-       NTSTATUS Status = STATUS_SUCCESS;\r
+       NTSTATUS                  Status = STATUS_SUCCESS;\r
 \r
        DPRINT("SM: %s called\n", __FUNCTION__);\r
-       \r
-       Status = SmCompleteClientInitialization (Request->Header.ClientId.UniqueProcess);\r
-       if(!NT_SUCCESS(Status))\r
+\r
+       DPRINT("SM: %s: ClientId.UniqueProcess=%lx\n",\r
+               __FUNCTION__, Request->Header.ClientId.UniqueProcess);\r
+       Status = SmCompleteClientInitialization ((ULONG) Request->Header.ClientId.UniqueProcess);\r
+       if (!NT_SUCCESS(Status))\r
        {\r
-               Request->SmHeader.Status = STATUS_UNSUCCESSFUL;\r
+               DPRINT1("SM: %s: NtQueryInformationProcess failed (Status=0x%08lx)\n",\r
+                       __FUNCTION__, Status);\r
        }\r
-       return Status;\r
+       Request->SmHeader.Status = Status;\r
+       return STATUS_SUCCESS;\r
 }\r
 \r
 \r
index f74ac34..445966b 100644 (file)
 /**********************************************************************\r
  * SmCreateUserProcess/5\r
  *\r
+ * DESCRIPTION\r
+ *\r
+ * ARGUMENTS\r
+ *     ImagePath: bsolute path of the image to run;\r
+ *     CommandLine: arguments and options for ImagePath;\r
+ *     WaitForIt: TRUE for boot time processes and FALSE for\r
+ *             subsystems bootstrapping;\r
+ *     Timeout: optional: used if WaitForIt==TRUE;\r
+ *     ProcessHandle: optional: a duplicated handle for\r
+               the child process (storage provided by the caller).\r
+ *\r
+ * RETURN VALUE\r
+ *     NTSTATUS:\r
+ *\r
  */\r
 NTSTATUS STDCALL\r
 SmCreateUserProcess (LPWSTR ImagePath,\r
                     LPWSTR CommandLine,\r
                     BOOLEAN WaitForIt,\r
                     PLARGE_INTEGER Timeout OPTIONAL,\r
-                    BOOLEAN TerminateIt,\r
-                    PRTL_PROCESS_INFO UserProcessInfo OPTIONAL\r
-                    )\r
+                    PRTL_PROCESS_INFO UserProcessInfo OPTIONAL)\r
 {\r
        UNICODE_STRING                  ImagePathString = {0};\r
        UNICODE_STRING                  CommandLineString = {0};\r
@@ -48,8 +60,12 @@ SmCreateUserProcess (LPWSTR ImagePath,
        PRTL_PROCESS_INFO               pProcessInfo = & ProcessInfo;\r
        NTSTATUS                        Status = STATUS_SUCCESS;\r
 \r
-\r
-       DPRINT("SM: %s called\n",__FUNCTION__);\r
+       DPRINT("SM: %s called\n", __FUNCTION__);\r
+       \r
+       if (NULL != UserProcessInfo)\r
+       {\r
+               pProcessInfo = UserProcessInfo;\r
+       }\r
 \r
        RtlInitUnicodeString (& ImagePathString, ImagePath);\r
        RtlInitUnicodeString (& CommandLineString, CommandLine);\r
@@ -65,12 +81,6 @@ SmCreateUserProcess (LPWSTR ImagePath,
                                   NULL,\r
                                   NULL);\r
 \r
-       if(NULL != UserProcessInfo)\r
-       {\r
-               /* Use caller provided storage */\r
-               pProcessInfo = UserProcessInfo;\r
-       }\r
-\r
        Status = RtlCreateUserProcess (& ImagePathString,\r
                                       OBJ_CASE_INSENSITIVE,\r
                                       ProcessParameters,\r
@@ -82,7 +92,7 @@ SmCreateUserProcess (LPWSTR ImagePath,
                                       NULL,\r
                                       pProcessInfo);\r
                    \r
-   RtlDestroyProcessParameters (ProcessParameters);\r
+       RtlDestroyProcessParameters (ProcessParameters);\r
    \r
        if (!NT_SUCCESS(Status))\r
        {\r
@@ -90,25 +100,52 @@ SmCreateUserProcess (LPWSTR ImagePath,
                        __FUNCTION__, ImagePathString.Buffer, Status);\r
                return Status;\r
        }\r
-\r
-   ZwResumeThread(pProcessInfo->ThreadHandle, NULL);\r
-\r
-\r
-       /* Wait for process termination */\r
-       if(WaitForIt)\r
+       /*\r
+        * It the caller is *not* interested in the child info,\r
+        * resume it immediately.\r
+        */\r
+       if (NULL == UserProcessInfo)\r
        {\r
-               NtWaitForSingleObject (pProcessInfo->ProcessHandle,\r
-                                      FALSE,\r
-                                      Timeout);\r
+               Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);\r
+               if(!NT_SUCCESS(Status))\r
+               {\r
+                       DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",\r
+                               __FUNCTION__, Status);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               HANDLE DupProcessHandle = (HANDLE) 0;\r
+               \r
+               Status = NtDuplicateObject (NtCurrentProcess(),\r
+                                           pProcessInfo->ProcessHandle,\r
+                                           NtCurrentProcess(),\r
+                                           & DupProcessHandle,\r
+                                           PROCESS_ALL_ACCESS,\r
+                                           0, 0);\r
+               if(!NT_SUCCESS(Status))\r
+               {\r
+                       DPRINT1("SM: %s: NtDuplicateObject failed (Status=0x%08lx)\n",\r
+                               __FUNCTION__, Status);\r
+               }\r
+               pProcessInfo->ProcessHandle = DupProcessHandle;\r
+               \r
        }\r
 \r
-       /* Terminate process */\r
-       if(TerminateIt)\r
+       /* Wait for process termination */\r
+       if (WaitForIt)\r
        {\r
-               NtClose(pProcessInfo->ThreadHandle);\r
-               NtClose(pProcessInfo->ProcessHandle);\r
+               Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle,\r
+                                               FALSE,\r
+                                               Timeout);\r
+               if (!NT_SUCCESS(Status))\r
+               {\r
+                       DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",\r
+                               __FUNCTION__, Status);\r
+               }\r
+               \r
        }\r
-       return STATUS_SUCCESS;\r
+       return Status;\r
 }\r
 \r
 /**********************************************************************\r
@@ -259,61 +296,94 @@ SMAPI(SmExecPgm)
           (ExecPgm->NameLength <= SM_EXEXPGM_MAX_LENGTH) &&\r
           TRUE /* TODO: check LPC payload size */)\r
        {\r
+               WCHAR Data [MAX_PATH + 1] = {0};\r
+               ULONG DataLength = sizeof Data;\r
+               ULONG DataType = REG_EXPAND_SZ;\r
+\r
                \r
                RtlZeroMemory (Name, sizeof Name);\r
                RtlCopyMemory (Name,\r
                               ExecPgm->Name,\r
                               (sizeof ExecPgm->Name[0] * ExecPgm->NameLength));\r
                DPRINT("SM: %s: Name='%S'\n", __FUNCTION__, Name);\r
-               /*\r
-                * Check if program name is internal\r
-                * (Is this correct? Debug is in the registry too)\r
-                */\r
-               if(0 == _wcsicmp(L"DEBUG", Name))\r
-               {\r
-                       /*\r
-                        * Initialize DBGSS.\r
-                        * NOTE: probably in early prototypes it was an\r
-                        * independent process; now it is embedded in the\r
-                        * SM for performance or security.\r
-                        */\r
-                       Request->SmHeader.Status = SmInitializeDbgSs();\r
-               }\r
-               else\r
+               /* Lookup Name in the registry */\r
+               Status = SmLookupSubsystem (Name,\r
+                                           Data,\r
+                                           & DataLength,\r
+                                           & DataType,\r
+                                           TRUE); /* expand */\r
+               if(NT_SUCCESS(Status))\r
                {\r
-                       WCHAR Data [MAX_PATH + 1] = {0};\r
-                       ULONG DataLength = sizeof Data;\r
-                       ULONG DataType = REG_EXPAND_SZ;\r
-\r
-                       /* Lookup Name in the registry */\r
-                       Status = SmLookupSubsystem (Name,\r
-                                                   Data,\r
-                                                   & DataLength,\r
-                                                   & DataType,\r
-                                                   TRUE); /* expand */\r
-                       if(NT_SUCCESS(Status))\r
+                       /* Is the subsystem definition non-empty? */\r
+                       if (DataLength > sizeof Data[0])\r
                        {\r
                                WCHAR ImagePath [MAX_PATH + 1] = {0};\r
+                               PWCHAR CommandLine = ImagePath;\r
+                               RTL_PROCESS_INFO ProcessInfo = {0};\r
 \r
                                wcscpy (ImagePath, L"\\??\\");\r
                                wcscat (ImagePath, Data);\r
-                       \r
-                               /* Create native process */\r
-                               Request->SmHeader.Status = SmCreateUserProcess(ImagePath,\r
-                                                                     L"", /* FIXME */\r
-                                                                     FALSE, /* wait */\r
-                                                                     NULL,\r
-                                                                     FALSE, /* terminate */\r
-                                                                     NULL);\r
-                       }else{\r
-                               Request->SmHeader.Status = Status;\r
+                               /*\r
+                                * Look for the beginning of the command line.\r
+                                */\r
+                               for (;  (*CommandLine != L'\0') && (*CommandLine != L' ');\r
+                                       CommandLine ++);\r
+                               for (; *CommandLine == L' '; CommandLine ++)\r
+                               {\r
+                                       *CommandLine = L'\0';\r
+                               }\r
+                               /*\r
+                                * Create a native process (suspended).\r
+                                */\r
+                               ProcessInfo.Size = sizeof ProcessInfo;\r
+                               Request->SmHeader.Status =\r
+                                       SmCreateUserProcess(ImagePath,\r
+                                                             CommandLine,\r
+                                                             FALSE, /* wait */\r
+                                                             NULL, /* timeout */\r
+                                                             & ProcessInfo);\r
+                               if (NT_SUCCESS(Request->SmHeader.Status))\r
+                               {\r
+                                       Status = SmCreateClient (& ProcessInfo, Name);\r
+                                       if (NT_SUCCESS(Status))\r
+                                       {\r
+                                               Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);\r
+                                               if (!NT_SUCCESS(Status))\r
+                                               {\r
+                                                       //Status = SmDestroyClient TODO\r
+                                               }\r
+                                       } else {\r
+                                               DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",\r
+                                                       __FUNCTION__, Status);\r
+                                       }\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               /*\r
+                                * OK, the definition is empty, but check\r
+                                * if it is the name of an embedded subsystem.\r
+                                */\r
+                               if(0 == _wcsicmp(L"DEBUG", Name))\r
+                               {\r
+                                       /*\r
+                                        * Initialize the embedded DBGSS.\r
+                                        */\r
+                                       Request->SmHeader.Status = SmInitializeDbgSs();\r
+                               }\r
+                               else\r
+                               {\r
+                                       /*\r
+                                        * Badly defined subsystem. Check the registry!\r
+                                        */\r
+                                       Request->SmHeader.Status = STATUS_NOT_FOUND;\r
+                               }\r
                        }\r
+               } else {\r
+                       /* It couldn't lookup the Name! */\r
+                       Request->SmHeader.Status = Status;\r
                }\r
        }\r
-       else\r
-       {\r
-               Request->SmHeader.Status = Status = STATUS_INVALID_PARAMETER;\r
-       }\r
        return Status;\r
 }\r
 \r
index 03d8d37..627677a 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
-HANDLE SmSsProcessId = 0;
+ULONG SmSsProcessId = 0;
 
 /* Native image's entry point */
 
 VOID STDCALL
 NtProcessStartup(PPEB Peb)
 {
-  NTSTATUS Status;
+  NTSTATUS Status = STATUS_SUCCESS;
   PROCESS_BASIC_INFORMATION PBI = {0};
 
+PrintString("*** EXPERIMENTAL ***\n");
+  
   PrintString("ReactOS Session Manager %s (Build %s)\n",
             KERNEL_RELEASE_STR,
             KERNEL_VERSION_BUILD_STR);
@@ -52,7 +54,7 @@ NtProcessStartup(PPEB Peb)
                                      NULL);
   if(NT_SUCCESS(Status))
   {
-         SmSsProcessId = PBI.UniqueProcessId;
+         SmSsProcessId = (ULONG) PBI.UniqueProcessId;
   }
   /* Initialize the system */
   Status = InitSessionManager();
index 6b1bb40..bc099bf 100644 (file)
@@ -6,11 +6,8 @@
 #include <sm/api.h>
 #include <sm/helper.h>
 
-#define CHILD_CSRSS     0
-#define CHILD_WINLOGON  1
-
 /* smss.c */
-extern HANDLE SmSsProcessId;
+extern ULONG SmSsProcessId;
 
 /* init.c */
 NTSTATUS InitSessionManager(VOID);
@@ -63,8 +60,7 @@ NTSTATUS STDCALL SmCreateUserProcess(LPWSTR ImagePath,
                                     LPWSTR CommandLine,
                                     BOOLEAN WaitForIt,
                                     PLARGE_INTEGER Timeout OPTIONAL,
-                                    BOOLEAN TerminateIt,
-                                    PRTL_PROCESS_INFO ProcessInfo OPTIONAL);
+                                    PRTL_PROCESS_INFO UserProcessInfo OPTIONAL);
 NTSTATUS STDCALL
 SmLookupSubsystem (IN     PWSTR   Name,
                   IN OUT PWSTR   Data,
@@ -80,22 +76,30 @@ NTSTATUS FASTCALL SmCompSes(PSM_PORT_MESSAGE);
 NTSTATUS FASTCALL SmQryInfo(PSM_PORT_MESSAGE);
 
 /* client.c */
+#define SM_CLIENT_FLAG_CANDIDATE   0x8000
+#define SM_CLIENT_FLAG_INITIALIZED 0x0001
+#define SM_CLIENT_FLAG_REQUIRED    0x0002
 typedef struct _SM_CLIENT_DATA
 {
-       USHORT  SubsystemId;
-       BOOL    Initialized;
-       HANDLE  ServerProcess;
-       HANDLE  ApiPort;
-       HANDLE  ApiPortThread;
-       HANDLE  SbApiPort;
-       WCHAR   SbApiPortName [SM_SB_NAME_MAX_LENGTH];
-       struct _SM_CLIENT_DATA * Next;
+  RTL_CRITICAL_SECTION  Lock;
+  WCHAR                 ProgramName [SM_SB_NAME_MAX_LENGTH];
+  USHORT                SubsystemId;
+  WORD                  Flags;
+  WORD                  Unused;
+  ULONG                 ServerProcessId;
+  HANDLE               ServerProcess;
+  HANDLE               ApiPort;
+  HANDLE               ApiPortThread;
+  HANDLE               SbApiPort;
+  WCHAR                        SbApiPortName [SM_SB_NAME_MAX_LENGTH];
+  struct _SM_CLIENT_DATA * Next;
 
 } SM_CLIENT_DATA, *PSM_CLIENT_DATA;
-NTSTATUS SmInitializeClientManagement(VOID);
-NTSTATUS STDCALL SmCreateClient(PSM_PORT_MESSAGE,PSM_CLIENT_DATA*);
-NTSTATUS STDCALL SmDestroyClient(ULONG);
-NTSTATUS STDCALL SmCompleteClientInitialization (HANDLE hProcess);
+NTSTATUS SmInitializeClientManagement (VOID);
+NTSTATUS STDCALL SmCreateClient (PRTL_PROCESS_INFO,PWSTR);
+NTSTATUS STDCALL SmDestroyClient (ULONG);
+NTSTATUS STDCALL SmBeginClientInitialization (PSM_PORT_MESSAGE,PSM_CLIENT_DATA*);
+NTSTATUS STDCALL SmCompleteClientInitialization (ULONG);
 NTSTATUS FASTCALL SmGetClientBasicInformation (PSM_BASIC_INFORMATION);
 NTSTATUS FASTCALL SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION);