#include "stdafx.h"
#include "refresh.h"
#include "addctrl.h"
#include "token.h"
#include "commfunc.h"

static void system_notify(void)
{
	static DWORD_PTR snrv;

	SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_ABORTIFHUNG | SMTO_NORMAL, 5000, &snrv);
}

// 他のタスクに設定変更の通知を行う(Notify)
static void _notify_otherapp( void *hMainWindow )
{
	static volatile BYTE sflag = 0;

	if ( sflag == 0 ) {
		sflag = 1;
		SendMessage( (HWND)hMainWindow, R7MW_STATUS_BAR, 2, (LPARAM)"設定の変更を他のアプリケーションに通知しています..." );
		system_notify();
		SendMessage( (HWND)hMainWindow, R7MW_STATUS_BAR, 2, (LPARAM)"設定の変更を他のアプリケーションに通知しました。設定が有効にならない場合は、システムを再起動してみて下さい。" );
		sflag = 0;
	}
}

// シェルのアイコン再描画を行うべき設定変更(Flash)
// システムアイコンの変更を通知するため、アイコンのサイズを +1 して -1 する。
static void _refresh_otherapp( void *hMainWindow )
{
	HKEY hKey;
	UINT i = 32;
	static volatile BYTE sflag = 0;

	if ( sflag == 0 ) {
		sflag = 1;
		SendMessage( hMainWindow, R7MW_STATUS_BAR, 2, (LPARAM)"シェルに設定の変更を通知しています..." );

		if ( NULL != (hKey = tRegOpenKey(HKEY_CURRENT_USER, "Control Panel\\desktop\\windowmetrics", TREG_OPEN_CREATE)) ) {
			char buf[16], itbuf[16];

			tRegReadString(hKey, "Shell Icon Size", buf, 11);
			if (0 == (i = atoi(buf))) {
				i = 32;
			}

			if ( 0 == _ultoa_s(i>=127?i-1:i+1, itbuf, _countof(itbuf), 10) ) {
				tRegWriteString(hKey, "Shell Icon Size", itbuf, TREG_NORMAL_SZ );
			}
			RegCloseKey( hKey );
		}

		system_notify();

		if ( NULL != (hKey = tRegOpenKey(HKEY_CURRENT_USER, "Control Panel\\desktop\\windowmetrics", TREG_OPEN_CREATE)) ) {
			char itbuf[16];

			if ( 0 == _ultoa_s(i, itbuf, _countof(itbuf), 10) ) {
				tRegWriteString(hKey, "Shell Icon Size", itbuf, TREG_NORMAL_SZ );
			}
			RegCloseKey( hKey );
		}

		_notify_otherapp( hMainWindow );
		sflag = 0;
	}
	
}

void notify_otherapp( HWND hMainWindow, HWND hWnd, int how )
{
	switch( how ) {
		case 2:
			if ( -1 != _beginthread( _refresh_otherapp, 0, (void *)hMainWindow ) ) {
				return;
			}
			// そのまま下へ
		case 1:
			if ( -1 != _beginthread( _notify_otherapp, 0, (void *)hMainWindow ) ) {
				return;
			}
	}

	MessageBox(hWnd, "設定の変更を他のアプリケーションに通知するためのスレッドの生成に失敗しました。", "更新通知", MB_OK | MB_ICONSTOP );
}

// 設定変更を他のタスクに伝える i=0:何もしないことを予約 1:単純通知予約 2:シェル刺激予約 3:再起動予約 4:予約していたリフレッシュを実行
int system_refresh( HWND hMainWindow, HWND hWnd, BYTE i )
{
	static BYTE rsv_i;

	/* 予約 */
	if ( i == 0 ) { // 予約解除
        rsv_i = 0;
	}

	else if ( 1 <= i && i <= 3 ) { // 予約しておいて、あとで実行
		if ( rsv_i < i ) { // 設定しようとしている予約よりも高い数が設定されていた場合、書き換えはしない
			rsv_i = i;
		}
	}

	/* 実際の実行 */
	else if ( i == 4 ) { // 事前に予約されていたリフレッシュを実行
		switch( rsv_i ) {
			case 3: // 再起動を伴う設定変更(Reboot)
				if ( tp_nreboot == 0 && rnsf7RegRead( "Nreboot", 0 ) == 0 ) {
					if ( WinReboot(hMainWindow, hWnd) )
						return 1;
				}
				notify_otherapp( hMainWindow, hWnd, 1 );
				break;

			case 2: // シェルのアイコン再描画を行うべき設定変更(Flash)
				notify_otherapp( hMainWindow, hWnd, 2 );
				break;

			case 1: // 他のタスクに設定変更の通知を行う(Notify)
				notify_otherapp( hMainWindow, hWnd, 1 );
				break;
		}
		rsv_i = 0; // 予約されていたリフレッシュ方法をクリア
	}

	return 0;
}

