[CMAKE]
[reactos.git] / 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 need stopping? */
99 if (lpServiceStatus[i].ServiceStatus.dwCurrentState != SERVICE_STOPPED &&
100 lpServiceStatus[i].ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING)
101 {
102 /* Does this service have any dependents? */
103 if (TV2_HasDependantServices(lpServiceStatus[i].lpServiceName))
104 {
105 /* recall this function with the dependent */
106 BuildListOfServicesToStop(lpServiceList, lpServiceStatus[i].lpServiceName);
107 }
108
109 /* Add the service to the list */
110 *lpServiceList = AddServiceToList(lpServiceList, lpServiceStatus[i].lpServiceName);
111
112 /* We've got one */
113 bRet = TRUE;
114 }
115 }
116
117 HeapFree(GetProcessHeap(),
118 0,
119 lpServiceStatus);
120 }
121
122 return bRet;
123 }
124
125 LPWSTR
126 GetListOfServicesToStop(LPWSTR lpServiceName)
127 {
128 LPWSTR lpServiceList = NULL;
129
130 /* Call recursive function to get our list */
131 if (BuildListOfServicesToStop(&lpServiceList, lpServiceName))
132 return lpServiceList;
133 else
134 return NULL;
135 }
136
137
138 static VOID
139 AddServiceNamesToStop(HWND hServiceListBox,
140 LPWSTR lpServiceList)
141 {
142 LPQUERY_SERVICE_CONFIG lpServiceConfig;
143 LPWSTR lpStr;
144
145 lpStr = lpServiceList;
146
147 /* Loop through all the services in the list */
148 while (TRUE)
149 {
150 /* Break when we hit the double null */
151 if (*lpStr == L'\0' && *(lpStr + 1) == L'\0')
152 break;
153
154 /* If this isn't our first time in the loop we'll
155 have been left on a null char */
156 if (*lpStr == L'\0')
157 lpStr++;
158
159 /* Get the service's display name */
160 lpServiceConfig = GetServiceConfig(lpStr);
161 if (lpServiceConfig)
162 {
163 /* Add the service to the listbox */
164 SendMessageW(hServiceListBox,
165 LB_ADDSTRING,
166 0,
167 (LPARAM)lpServiceConfig->lpDisplayName);
168 }
169
170 /* Move onto the next string */
171 while (*lpStr != L'\0')
172 lpStr++;
173 }
174 }
175
176 static BOOL
177 DoInitDependsDialog(PMAIN_WND_INFO pInfo,
178 HWND hDlg)
179 {
180 HWND hServiceListBox;
181 LPWSTR lpPartialStr, lpStr;
182 DWORD fullLen;
183 HICON hIcon = NULL;
184 BOOL bRet = FALSE;
185
186 if (pInfo)
187 {
188 /* Tag the info to the window */
189 SetWindowLongPtrW(hDlg,
190 GWLP_USERDATA,
191 (LONG_PTR)pInfo);
192
193 /* Load the icon for the window */
194 hIcon = (HICON)LoadImageW(hInstance,
195 MAKEINTRESOURCE(IDI_SM_ICON),
196 IMAGE_ICON,
197 GetSystemMetrics(SM_CXSMICON),
198 GetSystemMetrics(SM_CXSMICON),
199 0);
200 if (hIcon)
201 {
202 /* Set it */
203 SendMessageW(hDlg,
204 WM_SETICON,
205 ICON_SMALL,
206 (LPARAM)hIcon);
207 DestroyIcon(hIcon);
208 }
209
210 /* Load the stop depends note */
211 if (AllocAndLoadString(&lpPartialStr,
212 hInstance,
213 IDS_STOP_DEPENDS))
214 {
215 /* Get the length required */
216 fullLen = wcslen(lpPartialStr) + wcslen(pInfo->pCurrentService->lpDisplayName) + 1;
217
218 lpStr = HeapAlloc(ProcessHeap,
219 0,
220 fullLen * sizeof(WCHAR));
221 if (lpStr)
222 {
223 /* Add the service name to the depends note */
224 _snwprintf(lpStr,
225 fullLen,
226 lpPartialStr,
227 pInfo->pCurrentService->lpDisplayName);
228
229 /* Add the string to the dialog */
230 SendDlgItemMessageW(hDlg,
231 IDC_STOP_DEPENDS,
232 WM_SETTEXT,
233 0,
234 (LPARAM)lpStr);
235
236 HeapFree(ProcessHeap,
237 0,
238 lpStr);
239
240 bRet = TRUE;
241 }
242
243 HeapFree(ProcessHeap,
244 0,
245 lpPartialStr);
246 }
247
248 /* Display the list of services which need stopping */
249 hServiceListBox = GetDlgItem(hDlg,
250 IDC_STOP_DEPENDS_LB);
251 if (hServiceListBox)
252 {
253 AddServiceNamesToStop(hServiceListBox,
254 (LPWSTR)pInfo->pTag);
255 }
256 }
257
258 return bRet;
259 }
260
261
262 INT_PTR CALLBACK
263 StopDependsDialogProc(HWND hDlg,
264 UINT message,
265 WPARAM wParam,
266 LPARAM lParam)
267 {
268 PMAIN_WND_INFO pInfo = NULL;
269
270 /* Get the window context */
271 pInfo = (PMAIN_WND_INFO)GetWindowLongPtrW(hDlg,
272 GWLP_USERDATA);
273 if (pInfo == NULL && message != WM_INITDIALOG)
274 {
275 return FALSE;
276 }
277
278 switch (message)
279 {
280 case WM_INITDIALOG:
281 {
282 BOOL bRet = FALSE;
283
284 pInfo = (PMAIN_WND_INFO)lParam;
285 if (pInfo != NULL)
286 {
287 bRet = DoInitDependsDialog(pInfo, hDlg);
288 }
289
290 return bRet;
291 }
292
293 case WM_COMMAND:
294 {
295 switch (LOWORD(wParam))
296 {
297 case IDOK:
298 case IDCANCEL:
299 {
300 EndDialog(hDlg,
301 LOWORD(wParam));
302 return TRUE;
303 }
304 }
305 }
306 }
307
308 return FALSE;
309 }