#include "pch.h"
#include "sApp.h"

#include "CreateDump.h"
#include "Tools.h"

#include <gdiplus.h>
#include "aLog.h"
#include "CTic.h"

using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

int sApp::preInit()
{
	CTic::Init();

	TCHAR path[MAX_PATH + 1];
	GetModuleFileName(NULL, path, MAX_PATH);
	ExeFullPath = path;					//完整路径
	wstrExeName = ExeFullPath.stem().wstring();	//保存去掉扩展名的文件名
	ExeDir = ExeFullPath.parent_path();		//exe所在路径

	setCreateDump((ExeDir / wstrExeName).c_str(), MiniDumpWithIndirectlyReferencedMemory | MiniDumpWithDataSegs | MiniDumpWithHandleData | MiniDumpWithThreadInfo);

	hInstance_Exe = GetModuleHandle(NULL);
	GetFileVersion(path, exeFileVerStr);

	// 如果版本号是以.0结尾，去掉
	auto pos = exeFileVerStr.rfind(L".0");
	if (pos != std::wstring::npos && pos == exeFileVerStr.size() - 2) {
		exeFileVerStr.erase(pos);
	}

	GetProductVersion(path, exeProductVerStr);
	pos = exeProductVerStr.rfind(L".0");
	if (pos != std::wstring::npos && pos == exeProductVerStr.size() - 2) {
		exeProductVerStr.erase(pos);
	}

	// 设置搜索dll的方式
	SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);

	// 默认工作目录是exe所在目录
	WorkDir = ExeDir;

	// 如果在Debug/Release目录之下调试，工作目录向上一级
	auto pathname = ExeDir.filename().wstring();
	if (pathname._Starts_with(L"Debug")
		|| pathname._Starts_with(L"Release")
		|| pathname._Starts_with(L"debug")
		|| pathname._Starts_with(L"release")) {
		WorkDir = ExeDir.parent_path();
		fs::path solutionDir = WorkDir.parent_path();
	}

	
	return 0;
}


// 子类不用调用sApp::init()，这里只是打个样;
int sApp::init()
{
	// 如果要更改WorkDir，在这开头修改

	SettingDir = WorkDir / L"Setting";
	LogDir = WorkDir / L"Log";

	if (!fs::exists(SettingDir)) {
		fs::create_directories(SettingDir);
	}

	// Log目录不存在则创建
	if (!fs::exists(LogDir)) {
		fs::create_directories(LogDir);
	}

	initGDI();

	
	initSocket();

	return 0;
}


int sApp::deinit()
{
	if(wsaData.wVersion) // 初始化过应该是0x0202
		WSACleanup();

	if(m_gdiplusToken) 
		GdiplusShutdown(m_gdiplusToken);

	return 0;
}

void sApp::initGDI()
{
	GdiplusStartupInput gdiplusStartupInput;

	// Initialize GDI+.
	GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
}

bool sApp::initSocket()
{
	//第一个参数为WinSock版本号，低字节为主版本号，高字节为修正版本号，第二个参数为WSADATA类型的指针 初始化成功返回0
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		alog->error("WSAStartup 失败");
		//TRACE(_T("WSAStartup 失败!\n"));
		return false;
	}

	return true;
}

void sApp::RestartWindows()
{
	HANDLE hToken;
	TOKEN_PRIVILEGES tkp;

	// Get a token for this process. 
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
		return;

	// Get the LUID for the shutdown privilege. 
	if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid)) {
		CloseHandle(hToken);
		return;
	}

	tkp.PrivilegeCount = 1;  // one privilege to set    
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	// Get the shutdown privilege for this process. 
	if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0)) {
		CloseHandle(hToken);
		return;
	}

	if (GetLastError() != ERROR_SUCCESS) {
		CloseHandle(hToken);
		return;
	}

	// Shut down the system and force all applications to close. 
	if (!ExitWindowsEx(EWX_REBOOT | EWX_FORCE,
		SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
		SHTDN_REASON_MINOR_UPGRADE)) {
		CloseHandle(hToken);
		return;
	}

	//shutdown was successful
	CloseHandle(hToken);
	return;
}

void sApp::ShutdownWindows()
{
	HANDLE hToken;
	TOKEN_PRIVILEGES tkp;

	// Get a token for this process. 
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
		return;

	// Get the LUID for the shutdown privilege. 
	if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid)) {
		CloseHandle(hToken);
		return;
	}

	tkp.PrivilegeCount = 1;  // one privilege to set    
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	// Get the shutdown privilege for this process. 
	if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0)) {
		CloseHandle(hToken);
		return;
	}

	if (GetLastError() != ERROR_SUCCESS) {
		CloseHandle(hToken);
		return;
	}

	// Shut down the system and force all applications to close. 
	if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE,
		SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
		SHTDN_REASON_MINOR_UPGRADE)) {
		CloseHandle(hToken);
		return;
	}

	//shutdown was successful
	CloseHandle(hToken);
	return;
}