Make the logic easier to read
[reactos.git] / reactos / base / applications / mscutils / servman / stop_dependencies.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/mscutils/servman/stop_dependencies.c
5 * PURPOSE: Routines related to stopping dependent services
6 * COPYRIGHT: Copyright 2006-2010 Ged Murphy <gedmurphy@reactos.org>
7 *
8 */
9
10 #include "precomp.h"
11
12
13 static LPWSTR
14 AddServiceToList(LPWSTR *lpServiceList,
15 LPWSTR lpServiceToAdd)
16 {
17 LPWSTR lpNewList = NULL;
18 LPWSTR ptr;
19 DWORD dwToAddSize;
20 DWORD dwCurSize;
21
22 dwToAddSize = wcslen(lpServiceToAdd) + 1;
23
24 /* Is this is the first in the list? */
25 if (!*lpServiceList)
26 {
27 /* Add another char for double null */
28 dwToAddSize++;
29
30 lpNewList = HeapAlloc(GetProcessHeap(),
31 0,
32 dwToAddSize * sizeof(WCHAR));
33 if (lpNewList)
34 {
35 /* Copy the service name */
36 wcscpy_s(lpNewList,
37 dwToAddSize,
38 lpServiceToAdd);
39
40 /* Add the double null char */
41 lpNewList[dwToAddSize - 1] = L'\0';
42 }
43 }
44 else
45 {
46 ptr = *lpServiceList;
47 dwCurSize = 0;
48
49 /* Get the list size */
50 while (TRUE)
51 {
52 /* Break when we hit the double null */
53 if (*ptr == L'\0' && *(ptr + 1) == L'\0')
54 break;
55
56 ptr++;
57 dwCurSize++;
58 }
59 dwCurSize++;
60
61 /* Add another char for double null */
62 dwCurSize++;
63
64 /* Extend the list size */
65 lpNewList = HeapReAlloc(GetProcessHeap(),
66 0,
67 *lpServiceList,
68 (dwCurSize + dwToAddSize) * sizeof(WCHAR));
69 if (lpNewList)
70 {
71 /* Copy the service name */
72 wcscpy_s(&lpNewList[dwCurSize - 1],
73 dwToAddSize,
74 lpServiceToAdd);
75
76 /* Add the double null char */
77 lpNewList[dwCurSize + dwToAddSize - 1] = L'\0';
78 }
79 }
80
81 return lpNewList;
82 }
83
84 static BOOL
85 BuildListOfServicesToStop(LPWSTR *lpServiceList,
86 LPWSTR lpServiceName)
87 {
88 LPENUM_SERVICE_STATUS lpServiceStatus;
89 DWORD dwCount, i;
90 BOOL bRet = FALSE;
91
92 /* Get a list of service dependents */
93 lpServiceStatus = TV2_GetDependants(lpServiceName, &dwCount);
94 if (lpServiceStatus)
95 {
96 for (i = 0; i < dwCount; i++)
97 {
98 /* Does this service have any dependents? */
99 if (TV2_HasDependantServices(lpServiceStatus[i].lpServiceName))
100 {
101 /* recall this function with the dependent */
102 BuildListOfServicesToStop(lpServiceList, lpServiceStatus[i].lpServiceName);
103 }
104
105 /* Add the service to the list */
106 *lpServiceList = AddServiceToList(lpServiceList, lpServiceStatus[i].lpServiceName);
107 }
108
109 bRet = TRUE;
110
111 HeapFree(GetProcessHeap(),
112 0,
113 lpServiceStatus);
114 }
115
116 return bRet;
117 }
118
119 LPWSTR
120 GetListOfServicesToStop(LPWSTR lpServiceName)
121 {
122 LPWSTR lpServiceList = NULL;
123
124 /* Call recursive function to get our list */
125 if (BuildListOfServicesToStop(&lpServiceList, lpServiceName))
126 return lpServiceList;
127 else
128 return NULL;
129 }
130
131
132 static VOID
133 AddServiceNamesToStop(HWND hServiceListBox,
134 LPWSTR lpServiceList)
135 {
136 LPQUERY_SERVICE_CONFIG lpServiceConfig;
137 LPWSTR lpStr;
138
139 lpStr = lpServiceList;
140
141 /* Loop through all the services in the list */
142 while (TRUE)
143 {
144 /* Break when we hit the double null */
145 if (*lpStr == L'\0' && *(lpStr + 1) == L'\0')
146 break;
147
148 /* If this isn't our first time in the loop we'll
149 have been left on a null char */
150 if (*lpStr == L'\0')
151 lpStr++;
152
153 /* Get the service's display name */
154 lpServiceConfig = GetServiceConfig(lpStr);
155 if (lpServiceConfig)
156 {
157 /* Add the service to the listbox */
158 SendMessageW(hServiceListBox,
159 LB_ADDSTRING,
160 0,
161 (LPARAM)lpServiceConfig->lpDisplayName);
162 }
163
164 /* Move onto the next string */
165 while (*lpStr != L'\0')
166 lpStr++;
167 }
168 }
169
170 static BOOL
171 DoInitDependsDialog(PMAIN_WND_INFO pInfo,
172 HWND hDlg)
173 {
174 HWND hServiceListBox;
175 LPWSTR lpPartialStr, lpStr;
176 DWORD fullLen;
177 HICON hIcon = NULL;
178 BOOL bRet = FALSE;
179
180 if (pInfo)
181 {
182 /* Tag the info to the window */
183 SetWindowLongPtrW(hDlg,
184 GWLP_USERDATA,
185 (LONG_PTR)pInfo);
186
187 /* Load the icon for the window */
188 hIcon = (HICON)LoadImageW(hInstance,
189 MAKEINTRESOURCE(IDI_SM_ICON),
190 IMAGE_ICON,
191 GetSystemMetrics(SM_CXSMICON),
192 GetSystemMetrics(SM_CXSMICON),
193 0);
194 if (hIcon)
195 {
196 /* Set it */
197 SendMessageW(hDlg,
198 WM_SETICON,
199 ICON_SMALL,
200 (LPARAM)hIcon);
201 DestroyIcon(hIcon);
202 }
203
204 /* Load the stop depends note */
205 if (AllocAndLoadString(&lpPartialStr,
206 hInstance,
207 IDS_STOP_DEPENDS))
208 {
209 /* Get the length required */
210 fullLen = wcslen(lpPartialStr) + wcslen(pInfo->pCurrentService->lpDisplayName) + 1;
211
212 lpStr = HeapAlloc(ProcessHeap,
213 0,
214 fullLen * sizeof(WCHAR));
215 if (lpStr)
216 {
217 /* Add the service name to the depends note */
218 _snwprintf(lpStr,
219 fullLen,
220 lpPartialStr,
221 pInfo->pCurrentService->lpDisplayName);
222
223 /* Add the string to the dialog */
224 SendDlgItemMessageW(hDlg,
225 IDC_STOP_DEPENDS,
226 WM_SETTEXT,
227 0,
228 (LPARAM)lpStr);
229
230 HeapFree(ProcessHeap,
231 0,
232 lpStr);
233
234 bRet = TRUE;
235 }
236
237 HeapFree(ProcessHeap,
238 0,
239 lpPartialStr);
240 }
241
242 /* Display the list of services which need stopping */
243 hServiceListBox = GetDlgItem(hDlg,
244 IDC_STOP_DEPENDS_LB);
245 if (hServiceListBox)
246 {
247 AddServiceNamesToStop(hServiceListBox,
248 (LPWSTR)pInfo->pTag);
249 }
250 }
251
252 return bRet;
253 }
254
255
256 INT_PTR CALLBACK
257 StopDependsDialogProc(HWND hDlg,
258 UINT message,
259 WPARAM wParam,
260 LPARAM lParam)
261 {
262 PMAIN_WND_INFO pInfo = NULL;
263
264 /* Get the window context */
265 pInfo = (PMAIN_WND_INFO)GetWindowLongPtrW(hDlg,
266 GWLP_USERDATA);
267 if (pInfo == NULL && message != WM_INITDIALOG)
268 {
269 return FALSE;
270 }
271
272 switch (message)
273 {
274 case WM_INITDIALOG:
275 {
276 BOOL bRet = FALSE;
277
278 pInfo = (PMAIN_WND_INFO)lParam;
279 if (pInfo != NULL)
280 {
281 bRet = DoInitDependsDialog(pInfo, hDlg);
282 }
283
284 return bRet;
285 }
286
287 case WM_COMMAND:
288 {
289 switch (LOWORD(wParam))
290 {
291 case IDOK:
292 case IDCANCEL:
293 {
294 EndDialog(hDlg,
295 LOWORD(wParam));
296 return TRUE;
297 }
298 }
299 }
300 }
301
302 return FALSE;
303 }