1 /*
2  * PROJECT:     ReactOS Services
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        base/applications/mscutils/servman/dependencies_tv2.c
5  * PURPOSE:     Helper functions for service dependents
6  * COPYRIGHT:   Copyright 2009 Ged Murphy <gedmurphy@reactos.org>
7  *
8  */
9 
10 #include "precomp.h"
11 
12 BOOL
TV2_HasDependantServices(LPWSTR lpServiceName)13 TV2_HasDependantServices(LPWSTR lpServiceName)
14 {
15     HANDLE hSCManager;
16     HANDLE hService;
17     DWORD dwBytesNeeded, dwCount;
18     BOOL bRet = FALSE;
19 
20     hSCManager = OpenSCManagerW(NULL,
21                                 NULL,
22                                 SC_MANAGER_ALL_ACCESS);
23     if (hSCManager)
24     {
25         hService = OpenServiceW(hSCManager,
26                                 lpServiceName,
27                                 SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS);
28         if (hService)
29         {
30             /* Does this have any dependencies? */
31             if (!EnumDependentServices(hService,
32                                        SERVICE_STATE_ALL,
33                                        NULL,
34                                        0,
35                                        &dwBytesNeeded,
36                                        &dwCount))
37             {
38                  if (GetLastError() == ERROR_MORE_DATA)
39                  {
40                      /* It does, return TRUE */
41                      bRet = TRUE;
42                  }
43             }
44 
45             CloseServiceHandle(hService);
46         }
47 
48         CloseServiceHandle(hSCManager);
49     }
50 
51     return bRet;
52 }
53 
54 LPENUM_SERVICE_STATUS
TV2_GetDependants(LPWSTR lpServiceName,LPDWORD lpdwCount)55 TV2_GetDependants(LPWSTR lpServiceName,
56                   LPDWORD lpdwCount)
57 {
58     SC_HANDLE hSCManager;
59     SC_HANDLE hService;
60     LPENUM_SERVICE_STATUSW lpDependencies = NULL;
61     DWORD dwBytesNeeded;
62     DWORD dwCount;
63 
64     /* Set the first items in each tree view */
65     hSCManager = OpenSCManagerW(NULL,
66                                 NULL,
67                                 SC_MANAGER_ALL_ACCESS);
68     if (hSCManager)
69     {
70         hService = OpenServiceW(hSCManager,
71                                 lpServiceName,
72                                 SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_QUERY_CONFIG);
73         if (hService)
74         {
75             /* Does this have any dependencies? */
76             if (!EnumDependentServicesW(hService,
77                                         SERVICE_STATE_ALL,
78                                         NULL,
79                                         0,
80                                         &dwBytesNeeded,
81                                         &dwCount) &&
82                 GetLastError() == ERROR_MORE_DATA)
83             {
84                 lpDependencies = (LPENUM_SERVICE_STATUSW)HeapAlloc(GetProcessHeap(),
85                                                                   0,
86                                                                   dwBytesNeeded);
87                 if (lpDependencies)
88                 {
89                     /* Get the list of dependents */
90                     if (EnumDependentServicesW(hService,
91                                                SERVICE_STATE_ALL,
92                                                lpDependencies,
93                                                dwBytesNeeded,
94                                                &dwBytesNeeded,
95                                                &dwCount))
96                     {
97                         /* Set the count */
98                         *lpdwCount = dwCount;
99                     }
100                     else
101                     {
102                         HeapFree(ProcessHeap,
103                                  0,
104                                  lpDependencies);
105 
106                         lpDependencies = NULL;
107                     }
108                 }
109             }
110 
111             CloseServiceHandle(hService);
112         }
113 
114         CloseServiceHandle(hSCManager);
115     }
116 
117     return lpDependencies;
118 }
119 
120 VOID
TV2_AddDependantsToTree(PDEPENDDATA pDependData,HTREEITEM hParent,LPWSTR lpServiceName)121 TV2_AddDependantsToTree(PDEPENDDATA pDependData,
122                         HTREEITEM hParent,
123                         LPWSTR lpServiceName)
124 {
125 
126     LPENUM_SERVICE_STATUSW lpServiceStatus;
127     LPWSTR lpNoDepends;
128     DWORD count, i;
129     BOOL bHasChildren;
130 
131     /* Get a list of service dependents */
132     lpServiceStatus = TV2_GetDependants(lpServiceName, &count);
133     if (lpServiceStatus)
134     {
135         for (i = 0; i < count; i++)
136         {
137             /* Does this item need a +/- box? */
138             bHasChildren = TV2_HasDependantServices(lpServiceStatus[i].lpServiceName);
139 
140             /* Add it */
141             AddItemToTreeView(pDependData->hDependsTreeView2,
142                               hParent,
143                               lpServiceStatus[i].lpDisplayName,
144                               lpServiceStatus[i].lpServiceName,
145                               lpServiceStatus[i].ServiceStatus.dwServiceType,
146                               bHasChildren);
147         }
148 
149         HeapFree(GetProcessHeap(),
150                  0,
151                  lpServiceStatus);
152     }
153     else
154     {
155         /* If there is no parent, set the tree to 'no dependencies' */
156         if (!hParent)
157         {
158             /* Load the 'No dependencies' string */
159             AllocAndLoadString(&lpNoDepends, hInstance, IDS_NO_DEPENDS);
160 
161             AddItemToTreeView(pDependData->hDependsTreeView2,
162                               NULL,
163                               lpNoDepends,
164                               NULL,
165                               0,
166                               FALSE);
167 
168             LocalFree(lpNoDepends);
169 
170             /* Disable the window */
171             EnableWindow(pDependData->hDependsTreeView2, FALSE);
172         }
173     }
174 }
175 
176 BOOL
TV2_Initialize(PDEPENDDATA pDependData,LPWSTR lpServiceName)177 TV2_Initialize(PDEPENDDATA pDependData,
178                LPWSTR lpServiceName)
179 {
180     BOOL bRet = FALSE;
181 
182     /* Associate the imagelist with TV2 */
183     pDependData->hDependsTreeView2 = GetDlgItem(pDependData->hDependsWnd, IDC_DEPEND_TREE2);
184     if (!pDependData->hDependsTreeView2)
185     {
186         ImageList_Destroy(pDependData->hDependsImageList);
187         pDependData->hDependsImageList = NULL;
188         return FALSE;
189     }
190     (void)TreeView_SetImageList(pDependData->hDependsTreeView2,
191                                 pDependData->hDependsImageList,
192                                 TVSIL_NORMAL);
193 
194     /* Set the first items in the control */
195     TV2_AddDependantsToTree(pDependData, NULL, lpServiceName);
196 
197     return bRet;
198 }
199