/*	
 *	main.c
 *
 *	IPEnableRouter - IP転送機能切り替えプログラム for Windows 2000/XP
 *	Copyright (C) 2005 Naoyuki Sawa
 *
 *	* Sat Aug 06 21:40:00 JST 2005 Naoyuki Sawa
 *	- 作成開始。
 *	* Sun Aug 20 05:20:00 JST 2005 Naoyuki Sawa
 *	- 参照・設定するレジストリ値の名前を「EnableRouter」→「IPEnableRouter」に修正。
 *	  Web上には、「EnableRouter」と書いてある資料がいくつかありますが、それらは誤りでした。
 */
#define STRICT
#include <windows.h>
#include "resource.h"

#define APP_TITLE	"IPEnableRouter"

/* Windows 2000、または、Windows XPのIP転送機能をOn/Offする方法：
 * "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter"=0、または、エントリが無ければ、IP転送機能Offです。
 * "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter"=1　　　　　　　　　　　ならば、IP転送機能On です。
 */
#define ROOT_KEY	HKEY_LOCAL_MACHINE
#define KEY_NAME	"System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
#define VALUE_NAME	"IPEnableRouter"

BOOL CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int QueryValue();
int SetValue(int value);

int PASCAL
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	int retval;
	HANDLE mutex;
	OSVERSIONINFO os;

	/* 二重起動防止用のミューテクスを作成します。 */
	mutex = CreateMutex(NULL, FALSE, APP_TITLE);
	if(mutex) {

		/* 二重起動防止用のミューテクスをロックします。 */
		retval = WaitForSingleObject(mutex, 0);
		if(retval == WAIT_OBJECT_0) {

			/* Windows 2000/XP以降であることを確認します。
			 * × Windows 95/98/Me    dwPlatformId=1 dwMajorVersion=4 dwMinorVersion=?
			 * × Windows NT 3.x      dwPlatformId=2 dwMajorVersion=3 dwMinorVersion=?
			 * × Windows NT 4.0      dwPlatformId=2 dwMajorVersion=4 dwMinorVersion=0
			 * ○ Windows 2000        dwPlatformId=2 dwMajorVersion=5 dwMinorVersion=0
			 * ○ Windows XP          dwPlatformId=2 dwMajorVersion=5 dwMinorVersion=1
			 * ○ Windows Server 2003 dwPlatformId=2 dwMajorVersion=5 dwMinorVersion=2
			 */
			os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
			retval = GetVersionEx(&os);
			if(!retval) {
				MessageBox(NULL, "OSのバージョン情報が取得できません。", APP_TITLE, MB_ICONSTOP | MB_OK);
				goto L_ERR;
			}
			if((os.dwPlatformId != VER_PLATFORM_WIN32_NT) || (os.dwMajorVersion < 5)) {
				MessageBox(NULL, "このアプリケーションはWindows 2000/XP以降専用です。", APP_TITLE, MB_ICONSTOP | MB_OK);
				goto L_ERR;
			}

			/* メインダイアログを表示します。 */
			DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DlgProc);
L_ERR:
			/* 二重起動防止用のミューテクスをロック解除します。 */
			ReleaseMutex(mutex);
		}

		/* 二重起動防止用のミューテクスを解放します。 */
		CloseHandle(mutex);
	}

	return 0;
}

/* ラジオボタンを変更する度にBN_CLICKEDが二回送られて来るので、二回目を無視するために選択状態を覚えておきます。 */
int id_sel;

BOOL CALLBACK
DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	int retval;
	int id;
	int notify;
	HICON icon;

	switch(uMsg) {
	case WM_INITDIALOG:
		/* ダイアログウインドウにアイコンを設定します。 */
		icon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON));
		if(icon) {
			SendMessage(hWnd, WM_SETICON, ICON_BIG  , (LPARAM)icon);
			SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon);
		}
		/* 現在のIP転送設定をラジオボタンの初期状態に反映します。 */
		retval = QueryValue();
		if(retval) { /* IPEnableRouter=1 */
			id_sel = IDC_ON;
		} else {     /* IPEnableRouter=0 */
			id_sel = IDC_OFF;
		}
		SendDlgItemMessage(hWnd, id_sel, BM_SETCHECK, BST_CHECKED, 0);
		return TRUE;

	case WM_COMMAND:
		/* ラジオボタンが選択されたら、すぐにIP転送設定へ反映します。 */
		id     = LOWORD(wParam);
		notify = HIWORD(wParam);
		switch(id) {
		case IDC_ON:
		case IDC_OFF:
			if((notify == BN_CLICKED) && (id != id_sel)) {
				id_sel = id;
				retval = SetValue(id_sel == IDC_ON);
				if(retval != 0) {
					MessageBox(hWnd, "レジストリの書き込みに失敗しました。", APP_TITLE, MB_ICONEXCLAMATION | MB_OK);
				}
			}
			return TRUE;
		}
		break;

	case WM_CLOSE:
		/* 右上の[×]ボタンが押されたら、ダイアログを終了します。 */
		EndDialog(hWnd, 0);
		return TRUE;
	}

	return FALSE;
}

/* "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter"の値を取得します。
 * このエントリが存在しない場合、0と同じ意味ですので、値の取得に失敗した場合は0を返します。
 */
int
QueryValue()
{
	HKEY key = NULL;
	int value = 0; /* IPEnableRouterのエントリが無い場合は、IPEnableRouter=0と同じです。 */
	//
	int retval;
	int type;
	int size;

	/* "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"を開きます。 */
	retval = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KEY_NAME, 0, KEY_ALL_ACCESS, &key);
	if(retval != 0) {
		goto L_EXIT;
	}

	/* "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter"を取得します。 */
	size = sizeof value;
	retval = RegQueryValueEx(key, VALUE_NAME, NULL, &type, (void*)&value, &size);
	if(retval != 0) {
		goto L_EXIT;
	}

L_EXIT:

	/* "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"を開いていたら、閉じます。 */
	if(key) {
		RegCloseKey(key);
	}

	return value;
}

/* "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter"の値を設定します。
 * 成功ならば0、失敗ならば0以外の値を返します。
 */
int
SetValue(int value)
{
	HKEY key = NULL;
	//
	int retval;

	/* "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"を開きます。 */
	retval = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KEY_NAME, 0, KEY_ALL_ACCESS, &key);
	if(retval != 0) {
		goto L_EXIT;
	}

	/* "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter"を設定します。 */
	retval = RegSetValueEx(key, VALUE_NAME, 0, REG_DWORD, (void*)&value, sizeof value);
	if(retval != 0) {
		goto L_EXIT;
	}

L_EXIT:

	/* "HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"を開いていたら、閉じます。 */
	if(key) {
		RegCloseKey(key);
	}

	return retval;
}

