[SERVMAN]

- Avoid a potential race whereby the current service selection can change before the propsheet thread starts up
- Cleanup the depends data, it doesn't need to be passed around the propsheet
This commit is contained in:
Ged Murphy 2017-12-05 22:13:02 +00:00 committed by GitHub
parent 4296826c58
commit e36b89addb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 95 deletions

View file

@ -10,8 +10,7 @@
#include "precomp.h" #include "precomp.h"
LPWSTR LPWSTR
TV1_GetDependants(PSERVICEPROPSHEET pDlgInfo, TV1_GetDependants(SC_HANDLE hService)
SC_HANDLE hService)
{ {
LPQUERY_SERVICE_CONFIG lpServiceConfig; LPQUERY_SERVICE_CONFIG lpServiceConfig;
LPWSTR lpStr = NULL; LPWSTR lpStr = NULL;
@ -80,7 +79,7 @@ TV1_GetDependants(PSERVICEPROPSHEET pDlgInfo,
} }
VOID VOID
TV1_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo, TV1_AddDependantsToTree(PDEPENDDATA pDependData,
HTREEITEM hParent, HTREEITEM hParent,
LPWSTR lpServiceName) LPWSTR lpServiceName)
{ {
@ -103,7 +102,7 @@ TV1_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo,
if (hService) if (hService)
{ {
/* Get a list of service dependents */ /* Get a list of service dependents */
lpDependants = TV1_GetDependants(pDlgInfo, hService); lpDependants = TV1_GetDependants(hService);
if (lpDependants) if (lpDependants)
{ {
lpStr = lpDependants; lpStr = lpDependants;
@ -127,7 +126,7 @@ TV1_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo,
} }
/* Add it */ /* Add it */
AddItemToTreeView(pDlgInfo->hDependsTreeView1, AddItemToTreeView(pDependData->hDependsTreeView1,
hParent, hParent,
lpServiceConfig->lpDisplayName, lpServiceConfig->lpDisplayName,
lpStr, lpStr,
@ -156,7 +155,7 @@ TV1_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo,
/* Load the 'No dependencies' string */ /* Load the 'No dependencies' string */
AllocAndLoadString(&lpNoDepends, hInstance, IDS_NO_DEPENDS); AllocAndLoadString(&lpNoDepends, hInstance, IDS_NO_DEPENDS);
AddItemToTreeView(pDlgInfo->hDependsTreeView1, AddItemToTreeView(pDependData->hDependsTreeView1,
NULL, NULL,
lpNoDepends, lpNoDepends,
NULL, NULL,
@ -166,7 +165,7 @@ TV1_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo,
LocalFree(lpNoDepends); LocalFree(lpNoDepends);
/* Disable the window */ /* Disable the window */
EnableWindow(pDlgInfo->hDependsTreeView1, FALSE); EnableWindow(pDependData->hDependsTreeView1, FALSE);
} }
} }
@ -178,25 +177,25 @@ TV1_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo,
} }
BOOL BOOL
TV1_Initialize(PSERVICEPROPSHEET pDlgInfo, TV1_Initialize(PDEPENDDATA pDependData,
LPWSTR lpServiceName) LPWSTR lpServiceName)
{ {
BOOL bRet = FALSE; BOOL bRet = FALSE;
/* Associate the imagelist with TV1 */ /* Associate the imagelist with TV1 */
pDlgInfo->hDependsTreeView1 = GetDlgItem(pDlgInfo->hDependsWnd, IDC_DEPEND_TREE1); pDependData->hDependsTreeView1 = GetDlgItem(pDependData->hDependsWnd, IDC_DEPEND_TREE1);
if (!pDlgInfo->hDependsTreeView1) if (!pDependData->hDependsTreeView1)
{ {
ImageList_Destroy(pDlgInfo->hDependsImageList); ImageList_Destroy(pDependData->hDependsImageList);
pDlgInfo->hDependsImageList = NULL; pDependData->hDependsImageList = NULL;
return FALSE; return FALSE;
} }
(void)TreeView_SetImageList(pDlgInfo->hDependsTreeView1, (void)TreeView_SetImageList(pDependData->hDependsTreeView1,
pDlgInfo->hDependsImageList, pDependData->hDependsImageList,
TVSIL_NORMAL); TVSIL_NORMAL);
/* Set the first items in the control */ /* Set the first items in the control */
TV1_AddDependantsToTree(pDlgInfo, NULL, lpServiceName); TV1_AddDependantsToTree(pDependData, NULL, lpServiceName);
return bRet; return bRet;
} }

View file

@ -118,7 +118,7 @@ TV2_GetDependants(LPWSTR lpServiceName,
} }
VOID VOID
TV2_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo, TV2_AddDependantsToTree(PDEPENDDATA pDependData,
HTREEITEM hParent, HTREEITEM hParent,
LPWSTR lpServiceName) LPWSTR lpServiceName)
{ {
@ -138,7 +138,7 @@ TV2_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo,
bHasChildren = TV2_HasDependantServices(lpServiceStatus[i].lpServiceName); bHasChildren = TV2_HasDependantServices(lpServiceStatus[i].lpServiceName);
/* Add it */ /* Add it */
AddItemToTreeView(pDlgInfo->hDependsTreeView2, AddItemToTreeView(pDependData->hDependsTreeView2,
hParent, hParent,
lpServiceStatus[i].lpDisplayName, lpServiceStatus[i].lpDisplayName,
lpServiceStatus[i].lpServiceName, lpServiceStatus[i].lpServiceName,
@ -158,7 +158,7 @@ TV2_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo,
/* Load the 'No dependencies' string */ /* Load the 'No dependencies' string */
AllocAndLoadString(&lpNoDepends, hInstance, IDS_NO_DEPENDS); AllocAndLoadString(&lpNoDepends, hInstance, IDS_NO_DEPENDS);
AddItemToTreeView(pDlgInfo->hDependsTreeView2, AddItemToTreeView(pDependData->hDependsTreeView2,
NULL, NULL,
lpNoDepends, lpNoDepends,
NULL, NULL,
@ -168,31 +168,31 @@ TV2_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo,
LocalFree(lpNoDepends); LocalFree(lpNoDepends);
/* Disable the window */ /* Disable the window */
EnableWindow(pDlgInfo->hDependsTreeView2, FALSE); EnableWindow(pDependData->hDependsTreeView2, FALSE);
} }
} }
} }
BOOL BOOL
TV2_Initialize(PSERVICEPROPSHEET pDlgInfo, TV2_Initialize(PDEPENDDATA pDependData,
LPWSTR lpServiceName) LPWSTR lpServiceName)
{ {
BOOL bRet = FALSE; BOOL bRet = FALSE;
/* Associate the imagelist with TV2 */ /* Associate the imagelist with TV2 */
pDlgInfo->hDependsTreeView2 = GetDlgItem(pDlgInfo->hDependsWnd, IDC_DEPEND_TREE2); pDependData->hDependsTreeView2 = GetDlgItem(pDependData->hDependsWnd, IDC_DEPEND_TREE2);
if (!pDlgInfo->hDependsTreeView2) if (!pDependData->hDependsTreeView2)
{ {
ImageList_Destroy(pDlgInfo->hDependsImageList); ImageList_Destroy(pDependData->hDependsImageList);
pDlgInfo->hDependsImageList = NULL; pDependData->hDependsImageList = NULL;
return FALSE; return FALSE;
} }
(void)TreeView_SetImageList(pDlgInfo->hDependsTreeView2, (void)TreeView_SetImageList(pDependData->hDependsTreeView2,
pDlgInfo->hDependsImageList, pDependData->hDependsImageList,
TVSIL_NORMAL); TVSIL_NORMAL);
/* Set the first items in the control */ /* Set the first items in the control */
TV2_AddDependantsToTree(pDlgInfo, NULL, lpServiceName); TV2_AddDependantsToTree(pDependData, NULL, lpServiceName);
return bRet; return bRet;
} }

