Author: gedmurphy
Date: Wed Apr 29 12:32:52 2009
New Revision: 40725

URL: http://svn.reactos.org/svn/reactos?rev=40725&view=rev
Log:
- Rewrite start and stop routines to make them much more robust
- Add the ability to check for and stop dependent services
- Untested at the moment, but unfinished anyway.

Modified:
    trunk/reactos/base/applications/mscutils/servman/lang/en-US.rc
    trunk/reactos/base/applications/mscutils/servman/resource.h
    trunk/reactos/base/applications/mscutils/servman/start.c
    trunk/reactos/base/applications/mscutils/servman/stop.c

Modified: trunk/reactos/base/applications/mscutils/servman/lang/en-US.rc
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/mscutils/servman/lang/en-US.rc?rev=40725&r1=40724&r2=40725&view=diff
==============================================================================
--- trunk/reactos/base/applications/mscutils/servman/lang/en-US.rc [iso-8859-1] 
(original)
+++ trunk/reactos/base/applications/mscutils/servman/lang/en-US.rc [iso-8859-1] 
Wed Apr 29 12:32:52 2009
@@ -147,6 +147,19 @@
   DEFPUSHBUTTON "No", IDCANCEL, 102, 129, 54, 13
 END
 
+IDD_DLG_DEPEND_STOP DIALOGEX 6,6,240,148
+CAPTION "Stop Other Services"
+FONT 8, "MS Shell Dlg",0,0
+STYLE DS_SHELLFONT | WS_BORDER | WS_DLGFRAME | DS_MODALFRAME
+BEGIN
+  ICON IDI_WARNING, IDC_STATIC, 10, 8, 24, 22
+  LTEXT "", IDC_STOP_DEPENDS, 40, 8, 170, 25
+  EDITTEXT IDC_DEL_DESC, 15, 40, 210, 60, WS_CHILD | WS_VISIBLE | 
WS_EX_STATICEDGE | ES_MULTILINE | ES_READONLY
+  LTEXT "Do you want to stop these services?",IDC_STATIC, 15, 110, 150, 10
+  DEFPUSHBUTTON "Yes", IDOK, 60, 129, 54, 14
+  PUSHBUTTON "No", IDCANCEL, 120, 129, 54, 14
+END
+
 IDD_DLG_HELP_OPTIONS DIALOGEX 6,6,200,150
 CAPTION "Options"
 FONT 8, "MS Shell Dlg",0,0
@@ -191,6 +204,7 @@
 STRINGTABLE DISCARDABLE
 BEGIN
   IDS_NUM_SERVICES "Num Services: %d"
+  IDS_STOP_DEPENDS "When %s stops, these other services will also stop"
   IDS_LICENSE "This program is free software; you can redistribute it and/or 
modify it under the terms of the GNU General Public License as published by the 
Free Software Foundation; either version 2 of the License, or (at your option) 
any later version.\r\n\r\nThis program is distributed in the hope that it will 
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
Public License for more details.\r\n\r\nYou 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."
 END
 

Modified: trunk/reactos/base/applications/mscutils/servman/resource.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/mscutils/servman/resource.h?rev=40725&r1=40724&r2=40725&view=diff
==============================================================================
--- trunk/reactos/base/applications/mscutils/servman/resource.h [iso-8859-1] 
(original)
+++ trunk/reactos/base/applications/mscutils/servman/resource.h [iso-8859-1] 
Wed Apr 29 12:32:52 2009
@@ -174,3 +174,8 @@
 #define IDS_PROGRESS_INFO_STOP   7005
 #define IDS_PROGRESS_INFO_PAUSE  7006
 #define IDS_PROGRESS_INFO_RESUME 7007
+
+/* stop dependencies */
+#define IDD_DLG_DEPEND_STOP 12000
+#define IDC_STOP_DEPENDS    12001
+#define IDS_STOP_DEPENDS    12001

