[ros-diffs] [ekohl] 45626: [SERVICES] Set default status to SERVICE_START_PENDING when starting a service. [SYSSETUP] Wait until PlugPlay service is up. Bug #4142. [UMPNPMGR] Update the service control manager's status information. Patches by Dmitry Gorbachev.

ekohl at svn.reactos.org ekohl at svn.reactos.org
Fri Feb 19 21:03:12 CET 2010


Author: ekohl
Date: Fri Feb 19 21:03:11 2010
New Revision: 45626

URL: http://svn.reactos.org/svn/reactos?rev=45626&view=rev
Log:
[SERVICES] Set default status to SERVICE_START_PENDING when starting a service.
[SYSSETUP] Wait until PlugPlay service is up. Bug #4142.
[UMPNPMGR] Update the service control manager's status information.

Patches by Dmitry Gorbachev.

Modified:
    trunk/reactos/base/services/umpnpmgr/umpnpmgr.c
    trunk/reactos/base/system/services/database.c
    trunk/reactos/dll/win32/syssetup/install.c

Modified: trunk/reactos/base/services/umpnpmgr/umpnpmgr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/services/umpnpmgr/umpnpmgr.c?rev=45626&r1=45625&r2=45626&view=diff
==============================================================================
--- trunk/reactos/base/services/umpnpmgr/umpnpmgr.c [iso-8859-1] (original)
+++ trunk/reactos/base/services/umpnpmgr/umpnpmgr.c [iso-8859-1] Fri Feb 19 21:03:11 2010
@@ -51,12 +51,11 @@
 
 /* GLOBALS ******************************************************************/
 
-static VOID CALLBACK
-ServiceMain(DWORD argc, LPTSTR *argv);
-
-static SERVICE_TABLE_ENTRY ServiceTable[2] =
-{
-    {TEXT("PlugPlay"), ServiceMain},
+static VOID CALLBACK ServiceMain(DWORD, LPWSTR *);
+static WCHAR ServiceName[] = L"PlugPlay";
+static SERVICE_TABLE_ENTRYW ServiceTable[] =
+{
+    {ServiceName, ServiceMain},
     {NULL, NULL}
 };
 
@@ -2446,16 +2445,92 @@
 }
 
 
-static VOID CALLBACK
-ServiceMain(DWORD argc, LPTSTR *argv)
+static DWORD WINAPI
+ServiceControlHandler(DWORD dwControl,
+                      DWORD dwEventType,
+                      LPVOID lpEventData,
+                      LPVOID lpContext)
+{
+    /* FIXME */
+    DPRINT1("ServiceControlHandler() called (control code %lu)\n", dwControl);
+    return ERROR_SUCCESS;
+}
+
+
+static DWORD
+ServiceInit(VOID)
 {
     HANDLE hThread;
     DWORD dwThreadId;
-
-    UNREFERENCED_PARAMETER(argc);
-    UNREFERENCED_PARAMETER(argv);
-
-    DPRINT("ServiceMain() called\n");
+    DWORD dwError;
+    BOOLEAN OldValue;
+
+    /* We need this privilege for using CreateProcessAsUserW */
+    RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE,
+                       TRUE,
+                       FALSE,
+                       &OldValue);
+
+    hInstallEvent = CreateEvent(NULL,
+                                TRUE,
+                                SetupIsActive()/*FALSE*/,
+                                NULL);
+    if (hInstallEvent == NULL)
+    {
+        dwError = GetLastError();
+        DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
+        return dwError;
+    }
+
+    hDeviceInstallListNotEmpty = CreateEvent(NULL,
+                                             FALSE,
+                                             FALSE,
+                                             NULL);
+    if (hDeviceInstallListNotEmpty == NULL)
+    {
+        dwError = GetLastError();
+        DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
+        return dwError;
+    }
+
+    hNoPendingInstalls = CreateEventW(NULL,
+                                      TRUE,
+                                      FALSE,
+                                      L"Global\\PnP_No_Pending_Install_Events");
+    if (hNoPendingInstalls == NULL)
+    {
+        dwError = GetLastError();
+        DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
+        return dwError;
+    }
+
+#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
+    InitializeSListHead(&DeviceInstallListHead);
+#else
+    InitializeListHead(&DeviceInstallListHead);
+#endif
+
+    dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                            L"System\\CurrentControlSet\\Enum",
+                            0,
+                            KEY_ALL_ACCESS,
+                            &hEnumKey);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
+        return dwError;
+    }
+
+    dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                            L"System\\CurrentControlSet\\Control\\Class",
+                            0,
+                            KEY_ALL_ACCESS,
+                            &hClassKey);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
+        return dwError;
+    }
 
     hThread = CreateThread(NULL,
                            0,
@@ -2463,8 +2538,11 @@
                            NULL,
                            0,
                            &dwThreadId);
-    if (hThread != NULL)
-        CloseHandle(hThread);
+    if (hThread == NULL)
+    {
+        return GetLastError();
+    }
+    CloseHandle(hThread);
 
     hThread = CreateThread(NULL,
                            0,
@@ -2472,8 +2550,11 @@
                            NULL,
                            0,
                            &dwThreadId);
-    if (hThread != NULL)
-        CloseHandle(hThread);
+    if (hThread == NULL)
+    {
+        return GetLastError();
+    }
+    CloseHandle(hThread);
 
     hThread = CreateThread(NULL,
                            0,
@@ -2481,87 +2562,80 @@
                            NULL,
                            0,
                            &dwThreadId);
