// Rnsf7 (いじくるつくーる ver.7)のメインモジュール

#include "stdafx.h"
#include "RNSF7.h"
#include "MainWindow.h"
#include "OpenSetting.h"
#include "token.h"
#include "inst.h"
#include "helpdlg.h"
#include "refresh.h"
#include "splash.h"
#include "MainListview.h"
#include "MainNavigator.h"
#include "commfunc.h"
#include "addctrl.h"
#include "symbol.h"
#include "regopendlg.h"
#include "sakura.h"

// 関数
ATOM	MyRegisterClass(HINSTANCE hInstance);
HWND	InitInstance(HINSTANCE, int wLeft, int wTop, int wWidth, int wHeight, int nCmdShow);
void	UninstallRndf7( void );

// グローバル変数 :
char *szTitle = "Rnsf7";						// タイトル バーのテキスト
const char szWindowClass[] = "Rnsf7";			// メイン ウィンドウ クラス名

// リリースナンバー
DWORD releasenumber = 70000;

// WinMain :
// (lpCmdLine の代わりに、__argc と __argv を使っている)
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int nCmdShow)
{
	MSG  msg;
	BOOL bRet = 0; // GetMessageからの戻り値を確認するための変数
	HWND mutexhd = NULL;
	bool already_running = 0, bDisableSplashWindow = 0;
	HACCEL	hAccel;
	HWND hWnd = NULL; // 最初のInitInstanceまでは、ここがNULLでなければ、他のプロセスでRnsfが起動済みで、そのウィンドウハンドル
	int  iRet = 1;		// メイン関数の戻り値
	int  wLeft = CW_USEDEFAULT, wTop = 0, wWidth = CW_USEDEFAULT, wHeight = 0;
	REG  reg;
	char exename[MAX_PATH*2];

	// CCPUの進行ログを出したい場合はON
	//SetEnvironmentVariable("CCPU32_DEBUGOUT","1");

	if ( rnsf7RegRead("NoMutex", 0) == 0 ) {
		// 二重起動の防止
		mutexhd = (HWND)CreateMutex(NULL, true, "Rnsfldr");
		if (GetLastError() == ERROR_ALREADY_EXISTS) {
			hWnd = FindWindow(szWindowClass, NULL);
			already_running = 1; // すでに起動している
		}
	}

	// カレントディレクトリを自分のところにセット
	SetCurrentDirectoryOwnDir();

	// ビルドナンバー(Rnsf7ではリリースナンバー)を、リソースから読み出す
	{
		DWORD dwSize;
		char *verdata, *lpFileVersion;
		UINT len,a = 0,b = 0,c = 0,d = 0;

		if ( !GetModuleFileName(NULL, exename, _countof(exename)) ) {
			exename[0] = 0; // 万が一エラーだった場合のことを考え、無効にしておく。
		}
		else {
			if (0 < (dwSize = GetFileVersionInfoSize(exename, 0))) {
				verdata = zalloc( dwSize+2 );
				if ( verdata ) {
					if ( GetFileVersionInfo(exename,0,dwSize,verdata) ) {
						if ( VerQueryValue(verdata,"\\StringFileInfo\\041104b0\\FileVersion",(LPVOID *)&lpFileVersion,&len) ) {
							sscanf_s(lpFileVersion, "%u.%u.%u.%u",&a,&b,&c,&d);
							releasenumber = a*10000+b*1000+c*100+d;
						}
					}
					safefree( verdata );
				}
			}
		}
	}

	// <旧互換> 旧ファイル群、旧rscを削除する
	DeleteFile("rstrct2.rsc");
	DeleteFile("rstrct.rss");
	DeleteFile("temp.reg");

	// バージョンアップ時に、旧バージョンのアップデート用のrkyを削除する対応
	{
		WIN32_FIND_DATA520 wfd;
		HANDLE hFind = FindFirstFile520("RNSF7UP7????.RKY", &wfd);
		if (hFind != INVALID_HANDLE_VALUE) {
			do {
				// ベースファイル名の後ろの5桁が、70000より大きく、releasenumberよりも小さかった場合は、
				// 旧バージョン用アップデート用ののrkyであるとみなし、削除する。
				// 条件に合ったものが1つでも見つかったら、削除してループを終了。
				// 2つ以上存在することはありえないし、あったとしても次回削除されるってことで無視。
				DWORD updatenumber = atou(&(wfd.cFileName[7]));
				if (70000 < updatenumber && updatenumber < releasenumber) {
					DeleteFile(wfd.cFileName);
					break;
				}
			} while(0 != FindNextFile520(hFind, &wfd));
			FindClose(hFind);
		}
	}

	// 言語確認
	if (LANG_JAPANESE != PRIMARYLANGID(GetSystemDefaultLangID())) {
		if (IDNO == MessageBox(NULL, "In this environment, this software may not run. Do you continue?", "Warning", MB_YESNO | MB_ICONQUESTION)) {
			return 0;
		}
	}

	// OSバージョンの取得、プラットフォームの判別
	winver = ccpu32_WinVer();
#if _MSC_VER < 1500
#ifndef _WIN64
	isNT = (unsigned short)ccpu32_isNT();
#endif /* _WIN64 */
#endif // _MSC_VER < 1500
	// <旧互換> Windowsのバージョンによる制限は、Rnsf7.rscにて行う

	// IE4以上の存在と、バージョン取得
	iever = ccpu32_GetIEVer();

	// グローバル変数にインスタンス処理を格納します。
	hInst = hInstance;

	// R-Script の動的初期代入変数の代入
	first_init_constvalues();

	// キーボードのアクセラレータ
	hAccel = LoadAccelerators(hInst, (LPSTR)IDR_ACCELERATOR1);

	// コモンコントロールの初期化
	InitCommonControls();
	CoInitialize( NULL );
	//CoInitializeEx(NULL, COINIT_MULTITHREADED); - Win95で使えないので使用を停止したが…今はWin95は動作対象外だし、オープンしてもいいかな。

	// まごころ対処(1)
	if (reg.OpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer")) {
		if (reg.ReadInteger("RestrictRun", 1) == 0) {
			reg.DeleteValue("RestrictRun");
		}
		reg.CloseKey();
	}
	// まごころ対処(2)
	if (reg.OpenKey(HKEY_CURRENT_USER, "AppEvents\\Schemes\\Apps\\.Default\\.Default", TREG_OPEN_CREATE)) {
		reg.CloseKey();
	}

	// まごころ対処(3)
	if ( pcheck_r7( hInstance, NULL, (LPCTSTR)IDC_PED_DIALOG ) ) {
		CoUninitialize();
		return 0;
	}

#ifdef VCHECK_ON
	else {
		vcheck_r7( NULL );
	}
#endif /* VCHECK_ON */

	// 自らのMD5値を取得・比較（ただし、比較元MD5が'x'32個なら比較しない
	{
		char lasttime[32] = "なし";

		if ( 0 == md5FileCheck( NULL, HKEY_CURRENT_USER, RNSF7REGKEY, lasttime ) ) {
			char s[300];

			wsprintf( s, "実行ファイルが壊れています。ウイルス感染の疑いもあります。\r\n念のためにウイルスチェックを行って下さい。\r\nまた、制作元のWebサイトより本ソフトウェアの正しいファイルを入手して下さい。\r\n\r\n最終正常起動日時：%s", lasttime );
			MessageBox(NULL, s, szTitle, MB_OK | MB_ICONSTOP);
			return 1;
		}
	}

	// エクスプローラ等からのDrag&Dropを許可する（Vista以上でUACを使っていると、メッセージがフィルタされるので）
	if (winver >= 600) {
		typedef BOOL (__stdcall *CWMF_FUNCTYPE)(UINT, DWORD);

		HMODULE hDll = LoadLibrary_System32("user32.dll");
		if (hDll) {
			CWMF_FUNCTYPE p_ChangeWindowMessageFilter = (CWMF_FUNCTYPE)GetProcAddress(hDll, "ChangeWindowMessageFilter"); // Vista以上の関数

			if(p_ChangeWindowMessageFilter) {
				// WM_DROPFILESは単一のメッセージのみで動いているものではないので、色々許可しなければならない
				p_ChangeWindowMessageFilter(WM_DROPFILES, 1 /*MSGFLT_ADD*/);
				p_ChangeWindowMessageFilter(WM_COPYDATA, 1 /*MSGFLT_ADD*/);
				p_ChangeWindowMessageFilter(0x0049, 1 /*MSGFLT_ADD*/);
			}
			FreeLibrary(hDll);
		}
	}

	// 管理権限の所有をチェック
	// HKLM内の特定のキーへのアクセスが可能かどうかで判断する。
	// ここではHKLM配下のキーと関連づけたコントロールをグレイアウトさせるためのフラグの設定を行う。
	// 警告メッセージの出力は Rnsf7.rsc にて行っているため、ここでは行わない。
	{
		REG reg;

		if (reg.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", TREG_OPEN_CREATE)) {
			reg.CloseKey();
		}
		else {
			bCannotWriteHKLM = 1;
		}
	}

	// 更新風鐸用
	if (reg.OpenKey(HKEY_CURRENT_USER, "Software\\Upcheck")) {
		REG reg2, reg3;
		

		// <旧互換> 旧メールアドレスのエントリを削除(1)
		if (reg2.OpenKey(reg.GetHKey(), "yabuki-4@pk.highway.ne.jp")) {
			DWORD dwNumSubKeys = 0;

			reg2.DeleteKey("RNSF7");
			RegQueryInfoKey(reg2.GetHKey(), NULL, 0, NULL, &dwNumSubKeys, NULL, NULL, NULL,
				            NULL, NULL, NULL, NULL);
			reg2.CloseKey();
			if (dwNumSubKeys == 0) {
				reg.DeleteKey("yabuki-4@pk.highway.ne.jp");
			}
		}

		// <旧互換> 旧メールアドレスのエントリを削除(2)
		if (reg2.OpenKey(reg.GetHKey(), "ayacy@yoshibaworks.com")) {
			DWORD dwNumSubKeys = 0;

			reg2.DeleteKey("RNSF7");
			RegQueryInfoKey(reg2.GetHKey(), NULL, 0, NULL, &dwNumSubKeys, NULL, NULL, NULL,
				            NULL, NULL, NULL, NULL);
			reg2.CloseKey();
			if (dwNumSubKeys == 0) {
				reg.DeleteKey("ayacy@yoshibaworks.com");
			}
		}


		// <旧互換> 旧メールアドレスのエントリを削除(3)
		if (reg2.OpenKey(reg.GetHKey(), "tyabuki@yoshibaworks.com")) {
			DWORD dwNumSubKeys = 0;

			reg2.DeleteKey("RNSF7");
			RegQueryInfoKey(reg2.GetHKey(), NULL, 0, NULL, &dwNumSubKeys, NULL, NULL, NULL,
				            NULL, NULL, NULL, NULL);
			reg2.CloseKey();
			if (dwNumSubKeys == 0) {
				reg.DeleteKey("tyabuki@yoshibaworks.com");
			}
		}

		// <旧互換> 旧メールアドレスのエントリを削除(3)
		if (reg2.OpenKey(reg.GetHKey(), "ytakuya@yoshibaworks.com")) {
			DWORD dwNumSubKeys = 0;

			reg2.DeleteKey("RNSF7");
			RegQueryInfoKey(reg2.GetHKey(), NULL, 0, NULL, &dwNumSubKeys, NULL, NULL, NULL,
				            NULL, NULL, NULL, NULL);
			reg2.CloseKey();
			if (dwNumSubKeys == 0) {
				reg.DeleteKey("ytakuya@yoshibaworks.com");
			}
		}

		// 最新バージョンの登録
		if (reg2.OpenKey(reg.GetHKey(), "tyabuki@inasoft.org", TREG_OPEN_CREATE)) {
			reg2.WriteString("Author", "矢吹拓也", 0);
			reg2.WriteString("InfoURL", "http://www.inasoft.org/update.inf", 0);
			reg2.WriteString("DisplayHost", "www.inasoft.org", 0);

			if (reg3.OpenKey(reg2.GetHKey(), "RNSF7", TREG_OPEN_CREATE)) {
				reg3.WriteInteger("Build", releasenumber);
				reg3.WriteString("DistinctName", "RNSF7", 0);
				reg3.WriteString("DisplayName", SOFTWARENAME, 0);
				reg3.WriteString("FilePath", exename, 0);
				reg3.CloseKey();
			}
			else {
				dispErrorMessage(NULL, MB_OK | MB_ICONWARNING, "更新風鐸への登録処理",
					             "レジストリキー'HKEY_CURRENT_USER\\Software\\Upcheck\\tyabuki@inasoft.org\\RNSF7'を書き込みアクセスで開こうとしてエラーになりました。キーを指定するためのレジストリキーを開けないため、更新風鐸のための登録処理を中止します。\nAPIが報告した原因：", getLastErrorString(tRegGetLastError()), NULL, NULL, NULL, NULL);
			}
			reg2.CloseKey();
		}
		else {
			dispErrorMessage(NULL, MB_OK | MB_ICONWARNING, "更新風鐸への登録処理",
				             "レジストリキー'HKEY_CURRENT_USER\\Software\\Upcheck\\tyabuki@inasoft.org'を書き込みアクセスで開こうとしてエラーになりました。キーを指定するためのレジストリキーを開けないため、更新風鐸のための登録処理を中止します。\nAPIが報告した原因：", getLastErrorString(tRegGetLastError()), NULL, NULL, NULL, NULL);
		}
		reg.CloseKey();
	}

	if ( __argc > 1 ) { // コマンドラインオプションの指定あり
		if ( __argv[1][0] == '/' ) { // コマンドラインオプションの解析
			if ( (__argv[1][1] == 'I' || __argv[1][1] == 'i') && __argv[1][2] == 0 ) {
				// インストールの最終処理 ( 常駐しているかもしれないプログラムファイルの処理 )
				install();
				/*if ( already_running ) {
					MessageBox( NULL, "インストール作業は最後まで達しましたが、インストールの時点で「いじくるツール」または「"SOFTWARENAME"」が起動しており、インストールに失敗したおそれがあります。\nインストールに失敗した場合、「いじくるツール」または「"SOFTWARENAME"」を閉じた状態で、もう一度インストールをやり直して下さい。", "インストール", MB_OK | MB_ICONINFORMATION );
				}*/
				CoUninitialize();
				return 3;
			}
			if ( (__argv[1][1] == 'U' || __argv[1][1] == 'u') && __argv[1][2] == 0 ) { // Inno Setup補助：Rscの個別アンインストール処理
				uninstalln();
				CoUninitialize();
				return 0;
			}
			else if ( (__argv[1][1] == 'D' || __argv[1][1] == 'd') && __argv[1][2] == 0 ) { // 旧バージョン互換のため、いちおうアンインストールの処理は残しておくが、使われない前提とする
				if ( __argc == 2 ) { // いじくるつくーる全体をアンインストール
					if ( already_running ) {
						MessageBox( NULL, "「"SOFTWARENAME"」または以前のバージョンのRnsfが起動しています。いったん終了して下さい。", "アンインストール", MB_OK | MB_ICONSTOP );
						CoUninitialize();
						return 1;
					}
					else {
						uninstall();
						CoUninitialize();
						return 0;
					}
				}
				else { // ファイルを個別に削除(非公開オプション)
					if ( already_running ) {
						MessageBox( NULL, "「"SOFTWARENAME"」または以前のバージョンのRnsfが起動しています。いったん終了して下さい。", "個別アンインストール", MB_OK | MB_ICONSTOP );
						CoUninitialize();
						return 1;
					}
					else {
						char *mes;

						mes = (char *)malloc( lstrlen(__argv[2]) + 60 );
						if ( mes ) {
							wsprintf( mes, "%sをアンインストールしてもよろしいですか?", __argv[2] );
							if ( IDYES == MessageBox(NULL, mes, "個別アンインストール", MB_YESNO | MB_ICONQUESTION) ) {
								MessageBox( NULL, (uninstall1( __argv[2] ))?"アンインストールが完了しました。":"アンインストールに失敗しました。", "個別アンインストール", MB_OK | MB_ICONINFORMATION );
							}
							safefree( mes );
						}
						CoUninitialize();
						return 0;
					}
				}
			}
			else if ( (__argv[1][1] == 'R' || __argv[1][1] == 'r') && __argv[1][2] == 0 ) {
				if ( __argc == 2 ) { // キーを指定してレジストリ エディタを開く（入力済み形式）
					regOpenKeyDlg(NULL, NULL);
				}
				else { // キーを指定してレジストリ エディタを開く
					regOpenKeyDlg(NULL, __argv[2]);
				}
				CoUninitialize();
				return 0;
			}
			else if ( (__argv[1][1] == '?') && __argv[1][2] == 0 ) {
				// コマンドラインオプションの説明
				if ( (HINSTANCE)32 > ShellExecute(NULL, "open", "hh.exe", "rnsf7.chm::/_RESOURCE/HLP000055.html", ".", SW_SHOWNORMAL) ) {
					MessageBox( NULL, "hh.exeでヘルプファイルを開けません", szTitle, MB_OK | MB_ICONSTOP );
				}
				CoUninitialize();
				return 3;
			}
			// 不明なオプションが付けられた場合には、無視する
		}
		else { // rscを個別に実行
			if ( already_running ) {
				MessageBox( NULL, "「"SOFTWARENAME"」または以前のバージョンのRnsfが起動中です。いったん終了するか、「"SOFTWARENAME"」のメインウィンドウにrscファイルをドロップして下さい。", "ファイル名を指定して開く", MB_OK | MB_ICONSTOP );
				CoUninitialize();
				return 2;
			}
			else {
				WNDCLASSEX wcex;

				// ヘルプウィンドウの登録 (失敗しても無視)
				wcex.cbSize = sizeof(WNDCLASSEX); 

				wcex.style			= CS_HREDRAW | CS_VREDRAW;
				wcex.lpfnWndProc	= (WNDPROC)HlpProc;
				wcex.cbClsExtra		= 0;
				wcex.cbWndExtra		= 0;
				wcex.hInstance		= hInstance;
				wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_RNSF7);
				wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
				wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
				wcex.lpszMenuName	= (LPCTSTR)IDR_MENUHELP;
				wcex.lpszClassName	= "helpdlg_rnsf7";
				wcex.hIconSm		= NULL;
				RegisterClassEx(&wcex);

				// アイコンハンドルと共有イメージリストの準備
			    createImageLists();

				// 第１引数をrscファイル名として、スクリプトを実行開始
				iRet = openrsc( NULL, __argv[1], NULL );
			}
		}
	}
	else {	// コマンドラインオプションの指定無し
		if ( already_running ) {
			if ( hWnd ) { // 二重起動を確認したら、すでに起動済みのウィンドウをアクティブにする
				if ( IsIconic(hWnd) ) { // アイコン化(タスクバーに収納)されていたら、元に戻す
					ShowWindow(hWnd, SW_RESTORE);
				}
				SetForegroundWindow( GetLastActivePopup(hWnd) );
				InvalidateRect(hWnd, NULL, FALSE);
			}
			else { // 二重起動を確認したのに、すでに起動済みのウィンドウが見つからなかった場合
				MessageBox(NULL, "「"SOFTWARENAME"」または以前のバージョンのRnsfが起動中です。\nこれらのアプリケーションは2つ以上同時に起動できません。", szTitle, MB_OK | MB_ICONEXCLAMATION);
			}
			CoUninitialize();
			return 2;
		}

		// ATMLチェック
		if (checkAtml()) {
			if (IDOK != MessageBox(NULL, "この環境には、トレンドマイクロ製品（ウイルスバスターや、NTTのOEMのセキュリティ製品等）のレジストリキーが存在しています。トレンドマイクロ製品がインストールされた環境で本ソフトを利用することはライセンス違反となります。\r\nトレンドマイクロ製品がインストールされていないことを確認するか、またはアンインストールが完了したら「OK」ボタンを押して動作を続行させて下さい。動作をキャンセルする場合は「キャンセル」ボタンを押して下さい。\r\n\r\n詳細は下記のページを参照して下さい：\r\nhttp://www.inasoft.org/webhelp/sdfr4/HLP000180.html", "ライセンスチェック", MB_OKCANCEL | MB_ICONQUESTION)) {
				return 1;
			}
		}

		// Shift+Ctrl+Altが押されていたら、レジストリ読みだしの一部をスキップし、初期設定で起動を行う
		// (AutoUpdateCheckが邪魔をして起動できない場合は、これで回避できる)
		// Splashウィンドウの生成も抑制
		if (!( (GetKeyState(VK_SHIFT)&0x8000) && (GetKeyState(VK_MENU)&0x8000) && (GetKeyState(VK_CONTROL)&0x8000) )) {
			// レジストリからウィンドウ設定を読み出し
			if ( NULL != (reg.OpenKey(HKEY_CURRENT_USER, RNSF7REGKEY)) ) {
				bCategory = reg.ReadInteger( "bCategory", 1 ) != 0?1:0;
				bNavigator = reg.ReadInteger( "bNavigator", 1 ) != 0?1:0;
				bDisableSplashWindow = reg.ReadInteger( "bDisableSplashWindow", 0 ) != 0?1:0;

				if ( 0 == reg.ReadInteger("NoSaveSettings", 0) ) {
					wLeft   = reg.ReadInteger("wLeft",   (DWORD)CW_USEDEFAULT);
					wTop    = reg.ReadInteger("wTop",    0);
					wWidth  = reg.ReadInteger("wWidth",  (DWORD)CW_USEDEFAULT);
					wHeight = reg.ReadInteger("wHeight", 0);

					if (0 != reg.ReadInteger( "wMax",    0)) {
						nCmdShow = SW_MAXIMIZE;
					}

					iBarVx = reg.ReadInteger("iBarVx", (DWORD)-1);
					iBarHy = reg.ReadInteger("iBarHy", (DWORD)-1);

					if (wWidth != CW_USEDEFAULT) {
						// ウィンドウの左上座標が画面外なら、ウィンドウ位置をデフォルトの位置にする
						POINT pt = {wLeft, wTop};
						if (NULL == MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
							wLeft   = CW_USEDEFAULT;
							wTop    = 0;
							wWidth  = CW_USEDEFAULT;
							wHeight = 0;
						}
					}
				}
	
				// リストビューのスタイル・第1項目指定などをレジストリから読み出し
				wLVStyle = (short)reg.ReadInteger("wLVStyle", 0);
				bLVFirstItemFile = reg.ReadInteger("bLVFirstItemFile", 0)?1:0;
				bAutoUpdateCheck = reg.ReadInteger("AutoUpdateCheck", 0)?1:0;

				reg.CloseKey();
			}

			/*    // InnoSetup導入にともない、本ソフト自身のインストール処理は削除する
			// アーカイブ版（非インストール版）を使用している場合の初起動時に、
			// インストールダイアログを表示する
			if ( ReadRkv("inst_firstcheck", 0) == 0 ) {
				install();        
			}*/

			// スプラッシュウィンドウの生成
			if ( !bDisableSplashWindow ) {
				// Rnsf7.bmp が存在したら、それをウィンドウ中央に表示
				hSplashWnd = show_splash_window( "RNSF7.BMP", 255 );
			}
		}

		// アイコンハンドルと共有イメージリストの準備
		createImageLists();

		// アプリケーションの初期化
		if (!MyRegisterClass(hInstance)) {
			destroy_splash_window();
			MessageBox(NULL, "ウィンドウクラスの登録に失敗しました。", szTitle, MB_OK | MB_ICONSTOP);
			iRet = 1;
		}
		else {
			// メインウィンドウの生成
			if (NULL == (hWnd = InitInstance(hInstance, wLeft, wTop, wWidth, wHeight, nCmdShow))) {
				destroy_splash_window();
				MessageBox(NULL, "メインウィンドウを作成できませんでした。", szTitle, MB_OK | MB_ICONSTOP);
				iRet = 1;
			}
			else {
				// リロードメッセージ送信
				StartNavigator = 1;
				SendMessage(hWnd, R7MW_READY, NULL, NULL);

				// hSplashWnd がまだ開いていたら、閉じる(開いている時間が1000msよりも短かったら、さらに500ms延長表示)
				fout_splash_window();

				// インターネット経由で更新を確認(スレッドの開始)
				if ( bAutoUpdateCheck ) {
					UpdateCheck( hWnd, 1 );
				}

				// メイン メッセージ ループ :
				while ( (bRet = GetMessage(&msg, NULL, 0, 0)) != 0 ) {
					if (bRet == -1) {
						break;
					}
					if ( !IsDialogMessage(hHelpWindow, &msg) ) {
						if ( !TranslateAccelerator(hWnd, hAccel, &msg) ) {
							TranslateMessage( &msg );
							DispatchMessage( &msg );
						}
					}
				}
				iRet = (int) msg.wParam;
			}
		}
	}

	// 終了処理

	// ナビゲータは音を鳴らすことがあるため、音を止めてから終了する
	PlaySound(NULL, 0, 0);

	// ミューテックスの削除（いちおう）
	if ( mutexhd ) {
		CloseHandle(mutexhd);
	}

	// アイコンハンドルと共有イメージリストの破棄
    destroyImageLists();

	// その他不要メモリ解放
	if (hBoldFont) {
		DeleteObject(hBoldFont);
		hBoldFont = NULL;
	}

	CoUninitialize();

	return iRet;
}