Modified: trunk/reactos/base/applications/mscutils/servman/start.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/mscutils/servman/start.c?rev=40725&r1=40724&r2=40725&view=diff
==============================================================================
--- trunk/reactos/base/applications/mscutils/servman/start.c [iso-8859-1] 
(original)
+++ trunk/reactos/base/applications/mscutils/servman/start.c [iso-8859-1] Wed 
Apr 29 12:32:52 2009
@@ -3,7 +3,7 @@
  * LICENSE:     GPL - See COPYING in the top level directory
  * FILE:        base/applications/mscutils/servman/start.c
  * PURPOSE:     Start a service
- * COPYRIGHT:   Copyright 2005-2007 Ged Murphy <[email protected]>
+ * COPYRIGHT:   Copyright 2005-2009 Ged Murphy <[email protected]>
  *
  */
 
@@ -14,102 +14,100 @@
                HWND hProgDlg)
 {
     SC_HANDLE hSCManager;
-    SC_HANDLE hSc;
+    SC_HANDLE hService;
     SERVICE_STATUS_PROCESS ServiceStatus;
     DWORD BytesNeeded = 0;
+    DWORD dwStartTickCount;
+    DWORD dwOldCheckPoint;
+    DWORD dwWaitTime;
+    DWORD dwMaxWait;
     BOOL bRet = FALSE;
-    BOOL bDispErr = TRUE;
 
-    hSCManager = OpenSCManager(NULL,
-                               NULL,
-                               SC_MANAGER_ALL_ACCESS);
-    if (hSCManager != NULL)
+    hSCManager = OpenSCManagerW(NULL,
+                                NULL,
+                                SC_MANAGER_ALL_ACCESS);
+    if (!hSCManager)
     {
-        hSc = OpenService(hSCManager,
-                          Info->pCurrentService->lpServiceName,
-                          SERVICE_ALL_ACCESS);
-        if (hSc != NULL)
+        return FALSE;
+    }
+
+    hService = OpenServiceW(hSCManager,
+                            Info->pCurrentService->lpServiceName,
+                            SERVICE_START | SERVICE_QUERY_STATUS);
+    if (hService)
+    {
+        bRet = StartServiceW(hService,
+                             0,
+                             NULL);
+        if (!bRet && GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
         {
-            if (StartService(hSc,
-                              0,
-                              NULL))
+            bRet = TRUE;
+        }
+        else if (bRet)
+        {
+            bRet = FALSE;
+
+            if (QueryServiceStatusEx(hService,
+                                     SC_STATUS_PROCESS_INFO,
+                                     (LPBYTE)&ServiceStatus,
+                                     sizeof(SERVICE_STATUS_PROCESS),
+                                     &BytesNeeded))
             {
-                bDispErr = FALSE;
+                dwStartTickCount = GetTickCount();
+                dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+                dwMaxWait = 30000; // 30 secs
 
-                if (QueryServiceStatusEx(hSc,
-                                         SC_STATUS_PROCESS_INFO,
-                                         (LPBYTE)&ServiceStatus,
-                                         sizeof(SERVICE_STATUS_PROCESS),
-                                         &BytesNeeded))
+                while (ServiceStatus.dwCurrentState != SERVICE_RUNNING)
                 {
-                    DWORD dwStartTickCount = GetTickCount();
-                    DWORD dwOldCheckPoint = ServiceStatus.dwCheckPoint;
-                    DWORD dwMaxWait = 2000 * 60; // wait for 2 mins
+                    dwWaitTime = ServiceStatus.dwWaitHint / 10;
 
-                    IncrementProgressBar(hProgDlg);
+                    if (!QueryServiceStatusEx(hService,
+                                              SC_STATUS_PROCESS_INFO,
+                                              (LPBYTE)&ServiceStatus,
+                                              sizeof(SERVICE_STATUS_PROCESS),
+                                              &BytesNeeded))
+                    {
+                        break;
+                    }
 
-                    while (ServiceStatus.dwCurrentState != SERVICE_RUNNING)
+                    if (ServiceStatus.dwCheckPoint > dwOldCheckPoint)
                     {
-                        DWORD dwWaitTime = ServiceStatus.dwWaitHint / 10;
-
-                        if (!QueryServiceStatusEx(hSc,
-                                                  SC_STATUS_PROCESS_INFO,
-                                                  (LPBYTE)&ServiceStatus,
-                                                  
sizeof(SERVICE_STATUS_PROCESS),
-                                                  &BytesNeeded))
+                        /* The service is making progress*/
+                        dwStartTickCount = GetTickCount();
+                        dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+                    }
+                    else
+                    {
+                        if (GetTickCount() >= dwStartTickCount + dwMaxWait)
                         {
+                            /* We exceeded our max wait time, give up */
                             break;
                         }
+                    }
 
-                        if (ServiceStatus.dwCheckPoint > dwOldCheckPoint)
-                        {
-                            /* The service is making progress, increment the 
progress bar */
-                            IncrementProgressBar(hProgDlg);
-                            dwStartTickCount = GetTickCount();
-                            dwOldCheckPoint = ServiceStatus.dwCheckPoint;
-                        }
-                        else
-                        {
-                            if(GetTickCount() >= dwStartTickCount + dwMaxWait)
-                            {
-                                /* give up */
-                                break;
-                            }
-                        }
+                    if (dwWaitTime < 200)
+                        dwWaitTime = 200;
+                    else if (dwWaitTime > 10000)
+                        dwWaitTime = 10000;
 
-                        if(dwWaitTime < 200)
-                            dwWaitTime = 200;
-                        else if (dwWaitTime > 10000)
-                            dwWaitTime = 10000;
+                    Sleep(dwWaitTime);
+                }
 
-                        Sleep(dwWaitTime);
-                    }
+                if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
+                {
+                    bRet = TRUE;
                 }
             }
-
-            CloseServiceHandle(hSc);
         }
 
-        CloseServiceHandle(hSCManager);
+        CloseServiceHandle(hService);
     }
 
-    if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
-    {
-        CompleteProgressBar(hProgDlg);
-        Sleep(500);
-        bRet = TRUE;
-    }
-    else
-    {
-        if (bDispErr)
-            GetError();
-        else
-            DisplayString(_T("The service failed to start"));
-    }
+    CloseServiceHandle(hSCManager);
+
 
     return bRet;
 }