-    if (hThread != NULL)
-        CloseHandle(hThread);
-
-    DPRINT("ServiceMain() done\n");
-}
-
-
-int
-wmain(int argc, WCHAR *argv[])
-{
-    BOOLEAN OldValue;
+    if (hThread == NULL)
+    {
+        return GetLastError();
+    }
+    CloseHandle(hThread);
+
+    return ERROR_SUCCESS;
+}
+
+
+static VOID CALLBACK
+ServiceMain(DWORD argc,
+            LPWSTR *argv)
+{
+    SERVICE_STATUS ServiceStatus;
+    SERVICE_STATUS_HANDLE ServiceStatusHandle;
     DWORD dwError;
 
     UNREFERENCED_PARAMETER(argc);
     UNREFERENCED_PARAMETER(argv);
 
-    DPRINT("Umpnpmgr: main() started\n");
-
-    /* We need this privilege for using CreateProcessAsUserW */
-    RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
-
-    hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
-    if (hInstallEvent == NULL)
+    DPRINT("ServiceMain() called\n");
+
+    ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
+                                                        ServiceControlHandler,
+                                                        NULL);
+    if (!ServiceStatusHandle)
     {
         dwError = GetLastError();
-        DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
-        return dwError;
-    }
-
-    hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (hDeviceInstallListNotEmpty == NULL)
-    {
-        dwError = GetLastError();
-        DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
-        return dwError;
-    }
-
-    hNoPendingInstalls = CreateEventW(NULL,
-                                      TRUE,
-                                      FALSE,
-                                      L"Global\\PnP_No_Pending_Install_Events");
-    if (hNoPendingInstalls == NULL)
-    {
-        dwError = GetLastError();
-        DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
-        return dwError;
-    }
-
-#ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
-    InitializeSListHead(&DeviceInstallListHead);
-#else
-    InitializeListHead(&DeviceInstallListHead);
-#endif
-
-    dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-                            L"System\\CurrentControlSet\\Enum",
-                            0,
-                            KEY_ALL_ACCESS,
-                            &hEnumKey);
+        DPRINT1("RegisterServiceCtrlHandlerW() failed! (Error %lu)\n", dwError);
+        return;
+    }
+
+    ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+    ServiceStatus.dwControlsAccepted = 0;
+    ServiceStatus.dwWin32ExitCode = NO_ERROR;
+    ServiceStatus.dwServiceSpecificExitCode = 0;
+    ServiceStatus.dwCheckPoint = 0;
+    ServiceStatus.dwWaitHint = 2000;
+
+    SetServiceStatus(ServiceStatusHandle,
+                     &ServiceStatus);
+
+    dwError = ServiceInit();
     if (dwError != ERROR_SUCCESS)
     {
-        DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
-        return dwError;
-    }
-
-    dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-                            L"System\\CurrentControlSet\\Control\\Class",
-                            0,
-                            KEY_ALL_ACCESS,
-                            &hClassKey);
-    if (dwError != ERROR_SUCCESS)
-    {
-        DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
-        return dwError;
-    }
-
-    StartServiceCtrlDispatcher(ServiceTable);
-
-    DPRINT("Umpnpmgr: main() done\n");
-
-    ExitThread(0);
+        DPRINT1("Service stopped\n");
+        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
+    }
+    else
+    {
+        ServiceStatus.dwCurrentState = SERVICE_RUNNING;
+    }
+
+    SetServiceStatus(ServiceStatusHandle,
+                     &ServiceStatus);
+
+    DPRINT("ServiceMain() done\n");
+}
+
+
+int
+wmain(int argc,
+      WCHAR *argv[])
+{
+    UNREFERENCED_PARAMETER(argc);
+    UNREFERENCED_PARAMETER(argv);
+
+    DPRINT1("Umpnpmgr: main() started\n");
+
+    StartServiceCtrlDispatcherW(ServiceTable);
+
+    DPRINT1("Umpnpmgr: main() done\n");
 
     return 0;
 }

Modified: trunk/reactos/base/system/services/database.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/database.c?rev=45626&r1=45625&r2=45626&view=diff
==============================================================================
--- trunk/reactos/base/system/services/database.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/services/database.c [iso-8859-1] Fri Feb 19 21:03:11 2010
@@ -1054,7 +1054,7 @@
         {
             Group->ServicesRunning = TRUE;
         }
-        Service->Status.dwCurrentState = SERVICE_RUNNING;
+        Service->Status.dwCurrentState = SERVICE_START_PENDING;
     }
 #if 0
     else

Modified: trunk/reactos/dll/win32/syssetup/install.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/syssetup/install.c?rev=45626&r1=45625&r2=45626&view=diff
==============================================================================
--- trunk/reactos/dll/win32/syssetup/install.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/syssetup/install.c [iso-8859-1] Fri Feb 19 21:03:11 2010
@@ -20,7 +20,7 @@
  * 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 @@
 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 = TRUE;
+    }
+
+    ret = QueryServiceStatusEx(hService,
+                               SC_STATUS_PROCESS_INFO,
+                               (LPBYTE)&ServiceStatus,
+                               sizeof(SERVICE_STATUS_PROCESS),
+                               &BytesNeeded);
+    if (!ret)
+        goto cleanup;
+
+    /* 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)




More information about the Ros-diffs mailing list