"Fossies" - the Fresh Open Source Software Archive

Member "src/Mount/Hotkeys.c" (10 Oct 2018, 17863 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Hotkeys.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include <windows.h>
   14 #include "Dlgcode.h"
   15 #include "Hotkeys.h"
   16 #include "Language.h"
   17 #include "Mount.h"
   18 #include "Resource.h"
   19 
   20 #include <Strsafe.h>
   21 
   22 #ifndef SRC_POS
   23 #define SRC_POS (__FUNCTION__ ":" TC_TO_STRING(__LINE__))
   24 #endif
   25 
   26 #define MAX_KEY_COMB_NAME_LEN   260
   27 
   28 TCHOTKEY    Hotkeys [NBR_HOTKEYS];
   29 static TCHOTKEY tmpHotkeys [NBR_HOTKEYS];
   30 
   31 static int nSelectedHotkeyId;
   32 static UINT currentVKeyCode;
   33 static BYTE vkeysDown[256];
   34 
   35 
   36 static void ScanAndProcessKey (UINT *vKeyCode, wchar_t *keyName)
   37 {
   38     UINT vKey;
   39     *vKeyCode = 0;
   40 
   41     for (vKey = 0; vKey <= 0xFF; vKey++)
   42     {
   43         if (GetAsyncKeyState (vKey) < 0)
   44         {
   45             if (!vkeysDown [vKey])
   46             {
   47                 vkeysDown [vKey] = 1;
   48                 if (GetKeyName (vKey, keyName)) // If the key is allowed and its name has been resolved
   49                     *vKeyCode = vKey;
   50             }
   51         }
   52         else
   53             vkeysDown [vKey] = 0;
   54     }
   55 }
   56 
   57 
   58 /* Returns TRUE if the key is allowed and its name is resolved. */
   59 BOOL GetKeyName (UINT vKey, wchar_t *keyName)
   60 {
   61     BOOL result = TRUE;
   62 
   63     if (vKey >= 0x30 && vKey <= 0x5a)
   64     {
   65         // ASCII characters
   66         StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%hc", (char) vKey);
   67     }
   68     else if (vKey >= 0xE9 && vKey <= 0xF5)
   69     {
   70         // OEM-specific
   71         StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM-%d", vKey);
   72 
   73         // mapping taken from:
   74         //  http://www.hotkeynet.com/ref/keynames.html
   75         //  https://mojoware.googlecode.com/svn-history/r3/trunk/mojo_engine/cKeyboard.cpp
   76         //  http://www.screenio.com/gui_screenio/gs_htmlhelp_subweb/download/SIMKEYS.cob
   77         //
   78         // These values seem to come from Nokia/Ericsson mobile device keys
   79 
   80         switch (vKey)
   81         {
   82         case 0xE9: // OEMReset = 0xE9
   83             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMReset)");
   84             break;
   85         case 0xEA: // OEMJump = 0xEA
   86             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMJump)");
   87             break;
   88         case 0xEB: // OEMPA1 = 0xEB
   89             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMPA1)");
   90             break;
   91         case 0xEC: // OEMPA2 = 0xEC
   92             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMPA2)");
   93             break;
   94         case 0xED: // OEMPA3 = 0xED
   95             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMPA3)");
   96             break;
   97         case 0xEE: // OEMWSCtrl = 0xEE
   98             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMWSCtrl)");
   99             break;
  100         case 0xEF: // OEMCUSel = 0xEF
  101             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMCUSel)");
  102             break;
  103         case 0xF0: // OEMATTN = 0xF0
  104             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMATTN)");
  105             break;
  106         case 0xF1: // OEMFinish = 0xF1
  107             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMFinish)");
  108             break;
  109         case 0xF2: // OEMCopy = 0xF2
  110             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMCopy)");
  111             break;
  112         case 0xF3: // OEMAuto = 0xF3
  113             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMAuto)");
  114             break;
  115         case 0xF4: // OEMENLW = 0xF4
  116             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMENLW)");
  117             break;
  118         case 0xF5: // OEMBackTab = 0xF5
  119             StringCbCatW (keyName, MAX_KEY_COMB_NAME_LEN, L" (OEMBackTab)");
  120             break;
  121         }
  122     }
  123     else if (vKey >= VK_F1 && vKey <= VK_F24)
  124     {
  125         // F1-F24
  126         StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"F%d", vKey - VK_F1 + 1);
  127     }
  128     else if (vKey >= VK_NUMPAD0 && vKey <= VK_NUMPAD9)
  129     {
  130         // Numpad numbers
  131         StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s %d", GetString ("VK_NUMPAD"), vKey - VK_NUMPAD0);
  132     }
  133     else
  134     {
  135         switch (vKey)
  136         {
  137         case VK_MULTIPLY:   StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s *", GetString ("VK_NUMPAD")); break;
  138         case VK_ADD:        StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s +", GetString ("VK_NUMPAD")); break;
  139         case VK_SEPARATOR:  StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s Separator", GetString ("VK_NUMPAD")); break;
  140         case VK_SUBTRACT:   StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s -", GetString ("VK_NUMPAD")); break;
  141         case VK_DECIMAL:    StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s .", GetString ("VK_NUMPAD")); break;
  142         case VK_DIVIDE:     StringCbPrintfW (keyName, MAX_KEY_COMB_NAME_LEN, L"%s /", GetString ("VK_NUMPAD")); break;
  143         case VK_OEM_1:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 1 (';')"); break;
  144         case VK_OEM_PLUS:   StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"+"); break;
  145         case VK_OEM_COMMA:  StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L","); break;
  146         case VK_OEM_MINUS:  StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"-"); break;
  147         case VK_OEM_PERIOD: StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L".");   break;
  148         case VK_OEM_2:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 2 ('/')"); break;
  149         case VK_OEM_3:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 3 (`)"); break;
  150         case VK_OEM_4:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 4 ('[')"); break;
  151         case VK_OEM_5:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 5 ('\\')"); break;
  152         case VK_OEM_6:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 6 (']')"); break;
  153         case VK_OEM_7:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 7 (')"); break;
  154         case VK_OEM_8:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 8"); break;
  155         case VK_OEM_AX:     StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM AX"); break;
  156         case VK_OEM_102:    StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM 102"); break;
  157         case VK_ICO_HELP:   StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"ICO_HELP"); break;
  158         case VK_ICO_00:     StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"ICO_00"); break;
  159         case VK_ICO_CLEAR:  StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"ICO_CLEAR"); break;
  160         case VK_ATTN:       StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"Attn"); break;
  161         case VK_CRSEL:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"CrSel"); break;
  162         case VK_EXSEL:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"ExSel"); break;
  163         case VK_EREOF:      StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"Erase EOF"); break;
  164         case VK_PA1:        StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"PA1"); break;
  165         case VK_OEM_CLEAR:  StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, L"OEM Clear"); break;
  166 
  167         case 0:
  168         case 1:
  169         case 0xFF:
  170             result = FALSE;
  171             break;
  172 
  173         default:
  174             {
  175                 char key[16];
  176                 wchar_t *desc;
  177                 StringCbPrintfA (key, sizeof(key),"VKEY_%02X", vKey);
  178                 desc = GetString (key);
  179                 if (desc == UnknownString)
  180                     result = FALSE;
  181                 else
  182                     StringCbCopyW (keyName, MAX_KEY_COMB_NAME_LEN, desc);
  183             }
  184         }
  185     }
  186     return result;
  187 }
  188 
  189 
  190 static BOOL ShortcutInUse (UINT vKeyCode, UINT modifiers, TCHOTKEY hotkeys[])
  191 {
  192     int i;
  193 
  194     for (i = 0; i < NBR_HOTKEYS; i++)
  195     {
  196         if (hotkeys[i].vKeyCode == vKeyCode && hotkeys[i].vKeyModifiers == modifiers)
  197             return TRUE;
  198     }
  199     return FALSE;
  200 }
  201 
  202 
  203 void UnregisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[])
  204 {
  205     int i;
  206 
  207     for (i = 0; i < NBR_HOTKEYS; i++)
  208     {
  209         if (hotkeys[i].vKeyCode != 0)
  210             UnregisterHotKey (hwndDlg, i);
  211 
  212     }
  213 }
  214 
  215 
  216 BOOL RegisterAllHotkeys (HWND hwndDlg, TCHOTKEY hotkeys[])
  217 {
  218     BOOL result = TRUE;
  219     int i;
  220 
  221     for (i = 0; i < NBR_HOTKEYS; i++)
  222     {
  223         if (hotkeys[i].vKeyCode != 0
  224         && !RegisterHotKey (hwndDlg, i, hotkeys[i].vKeyModifiers, hotkeys[i].vKeyCode))
  225             result = FALSE;
  226     }
  227 
  228     return result;
  229 }
  230 
  231 
  232 static void DisplayHotkeyList (HWND hwndDlg)
  233 {
  234     LVITEMW item;
  235     HWND hList = GetDlgItem (hwndDlg, IDC_HOTKEY_LIST);
  236     int i;
  237     wchar_t ShortcutMod [MAX_KEY_COMB_NAME_LEN];
  238     wchar_t ShortcutFinal [MAX_KEY_COMB_NAME_LEN*2];
  239     wchar_t Shortcut [MAX_KEY_COMB_NAME_LEN];
  240 
  241     SendMessage (hList, LVM_DELETEALLITEMS,0, (LPARAM)&item);
  242 
  243     for (i = 0; i < NBR_HOTKEYS; i++)
  244     {
  245         memset (&item,0,sizeof(item));
  246         item.mask = LVIF_TEXT;
  247         item.iItem = i;
  248         item.iSubItem = 0;
  249 
  250         switch (i)
  251         {
  252 
  253         case HK_AUTOMOUNT_DEVICES:
  254             item.pszText = GetString ("HK_AUTOMOUNT_DEVICES");
  255             break;
  256 
  257         case HK_DISMOUNT_ALL:
  258             item.pszText = GetString ("HK_DISMOUNT_ALL");
  259             break;
  260 
  261         case HK_WIPE_CACHE:
  262             item.pszText = GetString ("HK_WIPE_CACHE");
  263             break;
  264 
  265         case HK_DISMOUNT_ALL_AND_WIPE:
  266             item.pszText = GetString ("HK_DISMOUNT_ALL_AND_WIPE");
  267             break;
  268 
  269         case HK_FORCE_DISMOUNT_ALL_AND_WIPE:
  270             item.pszText = GetString ("HK_FORCE_DISMOUNT_ALL_AND_WIPE");
  271             break;
  272 
  273         case HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT:
  274             item.pszText = GetString ("HK_FORCE_DISMOUNT_ALL_AND_WIPE_AND_EXIT");
  275             break;
  276 
  277         case HK_MOUNT_FAVORITE_VOLUMES:
  278             item.pszText = GetString ("HK_MOUNT_FAVORITE_VOLUMES");
  279             break;
  280 
  281         case HK_SHOW_HIDE_MAIN_WINDOW:
  282             item.pszText = GetString ("HK_SHOW_HIDE_MAIN_WINDOW");
  283             break;
  284 
  285         case HK_CLOSE_SECURITY_TOKEN_SESSIONS:
  286             item.pszText = GetString ("IDM_CLOSE_ALL_TOKEN_SESSIONS");
  287             break;
  288 
  289         default:
  290             item.pszText = L"[?]";
  291         }
  292 
  293         SendMessageW (hList,LVM_INSERTITEMW,0,(LPARAM)&item);
  294 
  295         item.iSubItem = 1;
  296         Shortcut[0] = 0;
  297         ShortcutMod[0] = 0;
  298 
  299         if (GetKeyName (tmpHotkeys[i].vKeyCode, Shortcut))
  300         {
  301             if (tmpHotkeys[i].vKeyModifiers & MOD_CONTROL)
  302             {
  303                 StringCbCatW (ShortcutMod, sizeof(ShortcutMod),GetString ("VK_CONTROL"));
  304                 StringCbCatW (ShortcutMod, sizeof(ShortcutMod),L"+");
  305             }
  306 
  307             if (tmpHotkeys[i].vKeyModifiers & MOD_SHIFT)
  308             {
  309                 StringCbCatW (ShortcutMod, sizeof(ShortcutMod),GetString ("VK_SHIFT"));
  310                 StringCbCatW (ShortcutMod, sizeof(ShortcutMod),L"+");
  311             }
  312 
  313             if (tmpHotkeys[i].vKeyModifiers & MOD_ALT)
  314             {
  315                 StringCbCatW (ShortcutMod, sizeof(ShortcutMod),GetString ("VK_ALT"));
  316                 StringCbCatW (ShortcutMod, sizeof(ShortcutMod),L"+");
  317             }
  318 
  319             if (tmpHotkeys[i].vKeyModifiers & MOD_WIN)
  320             {
  321                 StringCbCatW (ShortcutMod, sizeof(ShortcutMod),GetString ("VK_WIN"));
  322                 StringCbCatW (ShortcutMod, sizeof(ShortcutMod),L"+");
  323             }
  324 
  325             StringCbPrintfW (ShortcutFinal, sizeof(ShortcutFinal), L"%s%s", ShortcutMod, Shortcut);
  326             item.pszText = ShortcutFinal;
  327         }
  328         else
  329             item.pszText = L"";
  330 
  331         SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&item);
  332     }
  333 }
  334 
  335 
  336 
  337 BOOL CALLBACK HotkeysDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  338 {
  339     WORD lw = LOWORD (wParam);
  340     WORD hw = HIWORD (wParam);
  341     static BOOL bKeyScanOn;
  342     static BOOL bTPlaySoundOnSuccessfulHkDismount;
  343     static BOOL bTDisplayBalloonOnSuccessfulHkDismount;
  344 
  345     switch (msg)
  346     {
  347     case WM_INITDIALOG:
  348         {
  349             LVCOLUMNW col;
  350             HWND hList = GetDlgItem (hwndDlg, IDC_HOTKEY_LIST);
  351 
  352             bKeyScanOn = FALSE;
  353             nSelectedHotkeyId = -1;
  354             currentVKeyCode = 0;
  355             memcpy (tmpHotkeys, Hotkeys, sizeof(tmpHotkeys));
  356             memset (vkeysDown, 0, sizeof(vkeysDown));
  357 
  358             SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
  359                 LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP
  360                 );
  361 
  362             memset (&col,0,sizeof(col));
  363             col.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT;
  364             col.pszText = GetString ("ACTION");
  365             col.cx = CompensateXDPI (341);
  366             col.fmt = LVCFMT_LEFT;
  367             SendMessageW (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&col);
  368 
  369             col.pszText = GetString ("SHORTCUT");
  370             col.cx = CompensateXDPI (190);
  371             col.fmt = LVCFMT_LEFT;
  372             SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&col);
  373 
  374             LocalizeDialog (hwndDlg, "IDD_HOTKEYS_DLG");
  375 
  376             SetCheckBox (hwndDlg, IDC_HK_MOD_CTRL, TRUE);
  377             SetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT, FALSE);
  378             SetCheckBox (hwndDlg, IDC_HK_MOD_ALT, TRUE);
  379             SetCheckBox (hwndDlg, IDC_HK_MOD_WIN, FALSE);
  380 
  381             SetCheckBox (hwndDlg, IDC_HK_DISMOUNT_PLAY_SOUND, bPlaySoundOnSuccessfulHkDismount);
  382             SetCheckBox (hwndDlg, IDC_HK_DISMOUNT_BALLOON_TOOLTIP, bDisplayBalloonOnSuccessfulHkDismount);
  383 
  384             bTPlaySoundOnSuccessfulHkDismount = bPlaySoundOnSuccessfulHkDismount;
  385             bTDisplayBalloonOnSuccessfulHkDismount = bDisplayBalloonOnSuccessfulHkDismount;
  386 
  387             EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
  388             EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
  389 
  390             DisplayHotkeyList(hwndDlg);
  391 
  392             if (SetTimer (hwndDlg, 0xfe, 10, NULL) == 0)
  393             {
  394                 Error ("CANNOT_SET_TIMER", MainDlg);
  395                 EndDialog (hwndDlg, IDCANCEL);
  396                 return 1;
  397             }
  398             return 1;
  399         }
  400 
  401     case WM_TIMER:
  402         {
  403             if ((nSelectedHotkeyId > -1) && (GetFocus () == GetDlgItem (hwndDlg, IDC_HOTKEY_KEY)))
  404             {
  405                 wchar_t keyName [MAX_KEY_COMB_NAME_LEN];
  406                 UINT tmpVKeyCode;
  407 
  408                 keyName[0] = 0;
  409 
  410                 ScanAndProcessKey (&tmpVKeyCode, &keyName[0]);
  411 
  412                 if (keyName[0] != 0)
  413                 {
  414                     currentVKeyCode = tmpVKeyCode;
  415                     SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), keyName);
  416                     EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), TRUE);
  417                 }
  418                 else if ((currentVKeyCode != 0) && GetKeyName (currentVKeyCode, keyName))
  419                 {
  420                     SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), keyName);
  421                 }
  422             }
  423             return 1;
  424         }
  425 
  426     case WM_NOTIFY:
  427         if (wParam == IDC_HOTKEY_LIST)
  428         {
  429             if (((LPNMHDR) lParam)->code == LVN_ITEMACTIVATE
  430                 || ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED))
  431             {
  432                 LVITEM item;
  433                 memset(&item,0,sizeof(item));
  434                 nSelectedHotkeyId = ((LPNMLISTVIEW) lParam)->iItem;
  435                 currentVKeyCode = 0;
  436                 memset (vkeysDown, 0, sizeof(vkeysDown));
  437                 SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), GetString ("PRESS_A_KEY_TO_ASSIGN"));
  438 
  439                 EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), (tmpHotkeys[nSelectedHotkeyId].vKeyCode > 0));
  440 
  441                 EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
  442                 bKeyScanOn = TRUE;
  443                 return 1;
  444             }
  445         }
  446 
  447         return 0;
  448 
  449     case WM_COMMAND:
  450         if (lw == IDC_HOTKEY_KEY && hw == EN_CHANGE)
  451         {
  452             if (!bKeyScanOn && nSelectedHotkeyId < 0 && GetWindowTextLengthW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY)))
  453                 SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
  454         }
  455 
  456         if (lw == IDC_HOTKEY_ASSIGN)
  457         {
  458             BOOL bOwnActiveShortcut = FALSE;
  459 
  460             if (nSelectedHotkeyId >= 0 && currentVKeyCode != 0)
  461             {
  462                 UINT modifiers = 0;
  463                 if (GetCheckBox (hwndDlg, IDC_HK_MOD_CTRL))
  464                     modifiers = MOD_CONTROL;
  465 
  466                 if (GetCheckBox (hwndDlg, IDC_HK_MOD_ALT))
  467                     modifiers |= MOD_ALT;
  468 
  469                 if (GetCheckBox (hwndDlg, IDC_HK_MOD_SHIFT))
  470                     modifiers |= MOD_SHIFT;
  471 
  472                 if (GetCheckBox (hwndDlg, IDC_HK_MOD_WIN))
  473                     modifiers |= MOD_WIN;
  474 
  475                 // Check if it's not already assigned
  476                 if (ShortcutInUse (currentVKeyCode, modifiers, tmpHotkeys))
  477                 {
  478                     Error ("SHORTCUT_ALREADY_IN_USE", hwndDlg);
  479                     return 1;
  480                 }
  481 
  482                 // Check for reserved system keys
  483                 switch (currentVKeyCode)
  484                 {
  485                 case VK_F1:
  486                 case VK_F12:
  487                     /* F1 is help and F12 is reserved for use by the debugger at all times */
  488                     if (modifiers == 0)
  489                     {
  490                         Error ("CANNOT_USE_RESERVED_KEY", hwndDlg);
  491                         return 1;
  492                     }
  493                     break;
  494                 }
  495 
  496                 bOwnActiveShortcut = ShortcutInUse (currentVKeyCode, modifiers, Hotkeys);
  497 
  498                 // Test if the shortcut can be assigned without errors
  499                 if (!bOwnActiveShortcut
  500                     && !RegisterHotKey (hwndDlg, nSelectedHotkeyId, modifiers, currentVKeyCode))
  501                 {
  502                     handleWin32Error(hwndDlg, SRC_POS);
  503                     return 1;
  504                 }
  505                 else
  506                 {
  507                     if (!bOwnActiveShortcut && !UnregisterHotKey (hwndDlg, nSelectedHotkeyId))
  508                         handleWin32Error(hwndDlg, SRC_POS);
  509 
  510                     tmpHotkeys[nSelectedHotkeyId].vKeyCode = currentVKeyCode;
  511                     tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = modifiers;
  512 
  513                     SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
  514                     EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
  515                     EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
  516                     nSelectedHotkeyId = -1;
  517                     bKeyScanOn = FALSE;
  518                     currentVKeyCode = 0;
  519                     memset (vkeysDown, 0, sizeof(vkeysDown));
  520                 }
  521             }
  522             DisplayHotkeyList(hwndDlg);
  523             return 1;
  524         }
  525 
  526         if (lw == IDC_HOTKEY_REMOVE)
  527         {
  528             if (nSelectedHotkeyId >= 0)
  529             {
  530                 tmpHotkeys[nSelectedHotkeyId].vKeyCode = 0;
  531                 tmpHotkeys[nSelectedHotkeyId].vKeyModifiers = 0;
  532                 SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
  533                 EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
  534                 EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
  535                 nSelectedHotkeyId = -1;
  536                 bKeyScanOn = FALSE;
  537                 currentVKeyCode = 0;
  538                 memset (vkeysDown, 0, sizeof(vkeysDown));
  539                 DisplayHotkeyList(hwndDlg);
  540             }
  541             return 1;
  542         }
  543 
  544         if (lw == IDC_RESET_HOTKEYS)
  545         {
  546             int i;
  547 
  548             for (i = 0; i < NBR_HOTKEYS; i++)
  549             {
  550                 tmpHotkeys[i].vKeyCode = 0;
  551                 tmpHotkeys[i].vKeyModifiers = 0;
  552             }
  553             SetWindowTextW (GetDlgItem (hwndDlg, IDC_HOTKEY_KEY), L"");
  554             EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_ASSIGN), FALSE);
  555             EnableWindow (GetDlgItem (hwndDlg, IDC_HOTKEY_REMOVE), FALSE);
  556             nSelectedHotkeyId = -1;
  557             bKeyScanOn = FALSE;
  558             currentVKeyCode = 0;
  559             memset (vkeysDown, 0, sizeof(vkeysDown));
  560             DisplayHotkeyList(hwndDlg);
  561             return 1;
  562         }
  563 
  564         if (lw == IDC_HK_DISMOUNT_PLAY_SOUND)
  565         {
  566             bTPlaySoundOnSuccessfulHkDismount = GetCheckBox (hwndDlg, IDC_HK_DISMOUNT_PLAY_SOUND);
  567         }
  568 
  569         if (lw == IDC_HK_DISMOUNT_BALLOON_TOOLTIP)
  570         {
  571             bTDisplayBalloonOnSuccessfulHkDismount = GetCheckBox (hwndDlg, IDC_HK_DISMOUNT_BALLOON_TOOLTIP);
  572         }
  573 
  574         if (lw == IDCANCEL || lw == IDCLOSE)
  575         {
  576             KillTimer (hwndDlg, 0xfe);
  577             EndDialog (hwndDlg, IDCANCEL);
  578             return 1;
  579         }
  580 
  581         if (lw == IDOK)
  582         {
  583             HWND hwndMainDlg = hwndDlg;
  584 
  585             while (GetParent (hwndMainDlg) != NULL)
  586             {
  587                 hwndMainDlg = GetParent (hwndMainDlg);
  588             }
  589             UnregisterAllHotkeys (hwndMainDlg, Hotkeys);
  590             memcpy (Hotkeys, tmpHotkeys, sizeof(Hotkeys));
  591             RegisterAllHotkeys (hwndMainDlg, Hotkeys);
  592             KillTimer (hwndDlg, 0xfe);
  593             bPlaySoundOnSuccessfulHkDismount = bTPlaySoundOnSuccessfulHkDismount;
  594             bDisplayBalloonOnSuccessfulHkDismount = bTDisplayBalloonOnSuccessfulHkDismount;
  595 
  596             SaveSettings (hwndDlg);
  597             EndDialog (hwndDlg, IDCANCEL);
  598             return 1;
  599         }
  600         return 0;
  601 
  602     case WM_CLOSE:
  603 
  604         KillTimer (hwndDlg, 0xfe);
  605         EndDialog (hwndDlg, IDCANCEL);
  606         return 1;
  607     }
  608     return 0;
  609 }
  610 
  611