// ウィンドウクラスの登録
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;
	ATOM atom;

	// メインウィンドウの登録
	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_RNSF7);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCTSTR)IDR_MENU1;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= NULL;

	if ( NULL == ( atom = RegisterClassEx(&wcex) ) ) {
		return 0;
	}

	// ヘルプウィンドウの登録 (失敗しても無視)
	wcex.lpfnWndProc	= (WNDPROC)HlpProc;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_FILE_BROWSE);
	wcex.lpszMenuName	= (LPCTSTR)IDR_MENUHELP;
	wcex.lpszClassName	= "helpdlg_rnsf7";
	RegisterClassEx(&wcex);

	// ヘルプウィンドウの登録の可否に関わらず、メインウィンドウの情報を返す
	return atom;
}

// アプリケーションの初期化とメインウィンドウの作成
HWND InitInstance(HINSTANCE hInstance, int wLeft, int wTop, int wWidth, int wHeight, int nCmdShow)
{
	HWND hWnd;

	hWnd = CreateWindowEx(WS_EX_ACCEPTFILES, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
		wLeft, wTop, wWidth, wHeight, NULL, NULL, hInstance, NULL);

	if ( hWnd ) {
		ShowWindow(hWnd, nCmdShow);
		UpdateWindow( hWnd );
	}
	return hWnd;
}

