|
@@ -0,0 +1,1808 @@
|
|
|
+#include "stdafx.h"
|
|
|
+#include "WinService.h"
|
|
|
+#include <psapi.h>
|
|
|
+#include <tlhelp32.h>
|
|
|
+#pragma comment ( lib, "psapi.lib" )
|
|
|
+#include <Aclapi.h>
|
|
|
+#include <strsafe.h>
|
|
|
+#include <shlwapi.h>
|
|
|
+
|
|
|
+
|
|
|
+namespace WinService
|
|
|
+{
|
|
|
+ SCVariant g_scVariant;
|
|
|
+
|
|
|
+ int InitWinSock()
|
|
|
+ {
|
|
|
+ WORD wVersionRequested;
|
|
|
+ WSADATA wsaData;
|
|
|
+ int nErrCode;
|
|
|
+
|
|
|
+ wVersionRequested = MAKEWORD(2, 2);
|
|
|
+ nErrCode = WSAStartup(wVersionRequested, &wsaData);
|
|
|
+ if (0 != nErrCode)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[7/20/2017 IT];
|
|
|
+ /* 描述:初始化服务名称和描述名称;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void InitServiceName(IN LPCTSTR lpServiceName, IN LPCTSTR lpServiceDescription)
|
|
|
+ {
|
|
|
+ if (lpServiceName == NULL || lpServiceName[0] == '\0')
|
|
|
+ {
|
|
|
+ TCHAR szModuleFileName[MAX_PATH] = { 0 };
|
|
|
+ TCHAR szExeName[MAX_PATH] = { 0 };
|
|
|
+ TCHAR szDrive[_MAX_DRIVE] = { 0 };
|
|
|
+ TCHAR szDir[_MAX_DIR] = { 0 };
|
|
|
+ TCHAR szFna[_MAX_DIR] = { 0 };
|
|
|
+ TCHAR szExt[_MAX_DIR] = { 0 };
|
|
|
+ ::GetModuleFileName(NULL, szModuleFileName, sizeof(szModuleFileName) / sizeof(TCHAR));
|
|
|
+ _tsplitpath_s(szModuleFileName, szDrive, szDir, szFna, szExt);
|
|
|
+
|
|
|
+ // 用程序名来当服务名称;
|
|
|
+ _stprintf_s(g_scVariant.scName, _T("%s"), szFna);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _stprintf_s(g_scVariant.scName, _T("%s"), lpServiceName);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (lpServiceDescription == NULL || lpServiceDescription[0] == '\0')
|
|
|
+ _stprintf_s(g_scVariant.scDescription, _T("%s"), g_scVariant.scName);
|
|
|
+ else
|
|
|
+ _stprintf_s(g_scVariant.scDescription, _T("%s"), lpServiceDescription);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[7/20/2017 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL IsInstalled()
|
|
|
+ {
|
|
|
+ BOOL bResult = FALSE;
|
|
|
+ // 打开服务控制管理器;
|
|
|
+ SC_HANDLE schSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
|
+ if (schSCM != NULL)
|
|
|
+ {// 打开服务;
|
|
|
+ SC_HANDLE schSvc = ::OpenService(schSCM, g_scVariant.scName, SERVICE_QUERY_CONFIG);
|
|
|
+ if (schSvc != NULL)
|
|
|
+ {
|
|
|
+ bResult = TRUE;
|
|
|
+ ::CloseServiceHandle(schSvc);
|
|
|
+ }
|
|
|
+ ::CloseServiceHandle(schSCM);
|
|
|
+ }
|
|
|
+
|
|
|
+ return bResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[7/20/2017 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL Install()
|
|
|
+ {
|
|
|
+ // 获取服务程序的绝对路径;
|
|
|
+ TCHAR szFilePath[MAX_PATH];
|
|
|
+ if (0 == ::GetModuleFileName(NULL, szFilePath, MAX_PATH))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("Cannot Install Service (%d)\n"), GetLastError());
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打开服务控制管理器,获取SCM数据库句柄;
|
|
|
+ SC_HANDLE schSCM = ::OpenSCManager(
|
|
|
+ NULL, // 本地计算机;
|
|
|
+ NULL, // ServicesActive database;
|
|
|
+ SC_MANAGER_ALL_ACCESS // 所有权限;
|
|
|
+ );
|
|
|
+
|
|
|
+ if (schSCM == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建服务;
|
|
|
+ SC_HANDLE schSvc = ::CreateService(
|
|
|
+ schSCM, // SCM数据库;
|
|
|
+ g_scVariant.scName, // 服务名称;
|
|
|
+ g_scVariant.scDisplayName, // 服务显示名称;
|
|
|
+ SERVICE_ALL_ACCESS, // 需要的访问权限;
|
|
|
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // 服务类型;
|
|
|
+ SERVICE_AUTO_START, //SERVICE_DEMAND_START, // 启动类型;
|
|
|
+ SERVICE_ERROR_NORMAL, // 错误控制类型;
|
|
|
+ szFilePath, // 服务程序路径;
|
|
|
+ NULL, // 无加载顺序组;
|
|
|
+ NULL, // 无标签标识;
|
|
|
+ _T(""), // 无依赖;
|
|
|
+ NULL, // 本地系统账号;
|
|
|
+ NULL // 无密码(no password);
|
|
|
+ );
|
|
|
+
|
|
|
+ if (schSvc == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("CreateService failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schSvc);
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置服务的描述;
|
|
|
+ SERVICE_DESCRIPTION ServiceDesc;
|
|
|
+ ServiceDesc.lpDescription = g_scVariant.scDescription;
|
|
|
+ ::ChangeServiceConfig2(schSvc, SERVICE_CONFIG_DESCRIPTION, &ServiceDesc);
|
|
|
+
|
|
|
+ // 释放资源;
|
|
|
+ ::CloseServiceHandle(schSvc);
|
|
|
+ ::CloseServiceHandle(schSCM);
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[7/20/2017 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL Uninstall()
|
|
|
+ {
|
|
|
+ if (!IsInstalled()) return TRUE;
|
|
|
+
|
|
|
+ SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
|
+
|
|
|
+ if (hSCM == NULL) return FALSE;
|
|
|
+
|
|
|
+ SC_HANDLE hService = ::OpenService(hSCM, g_scVariant.scName, SERVICE_STOP | DELETE);
|
|
|
+
|
|
|
+ if (hService == NULL)
|
|
|
+ {
|
|
|
+ ::CloseServiceHandle(hSCM);
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ SERVICE_STATUS scStatus;
|
|
|
+ ::ControlService(hService, SERVICE_CONTROL_STOP, &scStatus);
|
|
|
+
|
|
|
+ // 删除服务;
|
|
|
+ BOOL bDelete = ::DeleteService(hService);
|
|
|
+ ::CloseServiceHandle(hService);
|
|
|
+ ::CloseServiceHandle(hSCM);
|
|
|
+
|
|
|
+ if (bDelete)
|
|
|
+ {
|
|
|
+ //LOG4C((LOG_NOTICE,"服务成功卸载"));
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ //LOG4C((LOG_NOTICE,"服务卸载失败"));
|
|
|
+ LogEvent(_T("Service could not be deleted"));
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:ServiceMain[4/23/2016 home];
|
|
|
+ /* 描述:服务入口函数;
|
|
|
+ /* 参数:;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void WINAPI ServiceMain()
|
|
|
+ {
|
|
|
+ // 注册服务的控制函数;
|
|
|
+ g_scVariant.scStatusHandle = RegisterServiceCtrlHandler(g_scVariant.scName, SvcCtrlHandler);
|
|
|
+ if (g_scVariant.scStatusHandle == NULL)
|
|
|
+ {
|
|
|
+ SvcReportEvent(_T("Handler not installed"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 在这里设置服务状态;
|
|
|
+ g_scVariant.scStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
|
+ g_scVariant.scStatus.dwServiceSpecificExitCode = 0;
|
|
|
+
|
|
|
+ // 注册成功后向SCM报告服务状态信息,因为服务还没初始化完成;
|
|
|
+ // 所以当前服务状态为SERVICE_START_PENDING ;
|
|
|
+ ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 3000); // 处理第一个事件大约需要3秒钟;
|
|
|
+
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ // 开始初始化服务;
|
|
|
+ g_scVariant.hscEvent = ::CreateEvent(NULL, TRUE, FALSE, _T("CtrlService::g_hCtrlSvc"));
|
|
|
+ if (g_scVariant.hscEvent == NULL)
|
|
|
+ {
|
|
|
+ // 向SCM报告服务已停止;
|
|
|
+ ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 向SCM报告服务正在运行;
|
|
|
+ ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
|
|
|
+
|
|
|
+ // 开启工作者;
|
|
|
+ if (g_scVariant.lpStartWorkCallBack)
|
|
|
+ g_scVariant.lpStartWorkCallBack();
|
|
|
+
|
|
|
+ // 线程中的处理函数运行结束后返回ServiceMain(),
|
|
|
+ // ServiceMain()调用WaitForSingleObject,
|
|
|
+ // 因为服务被停止之前ServiceMain()不会结束
|
|
|
+ WaitForSingleObject(g_scVariant.hscEvent, INFINITE); // INFINITE表示无限等待,等待SCM的信号;
|
|
|
+ CloseHandle(g_scVariant.hscEvent);
|
|
|
+
|
|
|
+ // 结束工作者;
|
|
|
+ if (g_scVariant.lpEndofWorkCallBack)
|
|
|
+ g_scVariant.lpEndofWorkCallBack();
|
|
|
+
|
|
|
+ SvcReportEvent(_T("Service stopped"));
|
|
|
+
|
|
|
+ // 向SCM报告服务已停止工作;
|
|
|
+ ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:SvcCtrlHandler[4/23/2016 home];
|
|
|
+ /* 描述:每当有控制码发送给服务时被SCM调用;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] dwControlCode:发送给服务的控制码;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void WINAPI SvcCtrlHandler(IN DWORD dwControlCode)
|
|
|
+ {
|
|
|
+ BOOL bsucc = FALSE;
|
|
|
+ switch (dwControlCode)
|
|
|
+ {
|
|
|
+ case SERVICE_CONTROL_SHUTDOWN: // 关掉服务;
|
|
|
+ case SERVICE_CONTROL_STOP: // 停止服务;
|
|
|
+ bsucc = ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 0);
|
|
|
+ if (bsucc)
|
|
|
+ {
|
|
|
+ if (g_scVariant.lpEndofWorkCallBack)
|
|
|
+ g_scVariant.lpEndofWorkCallBack();
|
|
|
+ KillService();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case SERVICE_CONTROL_PAUSE:
|
|
|
+ // 暂停服务;
|
|
|
+ break;
|
|
|
+ case SERVICE_CONTROL_CONTINUE:
|
|
|
+ // 恢复被暂停的服务;
|
|
|
+ break;
|
|
|
+ case SERVICE_CONTROL_INTERROGATE:
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ SvcReportEvent(_T("Bad service request"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:ReportSvcStatus[4/22/2016 home];
|
|
|
+ /* 描述:设置当前服务状态,并将其报告给SCM;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] dwCurrentState:服务当前状态(详情见 SERVICE_STATUS);
|
|
|
+ /* [IN] dwWin32ExitCode:系统返回服务的错误码;
|
|
|
+ /* [IN] dwServiceSpecificExitCode:用户自定义的服务错误码;
|
|
|
+ /* [OUT] dwCheckPoint:;
|
|
|
+ /* [IN/OUT] dwWaitHint:挂起操作的估计用时;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
|
|
|
+ {
|
|
|
+ BOOL bSuccess;
|
|
|
+ // 填充SERVICE_STATUS结构体,以便用于设置服务状态;
|
|
|
+ g_scVariant.scStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; // 表示我们的服务是独占一个进程的服务 ;
|
|
|
+ g_scVariant.scStatus.dwCurrentState = dwCurrentState; // 当前服务状态;
|
|
|
+ g_scVariant.scStatus.dwWaitHint = dwWaitHint;
|
|
|
+
|
|
|
+ if (dwCurrentState == SERVICE_START_PENDING)
|
|
|
+ {
|
|
|
+ g_scVariant.scStatus.dwControlsAccepted = 0; // 不接受任何控制通知;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 通知 SCM 服务接受哪个控制通知:这里允许停止、关机、暂停继续;
|
|
|
+ g_scVariant.scStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; //|SERVICE_ACCEPT_PAUSE_CONTINUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED))
|
|
|
+ g_scVariant.scStatus.dwCheckPoint = 0;
|
|
|
+ else
|
|
|
+ g_scVariant.scStatus.dwCheckPoint = dwCheckPoint++;
|
|
|
+
|
|
|
+ // dwServiceSpecificExitCode在你终止服务并报告退出细节时很有用。
|
|
|
+ // 初始化服务时并不退出,因此值为 0;
|
|
|
+ if (dwServiceSpecificExitCode == 0)
|
|
|
+ {
|
|
|
+ g_scVariant.scStatus.dwWin32ExitCode = dwWin32ExitCode;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ g_scVariant.scStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; //用户自定义错误代码;
|
|
|
+ }
|
|
|
+ g_scVariant.scStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
|
|
|
+
|
|
|
+ //设置好nServiceStatus后,向SCM报告服务状态,非0表示成功,0表示失败;
|
|
|
+ bSuccess = SetServiceStatus(g_scVariant.scStatusHandle, &g_scVariant.scStatus);
|
|
|
+ if (!bSuccess)
|
|
|
+ {
|
|
|
+ SvcReportEvent(_T("Set Service Status failed (%d) "), GetLastError());
|
|
|
+ KillService();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 结束服务;
|
|
|
+ void KillService()
|
|
|
+ {
|
|
|
+ if (g_scVariant.hscEvent)
|
|
|
+ SetEvent(g_scVariant.hscEvent); //如果操作成功,则返回非零值,否则为0。设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用ResetEvent。这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记。如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。
|
|
|
+ //ReportStatusToSCMgr(SERVICE_STOPPED,NO_ERROR,0,0,0);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[4/23/2016 home];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void SvcReportEvent(IN LPCTSTR pFormat, ...)
|
|
|
+ {
|
|
|
+ TCHAR szReport[MAX_PATH] = { 0 };
|
|
|
+ HANDLE hEventSource;
|
|
|
+ LPCTSTR lpszStrings[2];
|
|
|
+ va_list pArg = NULL;
|
|
|
+
|
|
|
+ va_start(pArg, pFormat);
|
|
|
+ StringCchVPrintf(szReport, MAX_PATH, pFormat, pArg);
|
|
|
+ va_end(pArg);
|
|
|
+
|
|
|
+ hEventSource = RegisterEventSource(NULL, g_scVariant.scName);
|
|
|
+ if (hEventSource != NULL)
|
|
|
+ {
|
|
|
+ lpszStrings[0] = g_scVariant.scName;
|
|
|
+ lpszStrings[1] = szReport;
|
|
|
+
|
|
|
+ ReportEvent(
|
|
|
+ hEventSource, // 事件日志句柄;
|
|
|
+ EVENTLOG_INFORMATION_TYPE, // 事件类型;
|
|
|
+ 0, // 事件类别;
|
|
|
+ 0/*SVC_ERROR*/, // 事件标识;
|
|
|
+ NULL, // 无安全标识;
|
|
|
+ 2, // lpszStrings数组大小;
|
|
|
+ 0, // 无二进制数据;
|
|
|
+ lpszStrings, // 字符串数组;
|
|
|
+ NULL // 无二进制数据;
|
|
|
+ );
|
|
|
+
|
|
|
+ DeregisterEventSource(hEventSource);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:StartSvc[4/23/2016 home];
|
|
|
+ /* 描述:启动服务;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] lpSvcName:要打开的服务名称;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void StartSvc(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ TCHAR szSvcName[MAX_PATH] = { 0 };
|
|
|
+ if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ _stprintf_s(szSvcName, _T("%s"), g_scVariant.scName);
|
|
|
+ else
|
|
|
+ _stprintf_s(szSvcName, _T("%s"), lpSvcName);
|
|
|
+
|
|
|
+ SC_HANDLE schSCM;
|
|
|
+ SC_HANDLE schService;
|
|
|
+ SERVICE_STATUS_PROCESS ssStatus;
|
|
|
+ DWORD dwOldCheckPoint;
|
|
|
+ DWORD dwStartTickCount;
|
|
|
+ DWORD dwWaitTime;
|
|
|
+ DWORD dwBytesNeeded;
|
|
|
+
|
|
|
+ // 打开服务管理器;
|
|
|
+ schSCM = OpenSCManager(
|
|
|
+ NULL, // NULL表示要地计算机;
|
|
|
+ NULL, // NULl表示服务活动数据库;
|
|
|
+ SC_MANAGER_ALL_ACCESS); // 全部管理权限;
|
|
|
+
|
|
|
+ if (NULL == schSCM)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取服务句柄;
|
|
|
+ schService = OpenService(
|
|
|
+ schSCM, // SCM数据库;
|
|
|
+ szSvcName, // 服务名称;
|
|
|
+ SERVICE_ALL_ACCESS); // 全部权限;
|
|
|
+
|
|
|
+ if (schService == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 启动服务前,检查服务状态以防服务不是停止的状态;
|
|
|
+ if (!QueryServiceStatusEx(
|
|
|
+ schService, // 服务句柄;
|
|
|
+ SC_STATUS_PROCESS_INFO, // 要查询的服务状态类型;
|
|
|
+ (LPBYTE)&ssStatus, // 服务状态对象地址;
|
|
|
+ sizeof(SERVICE_STATUS_PROCESS), // 结构体大小;
|
|
|
+ &dwBytesNeeded)) // size needed if buffer is too small
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schService);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if the service is already running. It would be possible
|
|
|
+ // to stop the service here, but for simplicity this example just returns.
|
|
|
+ // 如果服务已经在运行,检查;可以在这里停止服务,简单起见,这里只返回;
|
|
|
+ if (ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("Cannot start the service because it is already running\n"));
|
|
|
+ CloseServiceHandle(schService);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Save the tick count and initial checkpoint.
|
|
|
+ // 保持计数值并初始化检查点;
|
|
|
+ dwStartTickCount = GetTickCount();
|
|
|
+ dwOldCheckPoint = ssStatus.dwCheckPoint;
|
|
|
+
|
|
|
+ // Wait for the service to stop before attempting to start it.
|
|
|
+ // 在尝试启动服务前,等待服务停止;
|
|
|
+ while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
|
|
|
+ {
|
|
|
+ // Do not wait longer than the wait hint. A good interval is
|
|
|
+ // one-tenth of the wait hint but not less than 1 second
|
|
|
+ // and not more than 10 seconds.
|
|
|
+
|
|
|
+ dwWaitTime = ssStatus.dwWaitHint / 10;
|
|
|
+
|
|
|
+ if (dwWaitTime < 1000)
|
|
|
+ dwWaitTime = 1000;
|
|
|
+ else if (dwWaitTime > 10000)
|
|
|
+ dwWaitTime = 10000;
|
|
|
+
|
|
|
+ Sleep(dwWaitTime);
|
|
|
+
|
|
|
+ // Check the status until the service is no longer stop pending.
|
|
|
+ // 检测状态直到服务不再停止等待;
|
|
|
+ if (!QueryServiceStatusEx(
|
|
|
+ schService, // handle to service
|
|
|
+ SC_STATUS_PROCESS_INFO, // information level
|
|
|
+ (LPBYTE)&ssStatus, // address of structure
|
|
|
+ sizeof(SERVICE_STATUS_PROCESS), // size of structure
|
|
|
+ &dwBytesNeeded)) // size needed if buffer is too small
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schService);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ssStatus.dwCheckPoint > dwOldCheckPoint)
|
|
|
+ {
|
|
|
+ // Continue to wait and check.
|
|
|
+ // 继续等待并检测;
|
|
|
+ dwStartTickCount = GetTickCount();
|
|
|
+ dwOldCheckPoint = ssStatus.dwCheckPoint;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (GetTickCount() - dwStartTickCount > ssStatus.dwWaitHint)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("Timeout waiting for service to stop\n"));
|
|
|
+ CloseServiceHandle(schService);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Attempt to start the service.
|
|
|
+ // 尝试启动服务;
|
|
|
+ if (!StartService(
|
|
|
+ schService, // handle to service
|
|
|
+ 0, // number of arguments
|
|
|
+ NULL)) // no arguments
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("StartService failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schService);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else printf("Service start pending...\n");
|
|
|
+
|
|
|
+ // Check the status until the service is no longer start pending.
|
|
|
+ // 检测服务状态直到服务不再启动挂起操作;
|
|
|
+ if (!QueryServiceStatusEx(
|
|
|
+ schService, // handle to service
|
|
|
+ SC_STATUS_PROCESS_INFO, // info level
|
|
|
+ (LPBYTE)&ssStatus, // address of structure
|
|
|
+ sizeof(SERVICE_STATUS_PROCESS), // size of structure
|
|
|
+ &dwBytesNeeded)) // if buffer too small
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schService);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Save the tick count and initial checkpoint.
|
|
|
+ dwStartTickCount = GetTickCount();
|
|
|
+ dwOldCheckPoint = ssStatus.dwCheckPoint;
|
|
|
+
|
|
|
+ while (ssStatus.dwCurrentState == SERVICE_START_PENDING)
|
|
|
+ {
|
|
|
+ // Do not wait longer than the wait hint. A good interval is
|
|
|
+ // one-tenth the wait hint, but no less than 1 second and no
|
|
|
+ // more than 10 seconds.
|
|
|
+
|
|
|
+ dwWaitTime = ssStatus.dwWaitHint / 10;
|
|
|
+
|
|
|
+ if (dwWaitTime < 1000)
|
|
|
+ dwWaitTime = 1000;
|
|
|
+ else if (dwWaitTime > 10000)
|
|
|
+ dwWaitTime = 10000;
|
|
|
+
|
|
|
+ Sleep(dwWaitTime);
|
|
|
+
|
|
|
+ // Check the status again.
|
|
|
+ if (!QueryServiceStatusEx(
|
|
|
+ schService, // handle to service
|
|
|
+ SC_STATUS_PROCESS_INFO, // info level
|
|
|
+ (LPBYTE)&ssStatus, // address of structure
|
|
|
+ sizeof(SERVICE_STATUS_PROCESS), // size of structure
|
|
|
+ &dwBytesNeeded)) // if buffer too small
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ssStatus.dwCheckPoint > dwOldCheckPoint)
|
|
|
+ {
|
|
|
+ // Continue to wait and check.
|
|
|
+ dwStartTickCount = GetTickCount();
|
|
|
+ dwOldCheckPoint = ssStatus.dwCheckPoint;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (GetTickCount() - dwStartTickCount > ssStatus.dwWaitHint)
|
|
|
+ {
|
|
|
+ // No progress made within the wait hint.
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Determine whether the service is running.
|
|
|
+ if (ssStatus.dwCurrentState == SERVICE_RUNNING)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("Service started successfully.\n"));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("Service not started. \n"));
|
|
|
+ _tprintf_s(_T(" Current State: %d\n"), ssStatus.dwCurrentState);
|
|
|
+ _tprintf_s(_T(" Exit Code: %d\n"), ssStatus.dwWin32ExitCode);
|
|
|
+ _tprintf_s(_T(" Check Point: %d\n"), ssStatus.dwCheckPoint);
|
|
|
+ _tprintf_s(_T(" Wait Hint: %d\n"), ssStatus.dwWaitHint);
|
|
|
+ }
|
|
|
+
|
|
|
+ CloseServiceHandle(schService);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:UpdateSvcDacl[4/23/2016 home];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void UpdateSvcDacl(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ return;
|
|
|
+
|
|
|
+ EXPLICIT_ACCESS ea;
|
|
|
+ SECURITY_DESCRIPTOR sd;
|
|
|
+ PSECURITY_DESCRIPTOR psd = NULL;
|
|
|
+ PACL pacl = NULL;
|
|
|
+ PACL pNewAcl = NULL;
|
|
|
+ BOOL bDaclPresent = FALSE;
|
|
|
+ BOOL bDaclDefaulted = FALSE;
|
|
|
+ DWORD dwError = 0;
|
|
|
+ DWORD dwSize = 0;
|
|
|
+ DWORD dwBytesNeeded = 0;
|
|
|
+
|
|
|
+ SC_HANDLE schSCManager;
|
|
|
+ SC_HANDLE schService;
|
|
|
+
|
|
|
+ // 获取SCM数据库的句柄值;
|
|
|
+ schSCManager = OpenSCManager(
|
|
|
+ NULL, // local computer
|
|
|
+ NULL, // ServicesActive database
|
|
|
+ SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
+
|
|
|
+ if (NULL == schSCManager)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get a handle to the service
|
|
|
+
|
|
|
+ schService = OpenService(
|
|
|
+ schSCManager, // SCManager database
|
|
|
+ lpSvcName, // name of service
|
|
|
+ READ_CONTROL | WRITE_DAC); // access
|
|
|
+
|
|
|
+ if (schService == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schSCManager);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the current security descriptor.
|
|
|
+ // 获取当前服务的安全描述符;
|
|
|
+ if (!QueryServiceObjectSecurity(schService,
|
|
|
+ DACL_SECURITY_INFORMATION,
|
|
|
+ &psd, // using NULL does not work on all versions
|
|
|
+ 0,
|
|
|
+ &dwBytesNeeded))
|
|
|
+ {
|
|
|
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
|
+ {
|
|
|
+ dwSize = dwBytesNeeded;
|
|
|
+ psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
|
|
|
+ if (psd == NULL)
|
|
|
+ {
|
|
|
+ // Note: HeapAlloc does not support GetLastError.
|
|
|
+ _tprintf_s(_T("HeapAlloc failed\n"));
|
|
|
+ goto dacl_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!QueryServiceObjectSecurity(schService,
|
|
|
+ DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QueryServiceObjectSecurity failed (%d)\n"), GetLastError());
|
|
|
+ goto dacl_cleanup;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QueryServiceObjectSecurity failed (%d)\n"), GetLastError());
|
|
|
+ goto dacl_cleanup;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the DACL.
|
|
|
+
|
|
|
+ if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
|
|
|
+ &bDaclDefaulted))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("GetSecurityDescriptorDacl failed(%d)\n"), GetLastError());
|
|
|
+ goto dacl_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Build the ACE.
|
|
|
+
|
|
|
+ BuildExplicitAccessWithName(&ea, TEXT("GUEST"),
|
|
|
+ SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE,
|
|
|
+ SET_ACCESS, NO_INHERITANCE);
|
|
|
+
|
|
|
+ dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);
|
|
|
+ if (dwError != ERROR_SUCCESS)
|
|
|
+ {
|
|
|
+ printf("SetEntriesInAcl failed(%d)\n", dwError);
|
|
|
+ goto dacl_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Initialize a new security descriptor.
|
|
|
+
|
|
|
+ if (!InitializeSecurityDescriptor(&sd,
|
|
|
+ SECURITY_DESCRIPTOR_REVISION))
|
|
|
+ {
|
|
|
+ printf("InitializeSecurityDescriptor failed(%d)\n", GetLastError());
|
|
|
+ goto dacl_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set the new DACL in the security descriptor.
|
|
|
+
|
|
|
+ if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))
|
|
|
+ {
|
|
|
+ printf("SetSecurityDescriptorDacl failed(%d)\n", GetLastError());
|
|
|
+ goto dacl_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set the new DACL for the service object.
|
|
|
+
|
|
|
+ if (!SetServiceObjectSecurity(schService,
|
|
|
+ DACL_SECURITY_INFORMATION, &sd))
|
|
|
+ {
|
|
|
+ printf("SetServiceObjectSecurity failed(%d)\n", GetLastError());
|
|
|
+ goto dacl_cleanup;
|
|
|
+ }
|
|
|
+ else printf("Service DACL updated successfully\n");
|
|
|
+
|
|
|
+ dacl_cleanup:
|
|
|
+ CloseServiceHandle(schSCManager);
|
|
|
+ CloseServiceHandle(schService);
|
|
|
+
|
|
|
+ if (NULL != pNewAcl)
|
|
|
+ LocalFree((HLOCAL)pNewAcl);
|
|
|
+ if (NULL != psd)
|
|
|
+ HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ void StopSvc(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ TCHAR szSvcName[MAX_PATH] = { 0 };
|
|
|
+ if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ _stprintf_s(szSvcName, _T("%s"), g_scVariant.scName);
|
|
|
+ else
|
|
|
+ _stprintf_s(szSvcName, _T("%s"), lpSvcName);
|
|
|
+
|
|
|
+ SERVICE_STATUS_PROCESS ssp;
|
|
|
+ DWORD dwStartTime = GetTickCount();
|
|
|
+ DWORD dwBytesNeeded;
|
|
|
+ DWORD dwTimeout = 30000; // 30-second time-out
|
|
|
+ DWORD dwWaitTime;
|
|
|
+
|
|
|
+ SC_HANDLE schSCManager;
|
|
|
+ SC_HANDLE schService;
|
|
|
+ // 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get a handle to the service.
|
|
|
+
|
|
|
+ schService = OpenService(
|
|
|
+ schSCManager, // SCM database
|
|
|
+ szSvcName, // name of service
|
|
|
+ SERVICE_STOP |
|
|
|
+ SERVICE_QUERY_STATUS |
|
|
|
+ SERVICE_ENUMERATE_DEPENDENTS);
|
|
|
+
|
|
|
+ if (schService == NULL)
|
|
|
+ {
|
|
|
+ printf("OpenService failed (%d)\n", GetLastError());
|
|
|
+ CloseServiceHandle(schSCManager);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Make sure the service is not already stopped.
|
|
|
+
|
|
|
+ if (!QueryServiceStatusEx(
|
|
|
+ schService,
|
|
|
+ SC_STATUS_PROCESS_INFO,
|
|
|
+ (LPBYTE)&ssp,
|
|
|
+ sizeof(SERVICE_STATUS_PROCESS),
|
|
|
+ &dwBytesNeeded))
|
|
|
+ {
|
|
|
+ printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
|
|
|
+ goto stop_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ssp.dwCurrentState == SERVICE_STOPPED)
|
|
|
+ {
|
|
|
+ printf("Service is already stopped.\n");
|
|
|
+ goto stop_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ // If a stop is pending, wait for it.
|
|
|
+
|
|
|
+ while (ssp.dwCurrentState == SERVICE_STOP_PENDING)
|
|
|
+ {
|
|
|
+ printf("Service stop pending...\n");
|
|
|
+
|
|
|
+ // Do not wait longer than the wait hint. A good interval is
|
|
|
+ // one-tenth of the wait hint but not less than 1 second
|
|
|
+ // and not more than 10 seconds.
|
|
|
+
|
|
|
+ dwWaitTime = ssp.dwWaitHint / 10;
|
|
|
+
|
|
|
+ if (dwWaitTime < 1000)
|
|
|
+ dwWaitTime = 1000;
|
|
|
+ else if (dwWaitTime > 10000)
|
|
|
+ dwWaitTime = 10000;
|
|
|
+
|
|
|
+ Sleep(dwWaitTime);
|
|
|
+
|
|
|
+ if (!QueryServiceStatusEx(
|
|
|
+ schService,
|
|
|
+ SC_STATUS_PROCESS_INFO,
|
|
|
+ (LPBYTE)&ssp,
|
|
|
+ sizeof(SERVICE_STATUS_PROCESS),
|
|
|
+ &dwBytesNeeded))
|
|
|
+ {
|
|
|
+ printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
|
|
|
+ goto stop_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ssp.dwCurrentState == SERVICE_STOPPED)
|
|
|
+ {
|
|
|
+ printf("Service stopped successfully.\n");
|
|
|
+ goto stop_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (GetTickCount() - dwStartTime > dwTimeout)
|
|
|
+ {
|
|
|
+ printf("Service stop timed out.\n");
|
|
|
+ goto stop_cleanup;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // If the service is running, dependencies must be stopped first.
|
|
|
+
|
|
|
+ StopDependentServices();
|
|
|
+
|
|
|
+ // Send a stop code to the service.
|
|
|
+
|
|
|
+ if (!ControlService(
|
|
|
+ schService,
|
|
|
+ SERVICE_CONTROL_STOP,
|
|
|
+ (LPSERVICE_STATUS)&ssp))
|
|
|
+ {
|
|
|
+ printf("ControlService failed (%d)\n", GetLastError());
|
|
|
+ goto stop_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Wait for the service to stop.
|
|
|
+
|
|
|
+ while (ssp.dwCurrentState != SERVICE_STOPPED)
|
|
|
+ {
|
|
|
+ Sleep(ssp.dwWaitHint);
|
|
|
+ if (!QueryServiceStatusEx(
|
|
|
+ schService,
|
|
|
+ SC_STATUS_PROCESS_INFO,
|
|
|
+ (LPBYTE)&ssp,
|
|
|
+ sizeof(SERVICE_STATUS_PROCESS),
|
|
|
+ &dwBytesNeeded))
|
|
|
+ {
|
|
|
+ printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
|
|
|
+ goto stop_cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ssp.dwCurrentState == SERVICE_STOPPED)
|
|
|
+ break;
|
|
|
+
|
|
|
+ if (GetTickCount() - dwStartTime > dwTimeout)
|
|
|
+ {
|
|
|
+ printf("Wait timed out\n");
|
|
|
+ goto stop_cleanup;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ printf("Service stopped successfully\n");
|
|
|
+
|
|
|
+ stop_cleanup:
|
|
|
+ CloseServiceHandle(schService);
|
|
|
+ CloseServiceHandle(schSCManager);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL StopDependentServices()
|
|
|
+ {
|
|
|
+ DWORD i;
|
|
|
+ DWORD dwBytesNeeded;
|
|
|
+ DWORD dwCount;
|
|
|
+
|
|
|
+ LPENUM_SERVICE_STATUS lpDependencies = NULL;
|
|
|
+ ENUM_SERVICE_STATUS ess;
|
|
|
+ SC_HANDLE hDepService;
|
|
|
+ SERVICE_STATUS_PROCESS ssp;
|
|
|
+
|
|
|
+ DWORD dwStartTime = GetTickCount();
|
|
|
+ DWORD dwTimeout = 30000; // 30-second time-out
|
|
|
+
|
|
|
+ SC_HANDLE schSCManager = NULL;
|
|
|
+ SC_HANDLE schService = NULL;
|
|
|
+
|
|
|
+ // Pass a zero-length buffer to get the required buffer size.
|
|
|
+ if (EnumDependentServices(schService, SERVICE_ACTIVE,
|
|
|
+ lpDependencies, 0, &dwBytesNeeded, &dwCount))
|
|
|
+ {
|
|
|
+ // If the Enum call succeeds, then there are no dependent
|
|
|
+ // services, so do nothing.
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (GetLastError() != ERROR_MORE_DATA)
|
|
|
+ return FALSE; // Unexpected error
|
|
|
+
|
|
|
+ // Allocate a buffer for the dependencies.
|
|
|
+ lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(
|
|
|
+ GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded);
|
|
|
+
|
|
|
+ if (!lpDependencies)
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ __try {
|
|
|
+ // Enumerate the dependencies.
|
|
|
+ if (!EnumDependentServices(schService, SERVICE_ACTIVE,
|
|
|
+ lpDependencies, dwBytesNeeded, &dwBytesNeeded,
|
|
|
+ &dwCount))
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ for (i = 0; i < dwCount; i++)
|
|
|
+ {
|
|
|
+ ess = *(lpDependencies + i);
|
|
|
+ // Open the service.
|
|
|
+ hDepService = OpenService(schSCManager,
|
|
|
+ ess.lpServiceName,
|
|
|
+ SERVICE_STOP | SERVICE_QUERY_STATUS);
|
|
|
+
|
|
|
+ if (!hDepService)
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ __try {
|
|
|
+ // Send a stop code.
|
|
|
+ if (!ControlService(hDepService,
|
|
|
+ SERVICE_CONTROL_STOP,
|
|
|
+ (LPSERVICE_STATUS)&ssp))
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ // Wait for the service to stop.
|
|
|
+ while (ssp.dwCurrentState != SERVICE_STOPPED)
|
|
|
+ {
|
|
|
+ Sleep(ssp.dwWaitHint);
|
|
|
+ if (!QueryServiceStatusEx(
|
|
|
+ hDepService,
|
|
|
+ SC_STATUS_PROCESS_INFO,
|
|
|
+ (LPBYTE)&ssp,
|
|
|
+ sizeof(SERVICE_STATUS_PROCESS),
|
|
|
+ &dwBytesNeeded))
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ if (ssp.dwCurrentState == SERVICE_STOPPED)
|
|
|
+ break;
|
|
|
+
|
|
|
+ if (GetTickCount() - dwStartTime > dwTimeout)
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ __finally
|
|
|
+ {
|
|
|
+ // Always release the service handle.
|
|
|
+ CloseServiceHandle(hDepService);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ __finally
|
|
|
+ {
|
|
|
+ // Always free the enumeration buffer.
|
|
|
+ HeapFree(GetProcessHeap(), 0, lpDependencies);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return TRUE;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[4/23/2016 home];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void DoQuerySvc(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("要查询的服务名称无效\n"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ SC_HANDLE hSCM;
|
|
|
+ SC_HANDLE hSvc;
|
|
|
+ LPQUERY_SERVICE_CONFIG lpsc;
|
|
|
+ LPSERVICE_DESCRIPTION lpsd;
|
|
|
+ DWORD dwBytesNeeded, cbBfuSize, dwError;
|
|
|
+
|
|
|
+ // 获取SCM句柄;
|
|
|
+ hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
|
+ if (hSCM == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取服务句柄;
|
|
|
+ hSvc = OpenService(
|
|
|
+ hSCM,
|
|
|
+ lpSvcName,
|
|
|
+ SERVICE_QUERY_CONFIG // 需要查询设置的权限;
|
|
|
+ );
|
|
|
+ if (hSvc == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(hSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取服务设置信息;
|
|
|
+ if (!QueryServiceConfig(hSvc, NULL, 0, &dwBytesNeeded))
|
|
|
+ {
|
|
|
+ dwError = GetLastError();
|
|
|
+ if (ERROR_INSUFFICIENT_BUFFER == dwError)
|
|
|
+ {
|
|
|
+ cbBfuSize = dwBytesNeeded;
|
|
|
+ lpsc = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_FIXED, cbBfuSize);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QueryServiceConfig failed (%d)\n"), dwError);
|
|
|
+ goto cleanup;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!QueryServiceConfig(hSvc, lpsc, cbBfuSize, &dwBytesNeeded))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QuerySericeConfig failed (%d)\n"), GetLastError());
|
|
|
+ goto cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &dwBytesNeeded))
|
|
|
+ {
|
|
|
+ dwError = GetLastError();
|
|
|
+ if (ERROR_INSUFFICIENT_BUFFER == dwError)
|
|
|
+ {
|
|
|
+ cbBfuSize = dwBytesNeeded;
|
|
|
+ lpsd = (LPSERVICE_DESCRIPTION)LocalAlloc(LMEM_FIXED, cbBfuSize);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QuerySericeConfig2 failed (%d)\n"), GetLastError());
|
|
|
+ goto cleanup;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)lpsd, cbBfuSize, &dwBytesNeeded))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("QuerySericeConfig2 failed (%d)\n"), GetLastError());
|
|
|
+ goto cleanup;
|
|
|
+ }
|
|
|
+
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ // 查询成功,组织要返回的东西;
|
|
|
+ _tprintf(TEXT("%s configuration: \n"), g_scVariant.scName);
|
|
|
+ _tprintf(TEXT(" Type: 0x%x\n"), lpsc->dwServiceType);
|
|
|
+ _tprintf(TEXT(" Start Type: 0x%x\n"), lpsc->dwStartType);
|
|
|
+ _tprintf(TEXT(" Error Control: 0x%x\n"), lpsc->dwErrorControl);
|
|
|
+ _tprintf(TEXT(" Binary path: %s\n"), lpsc->lpBinaryPathName);
|
|
|
+ _tprintf(TEXT(" Account: %s\n"), lpsc->lpServiceStartName);
|
|
|
+
|
|
|
+ if (lpsd->lpDescription != NULL && lstrcmp(lpsd->lpDescription, TEXT("")) != 0)
|
|
|
+ _tprintf(TEXT(" Description: %s\n"), lpsd->lpDescription);
|
|
|
+ if (lpsc->lpLoadOrderGroup != NULL && lstrcmp(lpsc->lpLoadOrderGroup, TEXT("")) != 0)
|
|
|
+ _tprintf(TEXT(" Load order group: %s\n"), lpsc->lpLoadOrderGroup);
|
|
|
+ if (lpsc->dwTagId != 0)
|
|
|
+ _tprintf(TEXT(" Tag ID: %d\n"), lpsc->dwTagId);
|
|
|
+ if (lpsc->lpDependencies != NULL && lstrcmp(lpsc->lpDependencies, TEXT("")) != 0)
|
|
|
+ _tprintf(TEXT(" Dependencies: %s\n"), lpsc->lpDependencies);
|
|
|
+
|
|
|
+ // 释放资源;
|
|
|
+ LocalFree(lpsc);
|
|
|
+ LocalFree(lpsd);
|
|
|
+
|
|
|
+ cleanup:
|
|
|
+ CloseServiceHandle(hSvc);
|
|
|
+ CloseServiceHandle(hSCM);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[4/23/2016 home];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void DoDisableSvc(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("要禁用的服务名称无效\n"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ SC_HANDLE schSCM;
|
|
|
+ SC_HANDLE schSvc;
|
|
|
+
|
|
|
+ // 打开SCM;
|
|
|
+ schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
|
+ if (schSCM == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取服务句柄;
|
|
|
+ schSvc = OpenService(schSCM, lpSvcName, SERVICE_CHANGE_CONFIG);
|
|
|
+ if (schSvc == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ChangeServiceConfig(
|
|
|
+ schSvc,
|
|
|
+ SERVICE_NO_CHANGE, // service type: no change
|
|
|
+ SERVICE_DISABLED, // service start type
|
|
|
+ SERVICE_NO_CHANGE, // error control: no change
|
|
|
+ NULL, // binary path: no change
|
|
|
+ NULL, // load order group: no change
|
|
|
+ NULL, // tag ID: no change
|
|
|
+ NULL, // dependencies: no change
|
|
|
+ NULL, // account name: no change
|
|
|
+ NULL, // password: no change
|
|
|
+ NULL)) // display name: no change
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("ChangeServiceConfig failed (%d)\n"), GetLastError());
|
|
|
+ }
|
|
|
+
|
|
|
+ CloseServiceHandle(schSvc);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[4/23/2016 home];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void DoEnableSvc(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("要启用的服务名称无效\n"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ SC_HANDLE schSCM;
|
|
|
+ SC_HANDLE schSvc;
|
|
|
+
|
|
|
+ // Get a handle to the SCM database.
|
|
|
+ // 获取SCM数据库句柄;
|
|
|
+ schSCM = OpenSCManager(
|
|
|
+ NULL, // local computer
|
|
|
+ NULL, // ServicesActive database
|
|
|
+ SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
+
|
|
|
+ if (NULL == schSCM)
|
|
|
+ {
|
|
|
+ printf("OpenSCManager failed (%d)\n", GetLastError());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get a handle to the service.
|
|
|
+ // 获取服务句柄值;
|
|
|
+ schSvc = OpenService(
|
|
|
+ schSCM, // SCM database
|
|
|
+ lpSvcName, // name of service
|
|
|
+ SERVICE_CHANGE_CONFIG); // need change config access
|
|
|
+
|
|
|
+ if (schSvc == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Change the service start type.
|
|
|
+ // 改变服务启动类型;
|
|
|
+ if (!ChangeServiceConfig(
|
|
|
+ schSvc, // 服务句柄;
|
|
|
+ SERVICE_NO_CHANGE, // service type: no change
|
|
|
+ SERVICE_DEMAND_START, // service start type
|
|
|
+ SERVICE_NO_CHANGE, // error control: no change
|
|
|
+ NULL, // binary path: no change
|
|
|
+ NULL, // load order group: no change
|
|
|
+ NULL, // tag ID: no change
|
|
|
+ NULL, // dependencies: no change
|
|
|
+ NULL, // account name: no change
|
|
|
+ NULL, // password: no change
|
|
|
+ NULL)) // display name: no change
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("ChangeServiceConfig failed (%d)\n"), GetLastError());
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("Service enabled successfully.\n"));
|
|
|
+ }
|
|
|
+
|
|
|
+ CloseServiceHandle(schSvc);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[4/23/2016 home];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void DoUpdateSvcDesc(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("要更新描述的服务名称无效\n"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ SC_HANDLE schSCM;
|
|
|
+ SC_HANDLE schSvc;
|
|
|
+ SERVICE_DESCRIPTION sd;
|
|
|
+ LPTSTR szDesc = TEXT("This is a test description");
|
|
|
+
|
|
|
+ // Get a handle to the SCM database.
|
|
|
+ // 获取SCM数据库句柄;
|
|
|
+ schSCM = OpenSCManager(
|
|
|
+ NULL, // NULL表示本地计算机;
|
|
|
+ NULL, // NULL表示:ServicesActive database
|
|
|
+ SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
+
|
|
|
+ if (NULL == schSCM)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get a handle to the service.
|
|
|
+ // 获取服务句柄值;
|
|
|
+ schSvc = OpenService(
|
|
|
+ schSCM, // SCM 数据库句柄;
|
|
|
+ lpSvcName, // 服务名称;
|
|
|
+ SERVICE_CHANGE_CONFIG); // need change config access
|
|
|
+
|
|
|
+ if (schSvc == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Change the service description.
|
|
|
+ // 改变服务描述;
|
|
|
+ sd.lpDescription = szDesc;
|
|
|
+
|
|
|
+ if (!ChangeServiceConfig2(
|
|
|
+ schSvc, // 服务句柄;
|
|
|
+ SERVICE_CONFIG_DESCRIPTION, // 要改变的类型: description;
|
|
|
+ &sd)) // 新描述;
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("ChangeServiceConfig2 failed\n"));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("Service description updated successfully.\n"));
|
|
|
+ }
|
|
|
+
|
|
|
+ CloseServiceHandle(schSvc);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[4/23/2016 home];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void DoDeleteSvc(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("要删除的服务名称无效\n"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ SC_HANDLE schSCM;
|
|
|
+ SC_HANDLE schSvc;
|
|
|
+ SERVICE_STATUS ssStatus;
|
|
|
+
|
|
|
+ // 打开服务管理器;
|
|
|
+ schSCM = OpenSCManager(
|
|
|
+ NULL, // NULL表示本地计算机;
|
|
|
+ NULL, // NULL表示ServicesActive database
|
|
|
+ SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
+
|
|
|
+ if (NULL == schSCM)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打开服务;
|
|
|
+ schSvc = OpenService(
|
|
|
+ schSCM, // SCM database
|
|
|
+ lpSvcName, // name of service
|
|
|
+ SERVICE_STOP | DELETE // need delete access
|
|
|
+ );
|
|
|
+
|
|
|
+ if (schSvc == NULL)
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除服务关,需要先停止服务;
|
|
|
+ if (!::ControlService(schSvc, SERVICE_CONTROL_STOP, &ssStatus))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("删除服务前停止服务失败 (%d)\n"), GetLastError());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 删除服务;
|
|
|
+ if (!DeleteService(schSvc))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("DeleteService failed (%d)\n"), GetLastError());
|
|
|
+ SvcReportEvent(_T("Service could not be deleted"));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("Service deleted successfully\n"));
|
|
|
+ }
|
|
|
+
|
|
|
+ CloseServiceHandle(schSvc);
|
|
|
+ CloseServiceHandle(schSCM);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:SetCallBack[5/5/2016 Home];
|
|
|
+ /* 描述:设置回调函数;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] lpStartWorkCallBack:工作开始回调指针;
|
|
|
+ /* [IN] lpEndofWorkCallBack:工作结束回调指针;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void SetCallBack(IN LPVOID lpStartWorkCallBack, IN LPVOID lpEndofWorkCallBack)
|
|
|
+ {
|
|
|
+ if (g_scVariant.lpStartWorkCallBack == NULL)
|
|
|
+ g_scVariant.lpStartWorkCallBack = (WorkEndofCallback)lpStartWorkCallBack;
|
|
|
+
|
|
|
+ if (g_scVariant.lpEndofWorkCallBack == NULL)
|
|
|
+ g_scVariant.lpEndofWorkCallBack = (WorkEndofCallback)lpEndofWorkCallBack;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:StartProcess[5/6/2016 IT];
|
|
|
+ /* 描述:在服务进程里,调用外部EXE;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL StartProcess(IN LPCTSTR lpExePath)
|
|
|
+ {
|
|
|
+#if 0
|
|
|
+ if (!lpExePath || !PathFileExists(lpExePath))
|
|
|
+ {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ HANDLE hToken;
|
|
|
+ if (!GetTokenByName(hToken, _T("EXPLORER.EXE")))
|
|
|
+ {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ STARTUPINFO si;
|
|
|
+ PROCESS_INFORMATION pi;
|
|
|
+
|
|
|
+ ZeroMemory(&si, sizeof(STARTUPINFO));
|
|
|
+ si.cb = sizeof(STARTUPINFO);
|
|
|
+ si.lpDesktop = TEXT("winsta0\\default");
|
|
|
+
|
|
|
+ BOOL bResult = CreateProcessAsUser(hToken, lpExePath, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
|
|
|
+ DWORD dwError = GetLastError();// 返回740错误,表示服务必须在Admin账号下运行才能创建成功;
|
|
|
+
|
|
|
+ //CreateProcessWithTokenW(hToken, )
|
|
|
+
|
|
|
+
|
|
|
+ CloseHandle(hToken);
|
|
|
+ if (bResult)
|
|
|
+ {
|
|
|
+ // WriteLogAlways(_T("C:\\serverlog.txt"),_T("CreateProcessAsUser ok"));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //WriteLogAlways(_T("C:\\servererrlog.txt"),_T("CreateProcessAsUser failed"));
|
|
|
+ }
|
|
|
+#else
|
|
|
+ HANDLE hPtoken = NULL;
|
|
|
+ GetExplorerToken(&hPtoken);
|
|
|
+ //if(!GetTokenByName(hPtoken,_T("EXPLORER.EXE")))
|
|
|
+ //{
|
|
|
+ // return FALSE;
|
|
|
+ //}
|
|
|
+ PROCESS_INFORMATION pi;
|
|
|
+ STARTUPINFOW si = { sizeof(STARTUPINFO), NULL, L"", NULL, 0, 0, 0, 0, 0, 0, 0, STARTF_USESHOWWINDOW, 0, 0, NULL, 0, 0, 0 };
|
|
|
+ si.wShowWindow = SW_SHOW;
|
|
|
+ si.lpDesktop = NULL;
|
|
|
+ ZeroMemory(&pi, sizeof(pi));
|
|
|
+
|
|
|
+ static HMODULE advapi32_dll = LoadLibraryW(L"advapi32.dll");
|
|
|
+ if (!advapi32_dll)
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ /*static F_CreateProcessWithTokenW f_CreateProcessWithTokenW = (F_CreateProcessWithTokenW)(
|
|
|
+ GetProcAddress(advapi32_dll,"CreateProcessWithTokenW"));
|
|
|
+ if (f_CreateProcessWithTokenW == NULL)
|
|
|
+ return ;
|
|
|
+ */
|
|
|
+ BOOL bResult = CreateProcessWithTokenW(hPtoken, LOGON_WITH_PROFILE, NULL, (LPWSTR)lpExePath, NULL, NULL, NULL, &si, &pi);
|
|
|
+
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ Sleep(1000);
|
|
|
+ CloseHandle(pi.hProcess);
|
|
|
+
|
|
|
+ CloseHandle(pi.hThread);
|
|
|
+#endif
|
|
|
+ return bResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[5/6/2016 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL GetTokenByName(IN HANDLE &hToken, IN LPCTSTR lpName)
|
|
|
+ {
|
|
|
+ if (!lpName)
|
|
|
+ {
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL bRet = FALSE;
|
|
|
+ HANDLE hProcessSnap = NULL;
|
|
|
+ PROCESSENTRY32 pe32 = { 0 };
|
|
|
+ hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
+ if (hProcessSnap == INVALID_HANDLE_VALUE)
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
+ if (Process32First(hProcessSnap, &pe32))
|
|
|
+ {
|
|
|
+ do
|
|
|
+ {
|
|
|
+ CString exefile = pe32.szExeFile;
|
|
|
+ CString paraname = lpName;
|
|
|
+ if (!exefile.CompareNoCase(lpName))
|
|
|
+ {
|
|
|
+ HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
|
|
|
+ bRet = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken);
|
|
|
+ CloseHandle(hProcessSnap);
|
|
|
+ return bRet;
|
|
|
+ }
|
|
|
+ } while (Process32Next(hProcessSnap, &pe32));
|
|
|
+ bRet = TRUE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ bRet = FALSE;
|
|
|
+
|
|
|
+ CloseHandle(hProcessSnap);
|
|
|
+ return bRet;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:[5/6/2016 IT];
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] :;
|
|
|
+ /* [OUT] :;
|
|
|
+ /* [IN/OUT] :;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ // Jeff.Hacker. WINDOWS NT 以上的内核需要提权,才能对系统进行高级管理;
|
|
|
+ BOOL GetDebugPriv()
|
|
|
+ {
|
|
|
+ // 返回的访问令牌指针;
|
|
|
+ HANDLE hToken;
|
|
|
+ // 接收所返回的制定特权名称的信息;
|
|
|
+ LUID sedebugnameValue;
|
|
|
+ // 新特权信息的指针(结构体);
|
|
|
+ TOKEN_PRIVILEGES tkp;
|
|
|
+ DWORD dwCurProcId = GetCurrentProcessId();
|
|
|
+ // 要修改访问权限的进程句柄;
|
|
|
+ HANDLE hCurProc;
|
|
|
+ hCurProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwCurProcId);
|
|
|
+
|
|
|
+ if (!::OpenProcessToken(hCurProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
|
|
+ {
|
|
|
+ //ShowSystemErrorInfo(_T("升级包OpenProcessToken失败."),GetLastError());
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
|
|
|
+ {
|
|
|
+ //ShowSystemErrorInfo(_T("升级包LookupPrivilegeValue失败."),GetLastError());
|
|
|
+ CloseHandle(hToken);
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ tkp.PrivilegeCount = 1;
|
|
|
+ tkp.Privileges[0].Luid = sedebugnameValue;
|
|
|
+ tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
+
|
|
|
+ if (!::AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL))
|
|
|
+ {
|
|
|
+ //ShowSystemErrorInfo(_T("升级包AdjustTokenPrivileges失败."),GetLastError());
|
|
|
+ CloseHandle(hToken);
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ CloseHandle(hCurProc);
|
|
|
+ CloseHandle(hToken);
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ DWORD GetExplorerToken(OUT HANDLE* phExplorerToken)
|
|
|
+ {
|
|
|
+ DWORD dwStatus = ERROR_FILE_NOT_FOUND;
|
|
|
+ BOOL bRet = FALSE;
|
|
|
+ HANDLE hProcess = NULL;
|
|
|
+ HANDLE hProcessSnap = NULL;
|
|
|
+ TCHAR szExplorerPath[MAX_PATH] = { 0 };
|
|
|
+ TCHAR FileName[MAX_PATH] = { 0 };
|
|
|
+ PROCESSENTRY32 pe32 = { 0 };
|
|
|
+ __try
|
|
|
+ {
|
|
|
+ GetWindowsDirectory(szExplorerPath, MAX_PATH);
|
|
|
+ _tcscat_s(szExplorerPath, MAX_PATH, _T("\\Explorer.EXE"));
|
|
|
+ hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
+ if (hProcessSnap == INVALID_HANDLE_VALUE)
|
|
|
+ {
|
|
|
+ dwStatus = GetLastError();
|
|
|
+ __leave;
|
|
|
+ }
|
|
|
+ pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
+ if (!Process32First(hProcessSnap, &pe32))
|
|
|
+ {
|
|
|
+ dwStatus = GetLastError();
|
|
|
+ __leave;
|
|
|
+ }
|
|
|
+
|
|
|
+ int ii = 0;
|
|
|
+ do
|
|
|
+ {
|
|
|
+ hProcess = OpenProcess(PROCESS_ALL_ACCESS/*PROCESS_QUERY_INFORMATION*/, FALSE, pe32.th32ProcessID);
|
|
|
+ if (NULL != hProcess)
|
|
|
+ {
|
|
|
+ ii++;
|
|
|
+ //if ( GetModuleFileNameEx(hProcess , NULL , FileName , MAX_PATH) )
|
|
|
+ //{
|
|
|
+ if (_tcsicmp(pe32.szExeFile, _T("Explorer.EXE")) == 0)
|
|
|
+ {
|
|
|
+ HANDLE hToken;
|
|
|
+ if (OpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken))
|
|
|
+ {
|
|
|
+ HANDLE hNewToken = NULL;
|
|
|
+ DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hNewToken);
|
|
|
+ *phExplorerToken = hNewToken;
|
|
|
+ dwStatus = 0;
|
|
|
+ CloseHandle(hToken);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ //}
|
|
|
+ CloseHandle(hProcess);
|
|
|
+ hProcess = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ } while (Process32Next(hProcessSnap, &pe32));
|
|
|
+ }
|
|
|
+ __finally
|
|
|
+ {
|
|
|
+ if (NULL != hProcess)
|
|
|
+ {
|
|
|
+ CloseHandle(hProcess);
|
|
|
+ }
|
|
|
+ if (NULL != hProcessSnap)
|
|
|
+ {
|
|
|
+ CloseHandle(hProcessSnap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return dwStatus;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打进服务事件日志里;
|
|
|
+ void LogEvent(IN LPCTSTR pFormat, ...)
|
|
|
+ {
|
|
|
+ TCHAR chMsg[MAX_PATH];
|
|
|
+ HANDLE hEventLog;
|
|
|
+ LPTSTR lpszStrings[1];
|
|
|
+ va_list pArg;
|
|
|
+
|
|
|
+ va_start(pArg, pFormat);
|
|
|
+ StringCchVPrintf(chMsg, MAX_PATH, pFormat, pArg);
|
|
|
+ va_end(pArg);
|
|
|
+
|
|
|
+ lpszStrings[0] = chMsg;
|
|
|
+
|
|
|
+ hEventLog = RegisterEventSource(NULL, g_scVariant.scName);
|
|
|
+ if (hEventLog != NULL)
|
|
|
+ {
|
|
|
+ ReportEvent(hEventLog, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*)&lpszStrings[0], NULL);
|
|
|
+ if (hEventLog)
|
|
|
+ DeregisterEventSource(hEventLog);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|