From d7e9b1a61fa3f68c4a55161b2686a09ede3aff8b Mon Sep 17 00:00:00 2001 From: Ged Murphy Date: Mon, 4 May 2009 18:44:54 +0000 Subject: [PATCH] Add most of the code for the dependencies tab in the property sheet. It's not quite complete but I'm getting bored with it now. May finish it tomorrow. svn path=/trunk/; revision=40789 --- .../mscutils/servman/dependencies.c | 228 ++++++++++ .../mscutils/servman/lang/en-US.rc | 1 + .../applications/mscutils/servman/mainwnd.c | 7 +- .../base/applications/mscutils/servman/misc.c | 71 +-- .../applications/mscutils/servman/precomp.h | 38 +- .../applications/mscutils/servman/propsheet.c | 427 +----------------- .../mscutils/servman/propsheet_depends.c | 314 +++++++++++++ .../mscutils/servman/propsheet_general.c | 371 +++++++++++++++ .../mscutils/servman/res/driver.ico | Bin 0 -> 40070 bytes .../mscutils/servman/res/nodepends.ico | Bin 0 -> 33982 bytes .../applications/mscutils/servman/resource.h | 4 + .../applications/mscutils/servman/rsrc.rc | 4 + .../mscutils/servman/servman.rbuild | 3 + .../base/applications/mscutils/servman/stop.c | 224 --------- 14 files changed, 1008 insertions(+), 684 deletions(-) create mode 100644 reactos/base/applications/mscutils/servman/dependencies.c create mode 100644 reactos/base/applications/mscutils/servman/propsheet_depends.c create mode 100644 reactos/base/applications/mscutils/servman/propsheet_general.c create mode 100644 reactos/base/applications/mscutils/servman/res/driver.ico create mode 100644 reactos/base/applications/mscutils/servman/res/nodepends.ico diff --git a/reactos/base/applications/mscutils/servman/dependencies.c b/reactos/base/applications/mscutils/servman/dependencies.c new file mode 100644 index 00000000000..976f69fa598 --- /dev/null +++ b/reactos/base/applications/mscutils/servman/dependencies.c @@ -0,0 +1,228 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/applications/mscutils/servman/dependencies.c + * PURPOSE: Helper functions for service dependents + * COPYRIGHT: Copyright 2006-2009 Ged Murphy + * + */ + +#include "precomp.h" + +LPENUM_SERVICE_STATUS +GetDependentServices(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; + +} + + +BOOL +HasDependentServices(SC_HANDLE hService) +{ + DWORD dwBytesNeeded, dwCount; + BOOL bRet = FALSE; + + if (hService) + { + if (!EnumDependentServices(hService, + SERVICE_ACTIVE, + NULL, + 0, + &dwBytesNeeded, + &dwCount)) + { + if (GetLastError() == ERROR_MORE_DATA) + bRet = TRUE; + } + } + + return bRet; +} + +static BOOL +DoInitDependsDialog(PSTOP_INFO pStopInfo, + HWND hDlg) +{ + LPENUM_SERVICE_STATUS lpDependencies; + DWORD dwCount; + LPTSTR lpPartialStr, lpStr; + DWORD fullLen; + HICON hIcon = NULL; + BOOL bRet = FALSE; + + if (pStopInfo) + { + SetWindowLongPtr(hDlg, + GWLP_USERDATA, + (LONG_PTR)pStopInfo); + + 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); + } + + /* Add the label */ + if (AllocAndLoadString(&lpPartialStr, + hInstance, + IDS_STOP_DEPENDS)) + { + fullLen = _tcslen(lpPartialStr) + _tcslen(pStopInfo->pInfo->pCurrentService->lpDisplayName) + 1; + + lpStr = HeapAlloc(ProcessHeap, + 0, + fullLen * sizeof(TCHAR)); + if (lpStr) + { + _sntprintf(lpStr, fullLen, lpPartialStr, pStopInfo->pInfo->pCurrentService->lpDisplayName); + + SendDlgItemMessage(hDlg, + IDC_STOP_DEPENDS, + WM_SETTEXT, + 0, + (LPARAM)lpStr); + + bRet = TRUE; + + HeapFree(ProcessHeap, + 0, + lpStr); + } + + HeapFree(ProcessHeap, + 0, + lpPartialStr); + } + + /* Get the list of dependencies */ + lpDependencies = GetDependentServices(pStopInfo->hMainService, &dwCount); + if (lpDependencies) + { + LPENUM_SERVICE_STATUS lpEnumServiceStatus; + DWORD i; + + for (i = 0; i < dwCount; i++) + { + lpEnumServiceStatus = &lpDependencies[i]; + + /* Add the service to the listbox */ + SendDlgItemMessage(hDlg, + IDC_STOP_DEPENDS_LB, + LB_ADDSTRING, + 0, + (LPARAM)lpEnumServiceStatus->lpDisplayName); + } + + HeapFree(ProcessHeap, + 0, + lpDependencies); + } + } + + return bRet; +} + + +INT_PTR CALLBACK +StopDependsDialogProc(HWND hDlg, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + PSTOP_INFO pStopInfo = NULL; + + /* Get the window context */ + pStopInfo = (PSTOP_INFO)GetWindowLongPtr(hDlg, + GWLP_USERDATA); + if (pStopInfo == NULL && message != WM_INITDIALOG) + { + return FALSE; + } + + switch (message) + { + case WM_INITDIALOG: + { + BOOL bRet = FALSE; + + pStopInfo = (PSTOP_INFO)lParam; + if (pStopInfo != NULL) + { + bRet = DoInitDependsDialog(pStopInfo, hDlg); + } + + return bRet; + } + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + { + EndDialog(hDlg, + LOWORD(wParam)); + return TRUE; + } + } + } + } + + return FALSE; +} diff --git a/reactos/base/applications/mscutils/servman/lang/en-US.rc b/reactos/base/applications/mscutils/servman/lang/en-US.rc index f4175112dfc..eabb6adecd9 100644 --- a/reactos/base/applications/mscutils/servman/lang/en-US.rc +++ b/reactos/base/applications/mscutils/servman/lang/en-US.rc @@ -205,6 +205,7 @@ STRINGTABLE DISCARDABLE BEGIN IDS_NUM_SERVICES "Num Services: %d" IDS_STOP_DEPENDS "When %s stops, these other services will also stop" + IDS_NO_DEPENDS "" 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/mainwnd.c b/reactos/base/applications/mscutils/servman/mainwnd.c index 77d0bfa0739..6c72e0a91b5 100644 --- a/reactos/base/applications/mscutils/servman/mainwnd.c +++ b/reactos/base/applications/mscutils/servman/mainwnd.c @@ -288,8 +288,9 @@ pCreateToolbar(PMAIN_WND_INFO Info) hImageList = InitImageList(IDB_PROP, IDB_RESTART, - 16, - 16); + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CXSMICON), + IMAGE_BITMAP); if (hImageList == NULL) return FALSE; @@ -890,7 +891,7 @@ CreateMainWindow(LPCTSTR lpCaption, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CW_USEDEFAULT, CW_USEDEFAULT, - 650, + 680, 450, NULL, NULL, diff --git a/reactos/base/applications/mscutils/servman/misc.c b/reactos/base/applications/mscutils/servman/misc.c index 6556df59bc8..3735eb76c9b 100644 --- a/reactos/base/applications/mscutils/servman/misc.c +++ b/reactos/base/applications/mscutils/servman/misc.c @@ -219,42 +219,59 @@ HIMAGELIST InitImageList(UINT StartResource, UINT EndResource, UINT Width, - UINT Height) + UINT Height, + ULONG type) { - HBITMAP hBitmap; - HIMAGELIST hImageList; + HANDLE hImage; + HIMAGELIST himl; UINT i; - INT Ret; + INT ret; /* Create the toolbar icon image list */ - hImageList = ImageList_Create(Width, - Height, - ILC_MASK | ILC_COLOR24, - EndResource - StartResource, - 0); - if (hImageList == NULL) + himl = ImageList_Create(Width, + Height, + ILC_MASK | ILC_COLOR32, + EndResource - StartResource, + 0); + if (himl == NULL) return NULL; - /* Add all icons to the image list */ - for (i = StartResource; i <= EndResource; i++) + ret = 0; + for (i = StartResource; i <= EndResource && ret != -1; i++) { - hBitmap = (HBITMAP) LoadImage(hInstance, - MAKEINTRESOURCE(i), - IMAGE_BITMAP, - Width, - Height, - LR_LOADTRANSPARENT); - if (hBitmap == NULL) - return NULL; + hImage = LoadImage(hInstance, + MAKEINTRESOURCE(i), + type, + Width, + Height, + LR_LOADTRANSPARENT); + if (hImage == NULL) + { + ImageList_Destroy(himl); + himl = NULL; + break; + } - Ret = ImageList_AddMasked(hImageList, - hBitmap, - RGB(255, 0, 128)); - if (Ret == -1) - return NULL; + if (type == IMAGE_BITMAP) + { + ret = ImageList_AddMasked(himl, + hImage, + RGB(255, 0, 128)); + } + else if (type == IMAGE_ICON) + { + ret = ImageList_AddIcon(himl, + hImage); + } - DeleteObject(hBitmap); + DeleteObject(hImage); } - return hImageList; + if (ret == -1) + { + ImageList_Destroy(himl); + himl = NULL; + } + + return himl; } diff --git a/reactos/base/applications/mscutils/servman/precomp.h b/reactos/base/applications/mscutils/servman/precomp.h index 796bb321167..6842de127f2 100644 --- a/reactos/base/applications/mscutils/servman/precomp.h +++ b/reactos/base/applications/mscutils/servman/precomp.h @@ -75,6 +75,14 @@ BOOL CreateListView(PMAIN_WND_INFO Info); /* start */ BOOL DoStart(PMAIN_WND_INFO Info); +/* stop */ +typedef struct _STOP_INFO +{ + PMAIN_WND_INFO pInfo; + SC_HANDLE hSCManager; + SC_HANDLE hMainService; +} STOP_INFO, *PSTOP_INFO; + /* control */ BOOL Control(PMAIN_WND_INFO Info, HWND hProgDlg, DWORD Control); BOOL DoStop(PMAIN_WND_INFO Info); @@ -97,12 +105,31 @@ BOOL RefreshServiceList(PMAIN_WND_INFO Info); BOOL UpdateServiceStatus(ENUM_SERVICE_STATUS_PROCESS* pService); BOOL GetServiceList(PMAIN_WND_INFO Info, DWORD *NumServices); -/* reg */ -BOOL SetDescription(LPTSTR, LPTSTR); +/* dependencies */ +LPENUM_SERVICE_STATUS GetDependentServices(SC_HANDLE hService, LPDWORD lpdwCount); +BOOL HasDependentServices(SC_HANDLE hService); +INT_PTR CALLBACK StopDependsDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); /* propsheet.c */ +typedef struct _SERVICEPROPSHEET +{ + PMAIN_WND_INFO Info; + ENUM_SERVICE_STATUS_PROCESS *pService; + HIMAGELIST hDependsImageList; +} SERVICEPROPSHEET, *PSERVICEPROPSHEET; + LONG APIENTRY OpenPropSheet(PMAIN_WND_INFO Info); +/* propsheet window procs */ +INT_PTR CALLBACK DependenciesPageProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); +INT_PTR CALLBACK GeneralPageProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + /* export.c */ VOID ExportFile(PMAIN_WND_INFO Info); @@ -128,9 +155,10 @@ INT GetTextFromEdit(OUT LPTSTR lpString, IN UINT Res); VOID GetError(VOID); VOID DisplayString(PTCHAR); -HIMAGELIST InitImageList(UINT NumButtons, - UINT StartResource, +HIMAGELIST InitImageList(UINT StartResource, + UINT EndResource, UINT Width, - UINT Height); + UINT Height, + ULONG type); #endif /* __SERVMAN_PRECOMP_H */ diff --git a/reactos/base/applications/mscutils/servman/propsheet.c b/reactos/base/applications/mscutils/servman/propsheet.c index bd52dd48ae0..17193cb4899 100644 --- a/reactos/base/applications/mscutils/servman/propsheet.c +++ b/reactos/base/applications/mscutils/servman/propsheet.c @@ -9,429 +9,6 @@ #include "precomp.h" -typedef struct _SERVICEPROPSHEET -{ - PMAIN_WND_INFO Info; - ENUM_SERVICE_STATUS_PROCESS *pService; -} SERVICEPROPSHEET, *PSERVICEPROPSHEET; - - -static VOID -SetButtonStates(PSERVICEPROPSHEET dlgInfo, - HWND hwndDlg) -{ - HWND hButton; - LPQUERY_SERVICE_CONFIG lpServiceConfig; - DWORD Flags, State; - UINT i; - - Flags = dlgInfo->pService->ServiceStatusProcess.dwControlsAccepted; - State = dlgInfo->pService->ServiceStatusProcess.dwCurrentState; - - for (i = IDC_START; i <= IDC_RESUME; i++) - { - hButton = GetDlgItem(hwndDlg, i); - EnableWindow (hButton, FALSE); - } - - lpServiceConfig = GetServiceConfig(dlgInfo->pService->lpServiceName); - if (State == SERVICE_STOPPED && - lpServiceConfig && lpServiceConfig->dwStartType != SERVICE_DISABLED) - { - hButton = GetDlgItem(hwndDlg, IDC_START); - EnableWindow (hButton, TRUE); - HeapFree(GetProcessHeap(), 0, lpServiceConfig); - } - else if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) ) - { - hButton = GetDlgItem(hwndDlg, IDC_STOP); - EnableWindow (hButton, TRUE); - } - else if ( (Flags & SERVICE_ACCEPT_PAUSE_CONTINUE) && (State == SERVICE_RUNNING) ) - { - hButton = GetDlgItem(hwndDlg, IDC_PAUSE); - EnableWindow (hButton, TRUE); - } - - /* set the main toolbar */ - SetMenuAndButtonStates(dlgInfo->Info); -} - - -static VOID -SetServiceStatusText(PSERVICEPROPSHEET dlgInfo, - HWND hwndDlg) -{ - LPTSTR lpStatus; - UINT id; - - if (dlgInfo->pService->ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING) - { - id = IDS_SERVICES_STARTED; - } - else - { - id = IDS_SERVICES_STOPPED; - } - - if (AllocAndLoadString(&lpStatus, - hInstance, - id)) - { - SendDlgItemMessage(hwndDlg, - IDC_SERV_STATUS, - WM_SETTEXT, - 0, - (LPARAM)lpStatus); - LocalFree(lpStatus); - } -} - -/* - * Fills the 'startup type' combo box with possible - * values and sets it to value of the selected item - */ -static VOID -SetStartupType(LPTSTR lpServiceName, - HWND hwndDlg) -{ - HWND hList; - LPQUERY_SERVICE_CONFIG pServiceConfig; - LPTSTR lpBuf; - DWORD StartUp = 0; - UINT i; - - hList = GetDlgItem(hwndDlg, IDC_START_TYPE); - - for (i = IDS_SERVICES_AUTO; i <= IDS_SERVICES_DIS; i++) - { - if (AllocAndLoadString(&lpBuf, - hInstance, - i)) - { - SendMessage(hList, - CB_ADDSTRING, - 0, - (LPARAM)lpBuf); - LocalFree(lpBuf); - } - } - - pServiceConfig = GetServiceConfig(lpServiceName); - - if (pServiceConfig) - { - switch (pServiceConfig->dwStartType) - { - case SERVICE_AUTO_START: StartUp = 0; break; - case SERVICE_DEMAND_START: StartUp = 1; break; - case SERVICE_DISABLED: StartUp = 2; break; - } - - SendMessage(hList, - CB_SETCURSEL, - StartUp, - 0); - - HeapFree(ProcessHeap, - 0, - pServiceConfig); - } -} - - -/* - * Populates the General Properties dialog with - * the relevant service information - */ -static VOID -InitGeneralPage(PSERVICEPROPSHEET dlgInfo, - HWND hwndDlg) -{ - LPQUERY_SERVICE_CONFIG pServiceConfig; - LPTSTR lpDescription; - - /* set the service name */ - SendDlgItemMessage(hwndDlg, - IDC_SERV_NAME, - WM_SETTEXT, - 0, - (LPARAM)dlgInfo->pService->lpServiceName); - - /* set the display name */ - SendDlgItemMessage(hwndDlg, - IDC_DISP_NAME, - WM_SETTEXT, - 0, - (LPARAM)dlgInfo->pService->lpDisplayName); - - /* set the description */ - if ((lpDescription = GetServiceDescription(dlgInfo->pService->lpServiceName))) - { - SendDlgItemMessage(hwndDlg, - IDC_DESCRIPTION, - WM_SETTEXT, - 0, - (LPARAM)lpDescription); - - HeapFree(ProcessHeap, - 0, - lpDescription); - } - - pServiceConfig = GetServiceConfig(dlgInfo->pService->lpServiceName); - if (pServiceConfig) - { - SendDlgItemMessage(hwndDlg, - IDC_EXEPATH, - WM_SETTEXT, - 0, - (LPARAM)pServiceConfig->lpBinaryPathName); - HeapFree(ProcessHeap, - 0, - pServiceConfig); - } - - - /* set startup type */ - SetStartupType(dlgInfo->pService->lpServiceName, hwndDlg); - - SetServiceStatusText(dlgInfo, - hwndDlg); - - if (dlgInfo->Info->bIsUserAnAdmin) - { - HWND hEdit = GetDlgItem(hwndDlg, - IDC_EDIT); - EnableWindow(hEdit, - TRUE); - } -} - - -VOID -SaveDlgInfo(PSERVICEPROPSHEET dlgInfo, - HWND hwndDlg) -{ - LPQUERY_SERVICE_CONFIG pServiceConfig = NULL; - HWND hList; - DWORD StartUp; - - pServiceConfig = HeapAlloc(ProcessHeap, - HEAP_ZERO_MEMORY, - sizeof(*pServiceConfig)); - if (pServiceConfig) - { - pServiceConfig->dwServiceType = SERVICE_NO_CHANGE; - pServiceConfig->dwErrorControl = SERVICE_NO_CHANGE; - - hList = GetDlgItem(hwndDlg, IDC_START_TYPE); - StartUp = SendMessage(hList, - CB_GETCURSEL, - 0, - 0); - switch (StartUp) - { - case 0: pServiceConfig->dwStartType = SERVICE_AUTO_START; break; - case 1: pServiceConfig->dwStartType = SERVICE_DEMAND_START; break; - case 2: pServiceConfig->dwStartType = SERVICE_DISABLED; break; - } - - if (SetServiceConfig(pServiceConfig, - dlgInfo->pService->lpServiceName, - NULL)) - { - ChangeListViewText(dlgInfo->Info, - dlgInfo->pService, - LVSTARTUP); - } - - HeapFree(ProcessHeap, - 0, - pServiceConfig); - } -} - - -/* - * General Property dialog callback. - * Controls messages to the General dialog - */ -static INT_PTR CALLBACK -GeneralPageProc(HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - PSERVICEPROPSHEET dlgInfo; - - /* Get the window context */ - dlgInfo = (PSERVICEPROPSHEET)GetWindowLongPtr(hwndDlg, - GWLP_USERDATA); - if (dlgInfo == NULL && uMsg != WM_INITDIALOG) - { - return FALSE; - } - - switch (uMsg) - { - case WM_INITDIALOG: - { - dlgInfo = (PSERVICEPROPSHEET)(((LPPROPSHEETPAGE)lParam)->lParam); - if (dlgInfo != NULL) - { - SetWindowLongPtr(hwndDlg, - GWLP_USERDATA, - (LONG_PTR)dlgInfo); - InitGeneralPage(dlgInfo, hwndDlg); - SetButtonStates(dlgInfo, hwndDlg); - } - } - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) - { - case IDC_START_TYPE: - if (HIWORD(wParam) == CBN_SELCHANGE) - PropSheet_Changed(GetParent(hwndDlg), hwndDlg); - break; - - case IDC_START: - if (DoStart(dlgInfo->Info)) - { - UpdateServiceStatus(dlgInfo->pService); - ChangeListViewText(dlgInfo->Info, dlgInfo->pService, LVSTATUS); - SetButtonStates(dlgInfo, hwndDlg); - SetServiceStatusText(dlgInfo, hwndDlg); - } - break; - - case IDC_STOP: - if (DoStop(dlgInfo->Info)) - { - UpdateServiceStatus(dlgInfo->pService); - ChangeListViewText(dlgInfo->Info, dlgInfo->pService, LVSTATUS); - SetButtonStates(dlgInfo, hwndDlg); - SetServiceStatusText(dlgInfo, hwndDlg); - } - break; - - case IDC_PAUSE: - if (DoPause(dlgInfo->Info)) - { - UpdateServiceStatus(dlgInfo->pService); - ChangeListViewText(dlgInfo->Info, dlgInfo->pService, LVSTATUS); - SetButtonStates(dlgInfo, hwndDlg); - SetServiceStatusText(dlgInfo, hwndDlg); - } - break; - - case IDC_RESUME: - if (DoResume(dlgInfo->Info)) - { - UpdateServiceStatus(dlgInfo->pService); - ChangeListViewText(dlgInfo->Info, dlgInfo->pService, LVSTATUS); - SetButtonStates(dlgInfo, hwndDlg); - SetServiceStatusText(dlgInfo, hwndDlg); - } - break; - - case IDC_EDIT: - { - HWND hName, hDesc, hExePath; - - hName = GetDlgItem(hwndDlg, IDC_DISP_NAME); - hDesc = GetDlgItem(hwndDlg, IDC_DESCRIPTION); - hExePath = GetDlgItem(hwndDlg, IDC_EXEPATH); - - SendMessage(hName, EM_SETREADONLY, FALSE, 0); - SendMessage(hDesc, EM_SETREADONLY, FALSE, 0); - SendMessage(hExePath, EM_SETREADONLY, FALSE, 0); - } - break; - - case IDC_START_PARAM: - PropSheet_Changed(GetParent(hwndDlg), hwndDlg); - break; - } - break; - - case WM_NOTIFY: - { - LPNMHDR lpnm = (LPNMHDR)lParam; - - switch (lpnm->code) - { - case PSN_APPLY: - SaveDlgInfo(dlgInfo, hwndDlg); - SetButtonStates(dlgInfo, hwndDlg); - break; - } - } - break; - } - - return FALSE; -} -/* -static VOID -InitDependPage(PSERVICEPROPSHEET dlgInfo, - HWND hwndDlg) -{ - - -} - - - -* - * Dependancies Property dialog callback. - * Controls messages to the Dependancies dialog - * -static INT_PTR CALLBACK -DependanciesPageProc(HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - PSERVICEPROPSHEET dlgInfo; - - dlgInfo = (PSERVICEPROPSHEET)GetWindowLongPtr(hwndDlg, - GWLP_USERDATA); - - if (dlgInfo == NULL && uMsg != WM_INITDIALOG) - { - return FALSE; - } - - switch (uMsg) - { - case WM_INITDIALOG: - { - dlgInfo = (PSERVICEPROPSHEET)(((LPPROPSHEETPAGE)lParam)->lParam); - if (dlgInfo != NULL) - { - SetWindowLongPtr(hwndDlg, - GWLP_USERDATA, - (LONG_PTR)dlgInfo); - - InitDependPage(dlgInfo, hwndDlg); - } - } - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) - { - - } - break; - } - - return FALSE; -} -*/ static VOID InitPropSheetPage(PROPSHEETPAGE *psp, @@ -453,7 +30,7 @@ LONG APIENTRY OpenPropSheet(PMAIN_WND_INFO Info) { PROPSHEETHEADER psh; - PROPSHEETPAGE psp[1]; + PROPSHEETPAGE psp[2]; PSERVICEPROPSHEET pServicePropSheet; LONG Ret = 0; @@ -481,7 +58,7 @@ OpenPropSheet(PMAIN_WND_INFO Info) InitPropSheetPage(&psp[0], pServicePropSheet, IDD_DLG_GENERAL, GeneralPageProc); //InitPropSheetPage(&psp[1], Info, IDD_DLG_GENERAL, LogonPageProc); //InitPropSheetPage(&psp[2], Info, IDD_DLG_GENERAL, RecoveryPageProc); - //InitPropSheetPage(&psp[1], pServicePropSheet, IDD_DLG_DEPEND, DependanciesPageProc); + InitPropSheetPage(&psp[1], pServicePropSheet, IDD_DLG_DEPEND, DependenciesPageProc); Ret = (LONG)(PropertySheet(&psh) != -1); diff --git a/reactos/base/applications/mscutils/servman/propsheet_depends.c b/reactos/base/applications/mscutils/servman/propsheet_depends.c new file mode 100644 index 00000000000..69354dea2a1 --- /dev/null +++ b/reactos/base/applications/mscutils/servman/propsheet_depends.c @@ -0,0 +1,314 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/applications/mscutils/servman/propsheet_depends.c + * PURPOSE: Property dialog box message handler + * COPYRIGHT: Copyright 2006-2009 Ged Murphy + * + */ + +#include "precomp.h" + + +static HTREEITEM +AddItemToTreeView(HWND hTreeView, + HTREEITEM hRoot, + LPTSTR lpLabel, + ULONG serviceType) +{ + TV_ITEM tvi; + TV_INSERTSTRUCT tvins; + + ZeroMemory(&tvi, sizeof(tvi)); + ZeroMemory(&tvins, sizeof(tvins)); + + tvi.mask = TVIF_TEXT | TVIF_SELECTEDIMAGE | TVIF_IMAGE; + tvi.pszText = lpLabel; + tvi.cchTextMax = lstrlen(lpLabel); + + if (serviceType == SERVICE_WIN32_OWN_PROCESS || + serviceType == SERVICE_WIN32_SHARE_PROCESS) + { + tvi.iImage = 1; + tvi.iSelectedImage = 1; + } + else if (serviceType == SERVICE_KERNEL_DRIVER || + serviceType == SERVICE_FILE_SYSTEM_DRIVER) + { + tvi.iImage = 2; + tvi.iSelectedImage = 2; + } + else + { + tvi.iImage = 0; + tvi.iSelectedImage = 0; + } + + tvins.item = tvi; + tvins.hParent = hRoot; + + return TreeView_InsertItem(hTreeView, &tvins); +} + +static VOID +AddServiceDependency(PSERVICEPROPSHEET dlgInfo, + HWND hTreeView, + SC_HANDLE hSCManager, + LPTSTR lpServiceName, + HTREEITEM hParent, + HWND hwndDlg) +{ + LPQUERY_SERVICE_CONFIG lpServiceConfig; + SC_HANDLE hService; + HTREEITEM hChild; + DWORD bytesNeeded; + LPTSTR lpStr; + LPTSTR lpNoDepends; + + hService = OpenService(hSCManager, + lpServiceName, + SERVICE_QUERY_CONFIG); + if (hService) + { + + if (!QueryServiceConfig(hService, + NULL, + 0, + &bytesNeeded) && + GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + lpServiceConfig = HeapAlloc(ProcessHeap, + 0, + bytesNeeded); + if (lpServiceConfig) + { + if (QueryServiceConfig(hService, + lpServiceConfig, + bytesNeeded, + &bytesNeeded)) + { + if (lpServiceConfig) + { + lpStr = lpServiceConfig->lpDependencies; + + if (*lpStr) + { + while (*lpStr) + { + hChild = AddItemToTreeView(hTreeView, + hParent, + lpServiceConfig->lpDisplayName, + lpServiceConfig->dwServiceType); + + AddServiceDependency(dlgInfo, + hTreeView, + hSCManager, + lpStr, + hChild, + hwndDlg); + + while (*lpStr++) + ; + } + } + else + { + if (TreeView_GetCount(hTreeView) == 0) + { + if (AllocAndLoadString(&lpNoDepends, hInstance, IDS_NO_DEPENDS)) + { + lpStr = lpNoDepends; + } + + AddItemToTreeView(hTreeView, + hParent, + lpStr, + 0); + + HeapFree(ProcessHeap, + 0, + lpNoDepends); + + EnableWindow(hTreeView, FALSE); + } + } + } + } + + HeapFree(ProcessHeap, + 0, + lpServiceConfig); + } + } + + CloseServiceHandle(hService); + } + +} + +static VOID +AddServiceDependent(PSERVICEPROPSHEET dlgInfo, + HWND hTreeView, + SC_HANDLE hSCManager, + LPTSTR lpServiceName, + HTREEITEM hParent, + HWND hwndDlg) +{ + LPENUM_SERVICE_STATUS lpServiceStatus; + SC_HANDLE hService; + HTREEITEM hChild; + LPTSTR lpNoDepends; + DWORD count; + INT i; + + hService = OpenService(hSCManager, + lpServiceName, + SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS); + if (hService) + { + lpServiceStatus = GetDependentServices(hService, &count); + if (lpServiceStatus) + { + for (i = 0; i < count; i++) + { + hChild = AddItemToTreeView(hTreeView, + hParent, + lpServiceStatus[i].lpDisplayName, + SERVICE_WIN32); + + AddServiceDependent(dlgInfo, + hTreeView, + hSCManager, + lpServiceStatus[i].lpServiceName, + hChild, + hwndDlg); + } + + HeapFree(ProcessHeap, + 0, + lpServiceStatus); + } + else + { + if (TreeView_GetCount(hTreeView) == 0) + { + AllocAndLoadString(&lpNoDepends, hInstance, IDS_NO_DEPENDS); + + AddItemToTreeView(hTreeView, + hParent, + lpNoDepends, + 0); + + HeapFree(ProcessHeap, + 0, + lpNoDepends); + + EnableWindow(hTreeView, FALSE); + } + } + } +} + + +static VOID +InitDependPage(PSERVICEPROPSHEET dlgInfo, + HWND hwndDlg) +{ + HWND hTreeView1, hTreeView2; + SC_HANDLE hSCManager; + + dlgInfo->hDependsImageList = InitImageList(IDI_NODEPENDS, + IDI_DRIVER, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CXSMICON), + IMAGE_ICON); + + + hTreeView1 = GetDlgItem(hwndDlg, IDC_DEPEND_TREE1); + if (!hTreeView1) + return; + + (void)TreeView_SetImageList(hTreeView1, + dlgInfo->hDependsImageList, + TVSIL_NORMAL); + + hTreeView2 = GetDlgItem(hwndDlg, IDC_DEPEND_TREE2); + if (!hTreeView2) + return; + + (void)TreeView_SetImageList(hTreeView2, + dlgInfo->hDependsImageList, + TVSIL_NORMAL); + + hSCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_ALL_ACCESS); + if (hSCManager) + { + AddServiceDependency(dlgInfo, + hTreeView1, + hSCManager, + dlgInfo->pService->lpServiceName, + NULL, + hwndDlg); + + AddServiceDependent(dlgInfo, + hTreeView2, + hSCManager, + dlgInfo->pService->lpServiceName, + NULL, + hwndDlg); + + CloseServiceHandle(hSCManager); + } + +} + + + +/* + * Dependancies Property dialog callback. + * Controls messages to the Dependancies dialog + */ +INT_PTR CALLBACK +DependenciesPageProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + PSERVICEPROPSHEET dlgInfo; + + /* Get the window context */ + dlgInfo = (PSERVICEPROPSHEET)GetWindowLongPtr(hwndDlg, + GWLP_USERDATA); + if (dlgInfo == NULL && uMsg != WM_INITDIALOG) + { + return FALSE; + } + + switch (uMsg) + { + case WM_INITDIALOG: + { + dlgInfo = (PSERVICEPROPSHEET)(((LPPROPSHEETPAGE)lParam)->lParam); + if (dlgInfo != NULL) + { + SetWindowLongPtr(hwndDlg, + GWLP_USERDATA, + (LONG_PTR)dlgInfo); + + InitDependPage(dlgInfo, hwndDlg); + } + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + + } + break; + } + + return FALSE; +} diff --git a/reactos/base/applications/mscutils/servman/propsheet_general.c b/reactos/base/applications/mscutils/servman/propsheet_general.c new file mode 100644 index 00000000000..0affae972fe --- /dev/null +++ b/reactos/base/applications/mscutils/servman/propsheet_general.c @@ -0,0 +1,371 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/applications/mscutils/servman/propsheet_general.c + * PURPOSE: Property dialog box message handler + * COPYRIGHT: Copyright 2006-2009 Ged Murphy + * + */ + +#include "precomp.h" + + + +static VOID +SetButtonStates(PSERVICEPROPSHEET dlgInfo, + HWND hwndDlg) +{ + HWND hButton; + LPQUERY_SERVICE_CONFIG lpServiceConfig; + DWORD Flags, State; + UINT i; + + Flags = dlgInfo->pService->ServiceStatusProcess.dwControlsAccepted; + State = dlgInfo->pService->ServiceStatusProcess.dwCurrentState; + + for (i = IDC_START; i <= IDC_RESUME; i++) + { + hButton = GetDlgItem(hwndDlg, i); + EnableWindow (hButton, FALSE); + } + + lpServiceConfig = GetServiceConfig(dlgInfo->pService->lpServiceName); + if (State == SERVICE_STOPPED && + lpServiceConfig && lpServiceConfig->dwStartType != SERVICE_DISABLED) + { + hButton = GetDlgItem(hwndDlg, IDC_START); + EnableWindow (hButton, TRUE); + HeapFree(GetProcessHeap(), 0, lpServiceConfig); + } + else if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) ) + { + hButton = GetDlgItem(hwndDlg, IDC_STOP); + EnableWindow (hButton, TRUE); + } + else if ( (Flags & SERVICE_ACCEPT_PAUSE_CONTINUE) && (State == SERVICE_RUNNING) ) + { + hButton = GetDlgItem(hwndDlg, IDC_PAUSE); + EnableWindow (hButton, TRUE); + } + + /* set the main toolbar */ + SetMenuAndButtonStates(dlgInfo->Info); +} + + +static VOID +SetServiceStatusText(PSERVICEPROPSHEET dlgInfo, + HWND hwndDlg) +{ + LPTSTR lpStatus; + UINT id; + + if (dlgInfo->pService->ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING) + { + id = IDS_SERVICES_STARTED; + } + else + { + id = IDS_SERVICES_STOPPED; + } + + if (AllocAndLoadString(&lpStatus, + hInstance, + id)) + { + SendDlgItemMessage(hwndDlg, + IDC_SERV_STATUS, + WM_SETTEXT, + 0, + (LPARAM)lpStatus); + LocalFree(lpStatus); + } +} + +/* + * Fills the 'startup type' combo box with possible + * values and sets it to value of the selected item + */ +static VOID +SetStartupType(LPTSTR lpServiceName, + HWND hwndDlg) +{ + HWND hList; + LPQUERY_SERVICE_CONFIG pServiceConfig; + LPTSTR lpBuf; + DWORD StartUp = 0; + UINT i; + + hList = GetDlgItem(hwndDlg, IDC_START_TYPE); + + for (i = IDS_SERVICES_AUTO; i <= IDS_SERVICES_DIS; i++) + { + if (AllocAndLoadString(&lpBuf, + hInstance, + i)) + { + SendMessage(hList, + CB_ADDSTRING, + 0, + (LPARAM)lpBuf); + LocalFree(lpBuf); + } + } + + pServiceConfig = GetServiceConfig(lpServiceName); + + if (pServiceConfig) + { + switch (pServiceConfig->dwStartType) + { + case SERVICE_AUTO_START: StartUp = 0; break; + case SERVICE_DEMAND_START: StartUp = 1; break; + case SERVICE_DISABLED: StartUp = 2; break; + } + + SendMessage(hList, + CB_SETCURSEL, + StartUp, + 0); + + HeapFree(ProcessHeap, + 0, + pServiceConfig); + } +} + + +/* + * Populates the General Properties dialog with + * the relevant service information + */ +static VOID +InitGeneralPage(PSERVICEPROPSHEET dlgInfo, + HWND hwndDlg) +{ + LPQUERY_SERVICE_CONFIG pServiceConfig; + LPTSTR lpDescription; + + /* set the service name */ + SendDlgItemMessage(hwndDlg, + IDC_SERV_NAME, + WM_SETTEXT, + 0, + (LPARAM)dlgInfo->pService->lpServiceName); + + /* set the display name */ + SendDlgItemMessage(hwndDlg, + IDC_DISP_NAME, + WM_SETTEXT, + 0, + (LPARAM)dlgInfo->pService->lpDisplayName); + + /* set the description */ + if ((lpDescription = GetServiceDescription(dlgInfo->pService->lpServiceName))) + { + SendDlgItemMessage(hwndDlg, + IDC_DESCRIPTION, + WM_SETTEXT, + 0, + (LPARAM)lpDescription); + + HeapFree(ProcessHeap, + 0, + lpDescription); + } + + pServiceConfig = GetServiceConfig(dlgInfo->pService->lpServiceName); + if (pServiceConfig) + { + SendDlgItemMessage(hwndDlg, + IDC_EXEPATH, + WM_SETTEXT, + 0, + (LPARAM)pServiceConfig->lpBinaryPathName); + HeapFree(ProcessHeap, + 0, + pServiceConfig); + } + + + /* set startup type */ + SetStartupType(dlgInfo->pService->lpServiceName, hwndDlg); + + SetServiceStatusText(dlgInfo, + hwndDlg); + + if (dlgInfo->Info->bIsUserAnAdmin) + { + HWND hEdit = GetDlgItem(hwndDlg, + IDC_EDIT); + EnableWindow(hEdit, + TRUE); + } +} + + +VOID +SaveDlgInfo(PSERVICEPROPSHEET dlgInfo, + HWND hwndDlg) +{ + LPQUERY_SERVICE_CONFIG pServiceConfig = NULL; + HWND hList; + DWORD StartUp; + + pServiceConfig = HeapAlloc(ProcessHeap, + HEAP_ZERO_MEMORY, + sizeof(*pServiceConfig)); + if (pServiceConfig) + { + pServiceConfig->dwServiceType = SERVICE_NO_CHANGE; + pServiceConfig->dwErrorControl = SERVICE_NO_CHANGE; + + hList = GetDlgItem(hwndDlg, IDC_START_TYPE); + StartUp = SendMessage(hList, + CB_GETCURSEL, + 0, + 0); + switch (StartUp) + { + case 0: pServiceConfig->dwStartType = SERVICE_AUTO_START; break; + case 1: pServiceConfig->dwStartType = SERVICE_DEMAND_START; break; + case 2: pServiceConfig->dwStartType = SERVICE_DISABLED; break; + } + + if (SetServiceConfig(pServiceConfig, + dlgInfo->pService->lpServiceName, + NULL)) + { + ChangeListViewText(dlgInfo->Info, + dlgInfo->pService, + LVSTARTUP); + } + + HeapFree(ProcessHeap, + 0, + pServiceConfig); + } +} + + +/* + * General Property dialog callback. + * Controls messages to the General dialog + */ +INT_PTR CALLBACK +GeneralPageProc(HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + PSERVICEPROPSHEET dlgInfo; + + /* Get the window context */ + dlgInfo = (PSERVICEPROPSHEET)GetWindowLongPtr(hwndDlg, + GWLP_USERDATA); + if (dlgInfo == NULL && uMsg != WM_INITDIALOG) + { + return FALSE; + } + + switch (uMsg) + { + case WM_INITDIALOG: + { + dlgInfo = (PSERVICEPROPSHEET)(((LPPROPSHEETPAGE)lParam)->lParam); + if (dlgInfo != NULL) + { + SetWindowLongPtr(hwndDlg, + GWLP_USERDATA, + (LONG_PTR)dlgInfo); + InitGeneralPage(dlgInfo, hwndDlg); + SetButtonStates(dlgInfo, hwndDlg); + } + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_START_TYPE: + if (HIWORD(wParam) == CBN_SELCHANGE) + PropSheet_Changed(GetParent(hwndDlg), hwndDlg); + break; + + case IDC_START: + if (DoStart(dlgInfo->Info)) + { + UpdateServiceStatus(dlgInfo->pService); + ChangeListViewText(dlgInfo->Info, dlgInfo->pService, LVSTATUS); + SetButtonStates(dlgInfo, hwndDlg); + SetServiceStatusText(dlgInfo, hwndDlg); + } + break; + + case IDC_STOP: + if (DoStop(dlgInfo->Info)) + { + UpdateServiceStatus(dlgInfo->pService); + ChangeListViewText(dlgInfo->Info, dlgInfo->pService, LVSTATUS); + SetButtonStates(dlgInfo, hwndDlg); + SetServiceStatusText(dlgInfo, hwndDlg); + } + break; + + case IDC_PAUSE: + if (DoPause(dlgInfo->Info)) + { + UpdateServiceStatus(dlgInfo->pService); + ChangeListViewText(dlgInfo->Info, dlgInfo->pService, LVSTATUS); + SetButtonStates(dlgInfo, hwndDlg); + SetServiceStatusText(dlgInfo, hwndDlg); + } + break; + + case IDC_RESUME: + if (DoResume(dlgInfo->Info)) + { + UpdateServiceStatus(dlgInfo->pService); + ChangeListViewText(dlgInfo->Info, dlgInfo->pService, LVSTATUS); + SetButtonStates(dlgInfo, hwndDlg); + SetServiceStatusText(dlgInfo, hwndDlg); + } + break; + + case IDC_EDIT: + { + HWND hName, hDesc, hExePath; + + hName = GetDlgItem(hwndDlg, IDC_DISP_NAME); + hDesc = GetDlgItem(hwndDlg, IDC_DESCRIPTION); + hExePath = GetDlgItem(hwndDlg, IDC_EXEPATH); + + SendMessage(hName, EM_SETREADONLY, FALSE, 0); + SendMessage(hDesc, EM_SETREADONLY, FALSE, 0); + SendMessage(hExePath, EM_SETREADONLY, FALSE, 0); + } + break; + + case IDC_START_PARAM: + PropSheet_Changed(GetParent(hwndDlg), hwndDlg); + break; + } + break; + + case WM_NOTIFY: + { + LPNMHDR lpnm = (LPNMHDR)lParam; + + switch (lpnm->code) + { + case PSN_APPLY: + SaveDlgInfo(dlgInfo, hwndDlg); + SetButtonStates(dlgInfo, hwndDlg); + break; + } + } + break; + } + + return FALSE; +} diff --git a/reactos/base/applications/mscutils/servman/res/driver.ico b/reactos/base/applications/mscutils/servman/res/driver.ico new file mode 100644 index 0000000000000000000000000000000000000000..5e86a5895dd4cab58ea434ad4c7c4477c3451cac GIT binary patch literal 40070 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 q&+uJ*=Q;SIJ7A~Ux`)K~6?*control.c create.c delete.c + dependencies.c export.c listview.c mainwnd.c misc.c progress.c propsheet.c + propsheet_depends.c + propsheet_general.c query.c servman.c start.c diff --git a/reactos/base/applications/mscutils/servman/stop.c b/reactos/base/applications/mscutils/servman/stop.c index a2ff4713ff6..6a5f5c88a6d 100644 --- a/reactos/base/applications/mscutils/servman/stop.c +++ b/reactos/base/applications/mscutils/servman/stop.c @@ -9,13 +9,6 @@ #include "precomp.h" -typedef struct _STOP_INFO -{ - PMAIN_WND_INFO pInfo; - SC_HANDLE hSCManager; - SC_HANDLE hMainService; -} STOP_INFO, *PSTOP_INFO; - static BOOL StopService(PSTOP_INFO pStopInfo, @@ -74,58 +67,6 @@ StopService(PSTOP_INFO pStopInfo, return bRet; } -static LPENUM_SERVICE_STATUS -GetDependentServices(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(PSTOP_INFO pStopInfo, SC_HANDLE hService) @@ -170,171 +111,6 @@ StopDependentServices(PSTOP_INFO pStopInfo, return bRet; } -static BOOL -HasDependentServices(SC_HANDLE hService) -{ - DWORD dwBytesNeeded, dwCount; - BOOL bRet = FALSE; - - if (hService) - { - if (!EnumDependentServices(hService, - SERVICE_ACTIVE, - NULL, - 0, - &dwBytesNeeded, - &dwCount)) - { - if (GetLastError() == ERROR_MORE_DATA) - bRet = TRUE; - } - } - - return bRet; -} - -static BOOL -DoInitDependsDialog(PSTOP_INFO pStopInfo, - HWND hDlg) -{ - LPENUM_SERVICE_STATUS lpDependencies; - DWORD dwCount; - LPTSTR lpPartialStr, lpStr; - DWORD fullLen; - HICON hIcon = NULL; - BOOL bRet = FALSE; - - if (pStopInfo) - { - SetWindowLongPtr(hDlg, - GWLP_USERDATA, - (LONG_PTR)pStopInfo); - - 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); - } - - /* Add the label */ - if (AllocAndLoadString(&lpPartialStr, - hInstance, - IDS_STOP_DEPENDS)) - { - fullLen = _tcslen(lpPartialStr) + _tcslen(pStopInfo->pInfo->pCurrentService->lpDisplayName) + 1; - - lpStr = HeapAlloc(ProcessHeap, - 0, - fullLen * sizeof(TCHAR)); - if (lpStr) - { - _sntprintf(lpStr, fullLen, lpPartialStr, pStopInfo->pInfo->pCurrentService->lpDisplayName); - - SendDlgItemMessage(hDlg, - IDC_STOP_DEPENDS, - WM_SETTEXT, - 0, - (LPARAM)lpStr); - - bRet = TRUE; - - HeapFree(ProcessHeap, - 0, - lpStr); - } - - HeapFree(ProcessHeap, - 0, - lpPartialStr); - } - - /* Get the list of dependencies */ - lpDependencies = GetDependentServices(pStopInfo->hMainService, &dwCount); - if (lpDependencies) - { - LPENUM_SERVICE_STATUS lpEnumServiceStatus; - DWORD i; - - for (i = 0; i < dwCount; i++) - { - lpEnumServiceStatus = &lpDependencies[i]; - - /* Add the service to the listbox */ - SendDlgItemMessage(hDlg, - IDC_STOP_DEPENDS_LB, - LB_ADDSTRING, - 0, - (LPARAM)lpEnumServiceStatus->lpDisplayName); - } - - HeapFree(ProcessHeap, - 0, - lpDependencies); - } - } - - return bRet; -} - - -INT_PTR CALLBACK -StopDependsDialogProc(HWND hDlg, - UINT message, - WPARAM wParam, - LPARAM lParam) -{ - PSTOP_INFO pStopInfo = NULL; - - /* Get the window context */ - pStopInfo = (PSTOP_INFO)GetWindowLongPtr(hDlg, - GWLP_USERDATA); - if (pStopInfo == NULL && message != WM_INITDIALOG) - { - return FALSE; - } - - switch (message) - { - case WM_INITDIALOG: - { - BOOL bRet = FALSE; - - pStopInfo = (PSTOP_INFO)lParam; - if (pStopInfo != NULL) - { - bRet = DoInitDependsDialog(pStopInfo, 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 pInfo)