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