原文:http://www.codeproject.com/Articles/1573/About-Windows-Services
#include <windows.h> #include <stdio.h> #include "resource.h" #include "services.h" #define BUFF_LEN 256 TCHAR g_szSelectedComputer[BUFF_LEN]; int g_iLen = BUFF_LEN; QUERY_SERVICE_CONFIG* g_psc = NULL; // main program int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DialogProc); return 0; } // Dialog procedure BOOL CALLBACK DialogProc(HWND p_hWnd, UINT p_uMsg, WPARAM p_wParam, LPARAM p_lParam) { HICON hIcon = NULL; static HWND hWndList = NULL; int iWidth = 120; switch (p_uMsg) { case WM_INITDIALOG: // Load Icon hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAIN)); SendMessage(p_hWnd, WM_SETICON, TRUE, (LPARAM)hIcon); // initilize common control InitCommonControls(); hWndList = GetDlgItem(p_hWnd, IDC_LIST_SERVICES); InsertColumn(hWndList, DISPLAY_NAME_COL, TEXT("Display Name"), iWidth); InsertColumn(hWndList, SERVICE_NAME_COL, TEXT("Service Name"), iWidth); InsertColumn(hWndList, TYPE_COL, TEXT("Type"), iWidth); InsertColumn(hWndList, STATE_COL, TEXT("Current State"), iWidth); InsertColumn(hWndList, CONTROL_COL, TEXT("Controls Accepted"), iWidth); // Set extended style of List control full row select SendMessage(hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, (LPARAM) LVS_EX_FULLROWSELECT); break; case WM_COMMAND: switch(LOWORD(p_wParam)) { // Exit from the program case IDC_BTN_EXIT: PostQuitMessage(0); break; case IDC_BTN_UPDATE: GetWindowServices(hWndList); break; case IDC_BTN_COMPUTER: if (DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG_COMPUTER), NULL, DialogProcComputer) == IDOK) { SetWindowText(GetDlgItem(p_hWnd, IDC_STATICCOMPUTER), g_szSelectedComputer); } break; } case WM_NOTIFY: switch (p_wParam) { case IDC_LIST_SERVICES: if (((NMHDR*)p_lParam)->code == NM_DBLCLK) { TCHAR szService[BUFF_LEN]; int iPos = SendMessage(hWndList, LVM_GETNEXTITEM, -1, LVIS_SELECTED); LVITEM lvItem; ZeroMemory(&lvItem, sizeof(LVITEM)); // get the text of second column lvItem.iSubItem = 1; lvItem.pszText = szService; lvItem.cchTextMax = g_iLen; SendMessage(hWndList, LVM_GETITEMTEXT, (WPARAM)iPos, (LPARAM)&lvItem); SC_HANDLE hSCM = OpenSCManager(g_szSelectedComputer, NULL, SC_MANAGER_ALL_ACCESS); SC_HANDLE hService = OpenService(hSCM, szService, SERVICE_ALL_ACCESS); QUERY_SERVICE_CONFIG sc; DWORD dwBytesNeeded = 0; // Try to get information about the query BOOL bRetVal = QueryServiceConfig(hService, &sc, sizeof(QUERY_SERVICE_CONFIG), &dwBytesNeeded); if (!bRetVal) { DWORD retVal = GetLastError(); // buffer size is small. // Required size is in dwBytesNeeded if (ERROR_INSUFFICIENT_BUFFER == retVal) { DWORD dwBytes = sizeof(QUERY_SERVICE_CONFIG) + dwBytesNeeded; g_psc = new QUERY_SERVICE_CONFIG[dwBytesNeeded]; bRetVal = QueryServiceConfig(hService, g_psc, dwBytes, &dwBytesNeeded); if (!bRetVal) { ErrorDescription(GetLastError()); delete [] g_psc; g_psc = NULL; break; } DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG_SERVICE), NULL, DialogProcService); delete [] g_psc; g_psc = NULL; } } CloseServiceHandle(hService); CloseServiceHandle(hSCM); } } break; } return FALSE; } // insert column in the list control int InsertColumn(HWND p_hWnd, int p_iCol, LPCTSTR p_lpszHeading, int p_iWidth) { LVCOLUMN column; column.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH; column.fmt = LVCFMT_LEFT; column.cx = p_iWidth; column.pszText = (LPTSTR)p_lpszHeading; column.iSubItem = -1; column.iImage = -1; column.iOrder = 0; return (int) SendMessage(p_hWnd, LVM_INSERTCOLUMN, p_iCol, (LPARAM)&column); } // insert rows in the list control int InsertItem(HWND p_hWnd, int p_iRow, LPCTSTR p_lpszText) { LVITEM lvItem; lvItem.mask = LVIF_TEXT; lvItem.iItem = p_iRow; lvItem.iSubItem = 0; lvItem.state = 0; lvItem.stateMask = 0; lvItem.pszText = (LPTSTR)p_lpszText; lvItem.iImage = 0; lvItem.lParam = 0; lvItem.iIndent = 0; return (int) SendMessage(p_hWnd, LVM_INSERTITEM, 0, (LPARAM)&lvItem); } // insert the item in the other columns of the list control int InsertSubItem(HWND p_hWnd, int p_iRow, LPCTSTR p_lpszText, int p_iSubItem) { LVITEM lvItem; lvItem.iSubItem = p_iSubItem; lvItem.pszText = (LPTSTR)p_lpszText; return (int) SendMessage(p_hWnd, LVM_SETITEMTEXT, p_iRow, (LPARAM)&lvItem); } // get all the services of the window BOOL GetWindowServices(HWND p_hWnd) { // first delete all item SendMessage(p_hWnd, LVM_DELETEALLITEMS, 0, 0); // open service manager SC_HANDLE hHandle = OpenSCManager(g_szSelectedComputer, NULL, SC_MANAGER_ENUMERATE_SERVICE); if (!hHandle) { ErrorDescription(GetLastError()); return FALSE; } ENUM_SERVICE_STATUS service; DWORD dwBytesNeeded = 0; DWORD dwServicesReturned = 0; DWORD dwResumedHandle = 0; // Query services BOOL retVal = EnumServicesStatus(hHandle, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_STATE_ALL, &service, sizeof(ENUM_SERVICE_STATUS), &dwBytesNeeded, &dwServicesReturned, &dwResumedHandle); if (!retVal) { // Need big buffer if (ERROR_MORE_DATA == GetLastError()) { // Set the buffer DWORD dwBytes = sizeof(ENUM_SERVICE_STATUS) + dwBytesNeeded; ENUM_SERVICE_STATUS* pServices = NULL; pServices = new ENUM_SERVICE_STATUS [dwBytes]; // Now query again for services EnumServicesStatus(hHandle, SERVICE_WIN32 | SERVICE_DRIVER, SERVICE_STATE_ALL, pServices, dwBytes, &dwBytesNeeded, &dwServicesReturned, &dwResumedHandle); // now traverse each service to get information for (unsigned iIndex = 0; iIndex < dwServicesReturned; iIndex++) { InsertItem(p_hWnd, iIndex, (pServices + iIndex)->lpDisplayName); InsertSubItem(p_hWnd, iIndex, (pServices + iIndex)->lpServiceName, SERVICE_NAME_COL); // get type of the service GetTypeOfService(p_hWnd, (pServices + iIndex)->ServiceStatus.dwServiceType, iIndex); // get current status of the services GetCurrentStatus(p_hWnd, (pServices + iIndex)->ServiceStatus.dwCurrentState, iIndex); // check the control code which service can accept GetControlCode(p_hWnd, (pServices + iIndex)->ServiceStatus.dwControlsAccepted, iIndex); } delete [] pServices; pServices = NULL; } else return FALSE; } CloseServiceHandle(hHandle); return TRUE; } // get type of the service void GetTypeOfService(HWND p_hWnd, DWORD p_dwType, int p_iIndex) { switch (p_dwType) { case SERVICE_WIN32_OWN_PROCESS: InsertSubItem(p_hWnd, p_iIndex, TEXT("Run its own process"), TYPE_COL); break; case SERVICE_WIN32_SHARE_PROCESS: InsertSubItem(p_hWnd, p_iIndex, TEXT("Share a process with other application"), TYPE_COL); break; case SERVICE_KERNEL_DRIVER: InsertSubItem(p_hWnd, p_iIndex, TEXT("Device driver"), TYPE_COL); break; case SERVICE_FILE_SYSTEM_DRIVER: InsertSubItem(p_hWnd, p_iIndex, TEXT("File system driver"), TYPE_COL); break; case SERVICE_INTERACTIVE_PROCESS: InsertSubItem(p_hWnd, p_iIndex, TEXT("Service can interactive with desktop"), TYPE_COL); break; } } // get current status of the services void GetCurrentStatus(HWND p_hWnd, DWORD p_dwType, int p_iIndex) { switch (p_dwType) { case SERVICE_STOPPED: InsertSubItem(p_hWnd, p_iIndex, TEXT("Not running"), STATE_COL); break; case SERVICE_START_PENDING: InsertSubItem(p_hWnd, p_iIndex, TEXT("Starting"), STATE_COL); break; case SERVICE_STOP_PENDING: InsertSubItem(p_hWnd, p_iIndex, TEXT("Stopping"), STATE_COL); break; case SERVICE_RUNNING: InsertSubItem(p_hWnd, p_iIndex, TEXT("Running"), STATE_COL); break; case SERVICE_CONTINUE_PENDING: InsertSubItem(p_hWnd, p_iIndex, TEXT("Continue is pending"), STATE_COL); break; case SERVICE_PAUSE_PENDING: InsertSubItem(p_hWnd, p_iIndex, TEXT("Pause is pending"), STATE_COL); break; case SERVICE_PAUSED: InsertSubItem(p_hWnd, p_iIndex, TEXT("Paused"), STATE_COL); break; } } // check the control code which service can accept void GetControlCode(HWND p_hWnd, DWORD p_dwType, int p_iIndex) { switch (p_dwType) { case SERVICE_ACCEPT_STOP: InsertSubItem(p_hWnd, p_iIndex, TEXT("Can Stop"), CONTROL_COL); break; case SERVICE_ACCEPT_PAUSE_CONTINUE: InsertSubItem(p_hWnd, p_iIndex, TEXT("Can Pause and continue"), CONTROL_COL); break; case SERVICE_ACCEPT_SHUTDOWN: InsertSubItem(p_hWnd, p_iIndex, TEXT("Notified when shutdown"), CONTROL_COL); break; // win 2000 and above case SERVICE_ACCEPT_PARAMCHANGE: InsertSubItem(p_hWnd, p_iIndex, TEXT("Reread startup paramater"), CONTROL_COL); break; // win 2000 and above case SERVICE_ACCEPT_NETBINDCHANGE: InsertSubItem(p_hWnd, p_iIndex, TEXT("Can change network binding"), CONTROL_COL); break; } } // dialog procedure for computer dialog BOOL CALLBACK DialogProcComputer(HWND p_hWnd, UINT p_uMsg, WPARAM p_wParam, LPARAM p_lParam) { HICON hIcon = NULL; static HWND hWndList = NULL; int iWidth = 85; int iPos = 0; switch (p_uMsg) { case WM_INITDIALOG: // Load Icon hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAIN)); SendMessage(p_hWnd, WM_SETICON, TRUE, (LPARAM)hIcon); hWndList = GetDlgItem(p_hWnd, IDC_LIST_COMPUTER); InsertColumn(hWndList, PLATEFORM_COLUMN, TEXT("Plateform"), iWidth); InsertColumn(hWndList, NAME_COLUMN, TEXT("Name"), iWidth); InsertColumn(hWndList, VERSION_COLUMN, TEXT("Version"), iWidth); InsertColumn(hWndList, TYPE_COLUMN, TEXT("Type"), iWidth); InsertColumn(hWndList, COMMENT_COLUMN, TEXT("Comment"), iWidth); // Set extended style of List control full row select SendMessage(hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, (LPARAM) LVS_EX_FULLROWSELECT); GetComputerInfo(hWndList); break; case WM_COMMAND: switch(LOWORD(p_wParam)) { case IDOK: iPos = SendMessage(hWndList, LVM_GETNEXTITEM, -1, LVIS_SELECTED); LVITEM lvItem; ZeroMemory(&lvItem, sizeof(LVITEM)); // get the text of second column lvItem.iSubItem = 1; lvItem.pszText = g_szSelectedComputer; lvItem.cchTextMax = g_iLen; SendMessage(hWndList, LVM_GETITEMTEXT, (WPARAM)iPos, (LPARAM)&lvItem); EndDialog(p_hWnd, IDOK); break; case IDCANCEL: strcpy(g_szSelectedComputer, TEXT("")); EndDialog(p_hWnd, IDCANCEL); break; } case WM_NOTIFY: switch (p_wParam) { case IDC_LIST_COMPUTER: if (((NMHDR*)p_lParam)->code == NM_DBLCLK) { SendMessage(p_hWnd, WM_COMMAND, IDOK, NULL); } break; } break; } return FALSE; } // get the information about the computer void GetComputerInfo(HWND p_hWnd) { NET_API_STATUS nStatus; LPSERVER_INFO_101 pBuff = NULL; DWORD dwEntriesRead = NULL; DWORD dwTotalEntries = NULL; DWORD dwResumeHandle = NULL; TCHAR buff[BUFF_LEN]; DWORD dwPrefMaxLen = -1; // get information nStatus = NetServerEnum(NULL, 101, (LPBYTE*)&pBuff, MAX_PREFERRED_LENGTH, &dwEntriesRead, &dwTotalEntries, SV_TYPE_SERVER, NULL, &dwResumeHandle); if ((NERR_Success == nStatus) || (ERROR_MORE_DATA == nStatus)) { // first delete all item SendMessage(p_hWnd, LVM_DELETEALLITEMS, 0, 0); for (unsigned int iIndex = 0; iIndex < dwEntriesRead; iIndex++) { if ((pBuff+iIndex)->sv101_platform_id == PLATFORM_ID_DOS) { sprintf(buff, TEXT("%s"), TEXT("DOS")); } else if ((pBuff+iIndex)->sv101_platform_id == PLATFORM_ID_OS2) { sprintf(buff, TEXT("%s"), TEXT("OS/2 or Win9x")); } else if ((pBuff+iIndex)->sv101_platform_id == PLATFORM_ID_NT) { sprintf(buff, TEXT("%s"), TEXT("Win NT/2000")); } else if ((pBuff+iIndex)->sv101_platform_id == PLATFORM_ID_VMS) { sprintf(buff, TEXT("%s"), TEXT("VMS")); } InsertItem(p_hWnd, iIndex, buff); // Name // convert UNICODE to ANSI sprintf(buff, TEXT("%S"), (pBuff+iIndex)->sv101_name); InsertSubItem(p_hWnd, iIndex, buff, NAME_COLUMN); // version sprintf(buff, TEXT("%d.%d"), (pBuff+iIndex)->sv101_version_major, (pBuff+iIndex)->sv101_version_minor); InsertSubItem(p_hWnd, iIndex, buff, VERSION_COLUMN); // type if ((pBuff+iIndex)->sv101_type & SV_TYPE_DOMAIN_CTRL) { sprintf(buff, TEXT("%s"), TEXT("PDC")); } else if ((pBuff+iIndex)->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) { sprintf(buff, TEXT("%s"), TEXT("BDC")); } else if ((pBuff+iIndex)->sv101_type & SV_TYPE_WORKSTATION){ sprintf(buff, TEXT("%s"), TEXT("WorkStation")); } InsertSubItem(p_hWnd, iIndex, buff, TYPE_COLUMN); // comment // convert UNICODE to ANSI sprintf(buff, TEXT("%S"), (pBuff+iIndex)->sv101_comment); InsertSubItem(p_hWnd, iIndex, buff, COMMENT_COLUMN); } } else { ErrorDescription(GetLastError()); } if (pBuff != NULL) { NetApiBufferFree(pBuff); } } // get the description of the error void ErrorDescription(DWORD p_dwError) { HLOCAL hLocal = NULL; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, p_dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),(LPTSTR)&hLocal, 0, NULL); MessageBox(NULL, (LPCTSTR)LocalLock(hLocal), TEXT("Error"), MB_OK | MB_ICONERROR); LocalFree(hLocal); } // call back function for service dialog BOOL CALLBACK DialogProcService(HWND p_hWnd, UINT p_uMsg, WPARAM p_wParam, LPARAM p_lParam) { HWND hWndEdit = NULL; HICON hIcon = NULL; TCHAR szBuff[BUFF_LEN]; switch(p_uMsg) { case WM_INITDIALOG: // Load Icon hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAIN)); SendMessage(p_hWnd, WM_SETICON, TRUE, (LPARAM)hIcon); // display information SetDlgItemText(p_hWnd, IDC_EDIT_PATH_NAME, g_psc->lpBinaryPathName); SetDlgItemText(p_hWnd, IDC_EDIT_DEPENDENCIES, g_psc->lpDependencies); SetDlgItemText(p_hWnd, IDC_EDIT_START_NAME, g_psc->lpServiceStartName); SetDlgItemText(p_hWnd, IDC_EDIT_DISPLAY_NAME, g_psc->lpDisplayName); SetDlgItemText(p_hWnd, IDC_EDIT_ORDER_GROUP, g_psc->lpLoadOrderGroup); SetServiceType(p_hWnd, g_psc->dwServiceType); SetStartType(p_hWnd, g_psc->dwStartType); SetErrorControl(p_hWnd, g_psc->dwErrorControl); sprintf(szBuff, TEXT("%d"), g_psc->dwTagId); SetDlgItemText(p_hWnd, IDC_EDIT_TAG_ID, szBuff); break; case WM_COMMAND: switch(LOWORD(p_wParam)) { case IDOK: EndDialog(p_hWnd, IDOK); break; } } return FALSE; } // display the service type void SetServiceType(HWND p_hWnd, DWORD p_dwType) { TCHAR szBuff[BUFF_LEN]; // service type switch(p_dwType) { case SERVICE_WIN32_OWN_PROCESS: sprintf(szBuff, TEXT("%s"), TEXT("Runs in its own process")); break; case SERVICE_WIN32_SHARE_PROCESS: sprintf(szBuff, TEXT("%s"), TEXT("Service shares a process with other services")); break; case SERVICE_KERNEL_DRIVER: sprintf(szBuff, TEXT("%s"), TEXT("Service is device driver")); break; case SERVICE_FILE_SYSTEM_DRIVER: sprintf(szBuff, TEXT("%s"), TEXT("Service is file system driver")); break; case SERVICE_INTERACTIVE_PROCESS: sprintf(szBuff, TEXT("%s"), TEXT("Service can interact with desktop")); break; } SetDlgItemText(p_hWnd, IDC_EDIT_SERVICE_TYPE, szBuff); } // dispalay the start type void SetStartType(HWND p_hWnd, DWORD p_dwType) { TCHAR szBuff[BUFF_LEN]; // service type switch(p_dwType) { case SERVICE_BOOT_START: sprintf(szBuff, TEXT("%s"), TEXT("Start by System Loader")); break; case SERVICE_SYSTEM_START: sprintf(szBuff, TEXT("%s"), TEXT("Started by IoInitSystem function")); break; case SERVICE_AUTO_START: sprintf(szBuff, TEXT("%s"), TEXT("Started by Service Control Manager")); break; case SERVICE_DEMAND_START: sprintf(szBuff, TEXT("%s"), TEXT("Start by StartService function")); break; case SERVICE_DISABLED: sprintf(szBuff, TEXT("%s"), TEXT("No Longer be started")); break; } SetDlgItemText(p_hWnd, IDC_EDIT_START_TYPE, szBuff); } // set error control void SetErrorControl(HWND p_hWnd, DWORD p_dwErrro) { TCHAR szBuff[BUFF_LEN]; // service type switch(p_dwErrro) { case SERVICE_ERROR_IGNORE: sprintf(szBuff, TEXT("%s"), TEXT("Logs error but continue operation")); break; case SERVICE_ERROR_NORMAL: sprintf(szBuff, TEXT("%s"), TEXT("Logs error and display message box")); break; case SERVICE_ERROR_SEVERE: sprintf(szBuff, TEXT("%s"), TEXT("Logs error and restarted with Last Known Good Configuration")); break; case SERVICE_ERROR_CRITICAL: sprintf(szBuff, TEXT("%s"), TEXT("Log error if possible")); break; } SetDlgItemText(p_hWnd, IDC_EDIT_ERROR_CONTROL, szBuff); }