| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 | 
							
- // 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;
 
- void WINAPI ServiceMain(DWORD argc, LPTSTR * argv)
 
- {
 
- 	//     DWORD status; 
 
- 	//     DWORD specificError; 
 
- 	CSimpleLog::Save("当用SCM启动程序的时候,程序执行下面的代码", true, CSimpleLog::info);
 
- 	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, 2);
 
- 	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, "DataServices", "DataServices",// 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, "DataServices", SERVICE_ALL_ACCESS);
 
- 	if (hService == NULL)
 
- 		return false;
 
- 	if (DeleteService(hService) == 0)
 
- 		return false;
 
- 	if (CloseServiceHandle(hService) == 0)
 
- 		return false;
 
- 	else
 
- 		return true;
 
- }
 
- 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("{}\\DataServiceS_{}_{: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");
 
- 	NOTIFYICONDATA nid;
 
- 	nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
 
- 	nid.hWnd = AfxGetMainWnd()->GetSafeHwnd();
 
- 	nid.uID = IDI_DATASERVICS;//删除图标,仅使用ID即可(我们使用的是图标的ID)
 
- 	Shell_NotifyIcon(NIM_DELETE, &nid);    //在托盘区删除图标
 
- 	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;
 
- }
 
- // CTimeSyncServerApp
 
- BEGIN_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;
 
- // 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, "DataServices");
 
- 	if (GetLastError() == ERROR_ALREADY_EXISTS)
 
- 		::TerminateProcess((HANDLE)-1, 0);
 
- 	std::string strParam = R"(netsh advfirewall firewall delete rule name="DataServices" dir=in & netsh advfirewall firewall add rule name="DataServices" dir=in protocol=tcp localport=10086,10088,10089,21006,21008,51609 action=allow & netsh advfirewall firewall delete rule name="DataServicesUDP" dir=in & netsh advfirewall firewall add rule name="DataServicesUDP" dir=in protocol=udp localport=51609 action=allow)";
 
- 	hjfunc_CmdExecParam(strParam, 1, SW_HIDE);
 
- 	//日志初始化
 
- 	CSpdlogMng::Instance()->InitLog("DataServices");
 
- 	//启动服务(两种方式:双击运行和SCM启动,执行流程如刚开始提到的那样),对话框在下面显示
 
- 	SERVICE_TABLE_ENTRY DispatchTable[] = { { "DataServices",ServiceMain },{ NULL,NULL } };
 
- 	//StartServiceCtrlDispatcher(DispatchTable); 
 
- 	if (!StartServiceCtrlDispatcher(DispatchTable))
 
- 	{
 
- 		CSimpleLog::Save("当不是用SCM启动程序的时候,程序执行下面的代码", true, CSimpleLog::info);
 
- 		std::thread th(CTimeSyncServerApp::StartTheAppServices, 2);
 
- 		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())
 
- 	{
 
- 		CSimpleLog::Info("启动成功.");
 
- 	}
 
- 	else
 
- 	{
 
- 		CSimpleLog::Error("启动失败.程序退出");
 
- 		::TerminateProcess((HANDLE)-1, 0);
 
- 	}
 
- }
 
 
  |