-
 
 BOOL
 DoStart(PMAIN_WND_INFO Info)
@@ -128,8 +126,20 @@
         bRet = DoStartService(Info,
                               hProgDlg);
 
+        if (bRet)
+        {
+            CompleteProgressBar(hProgDlg);
+            Sleep(500);
+            bRet = TRUE;
+        }
+        else
+        {
+            GetError();
+        }
+
         DestroyWindow(hProgDlg);
     }
 
     return bRet;
 }
+

Modified: trunk/reactos/base/applications/mscutils/servman/stop.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/mscutils/servman/stop.c?rev=40725&r1=40724&r2=40725&view=diff
==============================================================================
--- trunk/reactos/base/applications/mscutils/servman/stop.c [iso-8859-1] 
(original)
+++ trunk/reactos/base/applications/mscutils/servman/stop.c [iso-8859-1] Wed 
Apr 29 12:32:52 2009
@@ -3,96 +3,366 @@
  * LICENSE:     GPL - See COPYING in the top level directory
  * FILE:        base/applications/mscutils/servman/stop.c
  * PURPOSE:     Stops running a service
- * COPYRIGHT:   Copyright 2006-2007 Ged Murphy <[email protected]>
+ * COPYRIGHT:   Copyright 2006-2009 Ged Murphy <[email protected]>
  *
  */
 
 #include "precomp.h"
 
