mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 22:28:36 +00:00
![Ged Murphy](/assets/img/avatar_default.png)
- 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
199 lines
6.2 KiB
C
199 lines
6.2 KiB
C
/*
|
|
* PROJECT: ReactOS Services
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: base/applications/mscutils/servman/dependencies_tv2.c
|
|
* PURPOSE: Helper functions for service dependents
|
|
* COPYRIGHT: Copyright 2009 Ged Murphy <gedmurphy@reactos.org>
|
|
*
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
BOOL
|
|
TV2_HasDependantServices(LPWSTR lpServiceName)
|
|
{
|
|
HANDLE hSCManager;
|
|
HANDLE hService;
|
|
DWORD dwBytesNeeded, dwCount;
|
|
BOOL bRet = FALSE;
|
|
|
|
hSCManager = OpenSCManagerW(NULL,
|
|
NULL,
|
|
SC_MANAGER_ALL_ACCESS);
|
|
if (hSCManager)
|
|
{
|
|
hService = OpenServiceW(hSCManager,
|
|
lpServiceName,
|
|
SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS);
|
|
if (hService)
|
|
{
|
|
/* Does this have any dependencies? */
|
|
if (!EnumDependentServices(hService,
|
|
SERVICE_STATE_ALL,
|
|
NULL,
|
|
0,
|
|
&dwBytesNeeded,
|
|
&dwCount))
|
|
{
|
|
if (GetLastError() == ERROR_MORE_DATA)
|
|
{
|
|
/* It does, return TRUE */
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
CloseServiceHandle(hService);
|
|
}
|
|
|
|
CloseServiceHandle(hSCManager);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
LPENUM_SERVICE_STATUS
|
|
TV2_GetDependants(LPWSTR lpServiceName,
|
|
LPDWORD lpdwCount)
|
|
{
|
|
SC_HANDLE hSCManager;
|
|
SC_HANDLE hService;
|
|
LPENUM_SERVICE_STATUSW lpDependencies = NULL;
|
|
DWORD dwBytesNeeded;
|
|
DWORD dwCount;
|
|
|
|
/* Set the first items in each tree view */
|
|
hSCManager = OpenSCManagerW(NULL,
|
|
NULL,
|
|
SC_MANAGER_ALL_ACCESS);
|
|
if (hSCManager)
|
|
{
|
|
hService = OpenServiceW(hSCManager,
|
|
lpServiceName,
|
|
SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_QUERY_CONFIG);
|
|
if (hService)
|
|
{
|
|
/* Does this have any dependencies? */
|
|
if (!EnumDependentServicesW(hService,
|
|
SERVICE_STATE_ALL,
|
|
NULL,
|
|
0,
|
|
&dwBytesNeeded,
|
|
&dwCount) &&
|
|
GetLastError() == ERROR_MORE_DATA)
|
|
{
|
|
lpDependencies = (LPENUM_SERVICE_STATUSW)HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
dwBytesNeeded);
|
|
if (lpDependencies)
|
|
{
|
|
/* Get the list of dependents */
|
|
if (EnumDependentServicesW(hService,
|
|
SERVICE_STATE_ALL,
|
|
lpDependencies,
|
|
dwBytesNeeded,
|
|
&dwBytesNeeded,
|
|
&dwCount))
|
|
{
|
|
/* Set the count */
|
|
*lpdwCount = dwCount;
|
|
}
|
|
else
|
|
{
|
|
HeapFree(ProcessHeap,
|
|
0,
|
|
lpDependencies);
|
|
|
|
lpDependencies = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseServiceHandle(hService);
|
|
}
|
|
|
|
CloseServiceHandle(hSCManager);
|
|
}
|
|
|
|
return lpDependencies;
|
|
}
|
|
|
|
VOID
|
|
TV2_AddDependantsToTree(PDEPENDDATA pDependData,
|
|
HTREEITEM hParent,
|
|
LPWSTR lpServiceName)
|
|
{
|
|
|
|
LPENUM_SERVICE_STATUSW lpServiceStatus;
|
|
LPWSTR lpNoDepends;
|
|
DWORD count, i;
|
|
BOOL bHasChildren;
|
|
|
|
/* Get a list of service dependents */
|
|
lpServiceStatus = TV2_GetDependants(lpServiceName, &count);
|
|
if (lpServiceStatus)
|
|
{
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
/* Does this item need a +/- box? */
|
|
bHasChildren = TV2_HasDependantServices(lpServiceStatus[i].lpServiceName);
|
|
|
|
/* Add it */
|
|
AddItemToTreeView(pDependData->hDependsTreeView2,
|
|
hParent,
|
|
lpServiceStatus[i].lpDisplayName,
|
|
lpServiceStatus[i].lpServiceName,
|
|
lpServiceStatus[i].ServiceStatus.dwServiceType,
|
|
bHasChildren);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
lpServiceStatus);
|
|
}
|
|
else
|
|
{
|
|
/* If there is no parent, set the tree to 'no dependencies' */
|
|
if (!hParent)
|
|
{
|
|
/* Load the 'No dependencies' string */
|
|
AllocAndLoadString(&lpNoDepends, hInstance, IDS_NO_DEPENDS);
|
|
|
|
AddItemToTreeView(pDependData->hDependsTreeView2,
|
|
NULL,
|
|
lpNoDepends,
|
|
NULL,
|
|
0,
|
|
FALSE);
|
|
|
|
LocalFree(lpNoDepends);
|
|
|
|
/* Disable the window */
|
|
EnableWindow(pDependData->hDependsTreeView2, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
TV2_Initialize(PDEPENDDATA pDependData,
|
|
LPWSTR lpServiceName)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
/* Associate the imagelist with TV2 */
|
|
pDependData->hDependsTreeView2 = GetDlgItem(pDependData->hDependsWnd, IDC_DEPEND_TREE2);
|
|
if (!pDependData->hDependsTreeView2)
|
|
{
|
|
ImageList_Destroy(pDependData->hDependsImageList);
|
|
pDependData->hDependsImageList = NULL;
|
|
return FALSE;
|
|
}
|
|
(void)TreeView_SetImageList(pDependData->hDependsTreeView2,
|
|
pDependData->hDependsImageList,
|
|
TVSIL_NORMAL);
|
|
|
|
/* Set the first items in the control */
|
|
TV2_AddDependantsToTree(pDependData, NULL, lpServiceName);
|
|
|
|
return bRet;
|
|
}
|