View file

@ -128,11 +128,18 @@ typedef struct _SERVICEPROPSHEET
{ {
PMAIN_WND_INFO Info; PMAIN_WND_INFO Info;
ENUM_SERVICE_STATUS_PROCESS *pService; ENUM_SERVICE_STATUS_PROCESS *pService;
} SERVICEPROPSHEET, *PSERVICEPROPSHEET;
typedef struct _DEPENDDATA
{
PSERVICEPROPSHEET pDlgInfo;
HIMAGELIST hDependsImageList; HIMAGELIST hDependsImageList;
HWND hDependsWnd; HWND hDependsWnd;
HWND hDependsTreeView1; HWND hDependsTreeView1;
HWND hDependsTreeView2; HWND hDependsTreeView2;
} SERVICEPROPSHEET, *PSERVICEPROPSHEET;
} DEPENDDATA, *PDEPENDDATA;
HTREEITEM AddItemToTreeView(HWND hTreeView, HTREEITEM hRoot, LPWSTR lpDisplayName, LPWSTR lpServiceName, ULONG serviceType, BOOL bHasChildren); HTREEITEM AddItemToTreeView(HWND hTreeView, HTREEITEM hRoot, LPWSTR lpDisplayName, LPWSTR lpServiceName, ULONG serviceType, BOOL bHasChildren);
@ -147,12 +154,12 @@ LPWSTR DisplayName,
LPWSTR ServiceList); LPWSTR ServiceList);
/* tv1_dependencies */ /* tv1_dependencies */
BOOL TV1_Initialize(PSERVICEPROPSHEET pDlgInfo, LPWSTR lpServiceName); BOOL TV1_Initialize(PDEPENDDATA pDependData, LPWSTR lpServiceName);
VOID TV1_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo, HTREEITEM hParent, LPWSTR lpServiceName); VOID TV1_AddDependantsToTree(PDEPENDDATA pDependData, HTREEITEM hParent, LPWSTR lpServiceName);
/* tv2_dependencies */ /* tv2_dependencies */
BOOL TV2_Initialize(PSERVICEPROPSHEET pDlgInfo, LPWSTR lpServiceName); BOOL TV2_Initialize(PDEPENDDATA pDependData, LPWSTR lpServiceName);
VOID TV2_AddDependantsToTree(PSERVICEPROPSHEET pDlgInfo, HTREEITEM hParent, LPWSTR lpServiceName); VOID TV2_AddDependantsToTree(PDEPENDDATA pDependData, HTREEITEM hParent, LPWSTR lpServiceName);
BOOL TV2_HasDependantServices(LPWSTR lpServiceName); BOOL TV2_HasDependantServices(LPWSTR lpServiceName);
LPENUM_SERVICE_STATUS TV2_GetDependants(LPWSTR lpServiceName, LPDWORD lpdwCount); LPENUM_SERVICE_STATUS TV2_GetDependants(LPWSTR lpServiceName, LPDWORD lpdwCount);