+static BOOL
+StopService(PMAIN_WND_INFO pInfo,
+            SC_HANDLE hService)
+{
+    SERVICE_STATUS_PROCESS ServiceStatus;
+    DWORD dwBytesNeeded;
+    DWORD dwStartTime;
+    DWORD dwTimeout;
+    HWND hProgDlg;
+    BOOL bRet = FALSE;
+
+    dwStartTime = GetTickCount();
+    dwTimeout = 30000; // 30 secs
+
+    hProgDlg = CreateProgressDialog(pInfo->hMainWnd,
+                                    pInfo->pCurrentService->lpServiceName,
+                                    IDS_PROGRESS_INFO_STOP);
+    if (hProgDlg)
+    {
+        IncrementProgressBar(hProgDlg);
+
+        if (ControlService(hService,
+                           SERVICE_CONTROL_STOP,
+                           (LPSERVICE_STATUS)&ServiceStatus))
+        {
+            while (ServiceStatus.dwCurrentState != SERVICE_STOPPED)
+            {
+                Sleep(ServiceStatus.dwWaitHint);
+
+                if (QueryServiceStatusEx(hService,
+                                         SC_STATUS_PROCESS_INFO,
+                                         (LPBYTE)&ServiceStatus,
+                                         sizeof(SERVICE_STATUS_PROCESS),
+                                         &dwBytesNeeded))
+                {
+                    if (GetTickCount() - dwStartTime > dwTimeout)
+                    {
+                        /* We exceeded our max wait time, give up */
+                        break;
+                    }
+                }
+            }
+
+            if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
+            {
+                bRet = TRUE;
+            }
+        }
+
+        CompleteProgressBar(hProgDlg);
+        Sleep(500);
+        DestroyWindow(hProgDlg);
+    }
+
+    return bRet;
+}
+
+static LPENUM_SERVICE_STATUS
+GetDependentServices(PMAIN_WND_INFO pInfo,
+                     SC_HANDLE hService,
+                     LPDWORD lpdwCount)
+{
+    LPENUM_SERVICE_STATUS lpDependencies;
+    DWORD dwBytesNeeded;
+    DWORD dwCount;
+
+    if (EnumDependentServices(hService,
+                              SERVICE_ACTIVE,
+                              NULL,
+                              0,
+                              &dwBytesNeeded,
+                              &dwCount))
+    {
+        /* There are no dependent services */
+         return NULL;
+    }
+    else
+    {
+        if (GetLastError() != ERROR_MORE_DATA)
+            return NULL; // Unexpected error
+
+        lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(),
+                                                          0,
+                                                          dwBytesNeeded);
+        if (lpDependencies)
+        {
+            if (EnumDependentServices(hService,
+                                       SERVICE_ACTIVE,
+                                       lpDependencies,
+                                       dwBytesNeeded,
+                                       &dwBytesNeeded,
+                                       &dwCount))
+            {
+                *lpdwCount = dwCount;
+            }
+            else
+            {
+                HeapFree(ProcessHeap,
+                         0,
+                         lpDependencies);
+
+                lpDependencies = NULL;
+            }
+        }
+    }
+
+    return lpDependencies;
+
+}
+
+static BOOL
+StopDependentServices(PMAIN_WND_INFO pInfo,
+                      SC_HANDLE hSCManager,
+                      SC_HANDLE hService)
+{
+    LPENUM_SERVICE_STATUS lpDependencies;
+    SC_HANDLE hDepService;
+    DWORD dwCount;
+    BOOL bRet = FALSE;
+
+    lpDependencies = GetDependentServices(pInfo, hService, &dwCount);
+    if (lpDependencies)
+    {
+        LPENUM_SERVICE_STATUS lpEnumServiceStatus;
+        DWORD i;
+
+        for (i = 0; i < dwCount; i++)
+        {
+            lpEnumServiceStatus = &lpDependencies[i];
+
+            hDepService = OpenService(hSCManager,
+                                      lpEnumServiceStatus->lpServiceName,
+                                      SERVICE_STOP | SERVICE_QUERY_STATUS);
+            if (hDepService)
+            {
+                bRet = StopService(pInfo, hDepService);
+
+                CloseServiceHandle(hDepService);
+
+                if (!bRet)
+                {
+                    GetError();
+                    break;
+                }
+            }
+        }
+
+        HeapFree(GetProcessHeap(),
+                 0,
+                 lpDependencies);
+    }
+
+    return bRet;
+}
+
+static BOOL
+HasDependentServices(PMAIN_WND_INFO pInfo)
+{
+    SC_HANDLE hSCManager;
+    SC_HANDLE hService;
+    DWORD dwBytesNeeded, dwCount;
+    BOOL bRet = FALSE;
+
+    hSCManager = OpenSCManagerW(NULL,
+                                NULL,
+                                SC_MANAGER_ALL_ACCESS);
+    if (hSCManager)
+    {
+        hService = OpenServiceW(hSCManager,
+                                pInfo->pCurrentService->lpServiceName,
+                                SERVICE_ENUMERATE_DEPENDENTS);
+        if (hService)
+        {
+            if (!EnumDependentServices(hService,
+                                       SERVICE_ACTIVE,
+                                       NULL,
+                                       0,
+                                       &dwBytesNeeded,
+                                       &dwCount))
+            {
+                 if (GetLastError() == ERROR_MORE_DATA)
+                     bRet = TRUE;
+            }
+
+            CloseServiceHandle(hService);
+        }
+
+        CloseServiceHandle(hSCManager);
+    }
+
+    return bRet;
+}
+
+static BOOL
+DoInitDependsDialog(PMAIN_WND_INFO pInfo,
+                    HWND hDlg)
+{
+    LPTSTR lpPartialStr, lpStr;
+    DWORD fullLen;
+    HICON hIcon = NULL;
+    BOOL bRet = FALSE;
+
+    if (pInfo)
+    {
+        SetWindowLongPtr(hDlg,
+                         GWLP_USERDATA,
+                         (LONG_PTR)pInfo);
+
+        hIcon = (HICON)LoadImage(hInstance,
+                                 MAKEINTRESOURCE(IDI_SM_ICON),
+                                 IMAGE_ICON,
+                                 16,
+                                 16,
+                                 0);
+        if (hIcon)
+        {
+            SendMessage(hDlg,
+                        WM_SETICON,
+                        ICON_SMALL,
+                        (LPARAM)hIcon);
+            DestroyIcon(hIcon);
+        }
+
+        if (AllocAndLoadString(&lpPartialStr,
+                               hInstance,
+                               IDS_STOP_DEPENDS))
+        {
+            fullLen = _tcslen(lpPartialStr) + 
_tcslen(pInfo->pCurrentService->lpDisplayName) + 1;
+
+            lpStr = HeapAlloc(ProcessHeap,
+                              0,
+                              fullLen * sizeof(TCHAR));
+            if (lpStr)
+            {
+                _sntprintf(lpStr, fullLen, lpPartialStr, 
pInfo->pCurrentService->lpDisplayName);
+
+                SendDlgItemMessage(hDlg,
+                                   IDC_STOP_DEPENDS,
+                                   WM_SETTEXT,
+                                   0,
+                                   (LPARAM)lpStr);
+
+                bRet = TRUE;
+
+                HeapFree(ProcessHeap,
+                         0,
+                         lpStr);
+            }
+
+            HeapFree(ProcessHeap,
+                     0,
+                     lpPartialStr);
+        }
+    }
+
+    return bRet;
+}
+
+
+INT_PTR CALLBACK
+StopDependsDialogProc(HWND hDlg,
+                 UINT message,
+                 WPARAM wParam,
+                 LPARAM lParam)
+{
+    PMAIN_WND_INFO pInfo = NULL;
+    
+
+    /* Get the window context */
+    pInfo = (PMAIN_WND_INFO)GetWindowLongPtr(hDlg,
+                                             GWLP_USERDATA);
+    if (pInfo == NULL && message != WM_INITDIALOG)
+    {
+        return FALSE;
+    }
+
+    switch (message)
+    {
+        case WM_INITDIALOG:
+        {
+            BOOL bRet = FALSE;
+
+            pInfo = (PMAIN_WND_INFO)lParam;
+            if (pInfo != NULL)
+            {
+                bRet = DoInitDependsDialog(pInfo, hDlg);
+            }
+
+            return bRet;
+        }
+
+        case WM_COMMAND:
+        {
+            switch (LOWORD(wParam))
+            {
+                case IDOK:
+                case IDCANCEL:
+                {
+                    EndDialog(hDlg,
+                              LOWORD(wParam));
+                    return TRUE;
+                }
+            }
+        }
+    }
+
+    return FALSE;
+}
+
+
 BOOL
