VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/PKCS11/cryptoki.h
blob: 821d73a7ecb119a3ac16de489d7d714a9297ea9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* cryptoki.h include file for PKCS #11. */
/* $Revision: 1.4 $ */

/* License to copy and use this software is granted provided that it is
 * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
 * (Cryptoki)" in all material mentioning or referencing this software.

 * License is also granted to make and use derivative works provided that
 * such works are identified as "derived from the RSA Security Inc. PKCS #11
 * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
 * referencing the derived work.

 * RSA Security Inc. makes no representations concerning either the
 * merchantability of this software or the suitability of this software for
 * any particular purpose. It is provided "as is" without express or implied
 * warranty of any kind.
 */

/* This is a sample file containing the top level include directives
 * for building Win32 Cryptoki libraries and applications.
 */

#ifndef ___CRYPTOKI_H_INC___
#define ___CRYPTOKI_H_INC___

#pragma pack(push, cryptoki, 1)

/* Specifies that the function is a DLL entry point. */
#define CK_IMPORT_SPEC __declspec(dllimport)

/* Define CRYPTOKI_EXPORTS during the build of cryptoki libraries. Do
 * not define it in applications.
 */
#ifdef CRYPTOKI_EXPORTS
/* Specified that the function is an exported DLL entry point. */
#define CK_EXPORT_SPEC __declspec(dllexport)
#else
#define CK_EXPORT_SPEC CK_IMPORT_SPEC
#endif

/* Ensures the calling convention for Win32 builds */
#define CK_CALL_SPEC __cdecl

#define CK_PTR *

#define CK_DEFINE_FUNCTION(returnType, name) \
  returnType CK_EXPORT_SPEC CK_CALL_SPEC name

#define CK_DECLARE_FUNCTION(returnType, name) \
  returnType CK_EXPORT_SPEC CK_CALL_SPEC name

#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
  returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)

#define CK_CALLBACK_FUNCTION(returnType, name) \
  returnType (CK_CALL_SPEC CK_PTR name)

#ifndef NULL_PTR
#define NULL_PTR 0
#endif

#include "pkcs11.h"

#pragma pack(pop, cryptoki)

#endif /* ___CRYPTOKI_H_INC___ */
314' href='#n314'>314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
/*
 Copyright (c) 2005 TrueCrypt Developers Association. All rights reserved.

 Governed by the TrueCrypt License 3.0 the full text of which is contained in
 the file License.txt included in TrueCrypt binary and source code distribution
 packages.
*/

#include <windows.h>
#include "Dlgcode.h"
#include "Hotkeys.h"
#include "Language.h"
#include "Mount.h"
#include "Resource.h"

#include <Strsafe.h>

#define MAX_KEY_COMB_NAME_LEN	260

TCHOTKEY	Hotkeys [NBR_HOTKEYS];
static TCHOTKEY	tmpHotkeys [NBR_HOTKEYS];

static int nSelectedHotkeyId;
static UINT currentVKeyCode;


static void ScanAndProcessKey (UINT *vKeyCode, wchar_t *keyName)
{
	UINT vKey;
	*vKeyCode = 0;

	for (vKey = 0; vKey <= 0xFF; vKey++)
	{
		if (GetAsyncKeyState (vKey) < 0)
		{
			if (GetKeyName (vKey, keyName))	// If the key is allowed and its name has been resolved
				*vKeyCode = vKey;
		}
	}
}


