1 /* 2 * PROJECT: ReactOS Applications 3 * LICENSE: LGPL - See COPYING in the top level directory 4 * FILE: base/applications/msconfig/srvpage.c 5 * PURPOSE: Services page message handler 6 * COPYRIGHT: Copyright 2005-2006 Christoph von Wittich <Christoph@ApiViewer.de> 7 * 8 */ 9 10 #include "precomp.h" 11 12 #include <winsvc.h> 13 #include <winver.h> 14 15 HWND hServicesPage; 16 HWND hServicesListCtrl; 17 HWND hServicesDialog; 18 19 void GetServices ( void ); 20 21 INT_PTR CALLBACK 22 ServicesPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 23 { 24 LV_COLUMN column; 25 TCHAR szTemp[256]; 26 DWORD dwStyle; 27 28 UNREFERENCED_PARAMETER(lParam); 29 UNREFERENCED_PARAMETER(wParam); 30 31 switch (message) { 32 case WM_INITDIALOG: 33 34 hServicesListCtrl = GetDlgItem(hDlg, IDC_SERVICES_LIST); 35 hServicesDialog = hDlg; 36 37 dwStyle = (DWORD) SendMessage(hServicesListCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); 38 dwStyle = dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES; 39 SendMessage(hServicesListCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle); 40 41 SetWindowPos(hDlg, NULL, 10, 32, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER); 42 43 // Initialize the application page's controls 44 column.mask = LVCF_TEXT | LVCF_WIDTH; 45 46 LoadString(hInst, IDS_SERVICES_COLUMN_SERVICE, szTemp, 256); 47 column.pszText = szTemp; 48 column.cx = 200; 49 (void)ListView_InsertColumn(hServicesListCtrl, 0, &column); 50 51 column.mask = LVCF_TEXT | LVCF_WIDTH; 52 LoadString(hInst, IDS_SERVICES_COLUMN_REQ, szTemp, 256); 53 column.pszText = szTemp; 54 column.cx = 70; 55 (void)ListView_InsertColumn(hServicesListCtrl, 1, &column); 56 57 column.mask = LVCF_TEXT | LVCF_WIDTH; 58 LoadString(hInst, IDS_SERVICES_COLUMN_VENDOR, szTemp, 256); 59 column.pszText = szTemp; 60 column.cx = 200; 61 (void)ListView_InsertColumn(hServicesListCtrl, 2, &column); 62 63 column.mask = LVCF_TEXT | LVCF_WIDTH; 64 LoadString(hInst, IDS_SERVICES_COLUMN_STATUS, szTemp, 256); 65 column.pszText = szTemp; 66 column.cx = 70; 67 (void)ListView_InsertColumn(hServicesListCtrl, 3, &column); 68 69 GetServices(); 70 return TRUE; 71 } 72 73 return 0; 74 } 75 76 void 77 GetServices ( void ) 78 { 79 LV_ITEM item; 80 WORD wCodePage; 81 WORD wLangID; 82 SC_HANDLE ScHandle; 83 SC_HANDLE hService; 84 DWORD BytesNeeded = 0; 85 DWORD ResumeHandle = 0; 86 DWORD NumServices = 0; 87 DWORD dwHandle, dwLen; 88 size_t Index; 89 UINT BufLen; 90 TCHAR szStatus[128]; 91 TCHAR* lpData; 92 TCHAR* lpBuffer; 93 TCHAR szStrFileInfo[80]; 94 TCHAR FileName[MAX_PATH]; 95 LPVOID pvData; 96 97 LPSERVICE_FAILURE_ACTIONS pServiceFailureActions = NULL; 98 LPQUERY_SERVICE_CONFIG pServiceConfig = NULL; 99 ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL; 100 101 ScHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); 102 if (ScHandle != NULL) 103 { 104 if (EnumServicesStatusEx(ScHandle, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pServiceStatus, 0, &BytesNeeded, &NumServices, &ResumeHandle, 0) == 0) 105 { 106 /* Call function again if required size was returned */ 107 if (GetLastError() == ERROR_MORE_DATA) 108 { 109 /* reserve memory for service info array */ 110 pServiceStatus = HeapAlloc(GetProcessHeap(), 0, BytesNeeded); 111 if (!pServiceStatus) 112 { 113 CloseServiceHandle(ScHandle); 114 return; 115 } 116 117 /* fill array with service info */ 118 if (EnumServicesStatusEx(ScHandle, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pServiceStatus, BytesNeeded, &BytesNeeded, &NumServices, &ResumeHandle, 0) == 0) 119 { 120 HeapFree(GetProcessHeap(), 0, pServiceStatus); 121 CloseServiceHandle(ScHandle); 122 return; 123 } 124 } 125 else /* exit on failure */ 126 { 127 CloseServiceHandle(ScHandle); 128 return; 129 } 130 } 131 132 if (NumServices) 133 { 134 if (!pServiceStatus) 135 { 136 CloseServiceHandle(ScHandle); 137 return; 138 } 139 140 for (Index = 0; Index < NumServices; Index++) 141 { 142 memset(&item, 0, sizeof(LV_ITEM)); 143 item.mask = LVIF_TEXT; 144 item.iImage = 0; 145 item.pszText = pServiceStatus[Index].lpDisplayName; 146 item.iItem = ListView_GetItemCount(hServicesListCtrl); 147 item.lParam = 0; 148 item.iItem = ListView_InsertItem(hServicesListCtrl, &item); 149 150 if (pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING) 151 { 152 ListView_SetCheckState(hServicesListCtrl, item.iItem, TRUE); 153 } 154 155 BytesNeeded = 0; 156 hService = OpenService(ScHandle, pServiceStatus[Index].lpServiceName, SC_MANAGER_CONNECT); 157 if (hService != NULL) 158 { 159 /* check if service is required by the system*/ 160 if (!QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)NULL, 0, &BytesNeeded)) 161 { 162 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 163 { 164 pServiceFailureActions = HeapAlloc(GetProcessHeap(), 0, BytesNeeded); 165 if (pServiceFailureActions == NULL) 166 { 167 HeapFree(GetProcessHeap(), 0, pServiceStatus); 168 CloseServiceHandle(hService); 169 CloseServiceHandle(ScHandle); 170 return; 171 } 172 173 if (!QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)pServiceFailureActions, BytesNeeded, &BytesNeeded)) 174 { 175 HeapFree(GetProcessHeap(), 0, pServiceFailureActions); 176 HeapFree(GetProcessHeap(), 0, pServiceStatus); 177 CloseServiceHandle(hService); 178 CloseServiceHandle(ScHandle); 179 return; 180 } 181 } 182 else /* exit on failure */ 183 { 184 HeapFree(GetProcessHeap(), 0, pServiceStatus); 185 CloseServiceHandle(hService); 186 CloseServiceHandle(ScHandle); 187 return; 188 } 189 } 190 191 if (pServiceFailureActions != NULL) 192 { 193 if (pServiceFailureActions->cActions && pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT) 194 { 195 LoadString(hInst, IDS_SERVICES_YES, szStatus, 128); 196 item.pszText = szStatus; 197 item.iSubItem = 1; 198 SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item); 199 } 200 HeapFree(GetProcessHeap(), 0, pServiceFailureActions); 201 pServiceFailureActions = NULL; 202 } 203 204 /* get vendor of service binary */ 205 BytesNeeded = 0; 206 if (!QueryServiceConfig(hService, NULL, 0, &BytesNeeded)) 207 { 208 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 209 { 210 pServiceConfig = HeapAlloc(GetProcessHeap(), 0, BytesNeeded); 211 if (pServiceConfig == NULL) 212 { 213 HeapFree(GetProcessHeap(), 0, pServiceStatus); 214 CloseServiceHandle(hService); 215 CloseServiceHandle(ScHandle); 216 return; 217 } 218 if (!QueryServiceConfig(hService, pServiceConfig, BytesNeeded, &BytesNeeded)) 219 { 220 HeapFree(GetProcessHeap(), 0, pServiceConfig); 221 HeapFree(GetProcessHeap(), 0, pServiceStatus); 222 CloseServiceHandle(hService); 223 CloseServiceHandle(ScHandle); 224 return; 225 } 226 } 227 else /* exit on failure */ 228 { 229 HeapFree(GetProcessHeap(), 0, pServiceStatus); 230 CloseServiceHandle(hService); 231 CloseServiceHandle(ScHandle); 232 return; 233 } 234 } 235 236 if (pServiceConfig->lpBinaryPathName[0] != _T('"')) 237 { 238 /* Assume everything before the first space is the binary path */ 239 /* FIXME: This is a reasonable heuristic but some 240 * services use unquoted paths with spaces */ 241 StringCchCopyN(FileName, 242 _countof(FileName), 243 pServiceConfig->lpBinaryPathName, 244 _tcscspn(pServiceConfig->lpBinaryPathName, _T(" "))); 245 } 246 else 247 { 248 /* Binary path is inside the quotes */ 249 StringCchCopyN(FileName, 250 _countof(FileName), 251 pServiceConfig->lpBinaryPathName + 1, 252 _tcscspn(pServiceConfig->lpBinaryPathName + 1, _T("\""))); 253 } 254 255 HeapFree(GetProcessHeap(), 0, pServiceConfig); 256 pServiceConfig = NULL; 257 258 dwLen = GetFileVersionInfoSize(FileName, &dwHandle); 259 if (dwLen) 260 { 261 lpData = HeapAlloc(GetProcessHeap(), 0, dwLen); 262 if (lpData == NULL) 263 { 264 HeapFree(GetProcessHeap(), 0, pServiceStatus); 265 CloseServiceHandle(hService); 266 CloseServiceHandle(ScHandle); 267 return; 268 } 269 if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData)) 270 { 271 HeapFree(GetProcessHeap(), 0, lpData); 272 HeapFree(GetProcessHeap(), 0, pServiceStatus); 273 CloseServiceHandle(hService); 274 CloseServiceHandle(ScHandle); 275 return; 276 } 277 278 if (VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"), &pvData, (PUINT) &BufLen)) 279 { 280 wCodePage = LOWORD(*(DWORD*) pvData); 281 wLangID = HIWORD(*(DWORD*) pvData); 282 wsprintf(szStrFileInfo, _T("StringFileInfo\\%04X%04X\\CompanyName"), wCodePage, wLangID); 283 } 284 285 if (VerQueryValue (lpData, szStrFileInfo, (void**) &lpBuffer, (PUINT) &BufLen)) 286 { 287 item.pszText = lpBuffer; 288 item.iSubItem = 2; 289 SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item); 290 } 291 HeapFree(GetProcessHeap(), 0, lpData); 292 } 293 else 294 { 295 LoadString(hInst, IDS_SERVICES_UNKNOWN, szStatus, 128); 296 item.pszText = szStatus; 297 item.iSubItem = 2; 298 SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item); 299 } 300 CloseServiceHandle(hService); 301 } 302 303 LoadString(hInst, ((pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_STOPPED) ? IDS_SERVICES_STATUS_STOPPED : IDS_SERVICES_STATUS_RUNNING), szStatus, 128); 304 item.pszText = szStatus; 305 item.iSubItem = 3; 306 SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item); 307 308 } 309 } 310 311 HeapFree(GetProcessHeap(), 0, pServiceStatus); 312 CloseServiceHandle(ScHandle); 313 } 314 315 } 316