// Windows再起動
int  WinReboot(HWND hMainWindow, HWND hWnd)
{
	int  QReboot = rnsf7RegRead( "QReboot", 0 );

	if (IDYES == MessageBox(hWnd, ((isNT || winver >= 490) && QReboot)?"設定変更を有効にするために、ログオフしてもよろしいですか?":"設定変更を有効にするために、再起動してもよろしいですか?", ((isNT || winver >= 490) && QReboot)?"ログオフ":"再起動", MB_YESNO | MB_ICONQUESTION)) {
		if ( isNT ) {
			GetQuitRight();
			if (QReboot) {
				SendMessage( hMainWindow, R7MW_STATUS_BAR, 0, (LPARAM)"ログオフしています..." );
				if (ExitWindowsEx(EWX_LOGOFF, 0)) {
					DestroyWindow( hMainWindow );
					return 1;
				}
				else {
					SendMessage( hMainWindow, R7MW_STATUS_BAR, 0, (LPARAM)"ログオフできませんでした。" );
					MessageBox(hWnd, "ログオフに失敗しました", "ログオフ", MB_OK | MB_ICONSTOP);
				}
			}
			else {
				SendMessage( hMainWindow, R7MW_STATUS_BAR, 0, (LPARAM)"コンピュータを再起動しています..." );
				if (ExitWindowsEx(EWX_REBOOT,0)) {
					DestroyWindow( hMainWindow );
					return 1;
				}
				else {
					SendMessage( hMainWindow, R7MW_STATUS_BAR, 0, (LPARAM)"コンピュータを再起動できませんでした。" );
					MessageBox(hWnd, "再起動に失敗しました。\nなるべく速やかに、正しい手段でシステムを再起動して下さい。", "再起動", MB_OK | MB_ICONSTOP);
				}
			}
		}
#if _MSC_VER < 1500
		else {
			if (QReboot) {
				if ( winver >= 490 ) {
				SendMessage( hMainWindow, R7MW_STATUS_BAR, 0, (LPARAM)"ログオフしています..." );
					if (ExitWindowsEx(EWX_LOGOFF, 0)) {
						DestroyWindow( hMainWindow );
						return 1;
					}
					else {
						SendMessage( hMainWindow, R7MW_STATUS_BAR, 0, (LPARAM)"ログオフできませんでした。" );
						MessageBox(hWnd, "ログオフに失敗しました", "ログオフ", MB_OK | MB_ICONSTOP);
					}
				}
				else {
					SendMessage( hMainWindow, R7MW_STATUS_BAR, 0, (LPARAM)"システムのみを再起動しています..." );
					ShellExecute(hWnd, "open", "rundll.exe", "user.exe,exitwindowsexec", 0, SW_SHOWNORMAL);
				}
			}
			else {
				SendMessage( hMainWindow, R7MW_STATUS_BAR, 0, (LPARAM)"コンピュータを再起動しています..." );
				EndDialog(hWnd, 1);
				if (ExitWindowsEx(EWX_REBOOT,0)) {
					DestroyWindow( hMainWindow );
					return 1;
				}
				else {
					SendMessage( hMainWindow, R7MW_STATUS_BAR, 0, (LPARAM)"コンピュータを再起動できませんでした。" );
					MessageBox(hWnd,"再起動に失敗しました。\nなるべく速やかに、正しい手段でシステムを再起動して下さい。", "再起動", MB_OK | MB_ICONSTOP);
				}
			}
		}
#endif // _MSC_VER < 1500
	}

	return 0;
}
