1 /*
2  * PROJECT:     ReactOS Services
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        base/applications/mscutils/servman/dependencies_tv1.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 LPWSTR
13 TV1_GetDependants(SC_HANDLE hService)
14 {
15     LPQUERY_SERVICE_CONFIG lpServiceConfig;
16     LPWSTR lpStr = NULL;
17     DWORD bytesNeeded;
18     DWORD bytes;
19 
20     /* Get the info for this service */
21     if (!QueryServiceConfigW(hService,
22                              NULL,
23                              0,
24                              &bytesNeeded) &&
25         GetLastError() == ERROR_INSUFFICIENT_BUFFER)
26     {
27         lpServiceConfig = HeapAlloc(ProcessHeap,
28                                     0,
29                                     bytesNeeded);
30         if (lpServiceConfig)
31         {
32             if (QueryServiceConfigW(hService,
33                                     lpServiceConfig,
34                                     bytesNeeded,
35                                     &bytesNeeded))
36             {
37                 /* Does this service have any dependencies? */
38                 if (lpServiceConfig->lpDependencies &&
39                     *lpServiceConfig->lpDependencies != '\0')
40                 {
41                     lpStr = lpServiceConfig->lpDependencies;
42                     bytes = 0;
43 
44                     /* Work out how many bytes we need to hold the list */
45                     for (;;)
46                     {
47                         bytes++;
48 
49                         if (!*lpStr && !*(lpStr + 1))
50                         {
51                             bytes++;
52                             break;
53                         }
54 
55                         lpStr++;
56                     }
57 
58                     /* Allocate and copy the list */
59                     bytes *= sizeof(WCHAR);
60                     lpStr = HeapAlloc(ProcessHeap,
61                                       0,
62                                       bytes);
63                     if (lpStr)
64                     {
65                         CopyMemory(lpStr,
66                                    lpServiceConfig->lpDependencies,
67                                    bytes);
68                     }
69                 }
70             }
71 
72             HeapFree(GetProcessHeap(),
73                      0,
74                      lpServiceConfig);
75         }
76     }
77 
78     return lpStr;
79 }
80 
81 VOID
82 TV1_AddDependantsToTree(PDEPENDDATA pDependData,
83                         HTREEITEM hParent,
84                         LPWSTR lpServiceName)
85 {
86     SC_HANDLE hSCManager;
87     SC_HANDLE hService;
88     LPQUERY_SERVICE_CONFIG lpServiceConfig;
89     LPWSTR lpDependants;
90     LPWSTR lpStr;
91     LPWSTR lpNoDepends;
92     BOOL bHasChildren;
93 
94     hSCManager = OpenSCManagerW(NULL,
95                                 NULL,
96                                 SC_MANAGER_ALL_ACCESS);
97     if (hSCManager)
98     {
99         hService = OpenServiceW(hSCManager,
100                                 lpServiceName,
101                                 SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SERVICE_QUERY_CONFIG);
102         if (hService)
103         {
104             /* Get a list of service dependents */
105             lpDependants = TV1_GetDependants(hService);
106             if (lpDependants)
107             {
108                 lpStr = lpDependants;
109 
110                 /* Make sure this isn't the end of the list */
111                 while (*lpStr)
112                 {
113                     /* Get the info for this service */
114                     lpServiceConfig = GetServiceConfig(lpStr);
115                     if (lpServiceConfig)
116                     {
117                         /* Does this item need a +/- box? */
118                         if (lpServiceConfig->lpDependencies &&
119                             *lpServiceConfig->lpDependencies != '\0')
120                         {
121                             bHasChildren = TRUE;
122                         }
123                         else
124                         {
125                             bHasChildren = FALSE;
126                         }
127 
128                         /* Add it */
129                         AddItemToTreeView(pDependData->hDependsTreeView1,
130                                           hParent,
131                                           lpServiceConfig->lpDisplayName,
132                                           lpStr,
133                                           lpServiceConfig->dwServiceType,
134                                           bHasChildren);
135 
136                         HeapFree(GetProcessHeap(),
137                                  0,
138                                  lpServiceConfig);
139                     }
140 
141                     /* Move to the end of the string */
142                     while (*lpStr++)
143                         ;
144                 }
145 
146                 HeapFree(GetProcessHeap(),
147                          0,
148                          lpDependants);
149             }
150             else
151             {
152                 /* If there is no parent, set the tree to 'no dependencies' */
153                 if (!hParent)
154                 {
155                     /* Load the 'No dependencies' string */
156                     AllocAndLoadString(&lpNoDepends, hInstance, IDS_NO_DEPENDS);
157 
158                     AddItemToTreeView(pDependData->hDependsTreeView1,
159                                       NULL,
160                                       lpNoDepends,
161                                       NULL,
162                                       0,
163                                       FALSE);
164 
165                     LocalFree(lpNoDepends);
166 
167                     /* Disable the window */
168                     EnableWindow(pDependData->hDependsTreeView1, FALSE);
169                 }
170             }
171 
172             CloseServiceHandle(hService);
173         }
174 
175         CloseServiceHandle(hSCManager);
176     }
177 }
178 
179 BOOL
180 TV1_Initialize(PDEPENDDATA pDependData,
181                LPWSTR lpServiceName)
182 {
183     BOOL bRet = FALSE;
184 
185     /* Associate the imagelist with TV1 */
186     pDependData->hDependsTreeView1 = GetDlgItem(pDependData->hDependsWnd, IDC_DEPEND_TREE1);
187     if (!pDependData->hDependsTreeView1)
188     {
189         ImageList_Destroy(pDependData->hDependsImageList);
190         pDependData->hDependsImageList = NULL;
191         return FALSE;
192     }
193     (void)TreeView_SetImageList(pDependData->hDependsTreeView1,
194                                 pDependData->hDependsImageList,
195                                 TVSIL_NORMAL);
196 
197     /* Set the first items in the control */
198     TV1_AddDependantsToTree(pDependData, NULL, lpServiceName);
199 
200     return bRet;
201 }
202