View file

@ -3,7 +3,7 @@
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* FILE: base/applications/mscutils/servman/propsheet.c * FILE: base/applications/mscutils/servman/propsheet.c
* PURPOSE: Property dialog box message handler * PURPOSE: Property dialog box message handler
* COPYRIGHT: Copyright 2006-2007 Ged Murphy <gedmurphy@reactos.org> * COPYRIGHT: Copyright 2006-2017 Ged Murphy <gedmurphy@reactos.org>
* *
*/ */
@ -29,8 +29,20 @@ InitPropSheetPage(PROPSHEETPAGE *psp,
VOID VOID
OpenPropSheet(PMAIN_WND_INFO Info) OpenPropSheet(PMAIN_WND_INFO Info)
{ {
PSERVICEPROPSHEET pServicePropSheet;
HANDLE hThread; HANDLE hThread;
hThread = (HANDLE)_beginthreadex(NULL, 0, &PropSheetThread, Info, 0, NULL);
pServicePropSheet = HeapAlloc(ProcessHeap,
0,
sizeof(*pServicePropSheet));
if (!pServicePropSheet) return;
/* Set the current service in this calling thread to avoid
* it being updated before the thread is up */
pServicePropSheet->pService = Info->pCurrentService;
pServicePropSheet->Info = Info;
hThread = (HANDLE)_beginthreadex(NULL, 0, &PropSheetThread, pServicePropSheet, 0, NULL);
if (hThread) if (hThread)
{ {
CloseHandle(hThread); CloseHandle(hThread);
@ -40,35 +52,26 @@ OpenPropSheet(PMAIN_WND_INFO Info)
unsigned int __stdcall PropSheetThread(void* Param) unsigned int __stdcall PropSheetThread(void* Param)
{ {
PSERVICEPROPSHEET pServicePropSheet;
PROPSHEETHEADER psh; PROPSHEETHEADER psh;
PROPSHEETPAGE psp[4]; PROPSHEETPAGE psp[4];
PSERVICEPROPSHEET pServicePropSheet;
HWND hDlg = NULL; HWND hDlg = NULL;
MSG Msg; MSG Msg;
PMAIN_WND_INFO Info = (PMAIN_WND_INFO)Param; pServicePropSheet = (PSERVICEPROPSHEET)Param;
ZeroMemory(&psh, sizeof(PROPSHEETHEADER)); ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE | PSH_MODELESS; psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE | PSH_MODELESS;
psh.hwndParent = Info->hMainWnd; psh.hwndParent = pServicePropSheet->Info->hMainWnd;
psh.hInstance = hInstance; psh.hInstance = hInstance;
psh.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SM_ICON)); psh.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SM_ICON));
psh.pszCaption = Info->pCurrentService->lpDisplayName; psh.pszCaption = pServicePropSheet->Info->pCurrentService->lpDisplayName;
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE); psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
psh.nStartPage = 0; psh.nStartPage = 0;
psh.ppsp = psp; psh.ppsp = psp;
/* Initialize the tabs */
pServicePropSheet = HeapAlloc(ProcessHeap,
0,
sizeof(*pServicePropSheet));
if (pServicePropSheet)
{
/* Save current service, as it could change while the dialog is open */
pServicePropSheet->pService = Info->pCurrentService;
pServicePropSheet->Info = Info;
InitPropSheetPage(&psp[0], pServicePropSheet, IDD_DLG_GENERAL, GeneralPageProc); InitPropSheetPage(&psp[0], pServicePropSheet, IDD_DLG_GENERAL, GeneralPageProc);
InitPropSheetPage(&psp[1], pServicePropSheet, IDD_LOGON, LogonPageProc); InitPropSheetPage(&psp[1], pServicePropSheet, IDD_LOGON, LogonPageProc);
InitPropSheetPage(&psp[2], pServicePropSheet, IDD_RECOVERY, RecoveryPageProc); InitPropSheetPage(&psp[2], pServicePropSheet, IDD_RECOVERY, RecoveryPageProc);
@ -80,11 +83,10 @@ unsigned int __stdcall PropSheetThread(void* Param)
/* Pump the message queue */ /* Pump the message queue */
while (GetMessageW(&Msg, NULL, 0, 0)) while (GetMessageW(&Msg, NULL, 0, 0))
{ {
if (PropSheet_GetCurrentPageHwnd(hDlg) == NULL) if (PropSheet_GetCurrentPageHwnd(hDlg) == NULL)
{ {
/* The user hit the ok / cancel button, pull it down */ /* The user hit the ok / cancel button, pull it down */
EnableWindow(Info->hMainWnd, TRUE); EnableWindow(pServicePropSheet->Info->hMainWnd, TRUE);
DestroyWindow(hDlg); DestroyWindow(hDlg);
} }
@ -97,7 +99,6 @@ unsigned int __stdcall PropSheetThread(void* Param)
} }
HeapFree(GetProcessHeap(), 0, pServicePropSheet); HeapFree(GetProcessHeap(), 0, pServicePropSheet);
}
return (hDlg != NULL); return (hDlg != NULL);
} }

