
// YAServer.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "YAServer.h"
#include "YAServerDlg.h"
#include "def.h"
#include "INIFILE.h"
#include "Functions/Functions.h"
#include "minidupm.h"
#include "tlhelp32.h"

#include "ProcessRemodule.h"
#include "log_process_module.h"

#include "./system_basic_info/SystemAnalysis.h"
#include "./debug_server/debug_server_socket.h"

#pragma warning(disable: 4005)

extern int debug_server_init(void);

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CYAServerApp

BEGIN_MESSAGE_MAP(CYAServerApp, CWinApp)
	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CYAServerApp 构造

CYAServerApp::CYAServerApp()
{
	// 支持重新启动管理器
	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
	// TODO: 在此处添加构造代码，
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CYAServerApp 对象

CYAServerApp theApp;


// CYAServerApp 初始化

BOOL CYAServerApp::InitInstance()
{
	// 如果一个运行在 Windows XP 上的应用程序清单指定要
	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式，
	//则需要 InitCommonControlsEx()。否则，将无法创建窗口。
	CreateMutex(NULL, FALSE, _T("MyMux"));
	if(GetLastError() == ERROR_ALREADY_EXISTS){
		HWND hWnd = ::FindWindow(NULL, _T("永安信通数据采集系统"));
		::PostMessage(hWnd, WM_QUIT, 0, 0);
	}

	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	// 将它设置为包括所有要在应用程序中使用的
	// 公共控件类。
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	SetUnhandledExceptionFilter(ExceptionFilter);

	CWinApp::InitInstance();
	
	AfxEnableControlContainer();

	// 创建 shell 管理器，以防对话框包含
	// 任何 shell 树视图控件或 shell 列表视图控件。
	CShellManager *pShellManager = new CShellManager;

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小，则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串，
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	init_param();
	load_conf();
	
    service_task_init();
	debug_server_init();
	debug_print_syslog(0, "Service thread, SQL thread, log thread Started.");
	//debug_server_process_thread_init();
	CYAServerDlg dlg;
	m_pMainWnd = &dlg;

	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  “确定”来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  “取消”来关闭对话框的代码
	}

	// 删除上面创建的 shell 管理器。
	if (pShellManager != NULL)
	{
		delete pShellManager;
	}

	// 由于对话框已关闭，所以将返回 FALSE 以便退出应用程序，
	//  而不是启动应用程序的消息泵。
	return FALSE;
}

/*
 * 写入配置文件
 *
 * param
 *		section	------		字段名
 *		key     ------		键值
 *		value   ------		值
 *
 * 例子：
 * [DB]
 * user=root
 * DB为字段名， user为键值，root为键值
 *
 *
 * return
 *		无
 *
*/
void CYAServerApp::writeini( string section, string key, string value )
{
	WritePrivateProfileStringA(section.c_str(), key.c_str(), value.c_str(), FILEPATH_SERVER_CONFIG);
}

/*
 * 载入主数据库配置和备用数据库配置
 *
 * param
 *		无
 *
 * return
 *		无
 *
*/
void CYAServerApp::load_db_conf()
{
	IniFile ini;
	if(ini.open(FILEPATH_SERVER_CONFIG)){
		//主数据库ip
		dbhost = ini.read(CONF_SECT_DB, CONF_DB_KEY_HOST);
		//主数据库用户名
		dbuser = ini.read(CONF_SECT_DB, CONF_DB_KEY_USER);
		//主数据库密码
		dbpwd = ini.read(CONF_SECT_DB, CONF_DB_KEY_PWD);
		//主数据库数据库名
		dbname = ini.read(CONF_SECT_DB, CONF_DB_KEY_DBNAME);
		//是否使用备份数据库
		dbbackup = ini.read(CONF_SECT_DB, CONF_DB_KEY_DB_BACKUP);
		//主数据库服务器的端口
		dbport = atoi(ini.read(CONF_SECT_DB, CONF_DB_KEY_PORT).c_str());
		//主数据库的编码
		dbencoding = ini.read(CONF_SECT_DB, CONF_DB_KEY_ENCODING);

		//备用数据库ip
		dbhost_bk = ini.read(CONF_SECT_DB_BK, CONF_DB_KEY_HOST);
		//备用数据库用户名
		dbuser_bk = ini.read(CONF_SECT_DB_BK, CONF_DB_KEY_USER);
		//备用数据库密码
		dbpwd_bk = ini.read(CONF_SECT_DB_BK, CONF_DB_KEY_PWD);
		//备用数据库数据库名称
		dbname_bk = ini.read(CONF_SECT_DB_BK, CONF_DB_KEY_DBNAME);
		//备用数据库端口
		dbport_bk = atoi(ini.read(CONF_SECT_DB_BK, CONF_DB_KEY_PORT).c_str());
		//备用数据库编码
		dbencoding_bk = ini.read(CONF_SECT_DB_BK, CONF_DB_KEY_ENCODING);
	}
}