// ログオフやシャットダウンを行う
int QuitWindows(HWND hWnd, int mode)
{
	char *mes = NULL, *stmes = NULL, *fmes = NULL, *sTitle = NULL;
	UINT uFlags = 0;

	switch(mode&0x0f) {
		case QW_LOGOFF:
			sTitle = "現在のユーザーからログオフ";
			mes = "現在のユーザーからログオフしてもよろしいですか?";
			stmes = "ログオフしています...";
			fmes = "ログオフに失敗しました。";
			uFlags = EWX_LOGOFF;
			break;

		case QW_REBOOT:
			sTitle = (mode&QW_FORCE) ? "Windowsの強制再起動" : "Windowsの再起動";
			mes = (mode&QW_FORCE) ? "Windowsを強制再起動してもよろしいですか?" : "Windowsを再起動してもよろしいですか?";
			stmes = (mode&QW_FORCE) ? "Windowsを強制再起動しています..." : "Windowsを再起動しています...";
			fmes = (mode&QW_FORCE) ? "Windowsの強制再起動に失敗しました。" : "Windowsの再起動に失敗しました。";
			uFlags = EWX_REBOOT;
			break;

		default:
			sTitle = "Windowsの終了";
			mes = "Windowsを終了してもよろしいですか?";
			stmes = "Windowsを終了しています...";
			fmes = "Windowsの終了に失敗しました。";
			uFlags = EWX_SHUTDOWN;
			break;
	}

	if (mode&QW_FORCE) {
		uFlags |= EWX_FORCE;
	}

	if (IDYES == MessageBox(hWnd, mes, sTitle, MB_YESNO | MB_ICONQUESTION)) {
		GetQuitRight();
		if (hWnd) {
			SendMessage( hWnd, R7MW_STATUS_BAR, 0, (LPARAM)stmes );
		}
		if (ExitWindowsEx(uFlags, 0)) {
			if (hWnd) {
				DestroyWindow(hWnd);
			}
			return 1;
		}
		else {
			MessageBox(hWnd, fmes, sTitle, MB_OK | MB_ICONSTOP);
			return 0;
		}
	}

	return 2;
}
