| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 | 
// TimeSyncServer.cpp : 定义应用程序的类行为。//#include "stdafx.h"#include "TimeSyncServer.h"#include "TimeSyncServerDlg.h"#include "Simplelog.h"#include <thread>#include "AppService.h"#ifdef _DEBUG#define new DEBUG_NEW#endif//设置两个全局变量 SERVICE_STATUS m_ServiceStatus;SERVICE_STATUS_HANDLE m_ServiceStatusHandle;class CDumpCatch{public:	CDumpCatch();	~CDumpCatch();private:	static LPTOP_LEVEL_EXCEPTION_FILTER WINAPI TempSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);	static BOOL ReleaseDumpFile(const std::string& strPath, EXCEPTION_POINTERS* pException);	static LONG WINAPI UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS* pException);	static void MyPureCallHandler(void);	static void MyInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved);	BOOL AddExceptionHandle();	BOOL RemoveExceptionHandle();	BOOL PreventSetUnhandledExceptionFilter();	void SetInvalidHandle();	void UnSetInvalidHandle();private:	LPTOP_LEVEL_EXCEPTION_FILTER m_preFilter;	_invalid_parameter_handler m_preIph;	_purecall_handler m_prePch;};void WINAPI ServiceMain(DWORD argc, LPTSTR * argv){	//     DWORD status; 	//     DWORD specificError; 	SPDLOG_INFO("当用SCM启动程序的时候,程序执行下面的代码");	m_ServiceStatus.dwServiceType = SERVICE_WIN32;	m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;	m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;	m_ServiceStatus.dwWin32ExitCode = 0;	m_ServiceStatus.dwServiceSpecificExitCode = 0;	m_ServiceStatus.dwCheckPoint = 0;	m_ServiceStatus.dwWaitHint = 0;	m_ServiceStatusHandle = RegisterServiceCtrlHandler("TimeSyncServer", ServiceCtrlHandler);	if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)	{		CSimpleLog::Save("Handler not installed", true, CSimpleLog::error);		return;	}	m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;	m_ServiceStatus.dwCheckPoint = 0;	m_ServiceStatus.dwWaitHint = 0;	if (!SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus))	{	}	std::thread th(CTimeSyncServerApp::StartTheAppServices, 5);	th.detach();	return;}void WINAPI ServiceCtrlHandler(DWORD Opcode){	switch (Opcode)	{	case SERVICE_CONTROL_PAUSE:		m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;		break;	case SERVICE_CONTROL_CONTINUE:		m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;		break;	case SERVICE_CONTROL_STOP:		m_ServiceStatus.dwWin32ExitCode = 0;		m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;		m_ServiceStatus.dwCheckPoint = 0;		m_ServiceStatus.dwWaitHint = 0;		SetServiceStatus(m_ServiceStatusHandle, &m_ServiceStatus);		//bRunning=false;		break;	case SERVICE_CONTROL_INTERROGATE:		break;	}	return;}BOOL InstallService(CString &strPath)//无法创建其他应用程序为服务,因为它们不能响应启动请求{	//char strDir[1024]={0};	SC_HANDLE schSCManager, schService;	//   GetCurrentDirectory(1024,strDir);	//   strcat(strDir," //test.exe "); 	schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);	if (schSCManager == NULL)		return false;	//LPCTSTR lpszBinaryPathName=strDir;	LPCTSTR lpszBinaryPathName;	if (strPath == "")	{		AfxMessageBox("You must tell me Exepath!");		return FALSE;	}	else	{		lpszBinaryPathName = strPath;	}	schService = CreateService(schSCManager, "DataCenter", "DataCenter",// service name to display 		SERVICE_ALL_ACCESS,        // desired access 		SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // service type 																 //SERVICE_DEMAND_START,      // start type 		SERVICE_AUTO_START,        //系统启动时自动启动		SERVICE_ERROR_NORMAL,      // error control type 		lpszBinaryPathName,        // service's binary 		NULL,                      // no load ordering group 		NULL,                      // no tag identifier 		NULL,                      // no dependencies 		NULL,                      // LocalSystem account 		NULL);                     // no password 	if (schService == NULL)		return false;	CloseServiceHandle(schService);	return true;}BOOL DeleteService(){	SC_HANDLE schSCManager;	SC_HANDLE hService;	schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);	if (schSCManager == NULL)		return false;	hService = OpenService(schSCManager, "DataCenter", SERVICE_ALL_ACCESS);	if (hService == NULL)		return false;	if (DeleteService(hService) == 0)		return false;	if (CloseServiceHandle(hService) == 0)		return false;	else		return true;}// CTimeSyncServerAppBEGIN_MESSAGE_MAP(CTimeSyncServerApp, CWinApp)	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)END_MESSAGE_MAP()// CTimeSyncServerApp 构造CTimeSyncServerApp::CTimeSyncServerApp(){	// 支持重新启动管理器	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;	// TODO: 在此处添加构造代码,	// 将所有重要的初始化放置在 InitInstance 中}// 唯一的一个 CTimeSyncServerApp 对象CTimeSyncServerApp theApp;CDumpCatch g_dumpCatch;//////////////////////////////////////////////////////////////////////////////////////void CDumpCatch::MyPureCallHandler(void){	throw std::invalid_argument("");}void CDumpCatch::MyInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved){	//The parameters all have the value NULL unless a debug version of the CRT library is used.	throw std::invalid_argument("");}void CDumpCatch::SetInvalidHandle(){#if _MSC_VER >= 1400  // MSVC 2005/8	m_preIph = _set_invalid_parameter_handler(MyInvalidParameterHandler);#endif  // _MSC_VER >= 1400	m_prePch = _set_purecall_handler(MyPureCallHandler);   //At application, this call can stop show the error message box.}void CDumpCatch::UnSetInvalidHandle(){#if _MSC_VER >= 1400  // MSVC 2005/8	_set_invalid_parameter_handler(m_preIph);#endif  // _MSC_VER >= 1400	_set_purecall_handler(m_prePch); //At application this can stop show the error message box.}LPTOP_LEVEL_EXCEPTION_FILTER WINAPI CDumpCatch::TempSetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter){	return NULL;}BOOL CDumpCatch::AddExceptionHandle(){	m_preFilter = ::SetUnhandledExceptionFilter(UnhandledExceptionFilterEx);	PreventSetUnhandledExceptionFilter();	return TRUE;}BOOL CDumpCatch::RemoveExceptionHandle(){	if (m_preFilter != NULL)	{		::SetUnhandledExceptionFilter(m_preFilter);		m_preFilter = NULL;	}	return TRUE;}CDumpCatch::CDumpCatch(){	SetInvalidHandle();	AddExceptionHandle();}CDumpCatch::~CDumpCatch(){	UnSetInvalidHandle();	RemoveExceptionHandle();}BOOL CDumpCatch::ReleaseDumpFile(const std::string& strPath, EXCEPTION_POINTERS* pException){	HANDLE hDumpFile = ::CreateFile(strPath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);	if (hDumpFile == INVALID_HANDLE_VALUE)	{		return FALSE;	}	MINIDUMP_EXCEPTION_INFORMATION dumpInfo;	dumpInfo.ExceptionPointers = pException;	dumpInfo.ThreadId = ::GetCurrentThreadId();	dumpInfo.ClientPointers = TRUE;	//	::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);  	BOOL bRet = ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hDumpFile, MiniDumpWithFullMemory, &dumpInfo, NULL, NULL);	::CloseHandle(hDumpFile);	return bRet;}#include <spdlog/fmt/fmt.h>LONG WINAPI CDumpCatch::UnhandledExceptionFilterEx(struct _EXCEPTION_POINTERS* pException){	char szPath[MAX_PATH] = { 0 };	::GetModuleFileName(NULL, szPath, MAX_PATH);	::PathRemoveFileSpec(szPath);	SYSTEMTIME st;	GetLocalTime(&st);	std::string strPath = fmt::format("{}\\DataCenter_{}_{:0>4}{:0>2}{:0>2}_{:0>2}{:0>2}{:0>2}.dmp",		szPath, g_strVersion, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);	SPDLOG_CRITICAL("异常崩溃:{} 版本:{}", strPath, g_strVersion);	BOOL bRelease = ReleaseDumpFile(strPath.c_str(), pException);	//::FatalAppExit(0,  L"Error");	if (bRelease)	{		return EXCEPTION_EXECUTE_HANDLER;	}	return EXCEPTION_CONTINUE_SEARCH;}BOOL CDumpCatch::PreventSetUnhandledExceptionFilter(){	HMODULE hKernel32 = LoadLibrary("kernel32.dll");	if (hKernel32 == NULL)	{		return FALSE;	}	void* pOrgEntry = ::GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");	if (pOrgEntry == NULL)	{		return FALSE;	}	unsigned char newJump[5];	DWORD dwOrgEntryAddr = (DWORD)pOrgEntry;	dwOrgEntryAddr += 5; //jump instruction has 5 byte space.	void* pNewFunc = &TempSetUnhandledExceptionFilter;	DWORD dwNewEntryAddr = (DWORD)pNewFunc;	DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;	newJump[0] = 0xE9;  //jump	memcpy(&newJump[1], &dwRelativeAddr, sizeof(DWORD));	SIZE_T bytesWritten;	DWORD dwOldFlag, dwTempFlag;	::VirtualProtect(pOrgEntry, 5, PAGE_READWRITE, &dwOldFlag);	BOOL bRet = ::WriteProcessMemory(::GetCurrentProcess(), pOrgEntry, newJump, 5, &bytesWritten);	::VirtualProtect(pOrgEntry, 5, dwOldFlag, &dwTempFlag);	return bRet;}long   __stdcall   callback(_EXCEPTION_POINTERS* excp){	//CString strLog;	//strLog.Format("Error   address   %x\r\nCPU   register:\r\neax   %x   ebx   %x   ecx   %x   edx   %x\r\n",	//	excp->ExceptionRecord->ExceptionAddress, excp->ContextRecord->Eax, excp->ContextRecord->Ebx,excp->ContextRecord->Ecx,   	//	excp->ContextRecord->Edx);	SPDLOG_CRITICAL("异常,程序退出 {}", g_strVersion);	exit(0);	return   EXCEPTION_EXECUTE_HANDLER;}// CTimeSyncServerApp 初始化BOOL CTimeSyncServerApp::InitInstance(){	// 如果一个运行在 Windows XP 上的应用程序清单指定要	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,	//则需要 InitCommonControlsEx()。  否则,将无法创建窗口。	INITCOMMONCONTROLSEX InitCtrls;	InitCtrls.dwSize = sizeof(InitCtrls);	// 将它设置为包括所有要在应用程序中使用的	// 公共控件类。	InitCtrls.dwICC = ICC_WIN95_CLASSES;	InitCommonControlsEx(&InitCtrls);	CWinApp::InitInstance();	if (!AfxSocketInit())	{		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);		return FALSE;	}	AfxEnableControlContainer();	// 创建 shell 管理器,以防对话框包含	// 任何 shell 树视图控件或 shell 列表视图控件。	CShellManager *pShellManager = new CShellManager;	// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));	// 标准初始化	// 如果未使用这些功能并希望减小	// 最终可执行文件的大小,则应移除下列	// 不需要的特定初始化例程	// 更改用于存储设置的注册表项	// TODO: 应适当修改该字符串,	// 例如修改为公司或组织名	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));	HANDLE  hMutex = ::CreateMutex(NULL, FALSE, "DataCenter");	if (GetLastError() == ERROR_ALREADY_EXISTS)		::TerminateProcess((HANDLE)-1, 0);	std::string strParam = R"(netsh advfirewall firewall delete rule name="DataCenter" dir=in & netsh advfirewall firewall add rule name="DataCenter" dir=in protocol=tcp localport=10086,10088,10089,10090,21006,21008 action=allow)";	hjfunc_CmdExecParam(strParam, 1, SW_HIDE);	//日志初始化	CSpdlogMng::Instance()->InitLog("DataCenter");	//SPDLOG_DEBUG("debug");	//SPDLOG_INFO("info");	//SPDLOG_ERROR("error");	//SPDLOG_CRITICAL("critical");	//启动服务(两种方式:双击运行和SCM启动,执行流程如刚开始提到的那样),对话框在下面显示	SERVICE_TABLE_ENTRY DispatchTable[] = { { "DataCenter",ServiceMain },{ NULL,NULL } };	//StartServiceCtrlDispatcher(DispatchTable); 	if (!StartServiceCtrlDispatcher(DispatchTable))	{		SPDLOG_INFO("当不是用SCM启动程序的时候,程序执行下面的代码");		std::thread th(CTimeSyncServerApp::StartTheAppServices, 3);		th.detach();				CTimeSyncServerDlg dlg;		//m_pMainWnd = &dlg;		int nResponse = dlg.DoModal();		if (nResponse == IDOK)		{			// TODO: Place code here to handle when the dialog is			//  dismissed with OK		}		else if (nResponse == IDCANCEL)		{			// TODO: Place code here to handle when the dialog is			//  dismissed with Cancel		}	}	// 删除上面创建的 shell 管理器。	if (pShellManager != NULL)	{		delete pShellManager;	}#ifndef _AFXDLL	ControlBarCleanUp();#endif	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,	//  而不是启动应用程序的消息泵。	return FALSE;}void CTimeSyncServerApp::StartTheAppServices(WORD seconds){	for (auto i = 0; i < seconds; i++)		std::this_thread::sleep_for(std::chrono::seconds(1));	if (CAppService::Instance()->Start())	{			}	else	{		SPDLOG_CRITICAL("启动失败.程序退出");		::TerminateProcess((HANDLE)-1, 0);	}}
 |