/*
 * 保存主数据库配置和备用数据库配置到配置文件
 *
 * param
 *		无
 *
 * return
 *		无
 *
*/
void CYAServerApp::save_db_conf()
{
	char t[20];
	string s;
	sprintf_s(t, "%d", dbport);
	s = t;
	writeini(CONF_SECT_DB, CONF_DB_KEY_HOST, dbhost);
	writeini(CONF_SECT_DB, CONF_DB_KEY_USER, dbuser);
	writeini(CONF_SECT_DB, CONF_DB_KEY_PWD, dbpwd);
	writeini(CONF_SECT_DB, CONF_DB_KEY_DBNAME, dbname);
	writeini(CONF_SECT_DB, CONF_DB_KEY_DB_BACKUP, dbbackup);
	writeini(CONF_SECT_DB, CONF_DB_KEY_ENCODING, dbencoding);
	writeini(CONF_SECT_DB, CONF_DB_KEY_PORT, s);

	sprintf_s(t, "%d", dbport_bk);
	s = t;
	writeini(CONF_SECT_DB_BK, CONF_DB_KEY_HOST, dbhost_bk);
	writeini(CONF_SECT_DB_BK, CONF_DB_KEY_USER, dbuser_bk);
	writeini(CONF_SECT_DB_BK, CONF_DB_KEY_PWD, dbpwd_bk);
	writeini(CONF_SECT_DB_BK, CONF_DB_KEY_DBNAME, dbname_bk);
	writeini(CONF_SECT_DB_BK, CONF_DB_KEY_ENCODING, dbencoding_bk);
	writeini(CONF_SECT_DB_BK, CONF_DB_KEY_PORT, s);
}

/*
 * 从配置文件载入系统配置
 *
 * param
 *		无
 *
 * return
 *		无
 *
*/
void CYAServerApp::load_sys_conf()
{
	locate_type = 0;
	IniFile ini;
	if(ini.open(FILEPATH_SERVER_CONFIG)){
		ws_url = ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_WS_URL);
		ws_url_bk = ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_WS_URL_BK);
		tcp_host = ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_TCP_HOST);
		use_filter = (atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_USE_FILTER).c_str()) == 0 ? FALSE : TRUE);
		use_filter_odd = (atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_USE_FILTER_ODD).c_str()) == 0 ? FALSE : TRUE);
		recon_server = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_RECON_SERVER).c_str());
		recon_db = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_RECON_DB).c_str());
		reader_lost = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_READER_LOST).c_str());
		card_lost = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_CARD_LOST).c_str());
		timing_interval = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_TIMING_INTERVAL).c_str());
		sampling_interval = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_SAMPLING_INTERVAL).c_str());
		coor_error = atof(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_COORDINATE_ERROR).c_str());
		ranging_error = atof(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_RANGING_ERROR).c_str());
		move_error = atof(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_MOVING_ERROR).c_str());
		z_offset = atof(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_Z_OFFSET).c_str());
		locate_type = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SERVER_LOCATE_TYPE).c_str());

		send_json_postion = 1000;
		send_json_counting = 5000;
		send_json_alarm = 5000;
		send_json_device = 10000;
		ws_connect_interval = 2000;
		time_send_call = 5000;
		time_send_help = 5000;
		heart_interval = atoi(ini.read(CONF_SECT_SERVER_SETTING,CONF_SERVER_HEART_INTERVAL).c_str());
		send_json_postion = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SEND_JSON_POSION).c_str());
		send_json_counting = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SEND_JSON_COUNTING).c_str());
		send_json_alarm = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SEND_JSON_ALARM).c_str());
		send_json_device = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SEND_JSON_DEVICE).c_str());
		ws_connect_interval = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SEND_WS_CONNECT_INTERVAL).c_str());
		time_send_call = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SEND_CALLINFO_INTERVAL).c_str());
		time_send_help = atoi(ini.read(CONF_SECT_SERVER_SETTING, CONF_SEND_HELPINFO_INTERVAL).c_str());
	}
}

