"Fossies" - the Fresh Open Source Software Archive

Member "src/ExpandVolume/WinMain.cpp" (10 Oct 2018, 30475 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 "WinMain.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.22_Source_vs_1.23_Source.

    1 /*
    2  Legal Notice: Some portions of the source code contained in this file were
    3  derived from the source code of TrueCrypt 7.1a, which is
    4  Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
    5  governed by the TrueCrypt License 3.0, also from the source code of
    6  Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
    7  and which is governed by the 'License Agreement for Encryption for the Masses'
    8  and also from the source code of extcv, which is Copyright (c) 2009-2010 Kih-Oskh
    9  or Copyright (c) 2012-2013 Josef Schneider <josef@netpage.dk>
   10 
   11  Modifications and additions to the original source code (contained in this file)
   12  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
   13  and are governed by the Apache License 2.0 the full text of which is
   14  contained in the file License.txt included in VeraCrypt binary and source
   15  code distribution packages. */
   16 
   17 #include "Tcdefs.h"
   18 #include "cpu.h"
   19 
   20 #include <time.h>
   21 #include <math.h>
   22 #include <dbt.h>
   23 #include <fcntl.h>
   24 #include <io.h>
   25 #include <sys/stat.h>
   26 #include <windowsx.h>
   27 
   28 #include "Apidrvr.h"
   29 #include "BootEncryption.h"
   30 #include "Cmdline.h"
   31 #include "Crypto.h"
   32 #include "Dlgcode.h"
   33 #include "Combo.h"
   34 #include "Keyfiles.h"
   35 #include "Language.h"
   36 #include "../Mount/MainCom.h"
   37 #include "../Mount/Mount.h"
   38 #include "Pkcs5.h"
   39 #include "Random.h"
   40 #include "Registry.h"
   41 #include "Resource.h"
   42 #include "Password.h"
   43 #include "Xml.h"
   44 #include "../Boot/Windows/BootCommon.h"
   45 #include "../Common/Dictionary.h"
   46 #include "../Common/Common.h"
   47 #include "../Common/Resource.h"
   48 #include "../Common/SecurityToken.h"
   49 #include "../Platform/Finally.h"
   50 #include "../Platform/ForEach.h"
   51 #include <Strsafe.h>
   52 
   53 #include "ExpandVolume.h"
   54 
   55 using namespace VeraCrypt;
   56 
   57 const wchar_t szExpandVolumeInfo[] =
   58 L":: VeraCrypt Expander ::\n\nExpand a VeraCrypt volume on the fly without reformatting\n\n\n\
   59 All kind of volumes (container files, disks and partitions) formatted with \
   60 NTFS are supported. The only condition is that there must be enough free \
   61 space on the host drive or host device of the VeraCrypt volume.\n\n\
   62 Do not use this software to expand an outer volume containing a hidden \
   63 volume, because this destroys the hidden volume!\n\
   64 ";
   65 
   66 enum timer_ids
   67 {
   68     TIMER_ID_MAIN = 0xff,
   69     TIMER_ID_KEYB_LAYOUT_GUARD
   70 };
   71 
   72 enum hidden_os_read_only_notif_mode
   73 {
   74     TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE = 0,
   75     TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_COMPACT,
   76     TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_DISABLED
   77 };
   78 
   79 #define TIMER_INTERVAL_MAIN                 500
   80 #define TIMER_INTERVAL_KEYB_LAYOUT_GUARD    10
   81 
   82 namespace VeraCryptExpander
   83 {
   84 
   85 BOOL bExplore = FALSE;              /* Display explorer window after mount */
   86 BOOL bBeep = FALSE;                 /* Donot beep after mount */
   87 wchar_t szFileName[TC_MAX_PATH+1];      /* Volume to mount */
   88 wchar_t szDriveLetter[3];               /* Drive Letter to mount */
   89 wchar_t commandLineDrive = 0;
   90 BOOL bCacheInDriver = FALSE;        /* Cache any passwords we see */
   91 BOOL bCacheInDriverDefault = FALSE;
   92 BOOL bHistoryCmdLine = FALSE;       /* History control is always disabled */
   93 BOOL bCloseDismountedWindows=TRUE;  /* Close all open explorer windows of dismounted volume */
   94 BOOL bWipeCacheOnExit = FALSE;      /* Wipe password from chace on exit */
   95 BOOL bWipeCacheOnAutoDismount = TRUE;
   96 BOOL bEnableBkgTask = FALSE;
   97 BOOL bCloseBkgTaskWhenNoVolumes = FALSE;
   98 BOOL bDismountOnLogOff = TRUE;
   99 BOOL bDismountOnScreenSaver = TRUE;
  100 BOOL bDismountOnPowerSaving = FALSE;
  101 BOOL bForceAutoDismount = TRUE;
  102 BOOL bForceMount = FALSE;           /* Mount volume even if host file/device already in use */
  103 BOOL bForceUnmount = FALSE;         /* Unmount volume even if it cannot be locked */
  104 BOOL bWipe = FALSE;                 /* Wipe driver passwords */
  105 BOOL bAuto = FALSE;                 /* Do everything without user input */
  106 BOOL bAutoMountDevices = FALSE;     /* Auto-mount devices */
  107 BOOL bAutoMountFavorites = FALSE;
  108 BOOL bPlaySoundOnHotkeyMountDismount = TRUE;
  109 BOOL bDisplayMsgBoxOnHotkeyDismount = FALSE;
  110 BOOL bHibernationPreventionNotified = FALSE;    /* TRUE if the user has been notified that hibernation was prevented (system encryption) during the session. */
  111 BOOL bHiddenSysLeakProtNotifiedDuringSession = FALSE;   /* TRUE if the user has been notified during the session that unencrypted filesystems and non-hidden VeraCrypt volumes are mounted as read-only under hidden OS. */
  112 BOOL CloseSecurityTokenSessionsAfterMount = FALSE;
  113 
  114 BOOL MultipleMountOperationInProgress = FALSE;
  115 
  116 BOOL Quit = FALSE;                  /* Exit after processing command line */
  117 BOOL ComServerMode = FALSE;
  118 BOOL UsePreferences = TRUE;
  119 
  120 int HiddenSysLeakProtectionNotificationStatus = TC_HIDDEN_OS_READ_ONLY_NOTIF_MODE_NONE;
  121 int MaxVolumeIdleTime = -120;
  122 int nCurrentShowType = 0;           /* current display mode, mount, unmount etc */
  123 int nSelectedDriveIndex = -1;       /* Item number of selected drive */
  124 
  125 int cmdUnmountDrive = -2;           /* Volume drive letter to unmount (-1 = all) */
  126 Password VolumePassword;            /* Password used for mounting volumes */
  127 Password CmdVolumePassword;         /* Password passed from command line */
  128 BOOL CmdVolumePasswordValid = FALSE;
  129 MountOptions mountOptions;
  130 MountOptions defaultMountOptions;
  131 KeyFile *FirstCmdKeyFile;
  132 
  133 HBITMAP hbmLogoBitmapRescaled = NULL;
  134 wchar_t OrigKeyboardLayout [8+1] = L"00000409";
  135 BOOL bKeyboardLayoutChanged = FALSE;        /* TRUE if the keyboard layout was changed to the standard US keyboard layout (from any other layout). */
  136 BOOL bKeybLayoutAltKeyWarningShown = FALSE; /* TRUE if the user has been informed that it is not possible to type characters by pressing keys while the right Alt key is held down. */
  137 
  138 static KeyFilesDlgParam             hidVolProtKeyFilesParam;
  139 VOLUME_NOTIFICATIONS_LIST   VolumeNotificationsList;
  140 
  141 static int bPrebootPasswordDlgMode = FALSE;
  142 
  143 static void localcleanup (void)
  144 {
  145     // Wipe command line
  146     char *c = GetCommandLineA ();
  147     wchar_t *wc = GetCommandLineW ();
  148     burn(c, strlen (c));
  149     burn(wc, wcslen (wc) * sizeof (wchar_t));
  150 
  151     /* Delete buffered bitmaps (if any) */
  152     if (hbmLogoBitmapRescaled != NULL)
  153     {
  154         DeleteObject ((HGDIOBJ) hbmLogoBitmapRescaled);
  155         hbmLogoBitmapRescaled = NULL;
  156     }
  157 
  158     /* These items should have already been cleared by the functions that used them, but we're going to
  159     clear them for extra security. */
  160     burn (&VolumePassword, sizeof (VolumePassword));
  161     burn (&CmdVolumePassword, sizeof (CmdVolumePassword));
  162     burn (&mountOptions, sizeof (mountOptions));
  163     burn (&defaultMountOptions, sizeof (defaultMountOptions));
  164     burn (&szFileName, sizeof(szFileName));
  165 
  166     /* Cleanup common code resources */
  167     cleanup ();
  168 
  169     RandStop (TRUE);
  170 }
  171 
  172 
  173 void EndMainDlg (HWND hwndDlg)
  174 {
  175     if (!bHistory)
  176     {
  177         SetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), L"");
  178     }
  179 
  180     EndDialog (hwndDlg, 0);
  181 }
  182 
  183 BOOL CALLBACK MountOptionsDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  184 {
  185     // dummy (referenced by PasswordDlgProc() )
  186     return FALSE;
  187 }
  188 BOOL TCBootLoaderOnInactiveSysEncDrive (void)
  189 {
  190     // dummy (referenced by Dlgcode.c)
  191     return FALSE;
  192 }
  193 
  194 BOOL CheckSysEncMountWithoutPBA (const char *devicePath, BOOL quiet)
  195 {
  196     // dummy (referenced by Dlgcode.c)
  197     return FALSE;
  198 }
  199 
  200 static void InitMainDialog (HWND hwndDlg)
  201 {
  202     /* Call the common dialog init code */
  203     InitDialog (hwndDlg);
  204     LocalizeDialog (hwndDlg, NULL);
  205 
  206     SendMessage (GetDlgItem (hwndDlg, IDC_VOLUME), CB_LIMITTEXT, TC_MAX_PATH, 0);
  207     SetWindowTextW (hwndDlg, lpszTitle);
  208 
  209     SendMessage (GetDlgItem (hwndDlg, IDC_INFOEXPAND), WM_SETFONT, (WPARAM) hBoldFont, (LPARAM) TRUE);
  210     SetWindowText (GetDlgItem (hwndDlg, IDC_INFOEXPAND), szExpandVolumeInfo);
  211 
  212     // Resize the logo bitmap if the user has a non-default DPI
  213     if (ScreenDPI != USER_DEFAULT_SCREEN_DPI
  214         && hbmLogoBitmapRescaled == NULL)   // If not re-called (e.g. after language pack change)
  215     {
  216         hbmLogoBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_LOGO_288DPI),
  217             GetDlgItem (hwndDlg, IDC_LOGO),
  218             0, 0, 0, 0, FALSE, TRUE);
  219     }
  220 
  221     EnableDisableButtons (hwndDlg);
  222 }
  223 
  224 void EnableDisableButtons (HWND hwndDlg)
  225 {
  226     HWND hOKButton = GetDlgItem (hwndDlg, IDOK);
  227     WORD x;
  228 
  229     x = LOWORD (GetSelectedLong (GetDlgItem (hwndDlg, IDC_DRIVELIST)));
  230 
  231     EnableWindow (hOKButton, TRUE);
  232 
  233 }
  234 
  235 BOOL VolumeSelected (HWND hwndDlg)
  236 {
  237     return (GetWindowTextLength (GetDlgItem (hwndDlg, IDC_VOLUME)) > 0);
  238 }
  239 
  240 
  241 void LoadSettings (HWND hwndDlg)
  242 {
  243     WipeAlgorithmId savedWipeAlgorithm = TC_WIPE_NONE;
  244 
  245     LoadSysEncSettings ();
  246 
  247     if (LoadNonSysInPlaceEncSettings (&savedWipeAlgorithm) != 0)
  248         bInPlaceEncNonSysPending = TRUE;
  249 
  250     // If the config file has already been loaded during this session
  251     if (ConfigBuffer != NULL)
  252     {
  253         free (ConfigBuffer);
  254         ConfigBuffer = NULL;
  255     }
  256 
  257     // Options
  258     bExplore =                      ConfigReadInt ("OpenExplorerWindowAfterMount", FALSE);
  259     bCloseDismountedWindows =       ConfigReadInt ("CloseExplorerWindowsOnDismount", TRUE);
  260 
  261     bHistory =                      ConfigReadInt ("SaveVolumeHistory", FALSE);
  262 
  263     bCacheInDriverDefault = bCacheInDriver = ConfigReadInt ("CachePasswords", FALSE);
  264     bWipeCacheOnExit =              ConfigReadInt ("WipePasswordCacheOnExit", FALSE);
  265     bWipeCacheOnAutoDismount =      ConfigReadInt ("WipeCacheOnAutoDismount", TRUE);
  266 
  267     bStartOnLogon =                 ConfigReadInt ("StartOnLogon", FALSE);
  268     bMountDevicesOnLogon =          ConfigReadInt ("MountDevicesOnLogon", FALSE);
  269     bMountFavoritesOnLogon =        ConfigReadInt ("MountFavoritesOnLogon", FALSE);
  270 
  271     bEnableBkgTask =                ConfigReadInt ("EnableBackgroundTask", TRUE);
  272     bCloseBkgTaskWhenNoVolumes =    ConfigReadInt ("CloseBackgroundTaskOnNoVolumes", FALSE);
  273 
  274     bDismountOnLogOff =             ConfigReadInt ("DismountOnLogOff", TRUE);
  275     bDismountOnPowerSaving =        ConfigReadInt ("DismountOnPowerSaving", FALSE);
  276     bDismountOnScreenSaver =        ConfigReadInt ("DismountOnScreenSaver", FALSE);
  277     bForceAutoDismount =            ConfigReadInt ("ForceAutoDismount", TRUE);
  278     MaxVolumeIdleTime =             ConfigReadInt ("MaxVolumeIdleTime", -60);
  279 
  280     HiddenSectorDetectionStatus =   ConfigReadInt ("HiddenSectorDetectionStatus", 0);
  281 
  282     defaultKeyFilesParam.EnableKeyFiles = ConfigReadInt ("UseKeyfiles", FALSE);
  283 
  284     bPreserveTimestamp = defaultMountOptions.PreserveTimestamp = ConfigReadInt ("PreserveTimestamps", TRUE);
  285     bShowDisconnectedNetworkDrives = ConfigReadInt ("ShowDisconnectedNetworkDrives", FALSE);
  286     bHideWaitingDialog = ConfigReadInt ("HideWaitingDialog", FALSE);
  287     bUseSecureDesktop = ConfigReadInt ("UseSecureDesktop", FALSE);
  288     defaultMountOptions.Removable = ConfigReadInt ("MountVolumesRemovable", FALSE);
  289     defaultMountOptions.ReadOnly =  ConfigReadInt ("MountVolumesReadOnly", FALSE);
  290     defaultMountOptions.ProtectHiddenVolume = FALSE;
  291     defaultMountOptions.PartitionInInactiveSysEncScope = FALSE;
  292     defaultMountOptions.RecoveryMode = FALSE;
  293     defaultMountOptions.UseBackupHeader =  FALSE;
  294 
  295     mountOptions = defaultMountOptions;
  296 
  297     CloseSecurityTokenSessionsAfterMount = ConfigReadInt ("CloseSecurityTokenSessionsAfterMount", 0);
  298 
  299     {
  300         char szTmp[TC_MAX_PATH] = {0};
  301         WideCharToMultiByte (CP_UTF8, 0, SecurityTokenLibraryPath, -1, szTmp, sizeof (szTmp), NULL, NULL);
  302         ConfigReadString ("SecurityTokenLibrary", "", szTmp, sizeof (szTmp) - 1);
  303         MultiByteToWideChar (CP_UTF8, 0, szTmp, -1, SecurityTokenLibraryPath, ARRAYSIZE (SecurityTokenLibraryPath));
  304 
  305         if (SecurityTokenLibraryPath[0])
  306             InitSecurityTokenLibrary(hwndDlg);
  307     }
  308 
  309     /* we don't load the history */
  310 }
  311 
  312 
  313 BOOL SelectItem (HWND hTree, wchar_t nLetter)
  314 {
  315     int i;
  316     LVITEM item;
  317 
  318     for (i = 0; i < ListView_GetItemCount(hTree); i++)
  319     {
  320         memset(&item, 0, sizeof(LVITEM));
  321         item.mask = LVIF_PARAM;
  322         item.iItem = i;
  323 
  324         if (ListView_GetItem (hTree, &item) == FALSE)
  325             return FALSE;
  326         else
  327         {
  328             if (HIWORD (item.lParam) == nLetter)
  329             {
  330                 memset(&item, 0, sizeof(LVITEM));
  331                 item.state = LVIS_FOCUSED|LVIS_SELECTED;
  332                 item.stateMask = LVIS_FOCUSED|LVIS_SELECTED;
  333                 item.mask = LVIF_STATE;
  334                 item.iItem = i;
  335                 SendMessage(hTree, LVM_SETITEMSTATE, i, (LPARAM) &item);
  336                 return TRUE;
  337             }
  338         }
  339     }
  340 
  341     return TRUE;
  342 }
  343 
  344 
  345 
  346 LPARAM
  347 GetSelectedLong (HWND hTree)
  348 {
  349     int hItem = ListView_GetSelectionMark (hTree);
  350     LVITEM item;
  351 
  352     if (nSelectedDriveIndex >= 0)
  353         hItem = nSelectedDriveIndex;
  354 
  355     memset(&item, 0, sizeof(LVITEM));
  356     item.mask = LVIF_PARAM;
  357     item.iItem = hItem;
  358 
  359     if (ListView_GetItem (hTree, &item) == FALSE)
  360         return MAKELONG (0xffff, 0xffff);
  361     else
  362         return item.lParam;
  363 }
  364 
  365 LPARAM
  366 GetItemLong (HWND hTree, int itemNo)
  367 {
  368     LVITEM item;
  369 
  370     memset(&item, 0, sizeof(LVITEM));
  371     item.mask = LVIF_PARAM;
  372     item.iItem = itemNo;
  373 
  374     if (ListView_GetItem (hTree, &item) == FALSE)
  375         return MAKELONG (0xffff, 0xffff);
  376     else
  377         return item.lParam;
  378 }
  379 
  380 static wchar_t PasswordDlgVolume[MAX_PATH + 1] = {0};
  381 static BOOL PasswordDialogDisableMountOptions;
  382 static char *PasswordDialogTitleStringId;
  383 
  384 /* Except in response to the WM_INITDIALOG message, the dialog box procedure
  385    should return nonzero if it processes the message, and zero if it does
  386    not. - see DialogProc */
  387 BOOL CALLBACK ExtcvPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  388 {
  389     WORD lw = LOWORD (wParam);
  390     static Password *szXPwd;
  391     static int *pkcs5;
  392     static int *pim;
  393     static BOOL* truecryptMode;
  394 
  395     switch (msg)
  396     {
  397     case WM_INITDIALOG:
  398         {
  399             int i, nIndex;
  400             szXPwd = ((PasswordDlgParam *) lParam) -> password;
  401             pkcs5 = ((PasswordDlgParam *) lParam) -> pkcs5;
  402             pim = ((PasswordDlgParam *) lParam) -> pim;
  403             truecryptMode = ((PasswordDlgParam *) lParam) -> truecryptMode;
  404             LocalizeDialog (hwndDlg, "IDD_PASSWORD_DLG");
  405             DragAcceptFiles (hwndDlg, TRUE);
  406 
  407             if (PasswordDialogTitleStringId)
  408             {
  409                 SetWindowTextW (hwndDlg, GetString (PasswordDialogTitleStringId));
  410             }
  411             else if (wcslen (PasswordDlgVolume) > 0)
  412             {
  413                 wchar_t s[1024];
  414                 const int maxVisibleLen = 40;
  415 
  416                 if (wcslen (PasswordDlgVolume) > maxVisibleLen)
  417                 {
  418                     wstring volStr = PasswordDlgVolume;
  419                     StringCbPrintfW (s, sizeof(s), GetString ("ENTER_PASSWORD_FOR"), (L"..." + volStr.substr (volStr.size() - maxVisibleLen - 1)).c_str());
  420                 }
  421                 else
  422                     StringCbPrintfW (s, sizeof(s), GetString ("ENTER_PASSWORD_FOR"), PasswordDlgVolume);
  423 
  424                 SetWindowTextW (hwndDlg, s);
  425             }
  426 
  427             /* Populate the PRF algorithms list */
  428             HWND hComboBox = GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID);
  429             SendMessage (hComboBox, CB_RESETCONTENT, 0, 0);
  430 
  431             nIndex =(int) SendMessageW (hComboBox, CB_ADDSTRING, 0, (LPARAM) GetString ("AUTODETECTION"));
  432             SendMessage (hComboBox, CB_SETITEMDATA, (WPARAM) nIndex, (LPARAM) 0);
  433 
  434             for (i = FIRST_PRF_ID; i <= LAST_PRF_ID; i++)
  435             {
  436                 nIndex = (int) SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) get_pkcs5_prf_name(i));
  437                 SendMessage (hComboBox, CB_SETITEMDATA, (WPARAM) nIndex, (LPARAM) i);
  438             }
  439 
  440             /* make autodetection the default */
  441             SendMessage (hComboBox, CB_SETCURSEL, 0, 0);
  442 
  443             ToNormalPwdField (hwndDlg, IDC_PASSWORD);
  444             SendMessage (GetDlgItem (hwndDlg, IDC_CACHE), BM_SETCHECK, bCacheInDriver ? BST_CHECKED:BST_UNCHECKED, 0);
  445             SendMessage (GetDlgItem (hwndDlg, IDC_PIM), EM_LIMITTEXT, MAX_PIM, 0);
  446 
  447             SetPim (hwndDlg, IDC_PIM, *pim);
  448 
  449             /* make PIM field visible if a PIM value has been explicitely specified */
  450             if (*pim > 0)
  451             {
  452                 ShowWindow (GetDlgItem (hwndDlg, IDC_PIM_ENABLE), SW_HIDE);
  453                 ShowWindow (GetDlgItem( hwndDlg, IDT_PIM), SW_SHOW);
  454                 ShowWindow (GetDlgItem( hwndDlg, IDC_PIM), SW_SHOW);
  455                 ShowWindow (GetDlgItem( hwndDlg, IDC_PIM_HELP), SW_SHOW);
  456             }
  457 
  458             SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable);
  459 
  460             mountOptions.PartitionInInactiveSysEncScope = bPrebootPasswordDlgMode;
  461 
  462             if (bPrebootPasswordDlgMode)
  463             {
  464                 SendMessage (hwndDlg, TC_APPMSG_PREBOOT_PASSWORD_MODE, 0, 0);
  465             }
  466 
  467             if (PasswordDialogDisableMountOptions)
  468             {
  469                 EnableWindow (GetDlgItem (hwndDlg, IDC_CACHE), FALSE);
  470                 EnableWindow (GetDlgItem (hwndDlg, IDC_MOUNT_OPTIONS), FALSE);
  471             }
  472 
  473             /* No support for mounting TrueCrypt volumes */
  474             SetCheckBox (hwndDlg, IDC_TRUECRYPT_MODE, FALSE);
  475             EnableWindow (GetDlgItem (hwndDlg, IDC_TRUECRYPT_MODE), FALSE);
  476 
  477             if (!SetForegroundWindow (hwndDlg) && (FavoriteMountOnArrivalInProgress))
  478             {
  479                 SetWindowPos (hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  480 
  481                 FLASHWINFO flash;
  482                 flash.cbSize = sizeof (flash);
  483                 flash.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG;
  484                 flash.dwTimeout = 0;
  485                 flash.hwnd = hwndDlg;
  486                 flash.uCount = 0;
  487 
  488                 FlashWindowEx (&flash);
  489 
  490                 SetWindowPos (hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  491             }
  492         }
  493         return 0;
  494 
  495     case TC_APPMSG_PREBOOT_PASSWORD_MODE:
  496         {
  497             /* No support for mounting TrueCrypt system partition */
  498             SetCheckBox (hwndDlg, IDC_TRUECRYPT_MODE, FALSE);
  499             EnableWindow (GetDlgItem (hwndDlg, IDC_TRUECRYPT_MODE), FALSE);
  500 
  501             /* Repopulate the PRF algorithms list with algorithms that support system encryption */
  502             HWND hComboBox = GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID);
  503             SendMessage (hComboBox, CB_RESETCONTENT, 0, 0);
  504 
  505             int i, nIndex = (int) SendMessageW (hComboBox, CB_ADDSTRING, 0, (LPARAM) GetString ("AUTODETECTION"));
  506             SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) 0);
  507 
  508             BOOL bIsGPT = FALSE;
  509             try
  510             {
  511                 BootEncryption BootEncObj (hwndDlg);
  512                 bIsGPT = BootEncObj.GetSystemDriveConfiguration().SystemPartition.IsGPT;
  513             }
  514             catch (...) {}
  515 
  516             for (i = FIRST_PRF_ID; i <= LAST_PRF_ID; i++)
  517             {
  518                 if (bIsGPT || HashForSystemEncryption(i))
  519                 {
  520                     nIndex = (int) SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) get_pkcs5_prf_name(i));
  521                     SendMessage (hComboBox, CB_SETITEMDATA, (WPARAM) nIndex, (LPARAM) i);
  522                 }
  523             }
  524 
  525             /* make autodetection the default */
  526             SendMessage (hComboBox, CB_SETCURSEL, 0, 0);
  527 
  528             ToBootPwdField (hwndDlg, IDC_PASSWORD);
  529 
  530             // Attempt to wipe the password stored in the input field buffer
  531             wchar_t tmp[MAX_PASSWORD+1];
  532             wmemset (tmp, L'X', MAX_PASSWORD);
  533             tmp [MAX_PASSWORD] = 0;
  534             SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp);
  535             SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), L"");
  536 
  537             StringCbPrintfW (OrigKeyboardLayout, sizeof(OrigKeyboardLayout),L"%08X", (DWORD) GetKeyboardLayout (NULL) & 0xFFFF);
  538 
  539             DWORD keybLayout = (DWORD) LoadKeyboardLayout (L"00000409", KLF_ACTIVATE);
  540 
  541             if (keybLayout != 0x00000409 && keybLayout != 0x04090409)
  542             {
  543                 Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION", hwndDlg);
  544                 EndDialog (hwndDlg, IDCANCEL);
  545                 return 1;
  546             }
  547 
  548             if (SetTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD, TIMER_INTERVAL_KEYB_LAYOUT_GUARD, NULL) == 0)
  549             {
  550                 Error ("CANNOT_SET_TIMER", hwndDlg);
  551                 EndDialog (hwndDlg, IDCANCEL);
  552                 return 1;
  553             }
  554 
  555             if (GetCheckBox (hwndDlg, IDC_SHOW_PASSWORD))
  556             {
  557                 // simulate hiding password
  558                 SetCheckBox (hwndDlg, IDC_SHOW_PASSWORD, FALSE);
  559 
  560                 HandleShowPasswordFieldAction (hwndDlg, IDC_SHOW_PASSWORD, IDC_PASSWORD, IDC_PIM);
  561             }
  562 
  563             SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, FALSE);
  564             EnableWindow (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE), FALSE);
  565             EnableWindow (GetDlgItem (hwndDlg, IDC_KEY_FILES), FALSE);
  566 
  567             SetPim (hwndDlg, IDC_PIM, *pim);
  568 
  569             bPrebootPasswordDlgMode = TRUE;
  570         }
  571         return 1;
  572 
  573     case WM_TIMER:
  574         switch (wParam)
  575         {
  576         case TIMER_ID_KEYB_LAYOUT_GUARD:
  577             if (bPrebootPasswordDlgMode)
  578             {
  579                 DWORD keybLayout = (DWORD) GetKeyboardLayout (NULL);
  580 
  581                 if (keybLayout != 0x00000409 && keybLayout != 0x04090409)
  582                 {
  583                     // Keyboard layout is not standard US
  584 
  585                     // Attempt to wipe the password stored in the input field buffer
  586                     wchar_t tmp[MAX_PASSWORD+1];
  587                     wmemset (tmp, L'X', MAX_PASSWORD);
  588                     tmp [MAX_PASSWORD] = 0;
  589                     SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp);
  590                     SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), L"");
  591 
  592                     keybLayout = (DWORD) LoadKeyboardLayout (L"00000409", KLF_ACTIVATE);
  593 
  594                     if (keybLayout != 0x00000409 && keybLayout != 0x04090409)
  595                     {
  596                         KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD);
  597                         Error ("CANT_CHANGE_KEYB_LAYOUT_FOR_SYS_ENCRYPTION", hwndDlg);
  598                         EndDialog (hwndDlg, IDCANCEL);
  599                         return 1;
  600                     }
  601 
  602                     wchar_t szTmp [4096];
  603                     StringCbCopyW (szTmp, sizeof(szTmp), GetString ("KEYB_LAYOUT_CHANGE_PREVENTED"));
  604                     StringCbCatW (szTmp, sizeof(szTmp), L"\n\n");
  605                     StringCbCatW (szTmp, sizeof(szTmp), GetString ("KEYB_LAYOUT_SYS_ENC_EXPLANATION"));
  606                     MessageBoxW (MainDlg, szTmp, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST);
  607                 }
  608             }
  609             return 1;
  610         }
  611         return 0;
  612 
  613     case WM_COMMAND:
  614 
  615         if (lw == IDC_MOUNT_OPTIONS)
  616         {
  617             DialogBoxParamW (hInst,
  618                 MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), hwndDlg,
  619                 (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions);
  620 
  621             if (!bPrebootPasswordDlgMode && mountOptions.PartitionInInactiveSysEncScope)
  622                 SendMessage (hwndDlg, TC_APPMSG_PREBOOT_PASSWORD_MODE, 0, 0);
  623 
  624             return 1;
  625         }
  626 
  627         if (lw == IDC_PIM_ENABLE)
  628         {
  629             ShowWindow (GetDlgItem (hwndDlg, IDC_PIM_ENABLE), SW_HIDE);
  630             ShowWindow (GetDlgItem( hwndDlg, IDT_PIM), SW_SHOW);
  631             ShowWindow (GetDlgItem( hwndDlg, IDC_PIM), SW_SHOW);
  632             ShowWindow (GetDlgItem( hwndDlg, IDC_PIM_HELP), SW_SHOW);
  633 
  634             SetFocus (GetDlgItem (hwndDlg, IDC_PIM));
  635             return 1;
  636         }
  637 
  638         if (lw == IDC_SHOW_PASSWORD)
  639         {
  640             HandleShowPasswordFieldAction (hwndDlg, IDC_SHOW_PASSWORD, IDC_PASSWORD, IDC_PIM);
  641             return 1;
  642         }
  643 
  644         if (lw == IDC_KEY_FILES)
  645         {
  646             KeyFilesDlgParam param;
  647             param.EnableKeyFiles = KeyFilesEnable;
  648             param.FirstKeyFile = FirstKeyFile;
  649 
  650             if (IDOK == DialogBoxParamW (hInst,
  651                 MAKEINTRESOURCEW (IDD_KEYFILES), hwndDlg,
  652                 (DLGPROC) KeyFilesDlgProc, (LPARAM) &param))
  653             {
  654                 KeyFilesEnable = param.EnableKeyFiles;
  655                 FirstKeyFile = param.FirstKeyFile;
  656 
  657                 SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable);
  658             }
  659 
  660             return 1;
  661         }
  662 
  663         if (lw == IDC_KEYFILES_ENABLE)
  664         {
  665             KeyFilesEnable = GetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE);
  666 
  667             return 1;
  668         }
  669 
  670         if (lw == IDCANCEL || lw == IDOK)
  671         {
  672             wchar_t tmp[MAX_PASSWORD+1];
  673 
  674             if (lw == IDOK)
  675             {
  676                 if (mountOptions.ProtectHiddenVolume && hidVolProtKeyFilesParam.EnableKeyFiles)
  677                     KeyFilesApply (hwndDlg, &mountOptions.ProtectedHidVolPassword, hidVolProtKeyFilesParam.FirstKeyFile, PasswordDlgVolume);
  678 
  679                 if (GetPassword (hwndDlg, IDC_PASSWORD, (LPSTR) szXPwd->Text, MAX_PASSWORD + 1, TRUE))
  680                     szXPwd->Length = (unsigned __int32) (strlen ((char *) szXPwd->Text));
  681                 else
  682                     return 1;
  683 
  684                 bCacheInDriver = IsButtonChecked (GetDlgItem (hwndDlg, IDC_CACHE));
  685                 *pkcs5 = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_PKCS5_PRF_ID), CB_GETCURSEL, 0, 0), 0);
  686                 *truecryptMode = GetCheckBox (hwndDlg, IDC_TRUECRYPT_MODE);
  687 
  688                 *pim = GetPim (hwndDlg, IDC_PIM, 0);
  689 
  690                 /* check that PRF is supported in TrueCrypt Mode */
  691                 if (    (*truecryptMode)
  692                     && ((!is_pkcs5_prf_supported(*pkcs5, TRUE, PRF_BOOT_NO)) || (mountOptions.ProtectHiddenVolume && !is_pkcs5_prf_supported(mountOptions.ProtectedHidVolPkcs5Prf, TRUE, PRF_BOOT_NO)))
  693                     )
  694                 {
  695                     Error ("ALGO_NOT_SUPPORTED_FOR_TRUECRYPT_MODE", hwndDlg);
  696                     return 1;
  697                 }
  698 
  699                 if (    (*truecryptMode)
  700                     &&  (*pim != 0)
  701                     )
  702                 {
  703                     Error ("PIM_NOT_SUPPORTED_FOR_TRUECRYPT_MODE", hwndDlg);
  704                     return 1;
  705                 }
  706             }
  707 
  708             // Attempt to wipe password stored in the input field buffer
  709             wmemset (tmp, L'X', MAX_PASSWORD);
  710             tmp[MAX_PASSWORD] = 0;
  711             SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD), tmp);
  712             SetWindowText (GetDlgItem (hwndDlg, IDC_PASSWORD_PROT_HIDVOL), tmp);
  713 
  714             if (hidVolProtKeyFilesParam.FirstKeyFile != NULL)
  715             {
  716                 KeyFileRemoveAll (&hidVolProtKeyFilesParam.FirstKeyFile);
  717                 hidVolProtKeyFilesParam.EnableKeyFiles = FALSE;
  718             }
  719 
  720             if (bPrebootPasswordDlgMode)
  721             {
  722                 KillTimer (hwndDlg, TIMER_ID_KEYB_LAYOUT_GUARD);
  723 
  724                 // Restore the original keyboard layout
  725                 if (LoadKeyboardLayout (OrigKeyboardLayout, KLF_ACTIVATE | KLF_SUBSTITUTE_OK) == NULL)
  726                     Warning ("CANNOT_RESTORE_KEYBOARD_LAYOUT", hwndDlg);
  727             }
  728 
  729             EndDialog (hwndDlg, lw);
  730             return 1;
  731         }
  732         return 0;
  733 
  734     case WM_CONTEXTMENU:
  735         {
  736             RECT buttonRect;
  737             GetWindowRect (GetDlgItem (hwndDlg, IDC_KEY_FILES), &buttonRect);
  738 
  739             if (LOWORD (lParam) >= buttonRect.left && LOWORD (lParam) <= buttonRect.right
  740                 && HIWORD (lParam) >= buttonRect.top && HIWORD (lParam) <= buttonRect.bottom)
  741             {
  742                 // The "Keyfiles" button has been right-clicked
  743 
  744                 KeyFilesDlgParam param;
  745                 param.EnableKeyFiles = KeyFilesEnable;
  746                 param.FirstKeyFile = FirstKeyFile;
  747 
  748                 POINT popupPos;
  749                 popupPos.x = buttonRect.left + 2;
  750                 popupPos.y = buttonRect.top + 2;
  751 
  752                 if (KeyfilesPopupMenu (hwndDlg, popupPos, &param))
  753                 {
  754                     KeyFilesEnable = param.EnableKeyFiles;
  755                     FirstKeyFile = param.FirstKeyFile;
  756                     SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable);
  757                 }
  758             }
  759         }
  760         break;
  761 
  762     case WM_DROPFILES:
  763         {
  764             HDROP hdrop = (HDROP) wParam;
  765             int i = 0, count = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
  766 
  767             while (count-- > 0)
  768             {
  769                 KeyFile *kf = (KeyFile *) malloc (sizeof (KeyFile));
  770                 if (kf)
  771                 {
  772                     DragQueryFile (hdrop, i++, kf->FileName, ARRAYSIZE (kf->FileName));
  773                     FirstKeyFile = KeyFileAdd (FirstKeyFile, kf);
  774                     KeyFilesEnable = TRUE;
  775                 }
  776             }
  777 
  778             SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, KeyFilesEnable);
  779             DragFinish (hdrop);
  780         }
  781         return 1;
  782     }
  783 
  784     return 0;
  785 }
  786 
  787 void SaveSettings (HWND hwndDlg)
  788 {
  789     // dummy
  790 }
  791 
  792 int BackupVolumeHeader (HWND hwndDlg, BOOL bRequireConfirmation, char *lpszVolume)
  793 {
  794     // dummy
  795     return 0;
  796 }
  797 
  798 int RestoreVolumeHeader (HWND hwndDlg, char *lpszVolume)
  799 {
  800     // dummy
  801     return 0;
  802 }
  803 
  804 int ExtcvAskVolumePassword (HWND hwndDlg, const wchar_t* fileName, Password *password, int *pkcs5, int *pim, BOOL* truecryptMode, char *titleStringId, BOOL enableMountOptions)
  805 {
  806     INT_PTR result;
  807     PasswordDlgParam dlgParam;
  808 
  809     PasswordDialogTitleStringId = titleStringId;
  810     PasswordDialogDisableMountOptions = !enableMountOptions;
  811 
  812     dlgParam.password = password;
  813     dlgParam.pkcs5 = pkcs5;
  814     dlgParam.pim = pim;
  815     dlgParam.truecryptMode = truecryptMode;
  816 
  817     StringCbCopyW (PasswordDlgVolume, sizeof(PasswordDlgVolume), fileName);
  818 
  819     result = SecureDesktopDialogBoxParam (hInst,
  820         MAKEINTRESOURCEW (IDD_PASSWORD_DLG), hwndDlg,
  821         (DLGPROC) ExtcvPasswordDlgProc, (LPARAM) &dlgParam);
  822 
  823     if (result != IDOK)
  824     {
  825         password->Length = 0;
  826         *pkcs5 = 0;
  827         *pim = 0;
  828         *truecryptMode = FALSE;
  829         burn (&mountOptions.ProtectedHidVolPassword, sizeof (mountOptions.ProtectedHidVolPassword));
  830         burn (&mountOptions.ProtectedHidVolPkcs5Prf, sizeof (mountOptions.ProtectedHidVolPkcs5Prf));
  831     }
  832 
  833     return result == IDOK;
  834 }
  835 
  836 // GUI actions
  837 
  838 static BOOL SelectContainer (HWND hwndDlg)
  839 {
  840     if (BrowseFiles (hwndDlg, "OPEN_VOL_TITLE", szFileName, bHistory, FALSE, NULL) == FALSE)
  841         return FALSE;
  842 
  843     AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory);
  844     VeraCryptExpander::EnableDisableButtons (hwndDlg);
  845     SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST));
  846     return TRUE;
  847 }
  848 
  849 static BOOL SelectPartition (HWND hwndDlg)
  850 {
  851     RawDevicesDlgParam param;
  852     param.pszFileName = szFileName;
  853     INT_PTR nResult = DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_RAWDEVICES_DLG), hwndDlg,
  854         (DLGPROC) RawDevicesDlgProc, (LPARAM) & param);
  855     if (nResult == IDOK)
  856     {
  857         AddComboItem (GetDlgItem (hwndDlg, IDC_VOLUME), szFileName, bHistory);
  858         VeraCryptExpander::EnableDisableButtons (hwndDlg);
  859         SetFocus (GetDlgItem (hwndDlg, IDC_DRIVELIST));
  860         return TRUE;
  861     }
  862 
  863     return FALSE;
  864 }
  865 
  866 
  867 /* Except in response to the WM_INITDIALOG and WM_ENDSESSION messages, the dialog box procedure
  868    should return nonzero if it processes a message, and zero if it does not. */
  869 BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  870 {
  871     static UINT taskBarCreatedMsg;
  872     WORD lw = LOWORD (wParam);
  873 
  874     switch (uMsg)
  875     {
  876 
  877     case WM_INITDIALOG:
  878         {
  879             int exitCode = 0;
  880 
  881             MainDlg = hwndDlg;
  882 
  883             // Set critical default options in case UsePreferences is false
  884             bPreserveTimestamp = defaultMountOptions.PreserveTimestamp = TRUE;
  885             bShowDisconnectedNetworkDrives = FALSE;
  886             bHideWaitingDialog = FALSE;
  887             bUseSecureDesktop = FALSE;
  888 
  889             if (UsePreferences)
  890             {
  891                 // General preferences
  892                 VeraCryptExpander::LoadSettings (hwndDlg);
  893 
  894                 // Keyfiles
  895                 LoadDefaultKeyFilesParam ();
  896                 RestoreDefaultKeyFilesParam ();
  897             }
  898 
  899             InitMainDialog (hwndDlg);
  900 
  901             // Quit
  902             if (Quit)
  903             {
  904                 exit (exitCode);
  905             }
  906 
  907             Silent = FALSE;
  908         }
  909         return 0;
  910 
  911     case WM_SYSCOMMAND:
  912         if (lw == IDC_ABOUT)
  913         {
  914             DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc);
  915             return 1;
  916         }
  917         return 0;
  918 
  919     case WM_ENDSESSION:
  920         VeraCryptExpander::EndMainDlg (hwndDlg);
  921         localcleanup ();
  922         return 0;
  923 
  924     case WM_COMMAND:
  925 
  926         if (lw == IDCANCEL || lw == IDC_EXIT)
  927         {
  928             VeraCryptExpander::EndMainDlg (hwndDlg);
  929             return 1;
  930         }
  931 
  932         if ( lw == IDOK )
  933         {
  934             if (!VeraCryptExpander::VolumeSelected(hwndDlg))
  935             {
  936                 Warning ("NO_VOLUME_SELECTED", hwndDlg);
  937             }
  938             else
  939             {
  940                 wchar_t fileName[MAX_PATH];
  941                 GetWindowText (GetDlgItem (hwndDlg, IDC_VOLUME), fileName, ARRAYSIZE (fileName));
  942                 ExpandVolumeWizard(hwndDlg, fileName);
  943             }
  944             return 1;
  945         }
  946 
  947         if (lw == IDM_ABOUT )
  948         {
  949             DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc);
  950             return 1;
  951         }
  952 
  953         if (lw == IDM_HOMEPAGE )
  954         {
  955             ArrowWaitCursor ();
  956             ShellExecute (NULL, L"open", L"https://www.veracrypt.fr", NULL, NULL, SW_SHOWNORMAL);
  957             Sleep (200);
  958             NormalCursor ();
  959 
  960             return 1;
  961         }
  962 
  963         if (lw == IDC_SELECT_FILE)
  964         {
  965             SelectContainer (hwndDlg);
  966             return 1;
  967         }
  968 
  969         if (lw == IDC_SELECT_DEVICE)
  970         {
  971             SelectPartition (hwndDlg);
  972             return 1;
  973         }
  974 
  975         return 0;
  976 
  977     case WM_CLOSE:
  978         VeraCryptExpander::EndMainDlg (hwndDlg);
  979         return 1;
  980 
  981     default:
  982         ;
  983     }
  984 
  985     return 0;
  986 }
  987 
  988 }
  989 
  990 
  991 int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpszCommandLine, int nCmdShow)
  992 {
  993     int status;
  994     atexit (VeraCryptExpander::localcleanup);
  995     SetProcessShutdownParameters (0x100, 0);
  996 
  997     VirtualLock (&VeraCryptExpander::VolumePassword, sizeof (VeraCryptExpander::VolumePassword));
  998     VirtualLock (&VeraCryptExpander::CmdVolumePassword, sizeof (VeraCryptExpander::CmdVolumePassword));
  999     VirtualLock (&VeraCryptExpander::mountOptions, sizeof (VeraCryptExpander::mountOptions));
 1000     VirtualLock (&VeraCryptExpander::defaultMountOptions, sizeof (VeraCryptExpander::defaultMountOptions));
 1001     VirtualLock (&VeraCryptExpander::szFileName, sizeof(VeraCryptExpander::szFileName));
 1002 
 1003     InitApp (hInstance, lpszCommandLine);
 1004 
 1005     /* application title */
 1006     lpszTitle = L"VeraCrypt Expander";
 1007 
 1008     DetectX86Features ();
 1009 
 1010     status = DriverAttach ();
 1011     if (status != 0)
 1012     {
 1013         if (status == ERR_OS_ERROR)
 1014             handleWin32Error (NULL, SRC_POS);
 1015         else
 1016             handleError (NULL, status, SRC_POS);
 1017 
 1018         AbortProcess ("NODRIVER");
 1019     }
 1020 
 1021     /* Create the main dialog box */
 1022     DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_MOUNT_DLG), NULL, (DLGPROC) VeraCryptExpander::MainDialogProc,
 1023             (LPARAM) lpszCommandLine);
 1024 
 1025     /* Terminate */
 1026     return 0;
 1027 }