VeraCrypt/src/Mount/Hotkeys.c

612 lines
17 KiB
C

/*
Derived from source code of TrueCrypt 7.1a, which is
Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
by the TrueCrypt License 3.0.
Modifications and additions to the original source code (contained in this file)
and all other portions of this file are Copyright (c) 2013-2017 IDRIX
and are governed by the Apache License 2.0 the full text of which is
contained in the file License.txt included in VeraCrypt 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>
#ifndef SRC_POS
#define SRC_POS (__FUNCTION__ ":" TC_TO_STRING(__LINE__))
#endif
#define MAX_KEY_COMB_NAME_LEN 260
TCHOTKEY Hotkeys [NBR_HOTKEYS];
static TCHOTKEY tmpHotkeys [NBR_HOTKEYS];
static int nSelectedHotkeyId;
static UINT currentVKeyCode;
static BYTE vkeysDown[256];
static void ScanAndProcessKey (UINT *vKeyCode, wchar_t *keyName)
{
UINT vKey;
*vKeyCode = 0;
for (vKey = 0; vKey <= 0xFF; vKey++)
{
if (GetAsyncKeyState (vKey) < 0)
{
if (!vkeysDown [vKey])
{
vkeysDown [vKey] = 1;
if (GetKeyName (vKey, keyName)) // If the key is allowed and its name has been resolved
*vKeyCode = vKey;
}
}
else
vkeysDown [vKey] = 0;
}
}
/* 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);
// mapping taken from:
// http://www.hotkeynet.com/ref/keynames.html
// https://mojoware.googlecode.com/svn-history/r3/trunk/mojo_engine/cKeyboard.cpp
// http://www.screenio.com/gui_screenio/gs_htmlhelp_subweb/download/SIMKEYS.cob
//
// These values seem to come from Nokia/Ericsson mobile device keys
switch (vKey)
{
case 0xE9: // OEMReset = 0xE9
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMReset)");
break;
case 0xEA: // OEMJump = 0xEA
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMJump)");
break;
case 0xEB: // OEMPA1 = 0xEB
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMPA1)");
break;
case 0xEC: // OEMPA2 = 0xEC
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMPA2)");
break;
case 0xED: // OEMPA3 = 0xED
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMPA3)");
break;
case 0xEE: // OEMWSCtrl = 0xEE
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMWSCtrl)");
break;
case 0xEF: // OEMCUSel = 0xEF
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMCUSel)");
break;
case 0xF0: // OEMATTN = 0xF0
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMATTN)");
break;
case 0xF1: // OEMFinish = 0xF1
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMFinish)");
break;
case 0xF2: // OEMCopy = 0xF2
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMCopy)");
break;
case 0xF3: // OEMAuto = 0xF3
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMAuto)");
break;
case 0xF4: // OEMENLW = 0xF4
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMENLW)");
break;
case 0xF5: // OEMBackTab = 0xF5
StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMBackTab)");
break;
}
}
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));
memset (vkeysDown, 0, sizeof(vkeysDown));
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);
if (SetTimer (hwndDlg, 0xfe, 10, NULL) == 0)
{
Error ("CANNOT_SET_TIMER", MainDlg);
EndDialog (hwndDlg, IDCANCEL);
return 1;
}
return 1;
}
case WM_TIMER:
{
if ((nSelectedHotkeyId > -1) && (GetFocus () == GetDlgItem (hwndDlg, IDC_HOTKEY_KEY)))
{
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);
}
else if ((currentVKeyCode != 0) && GetKeyName (currentVKeyCode, keyName))
{
SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), keyName);
}
}
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;
currentVKeyCode = 0;
memset (vkeysDown, 0, sizeof(vkeysDown));
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, SRC_POS);
return 1;
}
else
{
if (!bOwnActiveShortcut && !UnregisterHotKey (hwndDlg, nSelectedHotkeyId))
handleWin32Error(hwndDlg, SRC_POS);
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;
currentVKeyCode = 0;
memset (vkeysDown, 0, sizeof(vkeysDown));
}
}
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;
currentVKeyCode = 0;
memset (vkeysDown, 0, sizeof(vkeysDown));
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;
currentVKeyCode = 0;
memset (vkeysDown, 0, sizeof(vkeysDown));
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;
}