/*
 * 保存系统设置到配置文件
 *
 * param
 *		无
 *
 * return
 *		无
 *
*/
void CYAServerApp::save_sys_conf()
{
	char t[20];
	string s;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_WS_URL, ws_url);
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_WS_URL_BK, ws_url_bk);
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_USE_FILTER, use_filter ? "1" : "0");
	sprintf_s(t, "%d", recon_server);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_RECON_SERVER, s);
	sprintf_s(t, "%d", recon_db);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_RECON_DB, s);
	sprintf_s(t, "%d", reader_lost);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_READER_LOST, s);
	sprintf_s(t, "%d", card_lost);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_CARD_LOST, s);
	sprintf_s(t, "%d", timing_interval);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_TIMING_INTERVAL, s);
	sprintf_s(t, "%d", sampling_interval);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_SAMPLING_INTERVAL, s);
	sprintf_s(t, "%f", z_offset);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_Z_OFFSET, s);
	sprintf_s(t, "%f", coor_error);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_COORDINATE_ERROR, s);
	sprintf_s(t, "%f", ranging_error);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_RANGING_ERROR, s);
	sprintf_s(t, "%f", move_error);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SERVER_MOVING_ERROR, s);
}

/*
 * 从配置文件载入日志配置
 *
 * param
 *		无
 *
 * return
 *		无
 *
*/
void CYAServerApp::load_log_conf()
{
	IniFile ini;
	if(ini.open(FILEPATH_SERVER_CONFIG)){
		//系统状态
		log_sys_status = (atoi(ini.read(CONF_SECT_SERVER_LOG, CONF_LOG_SYS_STATUS).c_str()) == 0 ? FALSE : TRUE);
		//原始数据，底层数据
		log_raw_data = (atoi(ini.read(CONF_SECT_SERVER_LOG, CONF_LOG_RAW_DATA).c_str()) == 0 ? FALSE : TRUE);
		//格式化数据
		log_parse_data = (atoi(ini.read(CONF_SECT_SERVER_LOG, CONF_LOG_PARSE_DATA).c_str()) == 0 ? FALSE : TRUE);
		//发送数据包
		log_send_package = (atoi(ini.read(CONF_SECT_SERVER_LOG, CONF_LOG_SEND_EVENT).c_str()) == 0 ? FALSE : TRUE);
		//接收数据包
		log_recv_package = (atoi(ini.read(CONF_SECT_SERVER_LOG, CONF_LOG_REV_EVENT).c_str()) == 0 ? FALSE : TRUE);
		//定位数据
		log_locate_data = (atoi(ini.read(CONF_SECT_SERVER_LOG, CONF_LOG_LOCATE_DATA).c_str()) == 0 ? FALSE : TRUE);
	}
}

/*
 * 保存日志设置
 *
 * param
 *		无
 *
 * return
 *		无
 *
*/
void CYAServerApp::save_log_conf()
{
	writeini(CONF_SECT_SERVER_LOG, CONF_LOG_SYS_STATUS, log_sys_status ? "1" : "0");
	writeini(CONF_SECT_SERVER_LOG, CONF_LOG_RAW_DATA, log_raw_data ? "1" : "0");
	writeini(CONF_SECT_SERVER_LOG, CONF_LOG_PARSE_DATA, log_parse_data ? "1" : "0");
	writeini(CONF_SECT_SERVER_LOG, CONF_LOG_SEND_EVENT, log_send_package ? "1" : "0");
	writeini(CONF_SECT_SERVER_LOG, CONF_LOG_REV_EVENT, log_recv_package ? "1" : "0");
	writeini(CONF_SECT_SERVER_LOG,CONF_LOG_LOCATE_DATA,log_locate_data ? "1" : "0");
}

/*
 * 设置监控服务器句柄以及路径
 *
 * param
 *		hwd ------	主对话框窗口句柄	
 *
 * return
 *		无
 *
*/
void CYAServerApp::set_server_handle(HWND hwd)
{
	char t[20];
	char szAppdir[MAX_PATH+1] = {0};
	GetModuleFileNameA(NULL, szAppdir , MAX_PATH);
	sprintf_s(t, "%d", DWORD(hwd));
	writeini(CONF_SECT_MONITOR, CONF_MONITOR_SERVER_HANDLE, t);
	writeini(CONF_SECT_MONITOR, CONF_MONITOR_SERVER_PATH, szAppdir);
}