View file

@ -159,20 +159,20 @@ TreeView_GetItemText(HWND hTreeView,
*/ */
static VOID static VOID
InitDependPage(PSERVICEPROPSHEET pDlgInfo) InitDependPage(PDEPENDDATA pDependData)
{ {
/* Initialize the image list */ /* Initialize the image list */
pDlgInfo->hDependsImageList = InitImageList(IDI_NODEPENDS, pDependData->hDependsImageList = InitImageList(IDI_NODEPENDS,
IDI_DRIVER, IDI_DRIVER,
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CXSMICON),
IMAGE_ICON); IMAGE_ICON);
/* Set the first tree view */ /* Set the first tree view */
TV1_Initialize(pDlgInfo, pDlgInfo->pService->lpServiceName); TV1_Initialize(pDependData, pDependData->pDlgInfo->pService->lpServiceName);
/* Set the second tree view */ /* Set the second tree view */
TV2_Initialize(pDlgInfo, pDlgInfo->pService->lpServiceName); TV2_Initialize(pDependData, pDependData->pDlgInfo->pService->lpServiceName);
} }
/* /*
@ -185,12 +185,13 @@ DependenciesPageProc(HWND hwndDlg,
WPARAM wParam, WPARAM wParam,
LPARAM lParam) LPARAM lParam)
{ {
PSERVICEPROPSHEET pDlgInfo;
PDEPENDDATA pDependData;
/* Get the window context */ /* Get the window context */
pDlgInfo = (PSERVICEPROPSHEET)GetWindowLongPtr(hwndDlg, pDependData = (PDEPENDDATA)GetWindowLongPtr(hwndDlg,
GWLP_USERDATA); GWLP_USERDATA);
if (pDlgInfo == NULL && uMsg != WM_INITDIALOG) if (pDependData == NULL && uMsg != WM_INITDIALOG)
{ {
return FALSE; return FALSE;
} }
@ -199,16 +200,17 @@ DependenciesPageProc(HWND hwndDlg,
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
{ {
pDlgInfo = (PSERVICEPROPSHEET)(((LPPROPSHEETPAGE)lParam)->lParam); pDependData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DEPENDDATA));
if (pDlgInfo != NULL) if (pDependData != NULL)
{ {
SetWindowLongPtr(hwndDlg, SetWindowLongPtr(hwndDlg,
GWLP_USERDATA, GWLP_USERDATA,
(LONG_PTR)pDlgInfo); (LONG_PTR)pDependData);
pDlgInfo->hDependsWnd = hwndDlg; pDependData->pDlgInfo = (PSERVICEPROPSHEET)(((LPPROPSHEETPAGE)lParam)->lParam);
pDependData->hDependsWnd = hwndDlg;
InitDependPage(pDlgInfo); InitDependPage(pDependData);
} }
} }
break; break;
@ -226,19 +228,19 @@ DependenciesPageProc(HWND hwndDlg,
if (lpnmtv->hdr.idFrom == IDC_DEPEND_TREE1) if (lpnmtv->hdr.idFrom == IDC_DEPEND_TREE1)
{ {
/* Has this node been expanded before */ /* Has this node been expanded before */
if (!TreeView_GetChild(pDlgInfo->hDependsTreeView1, lpnmtv->itemNew.hItem)) if (!TreeView_GetChild(pDependData->hDependsTreeView1, lpnmtv->itemNew.hItem))
{ {
/* It's not, add the children */ /* It's not, add the children */
TV1_AddDependantsToTree(pDlgInfo, lpnmtv->itemNew.hItem, (LPWSTR)lpnmtv->itemNew.lParam); TV1_AddDependantsToTree(pDependData, lpnmtv->itemNew.hItem, (LPWSTR)lpnmtv->itemNew.lParam);
} }
} }
else if (lpnmtv->hdr.idFrom == IDC_DEPEND_TREE2) else if (lpnmtv->hdr.idFrom == IDC_DEPEND_TREE2)
{ {
/* Has this node been expanded before */ /* Has this node been expanded before */
if (!TreeView_GetChild(pDlgInfo->hDependsTreeView2, lpnmtv->itemNew.hItem)) if (!TreeView_GetChild(pDependData->hDependsTreeView2, lpnmtv->itemNew.hItem))
{ {
/* It's not, add the children */ /* It's not, add the children */
TV2_AddDependantsToTree(pDlgInfo, lpnmtv->itemNew.hItem, (LPWSTR)lpnmtv->itemNew.lParam); TV2_AddDependantsToTree(pDependData, lpnmtv->itemNew.hItem, (LPWSTR)lpnmtv->itemNew.lParam);
} }
} }
} }
@ -256,11 +258,13 @@ DependenciesPageProc(HWND hwndDlg,
break; break;
case WM_DESTROY: case WM_DESTROY:
DestroyTreeView(pDlgInfo->hDependsTreeView1); DestroyTreeView(pDependData->hDependsTreeView1);
DestroyTreeView(pDlgInfo->hDependsTreeView2); DestroyTreeView(pDependData->hDependsTreeView2);
if (pDlgInfo->hDependsImageList) if (pDependData->hDependsImageList)
ImageList_Destroy(pDlgInfo->hDependsImageList); ImageList_Destroy(pDependData->hDependsImageList);
HeapFree(GetProcessHeap(), 0, pDependData);
} }
return FALSE; return FALSE;

View file

@ -170,7 +170,8 @@ ShowFailureActions(
{ {
WCHAR szBuffer[256]; WCHAR szBuffer[256];
PWSTR startPtr, endPtr; PWSTR startPtr, endPtr;
INT i, index, id, length; INT index, id, length;
DWORD i;
for (i = 0; i < min(pRecoveryData->pServiceFailure->cActions, 3); i++) for (i = 0; i < min(pRecoveryData->pServiceFailure->cActions, 3); i++)
{ {