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…
==============================================================================
--- 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…
==============================================================================
--- 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…
==============================================================================
--- 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 <gedmurphy(a)reactos.org>
+ * COPYRIGHT: Copyright 2005-2009 Ged Murphy <gedmurphy(a)reactos.org>
*
*/
@@ -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…
==============================================================================
--- 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 <gedmurphy(a)reactos.org>
+ * COPYRIGHT: Copyright 2006-2009 Ged Murphy <gedmurphy(a)reactos.org>
*
*/
#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;
+}