#include "stdafx.h"
#include "rnsf7.h"
#include "inst.h"
#include "OpenSetting.h"
#include "commfunc.h"
// インストールの最終処理
bool install( void )
{
	REG  reg;
/*
	char lfname[MAX_PATH*2], sfname[MAX_PATH*2+3];
*/
	HWND mutexhd;
	bool bStay = 0;

	// 管理者権限を持っているかどうかを簡易のチェック
	if (reg.OpenKey(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Runonce", TREG_OPEN_CREATE)) {
		reg.CloseKey();
	}
	else {
		dispErrorMessage(NULL, MB_OK | MB_ICONSTOP, SOFTWARENAME" インストール",
			             "HKEY_LOCAL_MACHINE下のレジストリキーを開くことができませんでした。\nこのプログラムは、管理者権限で利用されることを前提にしています。このまま利用されると、一部の機能が働かなかったり、アンインストーラが登録されていなかったりします。\n\n管理者権限を持つユーザーがインストールをやりなおして下さい。\nAPIが報告した原因：",
						 getLastErrorString(tRegGetLastError()), "\n開こうとしたキー：HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Runonce", NULL, NULL, NULL);
		return 0;
	}

	// bootrund.exe の常駐停止と上書きコピー
	mutexhd = (HWND)CreateMutex(NULL, TRUE, "rnsf7bootrund");
	if (GetLastError() == ERROR_ALREADY_EXISTS) {
		HWND hWnd = FindWindow("rnsf7bootrund", NULL);

		if ( hWnd ) {
			SendMessage( hWnd, WM_DESTROY, 0, NULL );
			bStay = 1;
			Sleep(500);
			//MessageBox(NULL, "スタートアップレジストリ監視／削除が常駐しているため、常駐解除します。\nインストール完了後に改めて常駐します。", SOFTWARENAME" インストール", MB_OK | MB_ICONEXCLAMATION );
			Sleep(500);
		}
	}

	if ( mutexhd ) {
		CloseHandle(mutexhd);
		Sleep(500);
	}
	
	if ( tFileExist("bootrund.tmp") ) {
		if ( CopyFile( "bootrund.tmp", "bootrund.exe", FALSE ) ) {
			DeleteFile( "bootrund.tmp" );
		}
		else {
			MessageBox(NULL, "bootrund.exeのコピーに失敗しました。新バージョンのbootrund.exeは、bootrund.tmpという名称で保留されています。", SOFTWARENAME" インストール", MB_OK | MB_ICONEXCLAMATION );
		}
	}

	if ( bStay ) {
		if ( (HINSTANCE)32 >= ShellExecute( NULL, "open", "bootrund.exe", NULL, ".", SW_SHOWNORMAL ) ) {
			MessageBox(NULL, "スタートアップレジストリ監視／削除の再常駐に失敗しました。", SOFTWARENAME" インストール", MB_OK | MB_ICONEXCLAMATION );
		}
	}
/*
	if ( GetModuleFileName(NULL, lfname, _countof(lfname)) ) {
		int res;

		// デスクトップアイコンの作成
		if ( ReadRkv("inst_desktopicon", 0) == 0 ) {
			res = showInstDlg(NULL, SOFTWARENAME" インストール",
							"デスクトップにショートカットを作成しますか?",
							"「はい」をクリックすると、デスクトップに、「" SOFTWARENAME "」を呼び出すためのアイコンが作成されます。", NULL, false);

			if ( res & SIDLG_YES ) {
				char DesktopLink[MAX_PATH*2];

				lstrcpy(DesktopLink,GetDesktopFolder());
				lstrcat(DesktopLink, "\\" SOFTWARENAME ".lnk");
				if ( !MakeLink(lfname, "", DesktopLink) ) {
					MessageBox( NULL, "ショートカットの作成に失敗しました。", SOFTWARENAME" インストール", MB_OK | MB_ICONSTOP );
				}
			}

			if ( res & SIDLG_NEVER ) { // このダイアログをもう表示しない
				WriteRkv("inst_desktopicon", 1);
			}
		}

		// アンインストール情報の登録
		if ( ReadRkv("inst_uninstall", 0) == 0 ) {
			res = showInstDlg(NULL, SOFTWARENAME" インストール",
							"「プログラムの追加と削除」にアンインストールの情報を登録しますか?",
							"「はい」をクリックすると、「コントロール パネル」の「プログラムの追加と削除」（古いバージョンのWindowsでは「アプリケーションの追加と削除」という名前になっています）から、"SOFTWARENAME"をアンインストールすることができるようになります。", NULL, false);

			if ( res & SIDLG_YES ) {
				if (reg.OpenKey(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Rnsf7",TREG_OPEN_CREATE)) {
					reg.WriteString("DisplayName", SOFTWARENAME);
					sfname[0] = '\"';
					lstrcpy(sfname+1, lfname);
					lstrcat(sfname,"\" /D");
					reg.WriteString ("UninstallString",sfname);
					reg.CloseKey();
				}
				else {
					dispErrorMessage(NULL, MB_OK | MB_ICONWARNING, SOFTWARENAME" インストール",
						             "レジストリキー'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Rnsf7'を書き込みアクセスで開こうとしてエラーになりました。アンインストール情報を登録することができません。\nAPIが報告した原因：",
						             getLastErrorString(tRegGetLastError()), NULL, NULL, NULL, NULL);
				}
			}

			if ( res & SIDLG_NEVER ) { // このダイアログをもう表示しない
				WriteRkv("inst_uninstall", 1);
			}
		}
	}


	// インストール済み
	WriteRkv("inst_firstcheck", 1);

	MessageBox(NULL, SOFTWARENAME"のインストールが完了しました。\nインストール版を用いてスタートメニューに登録した場合は、「スタートメニュー」→「プログラム」→「INASOFT」→「"SOFTWARENAME"」から起動できます。\n"SOFTWARENAME"の設定を変更したい場合は、"SOFTWARENAME"を起動し、「設定」メニュー→「オプション」を開いて下さい。", SOFTWARENAME"インストール完了", MB_OK | MB_ICONINFORMATION);
*/
	return 0;
}
/* - 自己削除型アンインストーラ（どうもWindows 2000の「アプリケーションの追加と削除」ウィンドウが暴走してくれるようなので、この方法は使わないことにする
// sleep3.com : 3秒間スリープするためのDOS外部コマンド
const unsigned char sleep3com[28] = {0xb4,0x2c,0xe8,0x0e,0x00,0xe8,0x0b,0x00,0xe8,0x08,
                                     0x00,0xe8,0x05,0x00,0xb8,0x00,0x4c,0xcd,0x21,0x88,
                                     0xf7,0xcd,0x21,0x38,0xf7,0x74,0xfa,0xc3};

// delme.bat : 自身を削除するためのバッチファイル
const char *delmebat_9x = "@echo off\r\nECHO しばらくお待ちください...\r\nCD \\\r\nSLEEP3\r\nATTRIB -R -H -S %1\r\n:RETRY\r\n\\SLEEP3\r\nDEL %1\r\nIF EXIST %1 GOTO RETRY\r\nDEL \\SLEEP3.COM\r\nRMDIR %2\r\nCLS\r\nECHO アンインストールは完了しました。\r\nECHO このウィンドウは[×]ボタンを押して閉じてください。\r\nstart command.com /c del \\MYDEL.BAT\r\n";
const char *delmebat_NT = "@echo off\r\nECHO しばらくお待ちください...\r\nCD \\\r\nSLEEP3\r\nATTRIB -R -H -S %1\r\n:RETRY\r\n\\SLEEP3\r\nDEL %1\r\nIF EXIST %1 GOTO RETRY\r\nDEL \\SLEEP3.COM\r\nRMDIR %2\r\nCLS\r\nECHO アンインストールは完了しました。\r\nECHO このウィンドウは[×]ボタンを押して閉じてください。\r\nstart cmd.exe /c del \\MYDEL.BAT\r\n";
*/

// 各RSCファイルを個別にアンインストール
bool uninstall1( const char *rscfile )
{
	rsc( NULL, rscfile, ":UNINST", 1, NULL );				// :uninst ラベルを実行
	return DeleteFile( rscfile ) ? true : false;	// ファイルを削除
}

// 全RSCファイルを順にアンインストール
void uninstalln( void )
{
	WIN32_FIND_DATA520 ffd;
	HANDLE	ffh;
	UINT    i, n;
	char  **fnames;

	// 全RSCファイルのアンインストール
	n = 0;
	// *.RSC ファイルの数を数える
	if ( INVALID_HANDLE_VALUE != (ffh = FindFirstFile520("*.RSC", &ffd)) ) {
		do {
			// .rscの拡張子を持つファイル
			if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
				n++;
			}
		} while( FindNextFile520( ffh, &ffd ) );
		FindClose( ffh );
	}
	if ( n > 0 ) {
		fnames = (char**)malloc(n * sizeof(char *));

		if ( fnames ) {
			n = 0;
			// *.RSC ファイルをメモリへ格納していく
			if ( INVALID_HANDLE_VALUE != (ffh = FindFirstFile520("*.RSC", &ffd)) ) {
				do {
					// .rscの拡張子を持つファイル
					if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
						fnames[n++] = _strdup( ffd.cFileName );
					}
				} while( FindNextFile520( ffh, &ffd ) );
				FindClose( ffh );
			}

			for(i=0 ; i<n ; i++) {
				if ( fnames[i] ) {
					uninstall1( fnames[i] );
					safefree( fnames[i] );
				}
			}

			safefree( fnames );
		}
	}

	// 全RSSファイルのアンインストール
	n = 0;
	// *.RSS ファイルの数を数える
	if ( INVALID_HANDLE_VALUE != (ffh = FindFirstFile520("*.RSS", &ffd)) ) {
		do {
			// .rssの拡張子を持つファイル
			if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
				n++;
			}
		} while( FindNextFile520( ffh, &ffd ) );
		FindClose( ffh );
	}
	if ( n > 0 ) {
		fnames = (char**)malloc(n * sizeof(char *));

		if ( fnames ) {
			n = 0;
			// *.RSS ファイルをメモリへ格納していく
			if ( INVALID_HANDLE_VALUE != (ffh = FindFirstFile520("*.RSS", &ffd)) ) {
				do {
					// .rssの拡張子を持つファイル
					if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
						fnames[n++] = _strdup( ffd.cFileName );
					}
				} while( FindNextFile520( ffh, &ffd ) );
				FindClose( ffh );
			}

			for(i=0 ; i<n ; i++) {
				if ( fnames[i] ) {
					DeleteFile( fnames[i] );
					safefree( fnames[i] );
				}
			}

			safefree( fnames );
		}
	}
}

