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 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 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 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 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 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 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 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