|
@@ -0,0 +1,1718 @@
|
|
|
+#include "stdafx.h"
|
|
|
+#include "WindowService.h"
|
|
|
+#include <psapi.h>
|
|
|
+#include <tlhelp32.h>
|
|
|
+#pragma comment ( lib, "psapi.lib" )
|
|
|
+#include <Aclapi.h>
|
|
|
+#include <strsafe.h>
|
|
|
+#include <shlwapi.h>
|
|
|
+
|
|
|
+namespace WindowsService
|
|
|
+{
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ // 全局变量;
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ SERVICE_STATUS_HANDLE g_SvcStatusHandle; // 服务句柄;
|
|
|
+ SERVICE_STATUS g_SvcStatus; // 服务状态;
|
|
|
+ HANDLE g_hCtrlSvc = NULL; // 服务控制事件;
|
|
|
+ TCHAR g_szlpSvrDescription[MAX_PATH] = _T(""); // 服务描述 ;
|
|
|
+ TCHAR g_szSvcName[MAX_PATH] = _T(""); // 服务名称;
|
|
|
+ WorkStartCallback g_lpStartWorkCallBack = NULL; // 开启工作者;
|
|
|
+ WorkEndofCallback g_lpEndofWorkCallBack = NULL; // 结束工作者;
|
|
|
+
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ // 全局函数;
|
|
|
+ int InitWinSock()
|
|
|
+ {
|
|
|
+ WORD wVersionRequested;
|
|
|
+ WSADATA wsaData;
|
|
|
+ int nErrCode;
|
|
|
+
|
|
|
+ wVersionRequested = MAKEWORD(2, 2);
|
|
|
+ nErrCode = WSAStartup( wVersionRequested, &wsaData );
|
|
|
+ if ( 0 != nErrCode )
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:InitSvcVar;
|
|
|
+ /* 描述:初始化服务变量;
|
|
|
+ /* 参数:;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void InitSvcVar()
|
|
|
+ {
|
|
|
+ g_SvcStatusHandle = NULL;
|
|
|
+ g_SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; // | SERVICE_INTERACTIVE_PROCESS与桌面交互;
|
|
|
+ g_SvcStatus.dwCurrentState = SERVICE_STOPPED;
|
|
|
+ g_SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
|
|
+ g_SvcStatus.dwWin32ExitCode = 0;
|
|
|
+ g_SvcStatus.dwServiceSpecificExitCode = 0;
|
|
|
+ g_SvcStatus.dwCheckPoint = 0;
|
|
|
+ g_SvcStatus.dwWaitHint = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:IsSvcInstalled;
|
|
|
+ /* 描述:判断服务是否安装;
|
|
|
+ /* 参数:;
|
|
|
+ /* 返回:若服务已安装返回TRUE,否则返回FALSE;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL IsSvcInstalled()
|
|
|
+ {
|
|
|
+ BOOL bResult = FALSE;
|
|
|
+ // 打开服务控制管理器;
|
|
|
+ SC_HANDLE schSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
|
+
|
|
|
+ if (schSCM != NULL)
|
|
|
+ {// 打开服务;
|
|
|
+ SC_HANDLE schSvc = ::OpenService(schSCM, g_szSvcName, SERVICE_QUERY_CONFIG);
|
|
|
+ if (schSvc != NULL)
|
|
|
+ {
|
|
|
+ bResult = TRUE;
|
|
|
+ ::CloseServiceHandle(schSvc);
|
|
|
+ }
|
|
|
+ ::CloseServiceHandle(schSCM);
|
|
|
+ }
|
|
|
+
|
|
|
+ return bResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:SvcInstall;
|
|
|
+ /* 描述:安装服务;
|
|
|
+ /* 参数:;
|
|
|
+ /* 返回:安装成功返回TRUE,否则返回FALSE;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ BOOL SvcInstall()
|
|
|
+ {
|
|
|
+ // 获取服务程序的绝对路径;
|
|
|
+ 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_szSvcName, // 服务名称;
|
|
|
+ g_szSvcName, // 服务描述;
|
|
|
+ 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_szlpSvrDescription;
|
|
|
+ ::ChangeServiceConfig2(schSvc, SERVICE_CONFIG_DESCRIPTION, &ServiceDesc);
|
|
|
+
|
|
|
+ // 释放资源;
|
|
|
+ ::CloseServiceHandle(schSvc);
|
|
|
+ ::CloseServiceHandle(schSCM);
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:ServiceMain;
|
|
|
+ /* 描述:服务入口函数;
|
|
|
+ /* 参数:;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void WINAPI ServiceMain()
|
|
|
+ {
|
|
|
+ // 注册服务的控制函数;
|
|
|
+ g_SvcStatusHandle = RegisterServiceCtrlHandler(g_szSvcName, SvcCtrlHandler);
|
|
|
+ if (g_SvcStatusHandle == NULL)
|
|
|
+ {
|
|
|
+ SvcReportEvent(_T("Handler not installed"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 在这里设置服务状态;
|
|
|
+ g_SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
|
+ g_SvcStatus.dwServiceSpecificExitCode = 0;
|
|
|
+
|
|
|
+ // 注册成功后向SCM报告服务状态信息,因为服务还没初始化完成;
|
|
|
+ // 所以当前服务状态为SERVICE_START_PENDING ;
|
|
|
+ ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 3000); // 处理第一个事件大约需要3秒钟;
|
|
|
+
|
|
|
+ //////////////////////////////////////////////////////////////////////////
|
|
|
+ // 开始初始化服务;
|
|
|
+ g_hCtrlSvc = ::CreateEvent( NULL,TRUE, FALSE, _T("CtrlService::g_hCtrlSvc"));
|
|
|
+ if (g_hCtrlSvc == NULL)
|
|
|
+ {
|
|
|
+ // 向SCM报告服务已停止;
|
|
|
+ ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 向SCM报告服务正在运行;
|
|
|
+ ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
|
|
|
+
|
|
|
+ // 开启工作者;
|
|
|
+ if ( g_lpStartWorkCallBack )
|
|
|
+ g_lpStartWorkCallBack();
|
|
|
+
|
|
|
+ // 线程中的处理函数运行结束后返回ServiceMain(),
|
|
|
+ // ServiceMain()调用WaitForSingleObject,
|
|
|
+ // 因为服务被停止之前ServiceMain()不会结束
|
|
|
+ WaitForSingleObject(g_hCtrlSvc,INFINITE); // INFINITE表示无限等待,等待SCM的信号;
|
|
|
+ CloseHandle(g_hCtrlSvc);
|
|
|
+
|
|
|
+ // 结束工作者;
|
|
|
+ if ( g_lpEndofWorkCallBack )
|
|
|
+ g_lpEndofWorkCallBack();
|
|
|
+
|
|
|
+ SvcReportEvent(_T("Service stopped"));
|
|
|
+
|
|
|
+ // 向SCM报告服务已停止工作;
|
|
|
+ ReportSvcStatus(SERVICE_STOPPED,NO_ERROR,0,0,0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:SvcCtrlHandler;
|
|
|
+ /* 描述:每当有控制码发送给服务时被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)
|
|
|
+ KillService();
|
|
|
+ break;
|
|
|
+ case SERVICE_CONTROL_PAUSE:
|
|
|
+ // 暂停服务;
|
|
|
+ break;
|
|
|
+ case SERVICE_CONTROL_CONTINUE:
|
|
|
+ // 恢复被暂停的服务;
|
|
|
+ break;
|
|
|
+ case SERVICE_CONTROL_INTERROGATE:
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ SvcReportEvent(_T("Bad service request"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:ReportSvcStatus;
|
|
|
+ /* 描述:设置当前服务状态,并将其报告给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_SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; // 表示我们的服务是独占一个进程的服务 ;
|
|
|
+ g_SvcStatus.dwCurrentState = dwCurrentState; // 当前服务状态;
|
|
|
+ g_SvcStatus.dwWaitHint = dwWaitHint;
|
|
|
+
|
|
|
+ if( dwCurrentState == SERVICE_START_PENDING )
|
|
|
+ {
|
|
|
+ g_SvcStatus.dwControlsAccepted = 0; // 不接受任何控制通知;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // 通知 SCM 服务接受哪个控制通知:这里允许停止、关机、暂停继续;
|
|
|
+ g_SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ; //|SERVICE_ACCEPT_PAUSE_CONTINUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( (dwCurrentState == SERVICE_RUNNING ) || ( dwCurrentState == SERVICE_STOPPED ) )
|
|
|
+ g_SvcStatus.dwCheckPoint = 0;
|
|
|
+ else
|
|
|
+ g_SvcStatus.dwCheckPoint = dwCheckPoint++;
|
|
|
+
|
|
|
+ // dwServiceSpecificExitCode在你终止服务并报告退出细节时很有用。
|
|
|
+ // 初始化服务时并不退出,因此值为 0;
|
|
|
+ if(dwServiceSpecificExitCode == 0)
|
|
|
+ {
|
|
|
+ g_SvcStatus.dwWin32ExitCode = dwWin32ExitCode;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ g_SvcStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; //用户自定义错误代码;
|
|
|
+ }
|
|
|
+ g_SvcStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
|
|
|
+
|
|
|
+ //设置好nServiceStatus后,向SCM报告服务状态,非0表示成功,0表示失败;
|
|
|
+ bSuccess = SetServiceStatus( g_SvcStatusHandle,&g_SvcStatus);
|
|
|
+ if( !bSuccess )
|
|
|
+ {
|
|
|
+ SvcReportEvent(_T("Set Service Status failed (%d) "), GetLastError());
|
|
|
+ KillService();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 结束服务;
|
|
|
+ void KillService()
|
|
|
+ {
|
|
|
+ //LOG4C((LOG_NOTICE,"KillService."));
|
|
|
+ SetEvent(g_hCtrlSvc); //如果操作成功,则返回非零值,否则为0。设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用ResetEvent。这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记。如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。
|
|
|
+ //ReportStatusToSCMgr(SERVICE_STOPPED,NO_ERROR,0,0,0);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:;
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [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_szSvcName);
|
|
|
+ if (hEventSource != NULL)
|
|
|
+ {
|
|
|
+ lpszStrings[0] = g_szSvcName;
|
|
|
+ lpszStrings[1] = szReport;
|
|
|
+
|
|
|
+ ReportEvent(
|
|
|
+ hEventSource, // 事件日志句柄;
|
|
|
+ EVENTLOG_INFORMATION_TYPE, // 事件类型;
|
|
|
+ 0, // 事件类别;
|
|
|
+ 0/*SVC_ERROR*/, // 事件标识;
|
|
|
+ NULL, // 无安全标识;
|
|
|
+ 2, // lpszStrings数组大小;
|
|
|
+ 0, // 无二进制数据;
|
|
|
+ lpszStrings, // 字符串数组;
|
|
|
+ NULL // 无二进制数据;
|
|
|
+ );
|
|
|
+
|
|
|
+ DeregisterEventSource(hEventSource);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:StartSvc;
|
|
|
+ /* 描述:启动服务;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] lpSvcName:要打开的服务名称;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void StartSvc(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("要启动的服务名空\n"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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数据库;
|
|
|
+ lpSvcName, // 服务名称;
|
|
|
+ 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;
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [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 DoStopSvc(IN LPCTSTR lpSvcName)
|
|
|
+ {
|
|
|
+ if ( lpSvcName == NULL || lpSvcName[0] == _T('\0'))
|
|
|
+ {
|
|
|
+ _tprintf_s(_T("指定要停止的服务名无效\n"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ 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
|
|
|
+ lpSvcName, // 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;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:;
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [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_szSvcName);
|
|
|
+ _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);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:;
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [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);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:;
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [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);
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:;
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [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);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:;
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [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;
|
|
|
+ /* 描述:设置回调函数;
|
|
|
+ /* 参数:;
|
|
|
+ /* [IN] lpStartWorkCallBack:工作开始回调指针;
|
|
|
+ /* [IN] lpEndofWorkCallBack:工作结束回调指针;
|
|
|
+ /* 返回:void;
|
|
|
+ /* 注意:;
|
|
|
+ /* 示例:;
|
|
|
+ /*
|
|
|
+ /* 修改:;
|
|
|
+ /* 日期:;
|
|
|
+ /* 内容:;
|
|
|
+ /************************************************************************/
|
|
|
+ void SetCallBack( IN LPVOID lpStartWorkCallBack, IN LPVOID lpEndofWorkCallBack )
|
|
|
+ {
|
|
|
+ if ( g_lpStartWorkCallBack == NULL )
|
|
|
+ g_lpStartWorkCallBack = (WorkEndofCallback)lpStartWorkCallBack;
|
|
|
+
|
|
|
+ if ( g_lpEndofWorkCallBack == NULL )
|
|
|
+ g_lpEndofWorkCallBack = (WorkEndofCallback)lpEndofWorkCallBack;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:StartProcess;
|
|
|
+ /* 描述:在服务进程里,调用外部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;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:;
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [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;
|
|
|
+ }
|
|
|
+
|
|
|
+ /************************************************************************/
|
|
|
+ /* 函数:;
|
|
|
+ /* 描述:;
|
|
|
+ /* 参数:;
|
|
|
+ /* [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 ;
|
|
|
+ }
|
|
|
+};
|