/* Returns TRUE if the key is allowed and its name is resolved. */
BOOL GetKeyName (UINT vKey, wchar_t *keyName)
{
	BOOL result = TRUE;

	if (vKey >= 0x30 && vKey <= 0x5a)	
	{
		// ASCII characters
		StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%hc", (char) vKey);
	}
	else if (vKey >= 0xE9 && vKey <= 0xF5)	
	{
		// OEM-specific
		StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM-%d", vKey);
	}
	else if (vKey >= VK_F1 && vKey <= VK_F24)
	{
		// F1-F24
		StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"F%d", vKey - VK_F1 + 1);
	}
	else if (vKey >= VK_NUMPAD0 && vKey <= VK_NUMPAD9)
	{
		// Numpad numbers
		StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s %d", GetString ("VK_NUMPAD"), vKey - VK_NUMPAD0); 
	}
	else
	{
		switch (vKey)
		{
		case VK_MULTIPLY:	StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s *", GetString ("VK_NUMPAD")); break;
		case VK_ADD:		StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s +", GetString ("VK_NUMPAD")); break;
		case VK_SEPARATOR:	StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s Separator", GetString ("VK_NUMPAD")); break;
		case VK_SUBTRACT:	StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s -", GetString ("VK_NUMPAD")); break;
		case VK_DECIMAL:	StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s .", GetString ("VK_NUMPAD")); break;
		case VK_DIVIDE:		StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s /", GetString ("VK_NUMPAD")); break;
		case VK_OEM_1:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 1 (';')"); break;
		case VK_OEM_PLUS:	StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"+"); break;
		case VK_OEM_COMMA:	StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L","); break;
		case VK_OEM_MINUS:	StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"-"); break;
		case VK_OEM_PERIOD:	StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L".");	break;
		case VK_OEM_2:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 2 ('/')"); break;
		case VK_OEM_3:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 3 (`)"); break;
		case VK_OEM_4:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 4 ('[')"); break;
		case VK_OEM_5:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 5 ('\\')"); break;
		case VK_OEM_6:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 6 (']')"); break;
		case VK_OEM_7:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 7 (')"); break;
		case VK_OEM_8:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 8"); break;
		case VK_OEM_AX:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM AX"); break;
		case VK_OEM_102:	StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 102"); break;
		case VK_ICO_HELP:	StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"ICO_HELP"); break;
		case VK_ICO_00:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"ICO_00"); break;
		case VK_ICO_CLEAR:	StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"ICO_CLEAR"); break;
		case VK_ATTN:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"Attn"); break;
		case VK_CRSEL:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"CrSel"); break;
		case VK_EXSEL:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"ExSel"); break;
		case VK_EREOF:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"Erase EOF"); break;
		case VK_PA1:		StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"PA1"); break;
		case VK_OEM_CLEAR:	StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM Clear"); break;

		case 0:
		case 1:
		case 0xFF:
			result = FALSE;
			break;

		default:
			{
				char key[16];
				wchar_t *desc;
				StringCbPrintfA (key, sizeof(key),"VKEY_%02X", vKey);
				desc = GetString (key);
				if (desc == UnknownString)
					result = FALSE;
				else
					StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, desc);
			}
		}
	}
	return result;
}


static BOOL ShortcutInUse (UINT vKeyCode, UINT modifiers, TCHOTKEY hotkeys[])
{
	int i;

	for (i = 0; i < NBR_HOTKEYS; i++)
	{
		if (hotkeys[i].vKeyCode == vKeyCode && hotkeys[i].vKeyModifiers == modifiers)
			return TRUE;
	}
	return FALSE;
}


void UnregisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[])
{
	int i;

	for (i = 0; i < NBR_HOTKEYS; i++)
	{
		if (hotkeys[i].vKeyCode != 0)
			UnregisterHotKey (hwndDlg, i);

	}
}


BOOL RegisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[])
{
	BOOL result = TRUE;
	int i;

	for (i = 0; i < NBR_HOTKEYS; i++)
	{
		if (hotkeys[i].vKeyCode != 0
		&& !RegisterHotKey (hwndDlg, i, hotkeys[i].vKeyModifiers, hotkeys[i].vKeyCode))
			result = FALSE;
	}

	return result;
}


static void DisplayHotkeyList (HWND hwndDlg)
{
	LVITEMW item;
	HWND hList = GetDlgItem (hwndDlg, IDC_HOTKEY_LIST);
	int i;
	wchar_t ShortcutMod [MAX_KEY_COMB_NAME_LEN];
	wchar_t ShortcutFinal [MAX_KEY_COMB_NAME_LEN*2];
	wchar_t Shortcut [MAX_KEY_COMB_NAME_LEN];

	SendMessage (hList, LVM_DELETEALLITEMS,0, (LPARAM)&item);

	for (i = 0; i < NBR_HOTKEYS; i++)
	{
		memset (&item,0,sizeof(item));
		item.mask = LVIF_TEXT;
		item.iItem = i;
		item.iSubItem = 0;

		switch (i)
		{
			
		case HK_AUTOMOUNT_DEVICES:	
			item.pszText = GetString ("HK_AUTOMOUNT_DEVICES");
			break;

		case HK_DISMOUNT_ALL:	
			item.pszText = GetString ("HK_DISMOUNT_ALL");
			break;

		case HK_WIPE_CACHE:	
			item.pszText = GetString ("HK_WIPE_CACHE");
			break;

		case HK_DISMOUNT_ALL_AND_WIPE:	
			item.pszText = GetString ("HK_DISMOUNT_ALL_AND_WIPE");
			break;

		case HK_FORCE_DISMOUNT_ALL_AND_WIPE:	
			item.pszText = GetString ("HK_FORCE_DISMOUNT_ALL_AND_WIPE");
			break;

		case HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT:	
			item.pszText = GetString ("HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT");
			break;

		case HK_MOUNT_FAVORITE_VOLUMES:	
			item.pszText = GetString ("HK_MOUNT_FAVORITE_VOLUMES");
			break;

		case HK_SHOW_HIDE_MAIN_WINDOW:	
			item.pszText = GetString ("HK_SHOW_HIDE_MAIN_WINDOW");
			break;

		case HK_CLOSE_SECURITY_TOKEN_SESSIONS:
			item.pszText = GetString ("IDM_CLOSE_ALL_TOKEN_SESSIONS");
			break;

		default:		
			item.pszText = L"[?]";
		}

		SendMessageW (hList,LVM_INSERTITEMW,0,(LPARAM)&item);

		item.iSubItem = 1;
		Shortcut[0] = 0;
		ShortcutMod[0] = 0;

		if (GetKeyName (tmpHotkeys[i].vKeyCode, Shortcut))
		{
			if (tmpHotkeys[i].vKeyModifiers & MOD_CONTROL)
			{
				StringCbCatW (ShortcutMod, sizeof(ShortcutMod),GetString ("VK_CONTROL"));
				StringCbCatW (ShortcutMod, sizeof(ShortcutMod),L"+");
			}

			if (tmpHotkeys[i].vKeyModifiers & MOD_SHIFT)
			{
				StringCbCatW (ShortcutMod, sizeof(ShortcutMod),GetString ("VK_SHIFT"));
				StringCbCatW (ShortcutMod, sizeof(ShortcutMod),L"+");
			}

			if (tmpHotkeys[i].vKeyModifiers & MOD_ALT)
			{
				StringCbCatW (ShortcutMod, sizeof(ShortcutMod),GetString ("VK_ALT"));
				StringCbCatW (ShortcutMod, sizeof(ShortcutMod),L"+");
			}

			if (tmpHotkeys[i].vKeyModifiers & MOD_WIN)
			{
				StringCbCatW (ShortcutMod, sizeof(ShortcutMod),GetString ("VK_WIN"));
				StringCbCatW (ShortcutMod, sizeof(ShortcutMod),L"+");
			}

			StringCbPrintfW (ShortcutFinal, sizeof(ShortcutFinal), L"%s%s", ShortcutMod, Shortcut);
			item.pszText = ShortcutFinal;
		}
		else
			item.pszText = L"";

		SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&item); 
	}
}



BOOL CALLBACK HotkeysDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{	
	WORD lw = LOWORD (wParam);
	WORD hw = HIWORD (wParam);
	static BOOL bKeyScanOn;
	static BOOL bTPlaySoundOnSuccessfulHkDismount;
	static BOOL bTDisplayBalloonOnSuccessfulHkDismount;

	switch (msg)
	{
	case WM_INITDIALOG:
		{
			LVCOLUMNW col;
			HWND hList = GetDlgItem (hwndDlg, IDC_HOTKEY_LIST);

			bKeyScanOn = FALSE;
			nSelectedHotkeyId = -1;
			currentVKeyCode = 0;
			memcpy (tmpHotkeys, Hotkeys, sizeof(tmpHotkeys));

			SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
				LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP 
				); 

			memset (&col,0,sizeof(col));               
			col.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT;  
			col.pszText = GetString ("ACTION");                           
			col.cx = CompensateXDPI (341);
			col.fmt = LVCFMT_LEFT;
			SendMessageW (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&col);

			col.pszText = GetString ("SHORTCUT");  
			col.cx = CompensateXDPI (190);           
			col.fmt = LVCFMT_LEFT;
			SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&col);

			LocalizeDialog (hwndDlg, "IDD_HOTKEYS_DLG");

			SetCheckBox (hwndDlg, IDC_HK_MOD_CTRL, TRUE);
			SetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT, FALSE);
			SetCheckBox (hwndDlg, IDC_HK_MOD_ALT, TRUE);
			SetCheckBox (hwndDlg, IDC_HK_MOD_WIN, FALSE);

			SetCheckBox (hwndDlg, IDC_HK_DISMOUNT_PLAY_SOUND, bPlaySoundOnSuccessfulHkDismount);
			SetCheckBox (hwndDlg, IDC_HK_DISMOUNT_BALLOON_TOOLTIP, bDisplayBalloonOnSuccessfulHkDismount);

			bTPlaySoundOnSuccessfulHkDismount = bPlaySoundOnSuccessfulHkDismount;
			bTDisplayBalloonOnSuccessfulHkDismount = bDisplayBalloonOnSuccessfulHkDismount;

			EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
			EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);

			DisplayHotkeyList(hwndDlg);
			
			SetTimer (hwndDlg, 0xfe, 10, NULL);
			return 1;
		}

	case WM_TIMER:
		{
			if (nSelectedHotkeyId > -1)
			{
				wchar_t keyName [MAX_KEY_COMB_NAME_LEN];
				UINT tmpVKeyCode;

				keyName[0] = 0;

				ScanAndProcessKey (&tmpVKeyCode, &keyName[0]);

				if (keyName[0] != 0)
				{
					currentVKeyCode = tmpVKeyCode;
					SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), keyName);
					EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), TRUE);
				}
			}
			return 1;
		}

	case WM_NOTIFY:
		if (wParam == IDC_HOTKEY_LIST)
		{
			if (((LPNMHDR) lParam)->code == LVN_ITEMACTIVATE
				|| ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED))
			{
				LVITEM item;
				memset(&item,0,sizeof(item));
				nSelectedHotkeyId = ((LPNMLISTVIEW) lParam)->iItem;
				SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), GetString ("PRESS_A_KEY_TO_ASSIGN"));

				EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), (tmpHotkeys[nSelectedHotkeyId].vKeyCode > 0));

				EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
				bKeyScanOn = TRUE;
				return 1;
			}
		}

		return 0;

	case WM_COMMAND:
		if (lw == IDC_HOTKEY_KEY && hw == EN_CHANGE)
		{
			if (!bKeyScanOn && nSelectedHotkeyId < 0 && GetWindowTextLengthW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY)))
				SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
		}

		if (lw == IDC_HOTKEY_ASSIGN)
		{
			BOOL bOwnActiveShortcut = FALSE;

			if (nSelectedHotkeyId >= 0 && currentVKeyCode != 0)
			{
				UINT modifiers = 0; 
				if (GetCheckBox (hwndDlg, IDC_HK_MOD_CTRL))
					modifiers = MOD_CONTROL;

				if (GetCheckBox (hwndDlg, IDC_HK_MOD_ALT))
					modifiers |= MOD_ALT;

				if (GetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT))
					modifiers |= MOD_SHIFT;

				if (GetCheckBox (hwndDlg, IDC_HK_MOD_WIN))
					modifiers |= MOD_WIN;

				// Check if it's not already assigned
				if (ShortcutInUse (currentVKeyCode, modifiers, tmpHotkeys))
				{
					Error ("SHORTCUT_ALREADY_IN_USE", hwndDlg);
					return 1;
				}

				// Check for reserved system keys
				switch (currentVKeyCode)
				{
				case VK_F1:
				case VK_F12:
					/* F1 is help and F12 is reserved for use by the debugger at all times */
					if (modifiers == 0)
					{
						Error ("CANNOT_USE_RESERVED_KEY", hwndDlg);
						return 1;
					}
					break;
				}

				bOwnActiveShortcut = ShortcutInUse (currentVKeyCode, modifiers, Hotkeys);

				// Test if the shortcut can be assigned without errors
				if (!bOwnActiveShortcut
					&& !RegisterHotKey (hwndDlg, nSelectedHotkeyId, modifiers, currentVKeyCode))
				{
					handleWin32Error(hwndDlg);
					return 1;
				}
				else
				{
					if (!bOwnActiveShortcut && !UnregisterHotKey (hwndDlg, nSelectedHotkeyId))
						handleWin32Error(hwndDlg);

					tmpHotkeys[nSelectedHotkeyId].vKeyCode = currentVKeyCode;
					tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = modifiers;

					SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
					EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
					EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
					nSelectedHotkeyId = -1;
					bKeyScanOn = FALSE;
				}
			}
			DisplayHotkeyList(hwndDlg);
			return 1;
		}

		if (lw == IDC_HOTKEY_REMOVE)
		{
			if (nSelectedHotkeyId >= 0)
			{
				tmpHotkeys[nSelectedHotkeyId].vKeyCode = 0;
				tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = 0;
				SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
				EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
				EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
				nSelectedHotkeyId = -1;
				bKeyScanOn = FALSE;
				DisplayHotkeyList(hwndDlg);
			}
			return 1;
		}

		if (lw == IDC_RESET_HOTKEYS)
		{
			int i;

			for (i = 0; i < NBR_HOTKEYS; i++)
			{
				tmpHotkeys[i].vKeyCode = 0;
				tmpHotkeys[i].vKeyModifiers = 0;
			}
			SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
			EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
			EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
			nSelectedHotkeyId = -1;
			bKeyScanOn = FALSE;
			DisplayHotkeyList(hwndDlg);
			return 1;
		}

		if (lw == IDC_HK_DISMOUNT_PLAY_SOUND)
		{
			bTPlaySoundOnSuccessfulHkDismount = GetCheckBox (hwndDlg, IDC_HK_DISMOUNT_PLAY_SOUND);
		}

		if (lw == IDC_HK_DISMOUNT_BALLOON_TOOLTIP)
		{
			bTDisplayBalloonOnSuccessfulHkDismount = GetCheckBox (hwndDlg, IDC_HK_DISMOUNT_BALLOON_TOOLTIP);
		}

		if (lw == IDCANCEL || lw == IDCLOSE)
		{
			KillTimer (hwndDlg, 0xfe);
			EndDialog (hwndDlg, IDCANCEL);
			return 1;
		}

		if (lw == IDOK)
		{
			HWND hwndMainDlg = hwndDlg;

			while (GetParent (hwndMainDlg) != NULL)
			{
				hwndMainDlg = GetParent (hwndMainDlg);
			}
			UnregisterAllHotkeys (hwndMainDlg, Hotkeys);
			memcpy (Hotkeys, tmpHotkeys, sizeof(Hotkeys));
			RegisterAllHotkeys (hwndMainDlg, Hotkeys);
			KillTimer (hwndDlg, 0xfe);
			bPlaySoundOnSuccessfulHkDismount = bTPlaySoundOnSuccessfulHkDismount;
			bDisplayBalloonOnSuccessfulHkDismount = bTDisplayBalloonOnSuccessfulHkDismount;

			SaveSettings (hwndDlg);
			EndDialog (hwndDlg, IDCANCEL);
			return 1;
		}
		return 0;

	case WM_CLOSE:

		KillTimer (hwndDlg, 0xfe);
		EndDialog (hwndDlg, IDCANCEL);
		return 1;
	}
	return 0;
}