// 04WebServer.cpp : アプリケーションのクラス動作を定義します。
//

#include "stdafx.h"
#include "04WebServer.h"
#include "04WebServerDlg.h"
#include "InitWinsock.h"
#include "ServerStartException.h"
#include <initguid.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMy04WebServerApp

BEGIN_MESSAGE_MAP(CMy04WebServerApp, CWinApp)
	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()


// CMy04WebServerApp コンストラクション

CMy04WebServerApp::CMy04WebServerApp()
{
	m_server = NULL;
	m_serviceMode = 0;
	m_serverStatus = _T("サーバは停止中です。");
	m_exitCode = 0;
}


// 唯一の CMy04WebServerApp オブジェクトです。

CMy04WebServerApp theApp;


// CMy04WebServerApp 初期化

BOOL CMy04WebServerApp::InitInstance()
{
	SetServerSecurityDescripter();

	//	COM初期化
	CoInitialize(NULL);

	//	いろいろ初期化
	InitCommonControls();
	CWinApp::InitInstance();
	AfxEnableControlContainer();
	InitWinSock();

	// コマンドライン解析
	CString				cmdString = GetCommandOption();
	CCommandLineInfo	cmdInfo;
	ParseCommandLine(cmdInfo);

	if(cmdString.IsEmpty())
	{
		//	指定なしなので、コントローラーをランチ
		CString path = GetAppPath() + "ServerController.exe";
		::ShellExecute(0, _T("open"), path.GetBuffer(0), 0, 0, SW_SHOWNORMAL);

		return FALSE;
	}
	else if(DoRegister(cmdString))
	{
		//	レジストリ登録処理なので、終了
		return FALSE;
	}

	//	多重起動チェック
	if(m_pipeServer.CheckOther())
	{
		AfxMessageBox("サーバはすでに起動中です、多重起動できません。",MB_ICONSTOP);
		return FALSE;
	}

	//	コントローラと通信開始
	if(m_pipeServer.Start())
	{
		AfxMessageBox("コントローラとの通信開始に失敗しました。",MB_ICONSTOP);
		return FALSE;
	}

	//	オプションによって判別
	if(cmdString.CompareNoCase("/Service") == 0)
	{
		//	サービス起動

		m_serviceMode = 1;
		m_serviceContext.RunService();
		return FALSE;
	}
	else if(cmdString.CompareNoCase("/Debug") == 0)
	{
		//	デバッグモード

		//	デバッグ実行？
		CMy04WebServerDlg dlg;
		m_pMainWnd = &dlg;
		dlg.DoModal();

		return FALSE;
	}
	else if(cmdString.CompareNoCase("/Application") == 0)
	{
		//	アプリケーションモード
		m_pMainWnd = &m_msgWindow;
		m_msgWindow.CreateMsgWindow();

		return TRUE;
	}
	else
	{
		//	オプションエラー
		AfxMessageBox("不正な起動オプションです。",MB_ICONSTOP);
		return FALSE;
	}
}

//	各種レジストリ処理
int CMy04WebServerApp::DoRegister(CString command)
{
	if(command.CompareNoCase("/UnInstall") == 0)
	{
		//	コントローラ停止
		KillAllController();

		// 全て削除
		RegisterService(FALSE);
		return TRUE;
	}
	else if (command.CompareNoCase("/InstallService") == 0)
	{
		// アプリケーションモードで登録
		RegisterService(TRUE);
		return TRUE;
	}
	else if (command.CompareNoCase("/UnInstallService") == 0)
	{
		//	コントローラ停止
		KillAllController();

		// サービスモード削除
		RegisterService(FALSE);
		return TRUE;
	}
	else if (command.CompareNoCase("/IsRunning") == 0)
	{
		// 実行中か検出
		m_exitCode = m_pipeServer.CheckOther();
		return TRUE;
	}
	return FALSE;
}



//	モジュールパスを取得
CString CMy04WebServerApp::GetAppPath(int directoryPath)
{
	if(!directoryPath)
		return CPathTools::GetAppPathName();
	else
		return CPathTools::GetAppPath();
}

//	終了
int CMy04WebServerApp::ExitInstance()
{
	//	念のため、停止する
	StopServer();

	CoUninitialize();

	CWinApp::ExitInstance();
	return m_exitCode;
}

//	サーバを起動します
int CMy04WebServerApp::StartServer()
{
	SCOPE_LOCK();

	//	とりあえず、停止
	StopServer();

	try
	{
		if(m_server == NULL)
			m_server = new CServer();

		m_serverStatus = "サーバは正常に作動中です。";
	}
	catch(CServerStartException e)
	{
		StopServer();
		m_serverStatus = e.m_info;
		return(-1);
	}

	return(0);
}

//	停止
int CMy04WebServerApp::StopServer()
{
	SCOPE_LOCK();

	if(m_server != NULL)
		delete m_server;
	m_server = NULL;

	m_serverStatus = "サーバは停止中です。";

	return(0);
}

