/* * PROJECT: ReactOS Applications * LICENSE: LGPL - See COPYING in the top level directory * FILE: base/applications/msconfig/srvpage.c * PURPOSE: Services page message handler * COPYRIGHT: Copyright 2005-2006 Christoph von Wittich * */ #include "precomp.h" #include #include HWND hServicesPage; HWND hServicesListCtrl; HWND hServicesDialog; void GetServices ( void ); INT_PTR CALLBACK ServicesPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { LV_COLUMN column; TCHAR szTemp[256]; DWORD dwStyle; UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(wParam); switch (message) { case WM_INITDIALOG: hServicesListCtrl = GetDlgItem(hDlg, IDC_SERVICES_LIST); hServicesDialog = hDlg; dwStyle = (DWORD) SendMessage(hServicesListCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); dwStyle = dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES; SendMessage(hServicesListCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle); SetWindowPos(hDlg, NULL, 10, 32, 0, 0, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER); // Initialize the application page's controls column.mask = LVCF_TEXT | LVCF_WIDTH; LoadString(hInst, IDS_SERVICES_COLUMN_SERVICE, szTemp, 256); column.pszText = szTemp; column.cx = 200; (void)ListView_InsertColumn(hServicesListCtrl, 0, &column); column.mask = LVCF_TEXT | LVCF_WIDTH; LoadString(hInst, IDS_SERVICES_COLUMN_REQ, szTemp, 256); column.pszText = szTemp; column.cx = 70; (void)ListView_InsertColumn(hServicesListCtrl, 1, &column); column.mask = LVCF_TEXT | LVCF_WIDTH; LoadString(hInst, IDS_SERVICES_COLUMN_VENDOR, szTemp, 256); column.pszText = szTemp; column.cx = 200; (void)ListView_InsertColumn(hServicesListCtrl, 2, &column); column.mask = LVCF_TEXT | LVCF_WIDTH; LoadString(hInst, IDS_SERVICES_COLUMN_STATUS, szTemp, 256); column.pszText = szTemp; column.cx = 70; (void)ListView_InsertColumn(hServicesListCtrl, 3, &column); GetServices(); return TRUE; } return 0; } void GetServices ( void ) { LV_ITEM item; WORD wCodePage; WORD wLangID; SC_HANDLE ScHandle; SC_HANDLE hService; DWORD BytesNeeded = 0; DWORD ResumeHandle = 0; DWORD NumServices = 0; DWORD dwHandle, dwLen; size_t Index; UINT BufLen; TCHAR szStatus[128]; TCHAR* lpData; TCHAR* lpBuffer; TCHAR szStrFileInfo[80]; TCHAR FileName[MAX_PATH]; LPVOID pvData; LPSERVICE_FAILURE_ACTIONS pServiceFailureActions = NULL; LPQUERY_SERVICE_CONFIG pServiceConfig = NULL; ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL; ScHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); if (ScHandle != NULL) { if (EnumServicesStatusEx(ScHandle, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pServiceStatus, 0, &BytesNeeded, &NumServices, &ResumeHandle, 0) == 0) { /* Call function again if required size was returned */ if (GetLastError() == ERROR_MORE_DATA) { /* reserve memory for service info array */ pServiceStatus = HeapAlloc(GetProcessHeap(), 0, BytesNeeded); if (!pServiceStatus) { CloseServiceHandle(ScHandle); return; } /* fill array with service info */ if (EnumServicesStatusEx(ScHandle, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pServiceStatus, BytesNeeded, &BytesNeeded, &NumServices, &ResumeHandle, 0) == 0) { HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(ScHandle); return; } } else /* exit on failure */ { CloseServiceHandle(ScHandle); return; } } if (NumServices) { if (!pServiceStatus) { CloseServiceHandle(ScHandle); return; } for (Index = 0; Index < NumServices; Index++) { memset(&item, 0, sizeof(LV_ITEM)); item.mask = LVIF_TEXT; item.iImage = 0; item.pszText = pServiceStatus[Index].lpDisplayName; item.iItem = ListView_GetItemCount(hServicesListCtrl); item.lParam = 0; item.iItem = ListView_InsertItem(hServicesListCtrl, &item); if (pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING) { ListView_SetCheckState(hServicesListCtrl, item.iItem, TRUE); } BytesNeeded = 0; hService = OpenService(ScHandle, pServiceStatus[Index].lpServiceName, SC_MANAGER_CONNECT); if (hService != NULL) { /* check if service is required by the system*/ if (!QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)NULL, 0, &BytesNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { pServiceFailureActions = HeapAlloc(GetProcessHeap(), 0, BytesNeeded); if (pServiceFailureActions == NULL) { HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(hService); CloseServiceHandle(ScHandle); return; } if (!QueryServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)pServiceFailureActions, BytesNeeded, &BytesNeeded)) { HeapFree(GetProcessHeap(), 0, pServiceFailureActions); HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(hService); CloseServiceHandle(ScHandle); return; } } else /* exit on failure */ { HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(hService); CloseServiceHandle(ScHandle); return; } } if (pServiceFailureActions != NULL) { if (pServiceFailureActions->cActions && pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT) { LoadString(hInst, IDS_SERVICES_YES, szStatus, 128); item.pszText = szStatus; item.iSubItem = 1; SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item); } HeapFree(GetProcessHeap(), 0, pServiceFailureActions); pServiceFailureActions = NULL; } /* get vendor of service binary */ BytesNeeded = 0; if (!QueryServiceConfig(hService, NULL, 0, &BytesNeeded)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { pServiceConfig = HeapAlloc(GetProcessHeap(), 0, BytesNeeded); if (pServiceConfig == NULL) { HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(hService); CloseServiceHandle(ScHandle); return; } if (!QueryServiceConfig(hService, pServiceConfig, BytesNeeded, &BytesNeeded)) { HeapFree(GetProcessHeap(), 0, pServiceConfig); HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(hService); CloseServiceHandle(ScHandle); return; } } else /* exit on failure */ { HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(hService); CloseServiceHandle(ScHandle); return; } } if (pServiceConfig->lpBinaryPathName[0] != _T('"')) { /* Assume everything before the first space is the binary path */ /* FIXME: This is a reasonable heuristic but some * services use unquoted paths with spaces */ StringCchCopyN(FileName, _countof(FileName), pServiceConfig->lpBinaryPathName, _tcscspn(pServiceConfig->lpBinaryPathName, _T(" "))); } else { /* Binary path is inside the quotes */ StringCchCopyN(FileName, _countof(FileName), pServiceConfig->lpBinaryPathName + 1, _tcscspn(pServiceConfig->lpBinaryPathName + 1, _T("\""))); } HeapFree(GetProcessHeap(), 0, pServiceConfig); pServiceConfig = NULL; dwLen = GetFileVersionInfoSize(FileName, &dwHandle); if (dwLen) { lpData = HeapAlloc(GetProcessHeap(), 0, dwLen); if (lpData == NULL) { HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(hService); CloseServiceHandle(ScHandle); return; } if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData)) { HeapFree(GetProcessHeap(), 0, lpData); HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(hService); CloseServiceHandle(ScHandle); return; } if (VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"), &pvData, (PUINT) &BufLen)) { wCodePage = LOWORD(*(DWORD*) pvData); wLangID = HIWORD(*(DWORD*) pvData); wsprintf(szStrFileInfo, _T("StringFileInfo\\%04X%04X\\CompanyName"), wCodePage, wLangID); } if (VerQueryValue (lpData, szStrFileInfo, (void**) &lpBuffer, (PUINT) &BufLen)) { item.pszText = lpBuffer; item.iSubItem = 2; SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item); } HeapFree(GetProcessHeap(), 0, lpData); } else { LoadString(hInst, IDS_SERVICES_UNKNOWN, szStatus, 128); item.pszText = szStatus; item.iSubItem = 2; SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item); } CloseServiceHandle(hService); } LoadString(hInst, ((pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_STOPPED) ? IDS_SERVICES_STATUS_STOPPED : IDS_SERVICES_STATUS_RUNNING), szStatus, 128); item.pszText = szStatus; item.iSubItem = 3; SendMessage(hServicesListCtrl, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item); } } HeapFree(GetProcessHeap(), 0, pServiceStatus); CloseServiceHandle(ScHandle); } }