-DoStop(PMAIN_WND_INFO Info)
+DoStop(PMAIN_WND_INFO pInfo)
 {
     SC_HANDLE hSCManager = NULL;
-    SC_HANDLE hSc = NULL;
-    LPQUERY_SERVICE_CONFIG lpServiceConfig = NULL;
-    HWND hProgDlg;
-    DWORD BytesNeeded = 0;
-    BOOL ret = FALSE;
+    SC_HANDLE hService;
+    BOOL bHasDepends;
+    BOOL bRet = FALSE;
+
+    bHasDepends = HasDependentServices(pInfo);
+    if (bHasDepends)
+    {
+        INT ret = DialogBoxParam(hInstance,
+                                 MAKEINTRESOURCE(IDD_DLG_DEPEND_STOP),
+                                 pInfo->hMainWnd,
+                                 StopDependsDialogProc,
+                                 (LPARAM)pInfo);
+        if (ret != IDOK)
+            return FALSE;
+    }
 
     hSCManager = OpenSCManager(NULL,
                                NULL,
-                               SC_MANAGER_ENUMERATE_SERVICE);
-    if (hSCManager == NULL)
-    {
-        GetError();
-        return FALSE;
-    }
-
-    hSc = OpenService(hSCManager,
-                      Info->pCurrentService->lpServiceName,
-                      SERVICE_QUERY_CONFIG);
-    if (hSc)
-    {
-        if (!QueryServiceConfig(hSc,
-                                lpServiceConfig,
-                                0,
-                                &BytesNeeded))
-        {
-            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
-            {
-                lpServiceConfig = 
(LPQUERY_SERVICE_CONFIG)HeapAlloc(ProcessHeap,
-                                                                    0,
-                                                                    
BytesNeeded);
-                if (lpServiceConfig == NULL)
-                    goto cleanup;
-
-                if (QueryServiceConfig(hSc,
-                                       lpServiceConfig,
-                                       BytesNeeded,
-                                       &BytesNeeded))
-                {
-#if 0
-                    if (lpServiceConfig->lpDependencies)
-                    {
-                        TCHAR str[500];
-
-                        _sntprintf(str, 499, _T("%s depends on this service, 
implement the dialog to allow closing of other services"),
-                                   lpServiceConfig->lpDependencies);
-                        MessageBox(NULL, str, NULL, 0);
-
-                        //FIXME: open 'stop other services' box
-                    }
-                    else
-                    {
-#endif
-                            hProgDlg = CreateProgressDialog(Info->hMainWnd,
-                                                            
Info->pCurrentService->lpServiceName,
-                                                            
IDS_PROGRESS_INFO_STOP);
-                            if (hProgDlg)
-                            {
-                                ret = Control(Info,
-                                              hProgDlg,
-                                              SERVICE_CONTROL_STOP);
-
-                                DestroyWindow(hProgDlg);
-                            }
-                    //}
-
-                    HeapFree(ProcessHeap,
-                             0,
-                             lpServiceConfig);
-
-                    lpServiceConfig = NULL;
-                }
-            }
-        }
-    }
-
-cleanup:
-    if (hSCManager != NULL)
+                               SC_MANAGER_ALL_ACCESS);
+    if (hSCManager)
+    {
+        hService = OpenService(hSCManager,
+                               pInfo->pCurrentService->lpServiceName,
+                               SERVICE_STOP | SERVICE_QUERY_STATUS | 
SERVICE_ENUMERATE_DEPENDENTS);
+        if (hService)
+        {
+            if (bHasDepends)
+            {
+                StopDependentServices(pInfo,
+                                      hSCManager,
+                                      hService);
+            }
+
+            bRet = StopService(pInfo, hService);
+
+            CloseServiceHandle(hService);
+        }
+
         CloseServiceHandle(hSCManager);
-    if (hSc != NULL)
-        CloseServiceHandle(hSc);
-
-    return ret;
-}
+    }
+
+    return bRet;
+}

Reply via email to