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-2015 Ged Murphy <gedmurphy@reactos.org>
7 *
8 */
9
10 #include "precomp.h"
11
12 typedef struct _STOP_DATA
13 {
14 LPWSTR ServiceName;
15 LPWSTR DisplayName;
16 LPWSTR ServiceList;
17
18 } STOP_DATA, *PSTOP_DATA;
19
20 static LPWSTR
AddServiceToList(LPWSTR * lpServiceList,LPWSTR lpServiceToAdd)21 AddServiceToList(LPWSTR *lpServiceList,
22 LPWSTR lpServiceToAdd)
23 {
24 LPWSTR lpNewList = NULL;
25 LPWSTR ptr;
26 DWORD dwToAddSize;
27 DWORD dwCurSize;
28
29 dwToAddSize = wcslen(lpServiceToAdd) + 1;
30
31 /* Is this is the first in the list? */
32 if (!*lpServiceList)
33 {
34 /* Add another char for double null */
35 dwToAddSize++;
36
37 lpNewList = HeapAlloc(GetProcessHeap(),
38 0,
39 dwToAddSize * sizeof(WCHAR));
40 if (lpNewList)
41 {
42 /* Copy the service name */
43 StringCchCopy(lpNewList,
44 dwToAddSize,
45 lpServiceToAdd);
46
47 /* Add the double null char */
48 lpNewList[dwToAddSize - 1] = L'\0';
49 }
50 }
51 else
52 {
53 ptr = *lpServiceList;
54 dwCurSize = 0;
55
56 /* Get the list size */
57 for (;;)
58 {
59 /* Break when we hit the double null */
60 if (*ptr == L'\0' && *(ptr + 1) == L'\0')
61 break;
62
63 ptr++;
64 dwCurSize++;
65 }
66 dwCurSize++;
67
68 /* Add another char for double null */
69 dwCurSize++;
70
71 /* Extend the list size */
72 lpNewList = HeapReAlloc(GetProcessHeap(),
73 0,
74 *lpServiceList,
75 (dwCurSize + dwToAddSize) * sizeof(WCHAR));
76 if (lpNewList)
77 {
78 /* Copy the service name */
79 StringCchCopy(&lpNewList[dwCurSize - 1],
80 dwToAddSize,
81 lpServiceToAdd);
82
83 /* Add the double null char */
84 lpNewList[dwCurSize + dwToAddSize - 1] = L'\0';
85 }
86 }
87
88 return lpNewList;
89 }
90
91 static BOOL
BuildListOfServicesToStop(LPWSTR * lpServiceList,LPWSTR lpServiceName)92 BuildListOfServicesToStop(LPWSTR *lpServiceList,
93 LPWSTR lpServiceName)
94 {
95 LPENUM_SERVICE_STATUS lpServiceStatus;
96 DWORD dwCount, i;
97 BOOL bRet = FALSE;
98
99 /* Get a list of service dependents */
100 lpServiceStatus = TV2_GetDependants(lpServiceName, &dwCount);
101 if (lpServiceStatus)
102 {
103 for (i = 0; i < dwCount; i++)
104 {
105 /* Does this service need stopping? */
106 if (lpServiceStatus[i].ServiceStatus.dwCurrentState != SERVICE_STOPPED &&
107 lpServiceStatus[i].ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING)
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
GetListOfServicesToStop(LPWSTR lpServiceName)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 static VOID
AddServiceNamesToStop(HWND hServiceListBox,LPWSTR lpServiceList)138 AddServiceNamesToStop(HWND hServiceListBox,
139 LPWSTR lpServiceList)
140 {
141 LPQUERY_SERVICE_CONFIG lpServiceConfig;
142 LPWSTR lpStr;
143
144 lpStr = lpServiceList;
145
146 /* Loop through all the services in the list */
147 for (;;)
148 {
149 /* Break when we hit the double null */
150 if (*lpStr == L'\0' && *(lpStr + 1) == L'\0')
151 break;
152
153 /* If this isn't our first time in the loop we'll
154 have been left on a null char */
155 if (*lpStr == L'\0')
156 lpStr++;
157
158 /* Get the service's display name */
159 lpServiceConfig = GetServiceConfig(lpStr);
160 if (lpServiceConfig)
161 {
162 /* Add the service to the listbox */
163 SendMessageW(hServiceListBox,
164 LB_ADDSTRING,
165 0,
166 (LPARAM)lpServiceConfig->lpDisplayName);
167
168 HeapFree(GetProcessHeap(), 0, lpServiceConfig);
169 }
170
171 /* Move onto the next string */
172 while (*lpStr != L'\0')
173 lpStr++;
174 }
175 }
176
177 static BOOL
InitDialog(HWND hDlg,UINT Message,WPARAM wParam,LPARAM lParam)178 InitDialog(HWND hDlg,
179 UINT Message,
180 WPARAM wParam,
181 LPARAM lParam)
182 {
183 PSTOP_DATA StopData;
184 HWND hServiceListBox;
185 LPWSTR lpPartialStr, lpStr;
186 DWORD fullLen;
187 HICON hIcon = NULL;
188 BOOL bRet = FALSE;
189
190 StopData = (PSTOP_DATA)lParam;
191
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(StopData->DisplayName) + 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 StopData->DisplayName);
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 LocalFree(lpPartialStr);
244 }
245
246 /* Display the list of services which need stopping */
247 hServiceListBox = GetDlgItem(hDlg, IDC_STOP_DEPENDS_LB);
248 if (hServiceListBox)
249 {
250 AddServiceNamesToStop(hServiceListBox,
251 (LPWSTR)StopData->ServiceList);
252 }
253
254 return bRet;
255 }
256
257 INT_PTR CALLBACK
StopDependsDialogProc(HWND hDlg,UINT Message,WPARAM wParam,LPARAM lParam)258 StopDependsDialogProc(HWND hDlg,
259 UINT Message,
260 WPARAM wParam,
261 LPARAM lParam)
262 {
263
264 switch (Message)
265 {
266 case WM_INITDIALOG:
267 {
268 return InitDialog(hDlg,
269 Message,
270 wParam,
271 lParam);
272 }
273
274 case WM_COMMAND:
275 {
276 switch (LOWORD(wParam))
277 {
278 case IDOK:
279 case IDCANCEL:
280 {
281 EndDialog(hDlg,
282 LOWORD(wParam));
283 return TRUE;
284 }
285 }
286 }
287 }
288
289 return FALSE;
290 }
291
292 BOOL
CreateStopDependsDialog(HWND hParent,LPWSTR ServiceName,LPWSTR DisplayName,LPWSTR ServiceList)293 CreateStopDependsDialog(HWND hParent,
294 LPWSTR ServiceName,
295 LPWSTR DisplayName,
296 LPWSTR ServiceList)
297 {
298 STOP_DATA StopData;
299 INT_PTR Result;
300
301 StopData.ServiceName = ServiceName;
302 StopData.DisplayName = DisplayName;
303 StopData.ServiceList = ServiceList;
304
305 Result = DialogBoxParamW(hInstance,
306 MAKEINTRESOURCEW(IDD_DLG_DEPEND_STOP),
307 hParent,
308 StopDependsDialogProc,
309 (LPARAM)&StopData);
310 if (Result == IDOK)
311 return TRUE;
312
313 return FALSE;
314 }
315