[SERVICES] Set default status to SERVICE_START_PENDING when starting a service.
[reactos.git] / reactos / dll / win32 / syssetup / install.c
index dfc6661..b3bd427 100644 (file)
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 /*
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS system libraries
  * PURPOSE:           System setup
- * FILE:              lib/syssetup/install.c
+ * FILE:              dll/win32/syssetup/install.c
  * PROGRAMER:         Eric Kohl
  */
 
@@ -473,30 +473,100 @@ InstallSysSetupInfComponents(VOID)
 static BOOL
 EnableUserModePnpManager(VOID)
 {
+    SERVICE_STATUS_PROCESS ServiceStatus;
     SC_HANDLE hSCManager = NULL;
     SC_HANDLE hService = NULL;
+    DWORD dwStartTickCount;
+    DWORD dwOldCheckPoint;
+    DWORD BytesNeeded = 0;
+    DWORD dwWaitTime;
+    DWORD dwMaxWait;
     BOOL ret = FALSE;
 
     hSCManager = OpenSCManager(NULL, NULL, 0);
     if (hSCManager == NULL)
         goto cleanup;
 
-    hService = OpenServiceW(hSCManager, L"PlugPlay", SERVICE_CHANGE_CONFIG | SERVICE_START);
+    hService = OpenServiceW(hSCManager,
+                            L"PlugPlay",
+                            SERVICE_CHANGE_CONFIG | SERVICE_START | SERVICE_QUERY_STATUS);
     if (hService == NULL)
         goto cleanup;
 
-    ret = ChangeServiceConfigW(
-        hService,
-        SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE,
-        NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+    ret = ChangeServiceConfigW(hService,
+                               SERVICE_NO_CHANGE,
+                               SERVICE_AUTO_START,
+                               SERVICE_NO_CHANGE,
+                               NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL);
     if (!ret)
         goto cleanup;
 
     ret = StartServiceW(hService, 0, NULL);
+    if (!ret)
+    {
+        /* If the service is already running, just return TRUE */
+        ret = GetLastError() == ERROR_SERVICE_ALREADY_RUNNING;
+        goto cleanup;
+    }
+
+    ret = QueryServiceStatusEx(hService,
+                               SC_STATUS_PROCESS_INFO,
+                               (LPBYTE)&ServiceStatus,
+                               sizeof(SERVICE_STATUS_PROCESS),
+                               &BytesNeeded);
     if (!ret)
         goto cleanup;
 
-    ret = TRUE;
+    /* We don't want to wait for more than 30 seconds */
+    dwMaxWait = 30000;
+    dwStartTickCount = GetTickCount();
+
+    /* Loop until it's running */
+    while (ServiceStatus.dwCurrentState != SERVICE_RUNNING)
+    {
+        dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+        dwWaitTime = ServiceStatus.dwWaitHint / 10;
+
+        /* Get the latest status info */
+        if (!QueryServiceStatusEx(hService,
+                                  SC_STATUS_PROCESS_INFO,
+                                  (LPBYTE)&ServiceStatus,
+                                  sizeof(SERVICE_STATUS_PROCESS),
+                                  &BytesNeeded))
+        {
+            /* Something went wrong... */
+            break;
+        }
+
+        /* Is the service making progress? */
+        if (ServiceStatus.dwCheckPoint > dwOldCheckPoint)
+        {
+            /* It is, get the latest tickcount to reset the max wait time */
+            dwStartTickCount = GetTickCount();
+            dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+        }
+        else
+        {
+            /* It's not, make sure we haven't exceeded our wait time */
+            if (GetTickCount() >= dwStartTickCount + dwMaxWait)
+            {
+                /* We have, give up */
+                break;
+            }
+        }
+
+        /* Adjust the wait hint times */
+        if (dwWaitTime < 200)
+            dwWaitTime = 200;
+        else if (dwWaitTime > 10000)
+            dwWaitTime = 10000;
+
+        /* Wait before trying again */
+        Sleep(dwWaitTime);
+    }
+
+    ret = ServiceStatus.dwCurrentState == SERVICE_RUNNING;
 
 cleanup:
     if (hSCManager != NULL)
@@ -799,6 +869,7 @@ CreateShortcuts(VOID)
     {
         CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_MPLAY32, _T("%SystemRoot%\\system32\\mplay32.exe"), IDS_CMT_MPLAY32, TRUE);
         CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNDVOL32, _T("%SystemRoot%\\system32\\sndvol32.exe"), IDS_CMT_SNDVOL32, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNDREC32, _T("%SystemRoot%\\system32\\sndrec32.exe"), IDS_CMT_SNDREC32, TRUE);
     }
 
     /* Create Games subfolder and fill if the exe is available */
@@ -806,6 +877,7 @@ CreateShortcuts(VOID)
     {
         CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SOLITAIRE, _T("%SystemRoot%\\system32\\sol.exe"), IDS_CMT_SOLITAIRE, TRUE);
         CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WINEMINE, _T("%SystemRoot%\\system32\\winemine.exe"), IDS_CMT_WINEMINE, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SPIDER, _T("%SystemRoot%\\system32\\spider.exe"), IDS_CMT_SPIDER, TRUE);
     }
 
     CoUninitialize();