/*
 * 从配置文件载入监控配置
 *
 * param
 *		无
 *
 * return
 *		无
 *
*/
void CYAServerApp::load_monitor_conf()
{
	IniFile ini;
	if(ini.open(FILEPATH_SERVER_CONFIG)){
		m_hwnd_monitor = HWND(atoi(ini.read(CONF_SECT_MONITOR, CONF_MONITOR_MONITOR_HANDLE).c_str()));
		string path = ini.read(CONF_SECT_MONITOR, CONF_MONITOR_MONITOR_PATH);
		sprintf_s(m_path_monitor.get(), MAX_PATH, "%s", path.c_str());
		//sprintf( m_path_monitor, "%s", path.c_str());
	}
}

/*
 * 初始化监视软件路径
 *
 * param
 *		无
 *
 * return
 *		无
 *
*/
void CYAServerApp::init_param()
{
	m_path_monitor = nullptr;
	std::unique_ptr<char> tmp(new char[MAX_PATH]);
	m_path_monitor = std::move(tmp);
	memset(m_path_monitor.get(),0,MAX_PATH*sizeof(char));
}

/*
 * 保存间隔配置到配置文件
 *
 * param
 *		无
 *
 * return
 *		无
 *
*/
void CYAServerApp::save_interval_conf()
{
	char t[20];
	string s;
	sprintf_s(t, "%d", send_json_postion);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SEND_JSON_POSION, s);
	sprintf_s(t, "%d", send_json_counting);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SEND_JSON_COUNTING, s);
	sprintf_s(t, "%d", send_json_alarm);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SEND_JSON_ALARM, s);
	sprintf_s(t, "%d", send_json_device);
	s = t;
	writeini(CONF_SECT_SERVER_SETTING, CONF_SEND_JSON_DEVICE, s);
}

void CYAServerApp::load_reader_conf()
{
	IniFile ini;
	if(ini.open(FILEPATH_SERVER_CONFIG)){
		//分站发送时间消息
		reader_interval_time = atoi(ini.read(CONF_SECT_READER, CONF_READER_INTERVAL_TIME).c_str());
	}
}

void CYAServerApp::save_reader_conf()
{
	char t[20] = {0};
	string s;
	sprintf_s(t, "%d", reader_interval_time);
	s = t;
	writeini(CONF_SECT_READER, CONF_READER_INTERVAL_TIME, s);
}

BOOL CYAServerApp::KillProcessFromName(CString strProcessName)
{
	//创建进程快照(TH32CS_SNAPPROCESS表示创建所有进程的快照)  
	HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);  

	//PROCESSENTRY32进程快照的结构体  
	PROCESSENTRY32 pe;  

	//实例化后使用Process32First获取第一个快照的进程前必做的初始化操作  
	pe.dwSize = sizeof(PROCESSENTRY32);  


	//下面的IF效果同:  
	//if(hProcessSnap == INVALID_HANDLE_VALUE)   无效的句柄  
	if(!Process32First(hSnapShot,&pe))  
	{  
		return FALSE;  
	}  

	//将字符串转换为小写  
	strProcessName.MakeLower();  

	//如果句柄有效  则一直获取下一个句柄循环下去  
	while (Process32Next(hSnapShot,&pe))  
	{  

		//pe.szExeFile获取当前进程的可执行文件名称  
		CString scTmp = pe.szExeFile;  


		//将可执行文件名称所有英文字母修改为小写  
		scTmp.MakeLower();  

		//比较当前进程的可执行文件名称和传递进来的文件名称是否相同  
		//相同的话Compare返回0  
		if(!scTmp.Compare(strProcessName))  
		{  

			//从快照进程中获取该进程的PID(即任务管理器中的PID)  
			DWORD dwProcessID = pe.th32ProcessID;  
			HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE,FALSE,dwProcessID);  
			::TerminateProcess(hProcess,0);  
			CloseHandle(hProcess);  
			return TRUE;  
		}  
		scTmp.ReleaseBuffer();  
	}  
	strProcessName.ReleaseBuffer();  
	return FALSE;  
}

void CYAServerApp::load_conf()
{
	load_db_conf();
	load_sys_conf();
	load_log_conf();
	load_reader_conf();
}
