diff --git a/reactos/base/applications/mscutils/servman/lang/en-US.rc b/reactos/base/applications/mscutils/servman/lang/en-US.rc index 0edc950f7a9..b9bbc7544dd 100644 --- a/reactos/base/applications/mscutils/servman/lang/en-US.rc +++ b/reactos/base/applications/mscutils/servman/lang/en-US.rc @@ -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 diff --git a/reactos/base/applications/mscutils/servman/resource.h b/reactos/base/applications/mscutils/servman/resource.h index ebaaedc4099..ba8cb60938b 100644 --- a/reactos/base/applications/mscutils/servman/resource.h +++ b/reactos/base/applications/mscutils/servman/resource.h @@ -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 diff --git a/reactos/base/applications/mscutils/servman/start.c b/reactos/base/applications/mscutils/servman/start.c index bac02d9810c..587cee323fb 100644 --- a/reactos/base/applications/mscutils/servman/start.c +++ b/reactos/base/applications/mscutils/servman/start.c @@ -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 + * COPYRIGHT: Copyright 2005-2009 Ged Murphy * */ @@ -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; } + diff --git a/reactos/base/applications/mscutils/servman/stop.c b/reactos/base/applications/mscutils/servman/stop.c index a082bc52c14..8c2bb07265d 100644 --- a/reactos/base/applications/mscutils/servman/stop.c +++ b/reactos/base/applications/mscutils/servman/stop.c @@ -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 + * COPYRIGHT: Copyright 2006-2009 Ged Murphy * */ #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; }