#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);
		}
	}
};
