[CMAKE]
[reactos.git] / base / applications / mscutils / servman / control.c
index a170e80..d6fcbba 100644 (file)
  * PROJECT:     ReactOS Services
  * LICENSE:     GPL - See COPYING in the top level directory
  * FILE:        base/applications/mscutils/servman/control.c
- * PURPOSE:     Stops, pauses and resumes a service
- * COPYRIGHT:   Copyright 2006-2007 Ged Murphy <gedmurphy@reactos.org>
+ * PURPOSE:     Pauses and resumes a service
+ * COPYRIGHT:   Copyright 2006-2010 Ged Murphy <gedmurphy@reactos.org>
  *
  */
 
 #include "precomp.h"
 
-BOOL
-Control(PMAIN_WND_INFO Info,
-        HWND hProgDlg,
-        DWORD Control)
+static BOOL
+DoControl(PMAIN_WND_INFO Info,
+          HWND hProgress,
+          DWORD Control)
 {
     SC_HANDLE hSCManager;
-    SC_HANDLE hSc;
-    SERVICE_STATUS_PROCESS ServiceStatus;
+    SC_HANDLE hService;
+    SERVICE_STATUS_PROCESS ServiceStatus = {0};
     SERVICE_STATUS Status;
     DWORD BytesNeeded = 0;
+    DWORD dwStartTickCount;
+    DWORD dwOldCheckPoint;
+    DWORD dwWaitTime;
+    DWORD dwMaxWait;
+    DWORD dwReqState;
     BOOL bRet = FALSE;
-    BOOL bDispErr = TRUE;
+
+    /* Set the state we're interested in */
+    switch (Control)
+    {
+        case SERVICE_CONTROL_PAUSE:
+            dwReqState = SERVICE_PAUSED;
+            break;
+        case SERVICE_CONTROL_CONTINUE:
+            dwReqState = SERVICE_RUNNING;
+            break;
+        default:
+            /* Unhandled control code */
+            return FALSE;
+    }
 
     hSCManager = OpenSCManager(NULL,
                                NULL,
-                               SC_MANAGER_ALL_ACCESS);
-    if (hSCManager != NULL)
+                               SC_MANAGER_CONNECT);
+    if (hSCManager)
     {
-        hSc = OpenService(hSCManager,
-                          Info->pCurrentService->lpServiceName,
-                          SERVICE_ALL_ACCESS);
-        if (hSc != NULL)
+        hService = OpenService(hSCManager,
+                               Info->pCurrentService->lpServiceName,
+                               SERVICE_PAUSE_CONTINUE | SERVICE_INTERROGATE | SERVICE_QUERY_STATUS);
+        if (hService)
         {
-            if (ControlService(hSc,
+            if (hProgress)
+            {
+                /* Increment the progress bar */
+                IncrementProgressBar(hProgress, DEFAULT_STEP);
+            }
+
+            /* Send the control message to the service */
+            if (ControlService(hService,
                                Control,
                                &Status))
             {
-                bDispErr = FALSE;
-
-                if (QueryServiceStatusEx(hSc,
+                /* Get the service status */
+                if (QueryServiceStatusEx(hService,
                                          SC_STATUS_PROCESS_INFO,
                                          (LPBYTE)&ServiceStatus,
                                          sizeof(SERVICE_STATUS_PROCESS),
                                          &BytesNeeded))
                 {
-                    DWORD dwStartTickCount = GetTickCount();
-                    DWORD dwOldCheckPoint = ServiceStatus.dwCheckPoint;
-                    DWORD dwMaxWait = 2000 * 60; // wait for 2 mins
-
-                    IncrementProgressBar(hProgDlg);
+                    /* We don't want to wait for more than 30 seconds */
+                    dwMaxWait = 30000;
+                    dwStartTickCount = GetTickCount();
 
-                    while (ServiceStatus.dwCurrentState != Control)
+                    /* Loop until it's at the correct state */
+                    while (ServiceStatus.dwCurrentState != dwReqState)
                     {
-                        DWORD dwWaitTime = ServiceStatus.dwWaitHint / 10;
+                        dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+                        dwWaitTime = ServiceStatus.dwWaitHint / 10;
 
-                        if (!QueryServiceStatusEx(hSc,
+                        /* 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)
                         {
-                            /* The service is making progress, increment the progress bar */
-                            IncrementProgressBar(hProgDlg);
+                            /* It is, get the latest tickcount to reset the max wait time */
                             dwStartTickCount = GetTickCount();
                             dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+                            IncrementProgressBar(hProgress, DEFAULT_STEP);
                         }
                         else
                         {
+                            /* It's not, make sure we haven't exceeded our wait time */
                             if(GetTickCount() >= dwStartTickCount + dwMaxWait)
                             {
-                                /* give up */
+                                /* We have, give up */
                                 break;
                             }
                         }
 
-                        if(dwWaitTime < 200)
+                        /* Adjust the wait hint times */
+                        if (dwWaitTime < 200)
                             dwWaitTime = 200;
                         else if (dwWaitTime > 10000)
                             dwWaitTime = 10000;
 
+                        /* Wait before trying again */
                         Sleep(dwWaitTime);
                     }
                 }
+
+                if (ServiceStatus.dwCurrentState == dwReqState)
+                {
+                    bRet = TRUE;
+                }
             }
 
-            CloseServiceHandle(hSc);
+            CloseServiceHandle(hService);
         }
 
         CloseServiceHandle(hSCManager);
     }
 
-    if (ServiceStatus.dwCurrentState == Control)
-    {
-        CompleteProgressBar(hProgDlg);
-        Sleep(500);
-        bRet = TRUE;
-    }
-    else
-    {
-        if (bDispErr)
-            GetError();
-        else
-            DisplayString(_T("The service failed to start"));
-    }
-
     return bRet;
-
-
 }
 
 
-BOOL DoPause(PMAIN_WND_INFO Info)
+BOOL
+DoPause(PMAIN_WND_INFO Info)
 {
-    BOOL ret = FALSE;
-    HWND hProgDlg;
+    HWND hProgress;
+    BOOL bRet = FALSE;
 
-    hProgDlg = CreateProgressDialog(Info->hMainWnd,
-                                    Info->pCurrentService->lpServiceName,
-                                    IDS_PROGRESS_INFO_PAUSE);
-    if (hProgDlg)
+    /* Create a progress window to track the progress of the pausing service */
+    hProgress = CreateProgressDialog(Info->hMainWnd,
+                                     IDS_PROGRESS_INFO_PAUSE);
+    if (hProgress)
     {
-        ret = Control(Info,
-                      hProgDlg,
-                      SERVICE_CONTROL_PAUSE);
+        /* Set the service name and reset the progress bag */
+        InitializeProgressDialog(hProgress, Info->pCurrentService->lpServiceName);
 
-        DestroyWindow(hProgDlg);
+        /* Resume the requested service */
+        bRet = DoControl(Info, hProgress, SERVICE_CONTROL_PAUSE);
+
+        /* Complete and destroy the progress bar */
+        DestroyProgressDialog(hProgress, bRet);
     }
 
-    return ret;
+    return bRet;
 }
 
 
-BOOL DoResume(PMAIN_WND_INFO Info)
+BOOL
+DoResume(PMAIN_WND_INFO Info)
 {
-    BOOL ret = FALSE;
-    HWND hProgDlg;
+    HWND hProgress;
+    BOOL bRet = FALSE;
 
-    hProgDlg = CreateProgressDialog(Info->hMainWnd,
-                                    Info->pCurrentService->lpServiceName,
-                                    IDS_PROGRESS_INFO_RESUME);
-    if (hProgDlg)
+    /* Create a progress window to track the progress of the resuming service */
+    hProgress = CreateProgressDialog(Info->hMainWnd,
+                                     IDS_PROGRESS_INFO_RESUME);
+    if (hProgress)
     {
-        ret = Control(Info,
-                      hProgDlg,
-                      SERVICE_CONTROL_CONTINUE);
+        /* Set the service name and reset the progress bag */
+        InitializeProgressDialog(hProgress, Info->pCurrentService->lpServiceName);
+
+        /* Resume the requested service */
+        bRet = DoControl(Info, hProgress, SERVICE_CONTROL_CONTINUE);
 
-        DestroyWindow(hProgDlg);
+        /* Complete and destroy the progress bar */
+        DestroyProgressDialog(hProgress, bRet);
     }
 
-    return ret;
+    return bRet;
 }