某些时候,我们需要启动服务提升权限及自启动完成。下面就是一个服务程序的一个基本例子。
头文件
// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #pragma once #include <stdio.h> #include <tchar.h> #include <Windows.h> #include <strsafe.h> #include <Wtsapi32.h> #include <Userenv.h> #include <TlHelp32.h> #pragma comment(lib, "Wtsapi32.lib") #pragma comment(lib, "Userenv.lib") // TODO: reference additional headers your program requires here // The following are message definitions. // // Values are 32 bit values layed out as follows: // // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 // +---+-+-+-----------------------+-------------------------------+ // |Sev|C|R| Facility | Code | // +---+-+-+-----------------------+-------------------------------+ // // where // // Sev - is the severity code // // 00 - Success // 01 - Informational // 10 - Warning // 11 - Error // // C - is the Customer code flag // // R - is a reserved bit // // Facility - is the facility code // // Code - is the facility's status code // // // Define the facility codes // #define FACILITY_SYSTEM 0x0 #define FACILITY_STUBS 0x3 #define FACILITY_RUNTIME 0x2 #define FACILITY_IO_ERROR_CODE 0x4 // // Define the severity codes // #define STATUS_SEVERITY_WARNING 0x2 #define STATUS_SEVERITY_SUCCESS 0x0 #define STATUS_SEVERITY_INFORMATIONAL 0x1 #define STATUS_SEVERITY_ERROR 0x3 // // MessageId: SVC_ERROR // // MessageText: // // An error has occurred (%2). // // #define SVC_ERROR ((DWORD)0xC0020001L) #include <map> #include <string> #if !defined(_UNICODE) && !defined(UNICODE) #define TSTRING std::string #else #define TSTRING std::wstring #endif __inline static BOOL CreateAdvanceProcess( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, DWORD dwCreateFlags, LPCTSTR lpCurrentDirectory = NULL, LPSTARTUPINFO lpStartupInfo = NULL, LPPROCESS_INFORMATION lpProcessInformation = NULL, LPVOID lpEnvironment = NULL, LPSECURITY_ATTRIBUTES lpProcessAttributes = NULL, LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL, BOOL bInheritHandles = FALSE) { STARTUPINFO si = { 0 }; PROCESS_INFORMATION pi = { 0 }; LPSTARTUPINFO lpsi = &si; LPPROCESS_INFORMATION lppi = π if (lpStartupInfo) { lpsi = lpStartupInfo; } if (lpProcessInformation) { lppi = lpProcessInformation; } return CreateProcess( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreateFlags, lpEnvironment, lpCurrentDirectory, lpsi, lppi ); } __inline static BOOL CreateAdvanceProcessAsUser( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, DWORD dwCreateFlags, LPCTSTR lpCurrentDirectory = NULL, LPSTARTUPINFO lpStartupInfo = NULL, LPPROCESS_INFORMATION lpProcessInformation = NULL, LPVOID lpEnvironment = NULL, LPSECURITY_ATTRIBUTES lpProcessAttributes = NULL, LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL, BOOL bInheritHandles = FALSE, HANDLE hToken = NULL) { STARTUPINFO si = { 0 }; PROCESS_INFORMATION pi = { 0 }; LPSTARTUPINFO lpsi = &si; LPPROCESS_INFORMATION lppi = π if (lpStartupInfo) { lpsi = lpStartupInfo; } if (lpProcessInformation) { lppi = lpProcessInformation; } return CreateProcessAsUser( hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreateFlags, lpEnvironment, lpCurrentDirectory, lpsi, lppi ); } //获取进程用户函数: __inline static BOOL GetProcessUserName(TSTRING & strUser, DWORD dwID) // 进程ID { HANDLE hToken = NULL; BOOL bResult = FALSE; DWORD dwSize = 0; TCHAR szUserName[256] = { 0 }; TCHAR szDomain[256] = { 0 }; DWORD dwDomainSize = 256; DWORD dwNameSize = 256; SID_NAME_USE SNU; PTOKEN_USER pTokenUser = NULL; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwID); strUser = _T("SYSTEM"); if (hProcess == NULL) { switch (GetLastError()) { case ERROR_ACCESS_DENIED: strUser = _T("SYSTEM"); break; default: strUser = _T("SYSTEM"); break; } return bResult; } __try { if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) { bResult = FALSE; __leave; } if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { bResult = FALSE; __leave; } } pTokenUser = NULL; pTokenUser = (PTOKEN_USER)malloc(dwSize); if (pTokenUser == NULL) { bResult = FALSE; __leave; } if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) { bResult = FALSE; __leave; } if (LookupAccountSid(NULL, pTokenUser->User.Sid, szUserName, &dwNameSize, szDomain, &dwDomainSize, &SNU) != 0) { strUser = szUserName; if (pTokenUser != NULL) { free(pTokenUser); pTokenUser = NULL; } return TRUE; } } __finally { if (pTokenUser != NULL) free(pTokenUser); } return FALSE; } /////////////////////////////////////////////////////////////////////// //获取进程映像名称 //Windows 2000 = GetModuleFileName() //Windows XP x32 = GetProcessImageFileName() //Windows XP x64 = GetProcessImageFileName() //Windows Vista = QueryFullProcessImageName() //Windows 7 = QueryFullProcessImageName() //Windows 8 = QueryFullProcessImageName() //Windows 8.1 = QueryFullProcessImageName() //Windows 10 = QueryFullProcessImageName() /////////////////////////////////////////////////////////////////////// __inline static BOOL EnumModules_R3(std::map<DWORD, MODULEENTRY32> * pmemap, DWORD dwPID) { BOOL bRet = FALSE; MODULEENTRY32 me = { 0 }; HANDLE hSnapModule = INVALID_HANDLE_VALUE; // Take a snapshot of all modules in the specified process. hSnapModule = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); if (hSnapModule == INVALID_HANDLE_VALUE) { goto __LEAVE_CLEAN__; } // Set the size of the structure before using it. me.dwSize = sizeof(MODULEENTRY32); // Retrieve information about the first module, // and exit if unsuccessful if (!Module32First(hSnapModule, &me)) { goto __LEAVE_CLEAN__; } // Now walk the module list of the process, // and display information about each module do { pmemap->insert(std::map<DWORD, MODULEENTRY32>::value_type(me.th32ModuleID, me)); } while (Module32Next(hSnapModule, &me)); __LEAVE_CLEAN__: //关闭句柄 CloseHandle(hSnapModule); hSnapModule = NULL; return bRet; } __inline static BOOL EnumModules32_R3(std::map<DWORD, MODULEENTRY32> * pmemap, DWORD dwPID) { BOOL bRet = FALSE; MODULEENTRY32 me = { 0 }; HANDLE hSnapModule = INVALID_HANDLE_VALUE; // Take a snapshot of all modules in the specified process. hSnapModule = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE32, dwPID); if (hSnapModule == INVALID_HANDLE_VALUE) { goto __LEAVE_CLEAN__; } // Set the size of the structure before using it. me.dwSize = sizeof(MODULEENTRY32); // Retrieve information about the first module, // and exit if unsuccessful if (!Module32First(hSnapModule, &me)) { goto __LEAVE_CLEAN__; } // Now walk the module list of the process, // and display information about each module do { pmemap->insert(std::map<DWORD, MODULEENTRY32>::value_type(me.th32ModuleID, me)); } while (Module32Next(hSnapModule, &me)); __LEAVE_CLEAN__: //关闭句柄 CloseHandle(hSnapModule); hSnapModule = NULL; return bRet; } __inline static BOOL EnumProcess_R3(std::map<DWORD, PROCESSENTRY32> * ppemap) { BOOL bRet = FALSE; PROCESSENTRY32 pe = { 0 }; HANDLE hSnapProcess = INVALID_HANDLE_VALUE; //创建快照 hSnapProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapProcess == INVALID_HANDLE_VALUE) { goto __LEAVE_CLEAN__; } pe.dwSize = sizeof(PROCESSENTRY32); //遍历进程 bRet = Process32First(hSnapProcess, &pe); if (!bRet) { goto __LEAVE_CLEAN__; } do { ppemap->insert(std::map<DWORD, PROCESSENTRY32>::value_type(pe.th32ProcessID, pe)); } while (Process32Next(hSnapProcess, &pe)); __LEAVE_CLEAN__: //关闭句柄 CloseHandle(hSnapProcess); hSnapProcess = NULL; return bRet; } __inline static BOOL EnumThread_R3(std::map<DWORD, THREADENTRY32> * ptemap, DWORD dwPID) { BOOL bRet = FALSE; THREADENTRY32 te = { 0 }; HANDLE hSnapThread = INVALID_HANDLE_VALUE; //创建快照 hSnapThread = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPID); if (hSnapThread == INVALID_HANDLE_VALUE) { goto __LEAVE_CLEAN__; } te.dwSize = sizeof(THREADENTRY32); //遍历进程 bRet = Thread32First(hSnapThread, &te); if (!bRet) { goto __LEAVE_CLEAN__; } do { ptemap->insert(std::map<DWORD, THREADENTRY32>::value_type(te.th32ThreadID, te)); } while (Thread32Next(hSnapThread, &te)); __LEAVE_CLEAN__: //关闭句柄 CloseHandle(hSnapThread); hSnapThread = NULL; return bRet; } __inline static BOOL EnumHeapList_R3(std::map<ULONG_PTR, HEAPLIST32> * phlmap, DWORD dwPID) { BOOL bRet = FALSE; HEAPLIST32 hl = { 0 }; HANDLE hSnapHeapList = INVALID_HANDLE_VALUE; //创建快照 hSnapHeapList = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, dwPID); if (hSnapHeapList == INVALID_HANDLE_VALUE) { goto __LEAVE_CLEAN__; } hl.dwSize = sizeof(HEAPLIST32); //遍历进程 bRet = Heap32ListFirst(hSnapHeapList, &hl); if (!bRet) { goto __LEAVE_CLEAN__; } do { phlmap->insert(std::map<ULONG_PTR, HEAPLIST32>::value_type(hl.th32HeapID, hl)); } while (Heap32ListNext(hSnapHeapList, &hl)); __LEAVE_CLEAN__: //关闭句柄 CloseHandle(hSnapHeapList); hSnapHeapList = NULL; return bRet; } __inline static DWORD GetProcessIdByProcessName(const _TCHAR * ptProcessName) { DWORD dwPID = 0; _TCHAR tzProcessName[MAX_PATH] = { 0 }; std::map<DWORD, PROCESSENTRY32> pemap; std::map<DWORD, PROCESSENTRY32>::iterator itEnd; std::map<DWORD, PROCESSENTRY32>::iterator itIdx; lstrcpy(tzProcessName, ptProcessName); EnumProcess_R3(&pemap); itEnd = pemap.end(); itIdx = pemap.begin(); for (; itIdx != itEnd; itIdx++) { if (!_tcsicmp(itIdx->second.szExeFile, tzProcessName)) { dwPID = itIdx->second.th32ProcessID; break; } } return dwPID; } __inline static BOOL GetProcessFileNameByProcessId(const DWORD dwProcessId, TSTRING & cstrPath) { HANDLE hProcess = NULL; BOOL bSuccess = FALSE; // 由于进程权限问题,有些进程是无法被OpenProcess的,如果将调用进程的权限 // 提到“调试”权限,则可能可以打开更多的进程 hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId); if (hProcess) { std::map<DWORD, MODULEENTRY32> memap; EnumModules_R3(&memap, dwProcessId); } // 释放句柄 if (NULL != hProcess) { CloseHandle(hProcess); hProcess = NULL; } return bSuccess; } __inline static HANDLE InitProcessHandle(DWORD dwPID) { // Open process return ::OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, dwPID); } __inline static HANDLE InitProcessHandle(const _TCHAR * ptProcessName) { DWORD dwPID = 0; dwPID = GetProcessIdByProcessName(ptProcessName); // Open process return ::OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION, FALSE, dwPID); } __inline static void ExitProcessHandle(HANDLE * pHandle) { if (pHandle && (*pHandle)) { CloseHandle((*pHandle)); (*pHandle) = NULL; } } __inline static BOOL EnablePriv() { HANDLE hToken; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) //用上面这个办法,在执行ExitWindowsEX注销的时候可以,但是重启,关机就不行了,改成以下可以解决 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { TOKEN_PRIVILEGES tkp; LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);//修改进程权限 tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL);//通知系统修改进程权限 return((GetLastError() == ERROR_SUCCESS)); } return TRUE; }
源文件
// serviceapp.cpp : Defines the entry point for the console application. // #include "stdafx.h" #pragma comment(lib, "advapi32.lib") #define SVCNAME TEXT("SvcName") SERVICE_STATUS gSvcStatus; SERVICE_STATUS_HANDLE gSvcStatusHandle; HANDLE ghSvcStopEvent = NULL; VOID SvcInstall(void); VOID WINAPI SvcCtrlHandler(DWORD); VOID WINAPI SvcMain(DWORD, LPTSTR *); VOID ReportSvcStatus(DWORD, DWORD, DWORD); VOID SvcInit(DWORD, LPTSTR *); VOID SvcReportEvent(LPTSTR); void MyTest() { EnablePriv(); DWORD dwSessionId = WTSGetActiveConsoleSessionId(); HANDLE hToken = NULL; HANDLE hUserTokenDup = NULL; HANDLE hSystemHandle = InitProcessHandle(_T("winlogon.exe")); _TCHAR tszCmdLine[MAX_PATH] = { 0 }; FILE * pFile = _tfopen(_T("d:\\svc.log"), _T("wb")); if (sizeof(_TCHAR) > sizeof(BYTE)) { fwrite("\xFF\xFE", sizeof(_TCHAR), sizeof(BYTE), pFile); } //WinExec("c:\\windows\\notepad.exe", SW_SHOW); dwSessionId = WTSGetActiveConsoleSessionId(); if (dwSessionId) { WTSQueryUserToken(dwSessionId, &hToken); _ftprintf(pFile, _T("WTSQueryUserToken hToken=%ld(0x%08X)\r\n"), hToken, hToken); fflush(pFile); } if (hSystemHandle) { OpenProcessToken(hSystemHandle, TOKEN_ALL_ACCESS, &hToken); ExitProcessHandle(&hSystemHandle); _ftprintf(pFile, _T("OpenProcessToken hToken=%ld(0x%08X)\r\n"), hToken, hToken); fflush(pFile); } if (hToken) { SECURITY_ATTRIBUTES sa = { 0 }; sa.nLength = sizeof(sa); DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, &sa, SECURITY_IMPERSONATION_LEVEL::SecurityIdentification, TOKEN_TYPE::TokenPrimary, &hUserTokenDup); if (hUserTokenDup) { LPVOID lpEnv = NULL; CreateEnvironmentBlock(&lpEnv, hUserTokenDup, FALSE); if (lpEnv) { STARTUPINFO sia = { 0 }; GetStartupInfo(&sia); if (pFile) { _ftprintf(pFile, _T("sia.lpDesktop=%s\r\n"), sia.lpDesktop); fflush(pFile); } STARTUPINFO si = { 0 }; si.cb = sizeof(si); si.lpDesktop = _T("WinSta0\\Default"); FILE * pf = fopen("D:\\appcmd.txt", "rb"); if (pf) { _TCHAR tzAppName[MAX_PATH] = { 0 }; _TCHAR tzCmdLine[MAX_PATH] = { 0 }; _ftscanf(pf, _T("%[^|]|%[^|]"), tzAppName, tzCmdLine); if (pFile) { _ftprintf(pFile, _T("read %s=%s\r\n"), tzAppName, tzCmdLine); fflush(pFile); } CreateAdvanceProcessAsUser( tzAppName, tzCmdLine, NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, 0, &si, 0, lpEnv, &sa, &sa, FALSE, hUserTokenDup); fclose(pf); } CreateAdvanceProcessAsUser( _T("C:\\windows\\system32\\cmd.exe"), NULL, NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, 0, &si, 0, lpEnv, &sa, &sa, FALSE, hUserTokenDup); CreateAdvanceProcessAsUser( _T("C:\\windows\\notepad.exe"), NULL, NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, 0, &si, 0, lpEnv, &sa, &sa, FALSE, hUserTokenDup); DestroyEnvironmentBlock(lpEnv); } CloseHandle(hUserTokenDup); } CloseHandle(hToken); } } // // Purpose: // Entry point for the process // // Parameters: // None // // Return value: // int // int _tmain(int argc, _TCHAR* argv[]) { STARTUPINFO si = { 0 }; GetStartupInfo(&si); //PROCESS_INFORMATION pi = { 0 }; //CreateAdvanceProcess(_T("C:\\windows\\notepad.exe"), 0, CREATE_NEW_CONSOLE, 0, &si, &pi); // If command-line parameter is "install", install the service. // Otherwise, the service is probably being started by the SCM. if (lstrcmpi(argv[1], TEXT("install")) == 0) { SvcInstall(); return 0; } // TO_DO: Add any additional services for the process to this table. SERVICE_TABLE_ENTRY DispatchTable[] = { { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain }, { NULL, NULL } }; // This call returns when the service has stopped. // The process should simply terminate when the call returns. if (!StartServiceCtrlDispatcher(DispatchTable)) { DWORD dwErr = GetLastError(); SvcReportEvent(TEXT("StartServiceCtrlDispatcher")); } else { printf("执行成功\r\n"); } return 0; } // // Purpose: // Installs a service in the SCM database // // Parameters: // None // // Return value: // None // VOID SvcInstall() { SC_HANDLE schSCManager; SC_HANDLE schService; TCHAR szPath[MAX_PATH]; if (!GetModuleFileName(NULL, szPath, MAX_PATH)) { printf("Cannot install service (%d)\n", GetLastError()); return; } // Get a handle to the SCM database. schSCManager = OpenSCManager( NULL, // local computer NULL, // ServicesActive database SC_MANAGER_ALL_ACCESS); // full access rights if (NULL == schSCManager) { printf("OpenSCManager failed (%d)\n", GetLastError()); return; } // Create the service schService = CreateService( schSCManager, // SCM database SVCNAME, // name of service SVCNAME, // service name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // service type SERVICE_DEMAND_START, // start type SERVICE_ERROR_NORMAL, // error control type szPath, // path to service's binary NULL, // no load ordering group NULL, // no tag identifier NULL, // no dependencies NULL, // LocalSystem account NULL); // no password if (schService == NULL) { printf("CreateService failed (%d)\n", GetLastError()); CloseServiceHandle(schSCManager); return; } else printf("Service installed successfully\n"); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); } // // Purpose: // Entry point for the service // // Parameters: // dwArgc - Number of arguments in the lpszArgv array // lpszArgv - Array of strings. The first string is the name of // the service and subsequent strings are passed by the process // that called the StartService function to start the service. // // Return value: // None. // VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv) { // Register the handler function for the service gSvcStatusHandle = RegisterServiceCtrlHandler( SVCNAME, SvcCtrlHandler); if (!gSvcStatusHandle) { SvcReportEvent(TEXT("RegisterServiceCtrlHandler")); return; } // These SERVICE_STATUS members remain as set here gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; gSvcStatus.dwServiceSpecificExitCode = 0; // Report initial status to the SCM ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000); // Perform service-specific initialization and work. SvcInit(dwArgc, lpszArgv); } // // Purpose: // The service code // // Parameters: // dwArgc - Number of arguments in the lpszArgv array // lpszArgv - Array of strings. The first string is the name of // the service and subsequent strings are passed by the process // that called the StartService function to start the service. // // Return value: // None // VOID SvcInit(DWORD dwArgc, LPTSTR *lpszArgv) { // TO_DO: Declare and set any required variables. // Be sure to periodically call ReportSvcStatus() with // SERVICE_START_PENDING. If initialization fails, call // ReportSvcStatus with SERVICE_STOPPED. // Create an event. The control handler function, SvcCtrlHandler, // signals this event when it receives the stop control code. ghSvcStopEvent = CreateEvent( NULL, // default security attributes TRUE, // manual reset event FALSE, // not signaled NULL); // no name if (ghSvcStopEvent == NULL) { ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); return; } // Report running status when initialization is complete. ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); // TO_DO: Perform work until service stops. MyTest(); while (1) { // Check whether to stop the service. WaitForSingleObject(ghSvcStopEvent, INFINITE); ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); return; } } // // Purpose: // Sets the current service status and reports it to the SCM. // // Parameters: // dwCurrentState - The current state (see SERVICE_STATUS) // dwWin32ExitCode - The system error code // dwWaitHint - Estimated time for pending operation, // in milliseconds // // Return value: // None // VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) { static DWORD dwCheckPoint = 1; // Fill in the SERVICE_STATUS structure. gSvcStatus.dwCurrentState = dwCurrentState; gSvcStatus.dwWin32ExitCode = dwWin32ExitCode; gSvcStatus.dwWaitHint = dwWaitHint; if (dwCurrentState == SERVICE_START_PENDING) gSvcStatus.dwControlsAccepted = 0; else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED)) gSvcStatus.dwCheckPoint = 0; else gSvcStatus.dwCheckPoint = dwCheckPoint++; // Report the status of the service to the SCM. SetServiceStatus(gSvcStatusHandle, &gSvcStatus); } // // Purpose: // Called by SCM whenever a control code is sent to the service // using the ControlService function. // // Parameters: // dwCtrl - control code // // Return value: // None // VOID WINAPI SvcCtrlHandler(DWORD dwCtrl) { // Handle the requested control code. switch (dwCtrl) { case SERVICE_CONTROL_STOP: ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); // Signal the service to stop. SetEvent(ghSvcStopEvent); ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0); return; case SERVICE_CONTROL_INTERROGATE: break; default: break; } } // // Purpose: // Logs messages to the event log // // Parameters: // szFunction - name of function that failed // // Return value: // None // // Remarks: // The service must have an entry in the Application event log. // VOID SvcReportEvent(LPTSTR szFunction) { HANDLE hEventSource; LPCTSTR lpszStrings[2]; TCHAR Buffer[80]; hEventSource = RegisterEventSource(NULL, SVCNAME); if (NULL != hEventSource) { StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError()); lpszStrings[0] = SVCNAME; lpszStrings[1] = Buffer; ReportEvent(hEventSource, // event log handle EVENTLOG_ERROR_TYPE, // event type 0, // event category SVC_ERROR, // event identifier NULL, // no security identifier 2, // size of lpszStrings array 0, // no binary data lpszStrings, // array of strings NULL); // no binary data DeregisterEventSource(hEventSource); } }
使用方法:
编译之后,命令行运行 service.exe install完成服务安装。
sc start SvcName完成服务的启动。也可以通过services.msc将SvcName服务设置为自启动。
收藏的用户(0)
X
正在加载信息~
2
最新回复 (0)