//	エラー情報を取得
CString CMy04WebServerApp::GetServerErrorInfo()
{
	SCOPE_LOCK();

	return(m_serverStatus);
}

//	サーバが実行中か取得する
int CMy04WebServerApp::ServerRunning()
{
	SCOPE_LOCK();

	if(m_server)
		return(TRUE);
	else
		return(FALSE);
}

//	サーバー情報取得
CString CMy04WebServerApp::GetServerInfoXML()
{
	SCOPE_LOCK();

	if(m_server)
	{
		return(m_server->m_infoRoot.ToXMLString());
	}
	else
		return("");
}

//	サーバー設定取得
CString CMy04WebServerApp::GetServerSettingXML()
{
	SCOPE_LOCK();

	if(m_server)
	{
		return(m_server->m_settingRoot.ToXMLString());
	}
	else
		return("");
}

//	サーバー設定取得
CString CMy04WebServerApp::GetServerContextXML()
{
	SCOPE_LOCK();

	if(m_server)
	{
		return(m_server->GetContextManager()->GetContextByXMLString());
	}
	else
		return("");
}


//	サーバーステータス設定
void CMy04WebServerApp::SetServerStatus(CString stat)
{
	SCOPE_LOCK();

	m_serverStatus = stat;
}

//	接続数の取得
int CMy04WebServerApp::GetConnectCount()
{
	SCOPE_LOCK();

	if(m_server)
	{
		return(m_server->GetConnectCount());
	}
	else
		return(0);
}

//	サービスモード
int CMy04WebServerApp::IsService()
{
	return(m_serviceMode);
}





/*!
	サーバ情報取得
*/
int CMy04WebServerApp::GetServerInfo(CWorkspaceAccess info)
{
	SCOPE_LOCK();

	if(m_server)
	{
		info.Copy(m_server->m_infoRoot.GetAccess(""));
		return(0);
	}
	else
		return(-1);
}

/*!
	サーバ設定取得
*/
int CMy04WebServerApp::GetServerSetting(CWorkspaceAccess setting)
{
	SCOPE_LOCK();

	if(m_server)
	{
		setting.Copy(m_server->m_settingRoot.GetAccess(""));
		return(0);
	}
	else
		return(-1);
}

/*!
	接続情報取得
*/
int CMy04WebServerApp::GetServerContext(CWorkspaceAccess context)
{
	SCOPE_LOCK();

	if(m_server)
	{
		m_server->GetContextManager()->GetContextCopy(context);
		return(0);
	}
	else
		return(-1);
}




//	デバッグログ
void CMy04WebServerApp::WriteDebugLog(LPCTSTR lpszFormat, ...)
{
	//	書式展開
	va_list argList;
	CString	str;
	va_start(argList, lpszFormat);
	str.FormatV(lpszFormat,argList);
	va_end(argList);

	FILE *text;
	if(!fopen_s(&text, GetAppPath() + "Debuglog.txt","at"))
	{
		fprintf(text,"[" SERVER_VER "] %s\n",str);
		fclose(text);
	}
}

//	コマンドオプションを取得
CString CMy04WebServerApp::GetCommandOption()
{
	CString	line = GetCommandLine();
	if(line.IsEmpty())
		line = m_lpCmdLine;

	int index = line.Find("/");
	if(index == -1)
	{
		index = line.Find("-");
		if(index == -1)
			return("");
	}

	return(line.Mid(index));
}

//	全てのコントローラを終了
void CMy04WebServerApp::KillAllController()
{
	::PostMessage(HWND_BROADCAST,::RegisterWindowMessage(_T("04WebServer All Quit")),0,0);
}


/*!
	内部情報をダンプ
*/
void CMy04WebServerApp::DumpContext()
{
	if(m_server != NULL)
	{
		CWorkspace	context;
		m_server->GetContextManager()->GetContextCopy(context.GetAccess(""));
		context.SaveToXMLFile(GET_APP()->GetAppPath() + "ContextDump.xml");

		m_server->m_infoRoot.SaveToXMLFile(GET_APP()->GetAppPath() + "InfoDump.xml");
	}
}


//	サーバが使用するセキュリティ記述子を取得
void CMy04WebServerApp::SetServerSecurityDescripter()
{

	//	既定のDACLを削除
	TOKEN_DEFAULT_DACL	dacl;
	dacl.DefaultDacl = NULL;

	HANDLE	token=NULL;
	::OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_DEFAULT,&token);
	::SetTokenInformation(token,TokenDefaultDacl,&dacl,sizeof(TOKEN_DEFAULT_DACL ));
	::CloseHandle(token);
}

//	サービスとして登録
void CMy04WebServerApp::RegisterService(int reg)
{
	if(reg)
	{
		if(CSystemService::AddToService())
		{
			AfxMessageBox("サービスの追加に失敗しました。",MB_ICONSTOP);
			m_exitCode = 0x100;
		}
	}
	else
	{
		if(CSystemService::DelFromService())
		{
			AfxMessageBox("サービスの削除に失敗しました。",MB_ICONSTOP);
			m_exitCode = 0x100;
		}
	}
}