// アンインストーラ : 実行ファイルはアンインストーラを兼ねており、Windowsの次回起動時に削除されます。
bool uninstall( void )
{
	REG reg;

	if (IDYES == MessageBox(NULL, SOFTWARENAME"のアンインストールを行います。\n\n注意：「起動時に実行」等のバックアップデータも失われます。\n\nアンインストールを開始しますか?", SOFTWARENAME" アンインストール", MB_YESNO | MB_ICONQUESTION)) {
		// いじくるつくーるのレジストリキーを削除
		const HKEY hives[2] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE};
		const char *hivenames[2] = {"HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE"};
		int i;

		for(int hi=0 ; hi<2 ; ++hi) {
			if (reg.OpenKey(hives[hi], "Software\\InaSoftAns", TREG_OPEN_CREATE)) {
				reg.DeleteSubKey( "Rnsf7" );
				RegQueryInfoKey(reg.GetHKey(), NULL, 0, NULL, (PULONG)&i, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
				reg.CloseKey();
				if (i == 0) { // 他にINASOFT製アプリケーションがなければInaSoftAnsキー自体も削除
					RegDeleteKey(hives[hi], "Software\\InaSoftAns");
				}
			}
			else {
				dispErrorMessage(NULL, MB_OK | MB_ICONWARNING, SOFTWARENAME" アンインストール", "レジストリキー'", hivenames[hi], "\\Software\\InaSoftAns",
								 "'を書き込みアクセスで開こうとしてエラーになりました。\nAPIが報告した原因：", getLastErrorString(tRegGetLastError()), NULL);
			}
		}

		// アンインストール情報からも削除
		RegDeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Rnsf7");

		// 実行ファイルの削除登録をレジストリに行う
		{
			char exename[MAX_PATH*2], txtname[MAX_PATH*2], dirname[MAX_PATH*2], cmdname[MAX_PATH*4];
			int  len;

			if ( GetModuleFileName(NULL, exename, _countof(exename)) ) {
				if ( reg.OpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce", TREG_OPEN_CREATE ) ) {
					getFileNameOnly(exename, txtname, _countof(txtname));
					lstrcat(txtname, ".TXT");
					getDirectoryName(exename, dirname, _countof(dirname));
					len = lstrlen( dirname );
					if ( len >= 4 && !isKanji1(dirname,len-2) && dirname[len-1] == '\\' ) { // ルートディレクトリを示しているのではない終わりの\は削除
						dirname[len-1] = 0;
					}

					// 実行ファイルを削除する
					// ただし、アンインストール直後にインストールしたという場合、削除はまずい。この場合、ドキュメントが同一ディレクトリ内にあるとして処理をとばす
					wsprintf(cmdname, "%s /C IF NOT EXIST \"%s\" DEL \"%s\"", isNT?"CMD.EXE":"COMMAND.COM", txtname, exename);
					reg.WriteString( "Rnsf7UninstallP1", cmdname, TREG_NORMAL_SZ );
					if ( len >= 4 ) { // len == 3 はルートディレクトリの処理であると見なせるので、この場合は何もしない
						wsprintf(cmdname, "%s /C IF NOT EXIST \"%s\" RD \"%s\"", isNT?"CMD.EXE":"COMMAND.COM", txtname, dirname);
						reg.WriteString( "Rnsf7UninstallP2", cmdname, TREG_NORMAL_SZ );
					}
					reg.CloseKey();
					MessageBox(NULL, SOFTWARENAME"をアンインストールしました。\n他ユーザーも利用していた場合、他ユーザーのレジストリキーについては削除されていません。他ユーザーのレジストリキーも削除したい場合は、他ユーザーの\n\n　HKEY_CURRENT_USER\\Software\\InaSoftAns\\Rnsf7\n\nキー以下を削除して下さい。\n\nなお、Rnsf7.exeは現時点では削除できなかったので、次のWindows起動時に削除します。", SOFTWARENAME" アンインストール", MB_OK | MB_ICONINFORMATION);

					return 0;
				}
				else {
					dispErrorMessage(NULL, MB_OK | MB_ICONWARNING, SOFTWARENAME" アンインストール", "レジストリキー'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce'を書き込みアクセスで開こうとしてエラーになりました。\nAPIが報告した原因：",
						             getLastErrorString(tRegGetLastError()), NULL, NULL, NULL, NULL);
				}
			}
		}
		MessageBox(NULL, "アンインストールに必要な作業は終わりましたが、Rnsf7.exeを次のWindows起動時に削除する設定を登録できませんでした。Rnsf7.exeは手動で削除して下さい。", SOFTWARENAME" アンインストール", MB_OK | MB_ICONINFORMATION);
		
/* - 自己削除型アンインストーラ（どうもWindows 2000の「アプリケーションの追加と削除」ウィンドウが暴走してくれるようなので、この方法は使わないことにする
		// いじくるつくーるの自己削除アンインストーラ
		MessageBox(NULL, "いじくるつくーるをアンインストールしました。\n他ユーザーも利用していた場合、他ユーザーのレジストリキーについては削除されていません。他ユーザーのレジストリキーも削除したい場合は、他ユーザーの\n\n　HKEY_CURRENT_USER\\Software\\InaSoftAns\\Rnsf7\n\nキー以下を削除して下さい。\n\n[OK]ボタンを押すと、アンインストーラは自身を削除して終了します。\n[OK]ボタンを押したら、しばらくお待ちください。", SOFTWARENAME" アンインストール", MB_OK | MB_ICONINFORMATION);

		HANDLE hFileBat;
		DWORD dwNum;
		char cmdparam[600], lcdir[MAX_PATH], lfname[MAX_PATH];

		GetCurrentDirectory(MAX_PATH, lcdir);
		if ( !GetModuleFileName(NULL, lfname, MAX_PATH) ) {
			lstrcpy( lfname, "rnsf7.exe" ); // 万が一エラーだった場合は、ダメかもしれないけど、普通にファイル名を入れておく
		}
		wsprintf(cmdparam,"/C \\MYDEL.BAT \"%s\" \"%s\"", lfname, lcdir);

		if (INVALID_HANDLE_VALUE != (hFileBat = CreateFile("\\MYDEL.BAT",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))) {
			WriteFile(hFileBat,isNT?delmebat_NT:delmebat_9x,lstrlen(isNT?delmebat_NT:delmebat_9x),&dwNum,NULL);
			CloseHandle(hFileBat);
			if (INVALID_HANDLE_VALUE != (hFileBat = CreateFile("\\SLEEP3.COM",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))) {
				WriteFile(hFileBat,sleep3com,28,&dwNum,NULL);
				CloseHandle(hFileBat);
				ShellExecute(GetDesktopWindow(), "open", isNT?"cmd.exe":"command.com", cmdparam,"\\",SW_SHOWMINNOACTIVE);
			}
			else {
				MessageBox(NULL, SOFTWARENAME"のアンインストールの最終課程でエラーがありました。\nRnsf7.exe、それの含まれるフォルダ、ルートディレクトリの MYDEL.BATは、ユーザー自身の手で削除してください。", SOFTWARENAME" アンインストール", MB_OK | MB_ICONSTOP );
			}
		}
		else {
			MessageBox(NULL, SOFTWARENAME"のアンインストールの最終課程でエラーがありました。\nRnsf7.exeおよび、それの含まれるフォルダは、ユーザー自身の手で削除してください。", SOFTWARENAME" アンインストール", MB_OK | MB_ICONSTOP );
		}
*/
	}
	return 0;
}
/*
// インストール時に表示される共通ダイアログのプロシージャ
const char *g_info0, *g_info1,*g_info2, *g_url;
bool        g_di_check, g_imgvisible;

LRESULT CALLBACK dlgInst( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
	switch( message ) {
		case WM_INITDIALOG:
			if (g_info0) SetWindowText(hDlg, g_info0);
			SetDlgItemText(hDlg, IDC_INFO1, g_info1);
			SetDlgItemText(hDlg, IDC_INFO2, g_info2);
			if ( !g_di_check ) {
                EnableWindow(GetDlgItem(hDlg, IDC_CHECK_NEVERSHOW), FALSE);
			}
			if ( g_url ) { // URL指定の場合は、ボタンを表示し、フォーカスを合わせる
				// Web表示のボタンを可視化
				HWND hGoWebButton = GetDlgItem(hDlg, IDC_GOWEB);
				ShowWindow(hGoWebButton, SW_SHOW);
				SetFocus(hGoWebButton);
			}
			//if ( g_imgvisible ) { // 画像ＯＮ
			//	ShowWindow(GetDlgItem(hDlg, IDC_STATIC_JWBANNER), SW_SHOW);
            //}
			return TRUE;

		case WM_COMMAND:
			switch ( LOWORD(wParam) ) {
				case IDOK:
					EndDialog(hDlg, SIDLG_YES | (SendDlgItemMessage(hDlg, IDC_CHECK_NEVERSHOW, BM_GETCHECK, 0, 0) == BST_CHECKED ? SIDLG_NEVER : 0));
					return TRUE;

				case IDCANCEL:
					EndDialog(hDlg, SIDLG_NO | (SendDlgItemMessage(hDlg, IDC_CHECK_NEVERSHOW, BM_GETCHECK, 0, 0) == BST_CHECKED ? SIDLG_NEVER : 0));
					return TRUE;

				case IDC_GOWEB:
					if ( g_url ) {
						if ((HINSTANCE)32 >= ShellExecute(hDlg, "open", g_url, NULL, NULL, SW_SHOWNORMAL))
							MessageBox(hDlg, "ブラウザを開けません。\nブラウザが正しくインストールされているかを確認して下さい。", szTitle, MB_OK | MB_ICONSTOP);
					}
					return TRUE;
			}
			break;
	}
    return FALSE;
}

// インストール時に表示される共通ダイアログを表示する
// hWnd = 親ウィンドウ（NULLの場合、インストール時と見なし、
//                     「次回以降は〜」チェックボックスを活性化する）
// title = ウィンドウタイトル（省略時は「インストール」）
// info1 = インフォメーションテキスト１（短い説明文）
// info2 = インフォメーションテキスト２（長い説明文）
// url   = Webサイトを表示するボタンを設置し、それにフォーカスを合わせる場合に指定する
// imgvisible = 画像を表示する
// 戻り値 : bit0=0 … No  1 … Yes
//          bit1=1 … 「次回以降は〜」がチェックされた
int showInstDlg( HWND hWnd, const char *title, const char *info1, const char *info2, const char *url, bool imgvisible )
{
	g_info0 = title;
	g_info1 = info1 ? info1 : "";
	g_info2 = info2 ? info2 : "";
	g_url = url;
	g_di_check = hWnd ? 0 : 1;
	g_imgvisible = imgvisible;
	return (int)DialogBox(hInst, (LPCTSTR)IDD_INSTDLG, hWnd, (DLGPROC)dlgInst);
}
*/