- 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.

svn path=/trunk/; revision=40725
This commit is contained in:
Ged Murphy 2009-04-29 08:32:52 +00:00
parent db68550e25
commit d8d8b19d4a
4 changed files with 441 additions and 142 deletions

View file

@ -147,6 +147,19 @@ BEGIN
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 @@ END
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

View file

@ -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

View file

@ -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@reactos.org>
* COPYRIGHT: Copyright 2005-2009 Ged Murphy <gedmurphy@reactos.org>
*
*/
@ -14,103 +14,101 @@ DoStartService(PMAIN_WND_INFO Info,
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);
while (ServiceStatus.dwCurrentState != SERVICE_RUNNING)
if (!QueryServiceStatusEx(hService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ServiceStatus,
sizeof(SERVICE_STATUS_PROCESS),
&BytesNeeded))
{
DWORD dwWaitTime = ServiceStatus.dwWaitHint / 10;
break;
}
if (!QueryServiceStatusEx(hSc,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ServiceStatus,
sizeof(SERVICE_STATUS_PROCESS),
&BytesNeeded))
if (ServiceStatus.dwCheckPoint > dwOldCheckPoint)
{
/* 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;
Sleep(dwWaitTime);
}
if (dwWaitTime < 200)
dwWaitTime = 200;
else if (dwWaitTime > 10000)
dwWaitTime = 10000;
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 @@ DoStart(PMAIN_WND_INFO Info)
bRet = DoStartService(Info,
hProgDlg);
if (bRet)
{
CompleteProgressBar(hProgDlg);
Sleep(500);
bRet = TRUE;
}
else
{
GetError();
}
DestroyWindow(hProgDlg);
}
return bRet;
}

View file

@ -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@reactos.org>
* COPYRIGHT: Copyright 2006-2009 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "precomp.h"
BOOL
DoStop(PMAIN_WND_INFO Info)
static BOOL
StopService(PMAIN_WND_INFO pInfo,
SC_HANDLE hService)
{
SC_HANDLE hSCManager = NULL;
SC_HANDLE hSc = NULL;
LPQUERY_SERVICE_CONFIG lpServiceConfig = NULL;
SERVICE_STATUS_PROCESS ServiceStatus;
DWORD dwBytesNeeded;
DWORD dwStartTime;
DWORD dwTimeout;
HWND hProgDlg;
DWORD BytesNeeded = 0;
BOOL ret = FALSE;
BOOL bRet = FALSE;
hSCManager = OpenSCManager(NULL,
NULL,
SC_MANAGER_ENUMERATE_SERVICE);
if (hSCManager == NULL)
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)
{
GetError();
return FALSE;
}
hSc = OpenService(hSCManager,
Info->pCurrentService->lpServiceName,
SERVICE_QUERY_CONFIG);
if (hSc)
switch (message)
{
if (!QueryServiceConfig(hSc,
lpServiceConfig,
0,
&BytesNeeded))
case WM_INITDIALOG:
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
BOOL bRet = FALSE;
pInfo = (PMAIN_WND_INFO)lParam;
if (pInfo != NULL)
{
lpServiceConfig = (LPQUERY_SERVICE_CONFIG)HeapAlloc(ProcessHeap,
0,
BytesNeeded);
if (lpServiceConfig == NULL)
goto cleanup;
bRet = DoInitDependsDialog(pInfo, hDlg);
}
if (QueryServiceConfig(hSc,
lpServiceConfig,
BytesNeeded,
&BytesNeeded))
return bRet;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
{
#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;
EndDialog(hDlg,
LOWORD(wParam));
return TRUE;
}
}
}
}
cleanup:
if (hSCManager != NULL)
CloseServiceHandle(hSCManager);
if (hSc != NULL)
CloseServiceHandle(hSc);
return ret;
return FALSE;
}
BOOL
DoStop(PMAIN_WND_INFO pInfo)
{
SC_HANDLE hSCManager = NULL;
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_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);
}
return bRet;
}