"Fossies" - the Fresh Open Source Software Archive

Member "src/Setup/Setup.c" (10 Oct 2018, 72157 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 "Setup.c" 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  Modifications and additions to the original source code (contained in this file)
    9  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
   10  and are governed by the Apache License 2.0 the full text of which is
   11  contained in the file License.txt included in VeraCrypt binary and source
   12  code distribution packages. */
   13 
   14 #include "Tcdefs.h"
   15 #include <SrRestorePtApi.h>
   16 #include <io.h>
   17 #include <propkey.h>
   18 #include <propvarutil.h>
   19 #include <sys/types.h>
   20 #include <sys/stat.h>
   21 #include <tchar.h>
   22 
   23 #include "Apidrvr.h"
   24 #include "BootEncryption.h"
   25 #include "Boot/Windows/BootCommon.h"
   26 #include "Combo.h"
   27 #include "ComSetup.h"
   28 #include "Dlgcode.h"
   29 #include "Language.h"
   30 #include "Registry.h"
   31 #include "Resource.h"
   32 
   33 #include "Dir.h"
   34 #include "Setup.h"
   35 #include "SelfExtract.h"
   36 #include "Wizard.h"
   37 
   38 #include "../Common/Resource.h"
   39 
   40 using namespace VeraCrypt;
   41 
   42 #pragma warning( disable : 4201 )
   43 #pragma warning( disable : 4115 )
   44 
   45 #include <shlobj.h>
   46 
   47 #pragma warning( default : 4201 )
   48 #pragma warning( default : 4115 )
   49 
   50 #include <Strsafe.h>
   51 
   52 wchar_t InstallationPath[TC_MAX_PATH];
   53 wchar_t SetupFilesDir[TC_MAX_PATH];
   54 wchar_t UninstallBatch[MAX_PATH];
   55 
   56 BOOL bUninstall = FALSE;
   57 BOOL bRestartRequired = FALSE;
   58 BOOL bMakePackage = FALSE;
   59 BOOL bDone = FALSE;
   60 BOOL Rollback = FALSE;
   61 BOOL bUpgrade = FALSE;
   62 BOOL bUpdateRescueDisk = FALSE;
   63 BOOL bDowngrade = FALSE;
   64 BOOL SystemEncryptionUpdate = FALSE;
   65 BOOL PortableMode = FALSE;
   66 BOOL bRepairMode = FALSE;
   67 BOOL bReinstallMode = FALSE;
   68 BOOL bChangeMode = FALSE;
   69 BOOL bDevm = FALSE;
   70 BOOL bPossiblyFirstTimeInstall = FALSE;
   71 BOOL bUninstallInProgress = FALSE;
   72 BOOL UnloadDriver = TRUE;
   73 
   74 BOOL bSystemRestore = TRUE;
   75 BOOL bDisableSwapFiles = FALSE;
   76 BOOL bForAllUsers = TRUE;
   77 BOOL bRegisterFileExt = TRUE;
   78 BOOL bAddToStartMenu = TRUE;
   79 BOOL bDesktopIcon = TRUE;
   80 
   81 BOOL bUserSetLanguage = FALSE;
   82 
   83 BOOL bDesktopIconStatusDetermined = FALSE;
   84 
   85 HMODULE volatile SystemRestoreDll = 0;
   86 
   87 void localcleanup (void)
   88 {
   89     localcleanupwiz ();
   90     cleanup ();
   91 
   92     CloseAppSetupMutex ();
   93 }
   94 
   95 BOOL ForceDeleteFile (LPCWSTR szFileName)
   96 {
   97     if (!DeleteFile (szFileName))
   98     {
   99         /* delete the renamed file when the machine reboots */
  100         return MoveFileEx (szFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  101     }
  102     else
  103         return TRUE;
  104 }
  105 
  106 BOOL StatDeleteFile (wchar_t *lpszFile, BOOL bCheckForOldFile)
  107 {
  108     struct __stat64 st;
  109 
  110     if (bCheckForOldFile)
  111     {
  112         wchar_t szOldPath[MAX_PATH + 1];
  113         StringCbCopyW (szOldPath, sizeof(szOldPath), lpszFile);
  114         StringCbCatW  (szOldPath, sizeof(szOldPath), VC_FILENAME_RENAMED_SUFFIX);
  115 
  116         if (_wstat64 (szOldPath, &st) == 0)
  117         {
  118             ForceDeleteFile (szOldPath);
  119         }
  120     }
  121 
  122     if (_wstat64 (lpszFile, &st) == 0)
  123         return ForceDeleteFile (lpszFile);
  124     else
  125         return TRUE;
  126 }
  127 
  128 BOOL StatRemoveDirectory (wchar_t *lpszDir)
  129 {
  130     struct __stat64 st;
  131 
  132     if (_wstat64 (lpszDir, &st) == 0)
  133     {
  134         return DeleteDirectory (lpszDir);
  135     }
  136     else
  137         return TRUE;
  138 }
  139 
  140 
  141 /* Recursively set the given OWNER security descriptor to the key and its subkeys */
  142 static void RecursiveSetOwner (HKEY hKey, PSECURITY_DESCRIPTOR pSD)
  143 {
  144     LSTATUS status = 0;
  145     DWORD dwIndex = 0, dwMaxNameLen = 0, dwNameLen = 0, numberSubKeys = 0;
  146     HKEY hSubKey;
  147 
  148     if (    (ERROR_SUCCESS == status) && (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, &numberSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL))
  149         &&  (numberSubKeys >= 1)
  150         )
  151     {
  152         dwMaxNameLen++;
  153         wchar_t* szNameValue = new wchar_t[dwMaxNameLen];
  154         while (true)
  155         {
  156             dwNameLen = dwMaxNameLen;
  157             status = RegEnumKeyExW (hKey, dwIndex++, szNameValue, &dwNameLen, NULL, NULL, NULL, NULL);
  158             if (status == ERROR_SUCCESS)
  159             {
  160                 status = RegOpenKeyExW (hKey, szNameValue, 0, WRITE_OWNER | KEY_READ , &hSubKey);
  161                 if (ERROR_SUCCESS == status)
  162                 {
  163                     RecursiveSetOwner (hSubKey, pSD);
  164                     RegCloseKey(hSubKey);
  165                 }
  166             }
  167             else
  168                 break;
  169         }
  170         delete [] szNameValue;
  171     }
  172 
  173     RegSetKeySecurity (hKey, OWNER_SECURITY_INFORMATION, pSD);
  174 }
  175 
  176 /* Recursively set the given DACL security descriptor to the key and its subkeys */
  177 static void RecursiveSetDACL (HKEY hKey, const wchar_t* SubKeyName, PSECURITY_DESCRIPTOR pSD)
  178 {
  179     HKEY hSubKey;
  180     DWORD dwIndex = 0, dwMaxNameLen = 0, dwNameLen = 0, numberSubKeys = 0;
  181     LSTATUS status = RegOpenKeyExW(hKey, SubKeyName, 0, WRITE_DAC | KEY_READ /*| ACCESS_SYSTEM_SECURITY*/, &hSubKey);
  182     if (status == ERROR_SUCCESS)
  183     {
  184         status = RegSetKeySecurity (hSubKey, DACL_SECURITY_INFORMATION, pSD);
  185         if (status == ERROR_SUCCESS)
  186         {
  187             RegCloseKey(hSubKey);
  188             status = RegOpenKeyExW(hKey, SubKeyName, 0, WRITE_DAC | KEY_READ , &hSubKey);
  189         }
  190 
  191         if ( (ERROR_SUCCESS == status)
  192             &&  (ERROR_SUCCESS == RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &numberSubKeys, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL))
  193             &&  (numberSubKeys >= 1)
  194             )
  195         {
  196             dwMaxNameLen++;
  197             wchar_t* szNameValue = new wchar_t[dwMaxNameLen];
  198             while (true)
  199             {
  200                 dwNameLen = dwMaxNameLen;
  201                 status = RegEnumKeyExW (hSubKey, dwIndex++, szNameValue, &dwNameLen, NULL, NULL, NULL, NULL);
  202                 if (status == ERROR_SUCCESS)
  203                 {
  204                     RecursiveSetDACL (hSubKey, szNameValue, pSD);
  205                 }
  206                 else
  207                     break;
  208             }
  209             delete [] szNameValue;
  210         }
  211     }
  212 }
  213 
  214 /* Correct the key permissions to allow its deletion */
  215 static void AllowKeyAccess(HKEY Key,const wchar_t* SubKeyName)
  216 {
  217     LSTATUS RegResult;
  218     HKEY SvcKey = NULL;
  219     DWORD dwLength = 0;
  220     HANDLE Token = NULL;
  221     PTOKEN_USER pTokenUser = NULL;
  222     std::string sNewSD;
  223 
  224     RegResult = RegOpenKeyExW(Key, SubKeyName, 0, WRITE_OWNER | KEY_READ, &SvcKey);
  225     if (RegResult==ERROR_SUCCESS)
  226     {
  227         if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token))
  228         {
  229             if (!GetTokenInformation(Token, TokenUser, pTokenUser, 0, &dwLength))
  230             {
  231                 if (GetLastError() ==ERROR_INSUFFICIENT_BUFFER)
  232                 {
  233                     pTokenUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
  234                     if (pTokenUser)
  235                     {
  236                         if (GetTokenInformation(Token, TokenUser, pTokenUser, dwLength, &dwLength))
  237                         {
  238                             SECURITY_DESCRIPTOR SecDesc;
  239                             if (    InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION)
  240                                 &&  SetSecurityDescriptorDacl(&SecDesc, TRUE, NULL, FALSE) // NULL DACL: full access to everyone
  241                                 && SetSecurityDescriptorOwner(&SecDesc, pTokenUser->User.Sid, FALSE)
  242                                 )
  243                             {
  244                                 RecursiveSetOwner(SvcKey, &SecDesc);
  245                             }
  246                         }
  247 
  248                     }
  249                 }
  250             }
  251         }
  252         RegCloseKey(SvcKey);
  253     }
  254 
  255     if (pTokenUser)
  256     {
  257         PSID pSid = pTokenUser->User.Sid;
  258         DWORD dwAclSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + ::GetLengthSid(pSid) - sizeof(DWORD);
  259         PACL pDacl = (PACL) new BYTE[dwAclSize];
  260         if (pDacl)
  261         {
  262             if (TRUE == ::InitializeAcl(pDacl, dwAclSize, ACL_REVISION))
  263             {
  264                 if (TRUE == AddAccessAllowedAceEx(pDacl, ACL_REVISION, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, WRITE_DAC | KEY_ALL_ACCESS, pSid))
  265                 {
  266                     SECURITY_DESCRIPTOR SecDesc;
  267                     if (TRUE == ::InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION))
  268                     {
  269                         if (TRUE == ::SetSecurityDescriptorDacl(&SecDesc, TRUE, pDacl, FALSE))
  270                         {
  271                             RecursiveSetDACL (Key, SubKeyName, &SecDesc);
  272                         }
  273                     }
  274                 }
  275             }
  276             delete [] pDacl;
  277         }
  278     }
  279 
  280     if (pTokenUser)
  281         HeapFree(GetProcessHeap(), 0, pTokenUser);
  282     if (Token)
  283         CloseHandle(Token);
  284 }
  285 
  286 void SearchAndDeleteRegistrySubString (HKEY hKey, const wchar_t *subKey, const wchar_t *str, BOOL bEnumSubKeys, const wchar_t* enumMatchSubStr)
  287 {
  288     HKEY hSubKey = 0;
  289     LSTATUS status = 0;
  290     DWORD dwIndex = 0, dwType, dwValueNameLen, dwDataLen;
  291     std::list<std::wstring> subKeysList;
  292     size_t subStringLength = str? wcslen(str) : 0;
  293 
  294     if (bEnumSubKeys)
  295     {
  296          DWORD dwMaxNameLen = 0;
  297          if (ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, &dwMaxNameLen, NULL, NULL, NULL, NULL, NULL, NULL))
  298          {
  299             dwMaxNameLen++;
  300             wchar_t* szNameValue = new wchar_t[dwMaxNameLen];
  301                dwIndex = 0;
  302                while (true)
  303                {
  304                    dwValueNameLen = dwMaxNameLen;
  305                    status = RegEnumKeyExW (hKey, dwIndex++, szNameValue, &dwValueNameLen, NULL, NULL, NULL, NULL);
  306                    if (status == ERROR_SUCCESS)
  307                    {
  308                         if (enumMatchSubStr && !wcsstr(szNameValue, enumMatchSubStr))
  309                             continue;
  310                     std::wstring entryName = szNameValue;
  311                     entryName += L"\\";
  312                     entryName += subKey;
  313                     entryName += L"\\";
  314                     subKeysList.push_back(entryName);
  315                    }
  316                    else
  317                        break;
  318                }
  319             delete [] szNameValue;
  320          }
  321     }
  322     else
  323     {
  324         subKeysList.push_back(subKey);
  325     }
  326 
  327     for (std::list<std::wstring>::iterator ItSubKey = subKeysList.begin(); ItSubKey != subKeysList.end(); ItSubKey++)
  328     {
  329         // if the string to search for is empty, delete the sub key, otherwise, look for matching value and delete them
  330         if (subStringLength == 0)
  331         {
  332             if (ERROR_ACCESS_DENIED == DeleteRegistryKey (hKey, ItSubKey->c_str()))
  333             {
  334                 // grant permission to delete
  335                 AllowKeyAccess (hKey, ItSubKey->c_str());
  336 
  337                 // try again
  338                 DeleteRegistryKey (hKey, ItSubKey->c_str());
  339             }
  340         }
  341         else
  342         {
  343             if (RegOpenKeyExW (hKey, ItSubKey->c_str(), 0, KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS)
  344             {
  345             DWORD dwMaxNameLen = 0, dwMaxDataLen = 0;
  346             if (ERROR_SUCCESS == RegQueryInfoKey(hSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxNameLen, &dwMaxDataLen, NULL, NULL))
  347             {
  348                dwMaxNameLen++;
  349                wchar_t* szNameValue = new wchar_t[dwMaxNameLen];
  350                LPBYTE pbData = new BYTE[dwMaxDataLen];
  351 
  352                    std::list<std::wstring> foundEntries;
  353                    dwIndex = 0;
  354                    do
  355                    {
  356                        dwValueNameLen = dwMaxNameLen;
  357                        dwDataLen = dwMaxDataLen;
  358                        status = RegEnumValueW(hSubKey, dwIndex++, szNameValue, &dwValueNameLen, NULL, &dwType, pbData, &dwDataLen);
  359                        if (status == ERROR_SUCCESS)
  360                        {
  361                            if ( (wcslen(szNameValue) >= subStringLength && wcsstr(szNameValue, str))
  362                                ||   (dwType == REG_SZ && wcslen((wchar_t*) pbData) >= subStringLength && wcsstr((wchar_t*) pbData, str))
  363                                )
  364                            {
  365                                foundEntries.push_back(szNameValue);
  366                            }
  367                        }
  368                    } while ((status == ERROR_SUCCESS) || (status == ERROR_MORE_DATA)); // we ignore ERROR_MORE_DATA errors since
  369                                                                                    // we are sure to use the correct sizes
  370 
  371                    // delete the entries
  372                    if (!foundEntries.empty())
  373                    {
  374                        for (std::list<std::wstring>::iterator It = foundEntries.begin();
  375                            It != foundEntries.end(); It++)
  376                        {
  377                            RegDeleteValueW (hSubKey, It->c_str());
  378                        }
  379                    }
  380 
  381                delete [] szNameValue;
  382                delete [] pbData;
  383             }
  384 
  385 
  386                 RegCloseKey (hSubKey);
  387             }
  388         }
  389     }
  390 }
  391 
  392 /*
  393  * Creates a VT_LPWSTR propvariant.
  394  * we use our own implementation to use SHStrDupW function pointer
  395  * that we retreive ourselves to avoid dll hijacking attacks
  396  */
  397 inline HRESULT VCInitPropVariantFromString(__in PCWSTR psz, __out PROPVARIANT *ppropvar)
  398 {
  399     ppropvar->vt = VT_LPWSTR;
  400     HRESULT hr = VCStrDupW(psz, &ppropvar->pwszVal);
  401     if (FAILED(hr))
  402     {
  403         PropVariantInit(ppropvar);
  404     }
  405     return hr;
  406 }
  407 
  408 HRESULT CreateLink (wchar_t *lpszPathObj, wchar_t *lpszArguments,
  409         wchar_t *lpszPathLink, const wchar_t* iconFile, int iconIndex)
  410 {
  411     HRESULT hres;
  412     IShellLink *psl;
  413 
  414     /* Get a pointer to the IShellLink interface.  */
  415     hres = CoCreateInstance (CLSID_ShellLink, NULL,
  416                    CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &psl);
  417     if (SUCCEEDED (hres))
  418     {
  419         IPersistFile *ppf;
  420 
  421         /* Set the path to the shortcut target, and add the
  422            description.  */
  423         psl->SetPath (lpszPathObj);
  424         psl->SetArguments (lpszArguments);
  425         if (iconFile)
  426         {
  427             psl->SetIconLocation (iconFile, iconIndex);
  428         }
  429 
  430         // Application ID
  431         if (_tcsstr (lpszPathObj, _T(TC_APP_NAME) _T(".exe")))
  432         {
  433             IPropertyStore *propStore;
  434 
  435             if (SUCCEEDED (psl->QueryInterface (IID_PPV_ARGS (&propStore))))
  436             {
  437                 PROPVARIANT propVariant;
  438                 if (SUCCEEDED (VCInitPropVariantFromString (TC_APPLICATION_ID, &propVariant)))
  439                 {
  440                     if (SUCCEEDED (propStore->SetValue (PKEY_AppUserModel_ID, propVariant)))
  441                         propStore->Commit();
  442 
  443                     PropVariantClear (&propVariant);
  444                 }
  445 
  446                 propStore->Release();
  447             }
  448         }
  449 
  450         /* Query IShellLink for the IPersistFile interface for saving
  451            the shortcut in persistent storage.  */
  452         hres = psl->QueryInterface (IID_IPersistFile,
  453                             (void **) &ppf);
  454 
  455         if (SUCCEEDED (hres))
  456         {
  457             /* Save the link by calling IPersistFile::Save.  */
  458             hres = ppf->Save (lpszPathLink, TRUE);
  459             ppf->Release ();
  460         }
  461         psl->Release ();
  462     }
  463     return hres;
  464 }
  465 
  466 BOOL IsSystemRestoreEnabled ()
  467 {
  468     BOOL bEnabled = FALSE;
  469     HKEY hKey;
  470     DWORD dwValue = 0, cbValue = sizeof (DWORD);
  471     wchar_t szRegPath[MAX_PATH];
  472     GetRestorePointRegKeyName (szRegPath, sizeof (szRegPath));
  473     if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szRegPath, 0, KEY_READ | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS)
  474     {
  475         if (IsOSAtLeast (WIN_VISTA))
  476         {
  477             if (    (ERROR_SUCCESS == RegQueryValueEx (hKey, L"RPSessionInterval", NULL, NULL, (LPBYTE) &dwValue, &cbValue))
  478                 &&  (dwValue == 1)
  479                 )
  480             {
  481                 bEnabled = TRUE;
  482             }
  483         }
  484         else
  485         {
  486             if (    (ERROR_SUCCESS == RegQueryValueEx (hKey, L"DisableSR", NULL, NULL, (LPBYTE) &dwValue, &cbValue))
  487                 &&  (dwValue == 0)
  488                 )
  489             {
  490                 bEnabled = TRUE;
  491             }
  492         }
  493 
  494 
  495         RegCloseKey (hKey);
  496     }
  497 
  498     return bEnabled;
  499 }
  500 
  501 void GetProgramPath (HWND hwndDlg, wchar_t *path)
  502 {
  503     ITEMIDLIST *i;
  504     HRESULT res;
  505 
  506     if (bForAllUsers)
  507         res = SHGetSpecialFolderLocation (hwndDlg, CSIDL_COMMON_PROGRAMS, &i);
  508     else
  509         res = SHGetSpecialFolderLocation (hwndDlg, CSIDL_PROGRAMS, &i);
  510 
  511     SHGetPathFromIDList (i, path);
  512 }
  513 
  514 void StatusMessage (HWND hwndDlg, char *stringId)
  515 {
  516     if (Rollback)
  517         return;
  518 
  519     SendMessageW (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_ADDSTRING, 0, (LPARAM) GetString (stringId));
  520 
  521     SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_SETTOPINDEX,
  522         SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0);
  523 }
  524 
  525 void StatusMessageParam (HWND hwndDlg, char *stringId, const wchar_t *param)
  526 {
  527     wchar_t szTmp[1024];
  528 
  529     if (Rollback)
  530         return;
  531 
  532     StringCbPrintfW (szTmp, sizeof(szTmp), L"%s %s", GetString (stringId), param);
  533     SendMessageW (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_ADDSTRING, 0, (LPARAM) szTmp);
  534 
  535     SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_SETTOPINDEX,
  536         SendDlgItemMessage (hwndDlg, IDC_LOG_WINDOW, LB_GETCOUNT, 0, 0) - 1, 0);
  537 }
  538 
  539 void ClearLogWindow (HWND hwndDlg)
  540 {
  541     SendMessage (GetDlgItem (hwndDlg, IDC_LOG_WINDOW), LB_RESETCONTENT, 0, 0);
  542 }
  543 
  544 void RegMessage (HWND hwndDlg, const wchar_t *txt)
  545 {
  546     StatusMessageParam (hwndDlg, "ADDING_REG", txt);
  547 }
  548 
  549 void _cdecl CopyMessage (HWND hwndDlg, const wchar_t *txt)
  550 {
  551     StatusMessageParam (hwndDlg, "INSTALLING", txt);
  552 }
  553 
  554 void RemoveMessage (HWND hwndDlg, const wchar_t *txt)
  555 {
  556     if (!Rollback)
  557         StatusMessageParam (hwndDlg, "REMOVING", txt);
  558 }
  559 
  560 void IconMessage (HWND hwndDlg, const wchar_t *txt)
  561 {
  562     StatusMessageParam (hwndDlg, "ADDING_ICON", txt);
  563 }
  564 
  565 void DetermineUpgradeDowngradeStatus (BOOL bCloseDriverHandle, LONG *driverVersionPtr)
  566 {
  567     LONG driverVersion = VERSION_NUM;
  568     int status = 0;
  569 
  570     if (hDriver == INVALID_HANDLE_VALUE)
  571         status = DriverAttach();
  572 
  573     if ((status == 0) && (hDriver != INVALID_HANDLE_VALUE))
  574     {
  575         DWORD dwResult;
  576         BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &driverVersion, sizeof (driverVersion), &dwResult, NULL);
  577 
  578         if (!bResult)
  579             bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &driverVersion, sizeof (driverVersion), &dwResult, NULL);
  580 
  581 
  582         bUpgrade = (bResult && driverVersion <= VERSION_NUM);
  583         bDowngrade = (bResult && driverVersion > VERSION_NUM);
  584         bReinstallMode = (bResult && driverVersion == VERSION_NUM);
  585 
  586         PortableMode = DeviceIoControl (hDriver, TC_IOCTL_GET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL);
  587 
  588         if (bCloseDriverHandle)
  589         {
  590             CloseHandle (hDriver);
  591             hDriver = INVALID_HANDLE_VALUE;
  592         }
  593     }
  594 
  595     *driverVersionPtr = driverVersion;
  596 }
  597 
  598 
  599 static BOOL IsFileInUse (const wstring &filePath)
  600 {
  601     HANDLE useTestHandle = CreateFile (filePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  602 
  603     if (useTestHandle != INVALID_HANDLE_VALUE)
  604         CloseHandle (useTestHandle);
  605     else if (GetLastError() == ERROR_SHARING_VIOLATION)
  606         return TRUE;
  607 
  608     return FALSE;
  609 }
  610 
  611 
  612 BOOL DoFilesInstall (HWND hwndDlg, wchar_t *szDestDir)
  613 {
  614     /* WARNING: Note that, despite its name, this function is used during UNinstallation as well. */
  615 
  616     wchar_t szTmp[TC_MAX_PATH];
  617     BOOL bOK = TRUE;
  618     int i, x, fileNo;
  619     wchar_t curFileName [TC_MAX_PATH] = {0};
  620 
  621     if (!bUninstall && !bDevm)
  622     {
  623         // Self-extract all files to memory
  624 
  625         GetModuleFileName (NULL, szTmp, ARRAYSIZE (szTmp));
  626 
  627         if (!SelfExtractInMemory (szTmp))
  628             return FALSE;
  629     }
  630 
  631     x = wcslen (szDestDir);
  632     if (x < 2)
  633         return FALSE;
  634 
  635     if (szDestDir[x - 1] != L'\\')
  636         StringCbCatW (szDestDir, MAX_PATH, L"\\");
  637 
  638     for (i = 0; i < sizeof (szFiles) / sizeof (szFiles[0]); i++)
  639     {
  640         BOOL bResult, driver64 = FALSE, zipFile = FALSE;
  641         wchar_t szDir[TC_MAX_PATH];
  642 
  643         if (wcsstr (szFiles[i], L"VeraCrypt Setup") != 0)
  644         {
  645             if (bUninstall)
  646                 continue;   // Prevent 'access denied' error
  647 
  648             if (bRepairMode)
  649                 continue;   // Destination = target
  650         }
  651 
  652         if ((*szFiles[i] == L'A') || (*szFiles[i] == L'X'))
  653             StringCbCopyW (szDir, sizeof(szDir), szDestDir);
  654         else if (*szFiles[i] == L'D')
  655         {
  656             if (Is64BitOs ())
  657                 driver64 = TRUE;
  658 
  659             GetSystemDirectory (szDir, ARRAYSIZE (szDir));
  660 
  661             x = wcslen (szDir);
  662             if (szDir[x - 1] != L'\\')
  663                 StringCbCatW (szDir, sizeof(szDir), L"\\");
  664 
  665             StringCbCatW (szDir, sizeof(szDir), L"Drivers\\");
  666         }
  667         else if (*szFiles[i] == L'W')
  668             GetWindowsDirectory (szDir, ARRAYSIZE (szDir));
  669 
  670         if (*szFiles[i] == L'I')
  671             continue;
  672 
  673         if (*szFiles[i] == L'X')
  674             zipFile = TRUE;
  675 
  676         StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szDir, szFiles[i] + 1);
  677         if (zipFile)
  678         {
  679             // build folder name by removing .zip extension
  680             wchar_t* ptr = wcsrchr (szTmp, L'.');
  681             if (ptr)
  682                 *ptr = 0;
  683         }
  684 
  685         if (bUninstall == FALSE)
  686             CopyMessage (hwndDlg, szTmp);
  687         else
  688             RemoveMessage (hwndDlg, szTmp);
  689 
  690         if (bUninstall == FALSE)
  691         {
  692             SetCurrentDirectory (SetupFilesDir);
  693 
  694             if (wcsstr (szFiles[i], L"VeraCrypt Setup") != 0)
  695             {
  696                 // Copy ourselves (the distribution package) to the destination location as 'VeraCrypt Setup.exe'
  697 
  698                 wchar_t mp[MAX_PATH];
  699 
  700                 GetModuleFileName (NULL, mp, ARRAYSIZE (mp));
  701                 bResult = TCCopyFile (mp, szTmp);
  702             }
  703             else
  704             {
  705                 StringCchCopyNW (curFileName, ARRAYSIZE(curFileName), szFiles[i] + 1, wcslen (szFiles[i]) - 1);
  706                 curFileName [wcslen (szFiles[i]) - 1] = 0;
  707 
  708                 if (Is64BitOs ()
  709                     && ((wcscmp (szFiles[i], L"Dveracrypt.sys") == 0) || (wcscmp (szFiles[i], L"Averacrypt.sys") == 0)))
  710                 {
  711                     StringCbCopyNW (curFileName, sizeof(curFileName), FILENAME_64BIT_DRIVER, sizeof (FILENAME_64BIT_DRIVER));
  712                 }
  713 
  714                 if (Is64BitOs ()
  715                     && wcscmp (szFiles[i], L"Averacrypt.cat") == 0)
  716                 {
  717                     StringCbCopyNW (curFileName, sizeof(curFileName), L"veracrypt-x64.cat", sizeof (L"veracrypt-x64.cat"));
  718                 }
  719 
  720                 if (Is64BitOs ()
  721                     && wcscmp (szFiles[i], L"AVeraCrypt.exe") == 0)
  722                 {
  723                     StringCbCopyNW (curFileName, sizeof(curFileName), L"VeraCrypt-x64.exe", sizeof (L"VeraCrypt-x64.exe"));
  724                 }
  725 
  726                 if (Is64BitOs ()
  727                     && wcscmp (szFiles[i], L"AVeraCryptExpander.exe") == 0)
  728                 {
  729                     StringCbCopyNW (curFileName, sizeof(curFileName), L"VeraCryptExpander-x64.exe", sizeof (L"VeraCryptExpander-x64.exe"));
  730                 }
  731 
  732                 if (Is64BitOs ()
  733                     && wcscmp (szFiles[i], L"AVeraCrypt Format.exe") == 0)
  734                 {
  735                     StringCbCopyNW (curFileName, sizeof(curFileName), L"VeraCrypt Format-x64.exe", sizeof (L"VeraCrypt Format-x64.exe"));
  736                 }
  737 
  738                 if (!bDevm)
  739                 {
  740                     bResult = FALSE;
  741 
  742                     // Find the correct decompressed file in memory
  743                     for (fileNo = 0; fileNo < NBR_COMPRESSED_FILES; fileNo++)
  744                     {
  745                         // Write the file (stored in memory) directly to the destination location
  746                         // (there will be no temporary files).
  747                         if (wmemcmp (
  748                             curFileName,
  749                             Decompressed_Files[fileNo].fileName,
  750                             min (wcslen (curFileName), (size_t) Decompressed_Files[fileNo].fileNameLength)) == 0)
  751                         {
  752                             // Dump filter driver cannot be installed to SysWOW64 directory
  753                             if (driver64 && !EnableWow64FsRedirection (FALSE))
  754                             {
  755                                 handleWin32Error (hwndDlg, SRC_POS);
  756                                 bResult = FALSE;
  757                                 goto err;
  758                             }
  759                             if (zipFile)
  760                             {
  761                                 bResult = DecompressZipToDir (
  762                                     Decompressed_Files[fileNo].fileContent,
  763                                     Decompressed_Files[fileNo].fileLength,
  764                                     szDir,
  765                                     CopyMessage,
  766                                     hwndDlg);
  767                             }
  768                             else
  769                             {
  770                                 bResult = SaveBufferToFile (
  771                                     (char *) Decompressed_Files[fileNo].fileContent,
  772                                     szTmp,
  773                                     Decompressed_Files[fileNo].fileLength,
  774                                     FALSE,
  775                                     TRUE);
  776                             }
  777 
  778                             if (driver64)
  779                             {
  780                                 if (!EnableWow64FsRedirection (TRUE))
  781                                 {
  782                                     handleWin32Error (hwndDlg, SRC_POS);
  783                                     bResult = FALSE;
  784                                     goto err;
  785                                 }
  786 
  787                                 if (!bResult)
  788                                     goto err;
  789 
  790                             }
  791 
  792                             break;
  793                         }
  794                     }
  795                 }
  796                 else
  797                 {
  798                     if (driver64)
  799                         EnableWow64FsRedirection (FALSE);
  800 
  801                     bResult = TCCopyFile (curFileName, szTmp);
  802 
  803                     if (driver64)
  804                         EnableWow64FsRedirection (TRUE);
  805                 }
  806 
  807                 if (bResult && wcscmp (szFiles[i], L"AVeraCrypt.exe") == 0)
  808                 {
  809                     if (Is64BitOs ())
  810                         EnableWow64FsRedirection (FALSE);
  811 
  812                     wstring servicePath = GetServiceConfigPath (_T(TC_APP_NAME) L".exe", false);
  813                     wstring serviceLegacyPath = GetServiceConfigPath (_T(TC_APP_NAME) L".exe", true);
  814                     wstring favoritesFile = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, false);
  815                     wstring favoritesLegacyFile = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, true);
  816 
  817                     if (    FileExists (servicePath.c_str())
  818                         ||  (Is64BitOs () && FileExists (serviceLegacyPath.c_str()))
  819                         )
  820                     {
  821                         CopyMessage (hwndDlg, (wchar_t *) servicePath.c_str());
  822                         bResult = CopyFile (szTmp, servicePath.c_str(), FALSE);
  823                     }
  824 
  825                     if (bResult && Is64BitOs ()
  826                         && FileExists (favoritesLegacyFile.c_str())
  827                         && !FileExists (favoritesFile.c_str()))
  828                     {
  829                         // copy the favorites XML file to the native system directory
  830                         bResult = CopyFile (favoritesLegacyFile.c_str(), favoritesFile.c_str(), FALSE);
  831                     }
  832 
  833                     if (bResult && Is64BitOs () && FileExists (favoritesFile.c_str()) && FileExists (servicePath.c_str()))
  834                     {
  835                         // Update the path of the service
  836                         BootEncryption BootEncObj (hwndDlg);
  837 
  838                         try
  839                         {
  840                             if (BootEncObj.GetDriverServiceStartType() == SERVICE_BOOT_START)
  841                             {
  842                                 BootEncObj.UpdateSystemFavoritesService ();
  843                             }
  844                         }
  845                         catch (...) {}
  846                     }
  847 
  848                     if (Is64BitOs ())
  849                     {
  850                         // delete files from legacy path
  851                         if (FileExists (favoritesLegacyFile.c_str()))
  852                         {
  853                             RemoveMessage (hwndDlg, (wchar_t *) favoritesLegacyFile.c_str());
  854                             ForceDeleteFile (favoritesLegacyFile.c_str());
  855                         }
  856 
  857                         if (FileExists (serviceLegacyPath.c_str()))
  858                         {
  859                             RemoveMessage (hwndDlg, (wchar_t *) serviceLegacyPath.c_str());
  860                             ForceDeleteFile (serviceLegacyPath.c_str());
  861                         }
  862 
  863                         EnableWow64FsRedirection (TRUE);
  864                     }
  865                 }
  866             }
  867         }
  868         else
  869         {
  870             if (driver64)
  871                 EnableWow64FsRedirection (FALSE);
  872             if (zipFile)
  873                 bResult = StatRemoveDirectory (szTmp);
  874             else
  875                 bResult = StatDeleteFile (szTmp, TRUE);
  876             if (driver64)
  877                 EnableWow64FsRedirection (TRUE);
  878 
  879             if (bResult && wcscmp (szFiles[i], L"AVeraCrypt.exe") == 0)
  880             {
  881                 if (Is64BitOs ())
  882                     EnableWow64FsRedirection (FALSE);
  883 
  884                 wstring servicePath = GetServiceConfigPath (_T(TC_APP_NAME) L".exe", false);
  885                 wstring serviceLegacyPath = GetServiceConfigPath (_T(TC_APP_NAME) L".exe", true);
  886                 wstring favoritesFile = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, false);
  887                 wstring favoritesLegacyFile = GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, true);
  888 
  889                 // delete all files related to system favorites service
  890                 if (FileExists (favoritesFile.c_str()))
  891                 {
  892                     RemoveMessage (hwndDlg, (wchar_t *) favoritesFile.c_str());
  893                     ForceDeleteFile (favoritesFile.c_str());
  894                 }
  895 
  896                 if (FileExists (servicePath.c_str()))
  897                 {
  898                     RemoveMessage (hwndDlg, (wchar_t *) servicePath.c_str());
  899                     ForceDeleteFile (servicePath.c_str());
  900                 }
  901 
  902                 if (Is64BitOs ())
  903                 {
  904                     if (FileExists (favoritesLegacyFile.c_str()))
  905                     {
  906                         RemoveMessage (hwndDlg, (wchar_t *) favoritesLegacyFile.c_str());
  907                         ForceDeleteFile (favoritesLegacyFile.c_str());
  908                     }
  909 
  910                     if (FileExists (serviceLegacyPath.c_str()))
  911                     {
  912                         RemoveMessage (hwndDlg, (wchar_t *) serviceLegacyPath.c_str());
  913                         ForceDeleteFile (serviceLegacyPath.c_str());
  914                     }
  915 
  916                     EnableWow64FsRedirection (TRUE);
  917                 }
  918             }
  919         }
  920 
  921 err:
  922         if (bResult == FALSE)
  923         {
  924             LPVOID lpMsgBuf;
  925             DWORD dwError = GetLastError ();
  926             wchar_t szTmp2[700];
  927             wchar_t szErrorValue[16];
  928             wchar_t* pszDesc;
  929 
  930             FormatMessage (
  931                           FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  932                           NULL,
  933                           dwError,
  934                  MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),    /* Default language */
  935                           (wchar_t *) &lpMsgBuf,
  936                           0,
  937                           NULL
  938                 );
  939 
  940             if (lpMsgBuf)
  941                 pszDesc = (wchar_t*) lpMsgBuf;
  942             else
  943             {
  944                 StringCbPrintfW (szErrorValue, sizeof (szErrorValue), L"0x%.8X", dwError);
  945                 pszDesc = szErrorValue;
  946             }
  947 
  948             if (bUninstall == FALSE)
  949                 StringCbPrintfW (szTmp2, sizeof(szTmp2), GetString ("INSTALL_OF_FAILED"), szTmp, pszDesc);
  950             else
  951                 StringCbPrintfW (szTmp2, sizeof(szTmp2), GetString ("UNINSTALL_OF_FAILED"), szTmp, pszDesc);
  952 
  953             if (lpMsgBuf) LocalFree (lpMsgBuf);
  954 
  955             if (!Silent && MessageBoxW (hwndDlg, szTmp2, lpszTitle, MB_YESNO | MB_ICONHAND) != IDYES)
  956                 return FALSE;
  957         }
  958     }
  959     
  960     if (bUninstall == FALSE)
  961     {
  962         WIN32_FIND_DATA f;
  963         HANDLE h;
  964 
  965         SetCurrentDirectory (szDestDir);
  966 
  967         // remove PDF from previous version if any
  968         h = FindFirstFile (L"VeraCrypt User Guide*.pdf", &f);
  969 
  970         if (h != INVALID_HANDLE_VALUE)
  971         {
  972             do
  973             {
  974                 StatDeleteFile (f.cFileName, TRUE);
  975             }
  976             while (FindNextFile(h, &f) != 0);
  977 
  978             FindClose (h);
  979         }
  980 
  981         // remove language XML files from previous version if any
  982         h = FindFirstFile (L"Language*.xml", &f);
  983 
  984         if (h != INVALID_HANDLE_VALUE)
  985         {
  986             do
  987             {
  988                 StatDeleteFile (f.cFileName, TRUE);
  989             }
  990             while (FindNextFile(h, &f) != 0);
  991 
  992             FindClose (h);
  993         }
  994         
  995         // remvove legacy files that are not needed anymore
  996         for (i = 0; i < sizeof (szLegacyFiles) / sizeof (szLegacyFiles[0]); i++)
  997         {
  998             StatDeleteFile (szLegacyFiles [i], TRUE);
  999         }
 1000 
 1001         SetCurrentDirectory (SetupFilesDir);
 1002     }
 1003 
 1004     return bOK;
 1005 }
 1006 
 1007 #ifndef PORTABLE
 1008 BOOL DoRegInstall (HWND hwndDlg, wchar_t *szDestDir, BOOL bInstallType)
 1009 {
 1010     wchar_t szDir[TC_MAX_PATH], *key;
 1011     wchar_t szTmp[TC_MAX_PATH*4];
 1012     HKEY hkey = 0;
 1013     BOOL bSlash, bOK = FALSE;
 1014     DWORD dw;
 1015     int x;
 1016 
 1017     if (SystemEncryptionUpdate)
 1018     {
 1019         if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt",
 1020             0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_WOW64_32KEY, NULL, &hkey, &dw) == ERROR_SUCCESS)
 1021         {
 1022             StringCbCopyW (szTmp, sizeof(szTmp), _T(VERSION_STRING));
 1023             RegSetValueEx (hkey, L"DisplayVersion", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t));
 1024 
 1025             StringCbCopyW (szTmp, sizeof(szTmp), TC_HOMEPAGE);
 1026             RegSetValueEx (hkey, L"URLInfoAbout", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t));
 1027 
 1028             RegCloseKey (hkey);
 1029         }
 1030 
 1031         return TRUE;
 1032     }
 1033 
 1034     StringCbCopyW (szDir, sizeof(szDir), szDestDir);
 1035     x = wcslen (szDestDir);
 1036     if (szDestDir[x - 1] == L'\\')
 1037         bSlash = TRUE;
 1038     else
 1039         bSlash = FALSE;
 1040 
 1041     if (bSlash == FALSE)
 1042         StringCbCatW (szDir, sizeof(szDir), L"\\");
 1043 
 1044     if (bInstallType)
 1045     {
 1046 
 1047         key = L"Software\\Classes\\VeraCryptVolume";
 1048         RegMessage (hwndDlg, key);
 1049         if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
 1050                     key,
 1051                     0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
 1052             goto error;
 1053 
 1054         StringCbCopyW (szTmp, sizeof(szTmp), L"VeraCrypt Volume");
 1055         if (RegSetValueEx (hkey, L"", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1056             goto error;
 1057 
 1058         StringCbPrintfW (szTmp, sizeof(szTmp), L"%ws", TC_APPLICATION_ID);
 1059         if (RegSetValueEx (hkey, L"AppUserModelID", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1060             goto error;
 1061 
 1062         RegCloseKey (hkey);
 1063         hkey = 0;
 1064 
 1065         key = L"Software\\Classes\\VeraCryptVolume\\DefaultIcon";
 1066         RegMessage (hwndDlg, key);
 1067         if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
 1068                     key,
 1069                     0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
 1070             goto error;
 1071 
 1072         StringCbPrintfW (szTmp, sizeof(szTmp), L"%sVeraCrypt.exe,1", szDir);
 1073         if (RegSetValueEx (hkey, L"", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1074             goto error;
 1075 
 1076         RegCloseKey (hkey);
 1077         hkey = 0;
 1078 
 1079         key = L"Software\\Classes\\VeraCryptVolume\\Shell\\open\\command";
 1080         RegMessage (hwndDlg, key);
 1081         if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
 1082                     key,
 1083                     0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
 1084             goto error;
 1085 
 1086         StringCbPrintfW (szTmp, sizeof(szTmp), L"\"%sVeraCrypt.exe\" /v \"%%1\"", szDir );
 1087         if (RegSetValueEx (hkey, L"", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1088             goto error;
 1089 
 1090         RegCloseKey (hkey);
 1091         hkey = 0;
 1092 
 1093         key = L"Software\\Classes\\.hc";
 1094         BOOL typeClassChanged = TRUE;
 1095         wchar_t typeClass[256];
 1096         DWORD typeClassSize = sizeof (typeClass);
 1097 
 1098         if (ReadLocalMachineRegistryString (key, L"", typeClass, &typeClassSize) && typeClassSize > 0 && wcscmp (typeClass, L"VeraCryptVolume") == 0)
 1099             typeClassChanged = FALSE;
 1100 
 1101         RegMessage (hwndDlg, key);
 1102         if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
 1103                     key,
 1104                     0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw) != ERROR_SUCCESS)
 1105             goto error;
 1106 
 1107         StringCbCopyW (szTmp, sizeof(szTmp), L"VeraCryptVolume");
 1108         if (RegSetValueEx (hkey, L"", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1109             goto error;
 1110 
 1111         RegCloseKey (hkey);
 1112         hkey = 0;
 1113 
 1114         if (typeClassChanged)
 1115             SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
 1116     }
 1117 
 1118     key = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt";
 1119     RegMessage (hwndDlg, key);
 1120     if (RegCreateKeyEx (HKEY_LOCAL_MACHINE,
 1121         key,
 1122         0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_WOW64_32KEY, NULL, &hkey, &dw) != ERROR_SUCCESS)
 1123         goto error;
 1124 
 1125     /* IMPORTANT: IF YOU CHANGE THIS IN ANY WAY, REVISE AND UPDATE SetInstallationPath() ACCORDINGLY! */
 1126     StringCbPrintfW (szTmp, sizeof(szTmp), L"\"%sVeraCrypt Setup.exe\" /u", szDir);
 1127     if (RegSetValueEx (hkey, L"UninstallString", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1128         goto error;
 1129 
 1130     StringCbPrintfW (szTmp, sizeof(szTmp), L"\"%sVeraCrypt Setup.exe\" /c", szDir);
 1131     if (RegSetValueEx (hkey, L"ModifyPath", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1132         goto error;
 1133 
 1134     StringCbPrintfW (szTmp, sizeof(szTmp), L"\"%sVeraCrypt Setup.exe\"", szDir);
 1135     if (RegSetValueEx (hkey, L"DisplayIcon", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1136         goto error;
 1137 
 1138     StringCbCopyW (szTmp, sizeof(szTmp), _T(VERSION_STRING));
 1139     if (RegSetValueEx (hkey, L"DisplayVersion", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1140         goto error;
 1141 
 1142     StringCbCopyW (szTmp, sizeof(szTmp), L"VeraCrypt");
 1143     if (RegSetValueEx (hkey, L"DisplayName", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1144         goto error;
 1145 
 1146     StringCbCopyW (szTmp, sizeof(szTmp), L"IDRIX");
 1147     if (RegSetValueEx (hkey, L"Publisher", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1148         goto error;
 1149 
 1150     StringCbCopyW (szTmp, sizeof(szTmp), TC_HOMEPAGE);
 1151     if (RegSetValueEx (hkey, L"URLInfoAbout", 0, REG_SZ, (BYTE *) szTmp, (wcslen (szTmp) + 1) * sizeof (wchar_t)) != ERROR_SUCCESS)
 1152         goto error;
 1153 
 1154     bOK = TRUE;
 1155 
 1156 error:
 1157     if (hkey != 0)
 1158         RegCloseKey (hkey);
 1159 
 1160     if (bOK == FALSE)
 1161     {
 1162         handleWin32Error (hwndDlg, SRC_POS);
 1163         Error ("REG_INSTALL_FAILED", hwndDlg);
 1164     }
 1165 
 1166     // Register COM servers for UAC
 1167     if (IsOSAtLeast (WIN_VISTA))
 1168     {
 1169         if (!RegisterComServers (szDir))
 1170         {
 1171             Error ("COM_REG_FAILED", hwndDlg);
 1172             return FALSE;
 1173         }
 1174     }
 1175 
 1176     return bOK;
 1177 }
 1178 
 1179 BOOL DoApplicationDataUninstall (HWND hwndDlg)
 1180 {
 1181     wchar_t path[MAX_PATH];
 1182     wchar_t path2[MAX_PATH];
 1183     BOOL bOK = TRUE;
 1184 
 1185     StatusMessage (hwndDlg, "REMOVING_APPDATA");
 1186 
 1187     SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path);
 1188     StringCbCatW (path, sizeof(path), L"\\VeraCrypt\\");
 1189 
 1190     // Delete favorite volumes file
 1191     StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_FAVORITE_VOLUMES);
 1192     RemoveMessage (hwndDlg, path2);
 1193     StatDeleteFile (path2, FALSE);
 1194 
 1195     // Delete keyfile defaults
 1196     StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_DEFAULT_KEYFILES);
 1197     RemoveMessage (hwndDlg, path2);
 1198     StatDeleteFile (path2, FALSE);
 1199 
 1200     // Delete history file
 1201     StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_HISTORY);
 1202     RemoveMessage (hwndDlg, path2);
 1203     StatDeleteFile (path2, FALSE);
 1204 
 1205     // Delete configuration file
 1206     StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_CONFIGURATION);
 1207     RemoveMessage (hwndDlg, path2);
 1208     StatDeleteFile (path2, FALSE);
 1209 
 1210     // Delete system encryption configuration file
 1211     StringCbPrintfW (path2, sizeof(path2), L"%s%s", path, TC_APPD_FILENAME_SYSTEM_ENCRYPTION);
 1212     RemoveMessage (hwndDlg, path2);
 1213     StatDeleteFile (path2, FALSE);
 1214 
 1215     SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path);
 1216     StringCbCatW (path, sizeof(path), L"\\VeraCrypt");
 1217     RemoveMessage (hwndDlg, path);
 1218     if (!StatRemoveDirectory (path))
 1219     {
 1220         handleWin32Error (hwndDlg, SRC_POS);
 1221         bOK = FALSE;
 1222     }
 1223 
 1224     // remove VeraCrypt under common appdata
 1225     if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path)))
 1226     {
 1227         StringCbCatW (path, sizeof(path), L"\\VeraCrypt");
 1228 
 1229         // Delete original bootloader
 1230         StringCbPrintfW (path2, sizeof(path2), L"%s\\%s", path, TC_SYS_BOOT_LOADER_BACKUP_NAME);
 1231         RemoveMessage (hwndDlg, path2);
 1232         StatDeleteFile (path2, FALSE);
 1233 
 1234         // remove VeraCrypt folder
 1235         RemoveMessage (hwndDlg, path);
 1236         StatRemoveDirectory (path);
 1237     }
 1238 
 1239 
 1240     return bOK;
 1241 }
 1242 
 1243 BOOL DoRegUninstall (HWND hwndDlg, BOOL bRemoveDeprecated)
 1244 {
 1245     wchar_t regk [64];
 1246     typedef LSTATUS (WINAPI *RegDeleteKeyExWFn) (HKEY hKey,LPCWSTR lpSubKey,REGSAM samDesired,WORD Reserved);
 1247     RegDeleteKeyExWFn RegDeleteKeyExWPtr = NULL;
 1248     HMODULE hAdvapiDll = LoadLibrary (L"Advapi32.dll");
 1249     if (hAdvapiDll)
 1250     {
 1251         RegDeleteKeyExWPtr = (RegDeleteKeyExWFn) GetProcAddress(hAdvapiDll, "RegDeleteKeyExW");
 1252     }
 1253 
 1254     // Unregister COM servers
 1255     if (!bRemoveDeprecated && IsOSAtLeast (WIN_VISTA))
 1256     {
 1257         if (!UnregisterComServers (InstallationPath))
 1258             StatusMessage (hwndDlg, "COM_DEREG_FAILED");
 1259     }
 1260 
 1261     if (!bRemoveDeprecated)
 1262         StatusMessage (hwndDlg, "REMOVING_REG");
 1263 
 1264     if (RegDeleteKeyExWPtr)
 1265     {
 1266         RegDeleteKeyExWPtr (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", KEY_WOW64_32KEY, 0);
 1267         RegDeleteKeyExWPtr (HKEY_CURRENT_USER, L"Software\\VeraCrypt", KEY_WOW64_32KEY, 0);
 1268     }
 1269     else
 1270     {
 1271         RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt");
 1272         RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\VeraCrypt");
 1273     }
 1274     RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume\\Shell\\open\\command");
 1275     RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume\\Shell\\open");
 1276     RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume\\Shell");
 1277     RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume\\DefaultIcon");
 1278     RegDeleteKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\VeraCryptVolume");
 1279 
 1280     if (!bRemoveDeprecated)
 1281     {
 1282         HKEY hKey;
 1283         GetStartupRegKeyName (regk, sizeof(regk));
 1284         DeleteRegistryValue (regk, L"VeraCrypt");
 1285 
 1286         DeleteRegistryKey (HKEY_LOCAL_MACHINE, L"Software\\Classes\\.hc");
 1287 
 1288         // enable the SE_TAKE_OWNERSHIP_NAME privilege for this operation
 1289         SetPrivilege (SE_TAKE_OWNERSHIP_NAME, TRUE);
 1290 
 1291         // clean MuiCache list from VeraCrypt entries
 1292         SearchAndDeleteRegistrySubString (HKEY_CLASSES_ROOT, L"Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache", L"VeraCrypt", FALSE, NULL);
 1293 
 1294         // clean other VeraCrypt entries from all users
 1295         SearchAndDeleteRegistrySubString (HKEY_USERS, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.hc", NULL, TRUE, NULL);
 1296         SearchAndDeleteRegistrySubString (HKEY_USERS, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Persisted", L"VeraCrypt", TRUE, NULL);
 1297         SearchAndDeleteRegistrySubString (HKEY_USERS, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage\\NewShortcuts", L"VeraCrypt", TRUE, NULL);
 1298 
 1299         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM", 0, KEY_ALL_ACCESS | WRITE_DAC | WRITE_OWNER, &hKey) == ERROR_SUCCESS)
 1300         {
 1301             SearchAndDeleteRegistrySubString (hKey, L"Enum\\Root\\LEGACY_VERACRYPT", NULL, TRUE, L"ControlSet");
 1302             SearchAndDeleteRegistrySubString (hKey, L"services\\veracrypt", NULL, TRUE, L"ControlSet");
 1303             RegCloseKey(hKey);
 1304         }
 1305 
 1306         // disable the SE_TAKE_OWNERSHIP_NAME privilege for this operation
 1307         SetPrivilege (SE_TAKE_OWNERSHIP_NAME, FALSE);
 1308 
 1309         SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
 1310     }
 1311 
 1312     if (hAdvapiDll)
 1313         FreeLibrary (hAdvapiDll);
 1314 
 1315     return TRUE;
 1316 }
 1317 
 1318 
 1319 BOOL DoServiceUninstall (HWND hwndDlg, wchar_t *lpszService)
 1320 {
 1321     SC_HANDLE hManager, hService = NULL;
 1322     BOOL bOK = FALSE, bRet;
 1323     SERVICE_STATUS status;
 1324     BOOL firstTry = TRUE;
 1325     int x;
 1326 
 1327     memset (&status, 0, sizeof (status));   /* Keep VC6 quiet */
 1328 
 1329 retry:
 1330 
 1331     hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
 1332     if (hManager == NULL)
 1333         goto error;
 1334 
 1335     hService = OpenService (hManager, lpszService, SERVICE_ALL_ACCESS);
 1336     if (hService == NULL)
 1337         goto error;
 1338 
 1339     if (wcscmp (L"veracrypt", lpszService) == 0)
 1340     {
 1341         try
 1342         {
 1343             BootEncryption bootEnc (hwndDlg);
 1344             if (bootEnc.GetDriverServiceStartType() == SERVICE_BOOT_START)
 1345             {
 1346                 try { bootEnc.RegisterFilterDriver (false, BootEncryption::DriveFilter); } catch (...) { }
 1347                 try { bootEnc.RegisterFilterDriver (false, BootEncryption::VolumeFilter); } catch (...) { }
 1348                 try { bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); } catch (...) { }
 1349             }
 1350         }
 1351         catch (...) { }
 1352 
 1353         StatusMessage (hwndDlg, "STOPPING_DRIVER");
 1354     }
 1355     else
 1356         StatusMessageParam (hwndDlg, "STOPPING", lpszService);
 1357 
 1358 #define WAIT_PERIOD 3
 1359 
 1360     for (x = 0; x < WAIT_PERIOD; x++)
 1361     {
 1362         bRet = QueryServiceStatus (hService, &status);
 1363         if (bRet != TRUE)
 1364             goto error;
 1365 
 1366         if (status.dwCurrentState != SERVICE_START_PENDING &&
 1367             status.dwCurrentState != SERVICE_STOP_PENDING &&
 1368             status.dwCurrentState != SERVICE_CONTINUE_PENDING)
 1369             break;
 1370 
 1371         Sleep (1000);
 1372     }
 1373 
 1374     if (status.dwCurrentState != SERVICE_STOPPED)
 1375     {
 1376         bRet = ControlService (hService, SERVICE_CONTROL_STOP, &status);
 1377         if (bRet == FALSE)
 1378             goto try_delete;
 1379 
 1380         for (x = 0; x < WAIT_PERIOD; x++)
 1381         {
 1382             bRet = QueryServiceStatus (hService, &status);
 1383             if (bRet != TRUE)
 1384                 goto error;
 1385 
 1386             if (status.dwCurrentState != SERVICE_START_PENDING &&
 1387                 status.dwCurrentState != SERVICE_STOP_PENDING &&
 1388               status.dwCurrentState != SERVICE_CONTINUE_PENDING)
 1389                 break;
 1390 
 1391             Sleep (1000);
 1392         }
 1393 
 1394         if (status.dwCurrentState != SERVICE_STOPPED && status.dwCurrentState != SERVICE_STOP_PENDING)
 1395             goto error;
 1396     }
 1397 
 1398 try_delete:
 1399 
 1400     if (wcscmp (L"veracrypt", lpszService) == 0)
 1401         StatusMessage (hwndDlg, "REMOVING_DRIVER");
 1402     else
 1403         StatusMessageParam (hwndDlg, "REMOVING", lpszService);
 1404 
 1405     if (hService != NULL)
 1406     {
 1407         CloseServiceHandle (hService);
 1408         hService = NULL;
 1409     }
 1410 
 1411     if (hManager != NULL)
 1412     {
 1413         CloseServiceHandle (hManager);
 1414         hManager = NULL;
 1415     }
 1416 
 1417     hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
 1418     if (hManager == NULL)
 1419         goto error;
 1420 
 1421     hService = OpenService (hManager, lpszService, SERVICE_ALL_ACCESS);
 1422     if (hService == NULL)
 1423         goto error;
 1424 
 1425     bRet = DeleteService (hService);
 1426     if (bRet == FALSE)
 1427     {
 1428         if (firstTry && GetLastError () == ERROR_SERVICE_MARKED_FOR_DELETE)
 1429         {
 1430             // Second try for an eventual no-install driver instance
 1431             CloseServiceHandle (hService);
 1432             CloseServiceHandle (hManager);
 1433             hService = NULL;
 1434             hManager = NULL;
 1435 
 1436             Sleep(1000);
 1437             firstTry = FALSE;
 1438             goto retry;
 1439         }
 1440 
 1441         goto error;
 1442     }
 1443 
 1444     bOK = TRUE;
 1445 
 1446 error:
 1447 
 1448     if (bOK == FALSE && GetLastError ()!= ERROR_SERVICE_DOES_NOT_EXIST)
 1449     {
 1450         handleWin32Error (hwndDlg, SRC_POS);
 1451         MessageBoxW (hwndDlg, GetString ("DRIVER_UINSTALL_FAILED"), lpszTitle, MB_ICONHAND);
 1452     }
 1453     else
 1454         bOK = TRUE;
 1455 
 1456     if (hService != NULL)
 1457         CloseServiceHandle (hService);
 1458 
 1459     if (hManager != NULL)
 1460         CloseServiceHandle (hManager);
 1461 
 1462     return bOK;
 1463 }
 1464 
 1465 
 1466 BOOL DoDriverUnload (HWND hwndDlg)
 1467 {
 1468     BOOL bOK = TRUE;
 1469     int status;
 1470 
 1471     status = DriverAttach ();
 1472     if (status != 0)
 1473     {
 1474         if (status == ERR_OS_ERROR && GetLastError () != ERROR_FILE_NOT_FOUND)
 1475         {
 1476             handleWin32Error (hwndDlg, SRC_POS);
 1477             AbortProcess ("NODRIVER");
 1478         }
 1479 
 1480         if (status != ERR_OS_ERROR)
 1481         {
 1482             handleError (NULL, status, SRC_POS);
 1483             AbortProcess ("NODRIVER");
 1484         }
 1485     }
 1486 
 1487     if (hDriver != INVALID_HANDLE_VALUE)
 1488     {
 1489         MOUNT_LIST_STRUCT driver;
 1490         LONG driverVersion = VERSION_NUM;
 1491         int refCount;
 1492         DWORD dwResult;
 1493         BOOL bResult;
 1494 
 1495         // Try to determine if it's upgrade (and not reinstall, downgrade, or first-time install).
 1496         DetermineUpgradeDowngradeStatus (FALSE, &driverVersion);
 1497 
 1498         // Test for encrypted boot drive
 1499         try
 1500         {
 1501             BootEncryption bootEnc (hwndDlg);
 1502             if (bootEnc.GetDriverServiceStartType() == SERVICE_BOOT_START)
 1503             {
 1504                 try
 1505                 {
 1506                     // Check hidden OS update consistency
 1507                     if (IsHiddenOSRunning())
 1508                     {
 1509                         if (bootEnc.GetInstalledBootLoaderVersion() != VERSION_NUM)
 1510                         {
 1511                             if (AskWarnNoYes ("UPDATE_TC_IN_DECOY_OS_FIRST", hwndDlg) == IDNO)
 1512                                 AbortProcessSilent ();
 1513                         }
 1514                     }
 1515                 }
 1516                 catch (...) { }
 1517 
 1518                 if (bUninstallInProgress && !bootEnc.GetStatus().DriveMounted)
 1519                 {
 1520                     try { bootEnc.RegisterFilterDriver (false, BootEncryption::DriveFilter); } catch (...) { }
 1521                     try { bootEnc.RegisterFilterDriver (false, BootEncryption::VolumeFilter); } catch (...) { }
 1522                     try { bootEnc.RegisterFilterDriver (false, BootEncryption::DumpFilter); } catch (...) { }
 1523                     bootEnc.SetDriverServiceStartType (SERVICE_SYSTEM_START);
 1524                 }
 1525                 else if (bUninstallInProgress || bDowngrade)
 1526                 {
 1527                     Error (bDowngrade ? "SETUP_FAILED_BOOT_DRIVE_ENCRYPTED_DOWNGRADE" : "SETUP_FAILED_BOOT_DRIVE_ENCRYPTED", hwndDlg);
 1528                     return FALSE;
 1529                 }
 1530                 else
 1531                 {
 1532                     if (CurrentOSMajor == 6 && CurrentOSMinor == 0 && CurrentOSServicePack < 1)
 1533                         AbortProcess ("SYS_ENCRYPTION_UPGRADE_UNSUPPORTED_ON_VISTA_SP0");
 1534 
 1535                     SystemEncryptionUpdate = TRUE;
 1536                     PortableMode = FALSE;
 1537                 }
 1538             }
 1539         }
 1540         catch (...) { }
 1541 
 1542         if (!bUninstall
 1543             && (bUpgrade || SystemEncryptionUpdate)
 1544             && (!bDevm || SystemEncryptionUpdate))
 1545         {
 1546             UnloadDriver = FALSE;
 1547         }
 1548 
 1549         if (PortableMode && !SystemEncryptionUpdate)
 1550             UnloadDriver = TRUE;
 1551 
 1552         if (UnloadDriver)
 1553         {
 1554             int volumesMounted = 0;
 1555 
 1556             // Check mounted volumes
 1557             bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL);
 1558 
 1559             if (!bResult)
 1560             {
 1561                 bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL);
 1562                 if (bResult)
 1563                     volumesMounted = driver.ulMountedDrives;
 1564             }
 1565 
 1566             if (bResult)
 1567             {
 1568                 if (volumesMounted != 0)
 1569                 {
 1570                     bOK = FALSE;
 1571                     MessageBoxW (hwndDlg, GetString ("DISMOUNT_ALL_FIRST"), lpszTitle, MB_ICONHAND);
 1572                 }
 1573             }
 1574             else
 1575             {
 1576                 bOK = FALSE;
 1577                 handleWin32Error (hwndDlg, SRC_POS);
 1578             }
 1579         }
 1580 
 1581         // Try to close all open TC windows
 1582         if (bOK)
 1583         {
 1584             BOOL TCWindowClosed = FALSE;
 1585 
 1586             EnumWindows (CloseTCWindowsEnum, (LPARAM) &TCWindowClosed);
 1587 
 1588             if (TCWindowClosed)
 1589                 Sleep (2000);
 1590         }
 1591 
 1592         // Test for any applications attached to driver
 1593         if (!bUpgrade)
 1594         {
 1595             bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount,
 1596                 sizeof (refCount), &dwResult, NULL);
 1597 
 1598             if (bOK && bResult && refCount > 1)
 1599             {
 1600                 MessageBoxW (hwndDlg, GetString ("CLOSE_TC_FIRST"), lpszTitle, MB_ICONSTOP);
 1601                 bOK = FALSE;
 1602             }
 1603         }
 1604 
 1605         if (!bOK || UnloadDriver)
 1606         {
 1607             CloseHandle (hDriver);
 1608             hDriver = INVALID_HANDLE_VALUE;
 1609         }
 1610     }
 1611     else
 1612     {
 1613         // Note that the driver may have already been unloaded during this session (e.g. retry after an error, etc.) so it is not
 1614         // guaranteed that the user is installing VeraCrypt for the first time now (we also cannot know if the user has already
 1615         // installed and used VeraCrypt on another system before).
 1616         bPossiblyFirstTimeInstall = TRUE;
 1617     }
 1618 
 1619     return bOK;
 1620 }
 1621 
 1622 
 1623 BOOL UpgradeBootLoader (HWND hwndDlg)
 1624 {
 1625     if (!SystemEncryptionUpdate)
 1626         return TRUE;
 1627 
 1628     try
 1629     {
 1630         BootEncryption bootEnc (hwndDlg);
 1631         uint64 bootLoaderVersion = bootEnc.GetInstalledBootLoaderVersion();
 1632         if ((bootLoaderVersion < VERSION_NUM) || (bReinstallMode && (bootLoaderVersion == VERSION_NUM)))
 1633         {
 1634             StatusMessage (hwndDlg, "INSTALLER_UPDATING_BOOT_LOADER");
 1635 
 1636             bootEnc.InstallBootLoader (true);
 1637 
 1638             if (bootEnc.GetInstalledBootLoaderVersion() <= TC_RESCUE_DISK_UPGRADE_NOTICE_MAX_VERSION)
 1639             {
 1640                 bUpdateRescueDisk = TRUE;
 1641                 Info (IsHiddenOSRunning() ? "BOOT_LOADER_UPGRADE_OK_HIDDEN_OS" : "BOOT_LOADER_UPGRADE_OK", hwndDlg);
 1642             }
 1643         }
 1644         return TRUE;
 1645     }
 1646     catch (Exception &e)
 1647     {
 1648         e.Show (hwndDlg);
 1649     }
 1650     catch (...) { }
 1651 
 1652     Error ("BOOT_LOADER_UPGRADE_FAILED", hwndDlg);
 1653     return FALSE;
 1654 }
 1655 
 1656 
 1657 BOOL DoShortcutsUninstall (HWND hwndDlg, wchar_t *szDestDir)
 1658 {
 1659     wchar_t szLinkDir[TC_MAX_PATH];
 1660     wchar_t szTmp2[TC_MAX_PATH];
 1661     BOOL bSlash, bOK = FALSE;
 1662     HRESULT hOle;
 1663     int x;
 1664     BOOL allUsers = FALSE;
 1665 
 1666     hOle = OleInitialize (NULL);
 1667 
 1668     // User start menu
 1669     SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_PROGRAMS, 0);
 1670     x = wcslen (szLinkDir);
 1671     if (szLinkDir[x - 1] == L'\\')
 1672         bSlash = TRUE;
 1673     else
 1674         bSlash = FALSE;
 1675 
 1676     if (bSlash == FALSE)
 1677         StringCbCatW (szLinkDir, sizeof(szLinkDir), L"\\");
 1678 
 1679     StringCbCatW (szLinkDir, sizeof(szLinkDir), L"VeraCrypt");
 1680 
 1681     // Global start menu
 1682     {
 1683         struct _stat st;
 1684         wchar_t path[TC_MAX_PATH];
 1685 
 1686         SHGetSpecialFolderPath (hwndDlg, path, CSIDL_COMMON_PROGRAMS, 0);
 1687         StringCbCatW (path, sizeof(path), L"\\VeraCrypt");
 1688 
 1689         if (_wstat (path, &st) == 0)
 1690         {
 1691             StringCbCopyW (szLinkDir, sizeof(szLinkDir), path);
 1692             allUsers = TRUE;
 1693         }
 1694     }
 1695 
 1696     // Start menu entries
 1697     StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCrypt.lnk");
 1698     RemoveMessage (hwndDlg, szTmp2);
 1699     if (StatDeleteFile (szTmp2, FALSE) == FALSE)
 1700         goto error;
 1701 
 1702     StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCryptExpander.lnk");
 1703     RemoveMessage (hwndDlg, szTmp2);
 1704     if (StatDeleteFile (szTmp2, FALSE) == FALSE)
 1705         goto error;
 1706 
 1707     StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCrypt Website.url");
 1708     RemoveMessage (hwndDlg, szTmp2);
 1709     if (StatDeleteFile (szTmp2, FALSE) == FALSE)
 1710         goto error;
 1711 
 1712     StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\Uninstall VeraCrypt.lnk");
 1713     RemoveMessage (hwndDlg, szTmp2);
 1714     if (StatDeleteFile (szTmp2, FALSE) == FALSE)
 1715         goto error;
 1716 
 1717     StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCrypt User's Guide.lnk");
 1718     StatDeleteFile (szTmp2, FALSE);
 1719 
 1720     // Start menu group
 1721     RemoveMessage ((HWND) hwndDlg, szLinkDir);
 1722     if (StatRemoveDirectory (szLinkDir) == FALSE)
 1723         handleWin32Error ((HWND) hwndDlg, SRC_POS);
 1724 
 1725     // Desktop icon
 1726 
 1727     if (allUsers)
 1728         SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_COMMON_DESKTOPDIRECTORY, 0);
 1729     else
 1730         SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_DESKTOPDIRECTORY, 0);
 1731 
 1732     StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCrypt.lnk");
 1733 
 1734     RemoveMessage (hwndDlg, szTmp2);
 1735     if (StatDeleteFile (szTmp2, FALSE) == FALSE)
 1736         goto error;
 1737 
 1738     bOK = TRUE;
 1739 
 1740 error:
 1741     OleUninitialize ();
 1742 
 1743     return bOK;
 1744 }
 1745 
 1746 BOOL DoShortcutsInstall (HWND hwndDlg, wchar_t *szDestDir, BOOL bProgGroup, BOOL bDesktopIcon)
 1747 {
 1748     wchar_t szLinkDir[TC_MAX_PATH], szDir[TC_MAX_PATH];
 1749     wchar_t szTmp[TC_MAX_PATH], szTmp2[TC_MAX_PATH], szTmp3[TC_MAX_PATH];
 1750     BOOL bSlash, bOK = FALSE;
 1751     HRESULT hOle;
 1752     int x;
 1753 
 1754     if (bProgGroup == FALSE && bDesktopIcon == FALSE)
 1755         return TRUE;
 1756 
 1757     hOle = OleInitialize (NULL);
 1758 
 1759     GetProgramPath (hwndDlg, szLinkDir);
 1760 
 1761     x = wcslen (szLinkDir);
 1762     if (szLinkDir[x - 1] == L'\\')
 1763         bSlash = TRUE;
 1764     else
 1765         bSlash = FALSE;
 1766 
 1767     if (bSlash == FALSE)
 1768         StringCbCatW (szLinkDir, sizeof(szLinkDir), L"\\");
 1769 
 1770     StringCbCatW (szLinkDir, sizeof(szLinkDir), L"VeraCrypt");
 1771 
 1772     StringCbCopyW (szDir, sizeof(szDir), szDestDir);
 1773     x = wcslen (szDestDir);
 1774     if (szDestDir[x - 1] == L'\\')
 1775         bSlash = TRUE;
 1776     else
 1777         bSlash = FALSE;
 1778 
 1779     if (bSlash == FALSE)
 1780         StringCbCatW (szDir, sizeof(szDir), L"\\");
 1781 
 1782     if (bProgGroup)
 1783     {
 1784         FILE *f;
 1785 
 1786         if (mkfulldir (szLinkDir, TRUE) != 0)
 1787         {
 1788             if (mkfulldir (szLinkDir, FALSE) != 0)
 1789             {
 1790                 wchar_t szTmpW[TC_MAX_PATH];
 1791 
 1792                 handleWin32Error (hwndDlg, SRC_POS);
 1793                 StringCbPrintfW (szTmpW, sizeof(szTmpW), GetString ("CANT_CREATE_FOLDER"), szLinkDir);
 1794                 MessageBoxW (hwndDlg, szTmpW, lpszTitle, MB_ICONHAND);
 1795                 goto error;
 1796             }
 1797         }
 1798 
 1799         StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szDir, L"VeraCrypt.exe");
 1800         StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCrypt.lnk");
 1801 
 1802         IconMessage (hwndDlg, szTmp2);
 1803         if (CreateLink (szTmp, L"", szTmp2, NULL, -1) != S_OK)
 1804             goto error;
 1805 
 1806         StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szDir, L"VeraCryptExpander.exe");
 1807         StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCryptExpander.lnk");
 1808 
 1809         IconMessage (hwndDlg, szTmp2);
 1810         if (CreateLink (szTmp, L"", szTmp2, NULL, -1) != S_OK)
 1811             goto error;
 1812 
 1813         StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCrypt Website.url");
 1814         IconMessage (hwndDlg, szTmp2);
 1815         f = _wfopen (szTmp2, L"w");
 1816         if (f)
 1817         {
 1818             fwprintf (f, L"[InternetShortcut]\nURL=%s\n", TC_APPLINK);
 1819 
 1820             CheckFileStreamWriteErrors (hwndDlg, f, szTmp2);
 1821             fclose (f);
 1822         }
 1823         else
 1824             goto error;
 1825 
 1826         StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szDir, L"VeraCrypt Setup.exe");
 1827         StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\Uninstall VeraCrypt.lnk");
 1828         if (GetSystemDirectory (szTmp3, ARRAYSIZE(szTmp3)))
 1829         {
 1830             StringCbCatW (szTmp3, sizeof(szTmp3), L"\\control.exe");
 1831         }
 1832         else
 1833             StringCbCopyW(szTmp3, sizeof(szTmp3), L"C:\\Windows\\System32\\control.exe");
 1834 
 1835         IconMessage (hwndDlg, szTmp2);
 1836         if (CreateLink (szTmp3, L"appwiz.cpl", szTmp2, szTmp, 0) != S_OK)
 1837             goto error;
 1838 
 1839         StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCrypt User's Guide.lnk");
 1840         StatDeleteFile (szTmp2, FALSE);
 1841     }
 1842 
 1843     if (bDesktopIcon)
 1844     {
 1845         StringCbCopyW (szDir, sizeof(szDir), szDestDir);
 1846         x = wcslen (szDestDir);
 1847         if (szDestDir[x - 1] == L'\\')
 1848             bSlash = TRUE;
 1849         else
 1850             bSlash = FALSE;
 1851 
 1852         if (bSlash == FALSE)
 1853             StringCbCatW (szDir, sizeof(szDir), L"\\");
 1854 
 1855         if (bForAllUsers)
 1856             SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_COMMON_DESKTOPDIRECTORY, 0);
 1857         else
 1858             SHGetSpecialFolderPath (hwndDlg, szLinkDir, CSIDL_DESKTOPDIRECTORY, 0);
 1859 
 1860         StringCbPrintfW (szTmp, sizeof(szTmp), L"%s%s", szDir, L"VeraCrypt.exe");
 1861         StringCbPrintfW (szTmp2, sizeof(szTmp2), L"%s%s", szLinkDir, L"\\VeraCrypt.lnk");
 1862 
 1863         IconMessage (hwndDlg, szTmp2);
 1864 
 1865         if (CreateLink (szTmp, L"", szTmp2, NULL, -1) != S_OK)
 1866             goto error;
 1867     }
 1868 
 1869     bOK = TRUE;
 1870 
 1871 error:
 1872     OleUninitialize ();
 1873 
 1874     return bOK;
 1875 }
 1876 
 1877 
 1878 void OutcomePrompt (HWND hwndDlg, BOOL bOK)
 1879 {
 1880     if (bOK)
 1881     {
 1882         EnableWindow (GetDlgItem ((HWND) hwndDlg, IDCANCEL), FALSE);
 1883 
 1884         bDone = TRUE;
 1885 
 1886         if (bUninstall == FALSE)
 1887         {
 1888             if (bDevm)
 1889                 PostMessage (MainDlg, WM_CLOSE, 0, 0);
 1890             else if (bPossiblyFirstTimeInstall || bRepairMode || (!bUpgrade && !bDowngrade))
 1891                 Info ("INSTALL_OK", hwndDlg);
 1892             else
 1893                 Info ("SETUP_UPDATE_OK", hwndDlg);
 1894         }
 1895         else
 1896         {
 1897             wchar_t str[4096];
 1898 
 1899             StringCbPrintfW (str, sizeof(str), GetString ("UNINSTALL_OK"), InstallationPath);
 1900             MessageBoxW (hwndDlg, str, lpszTitle, MB_ICONASTERISK);
 1901         }
 1902     }
 1903     else
 1904     {
 1905         if (bUninstall == FALSE)
 1906             Error ("INSTALL_FAILED", hwndDlg);
 1907         else
 1908             Error ("UNINSTALL_FAILED", hwndDlg);
 1909     }
 1910 }
 1911 
 1912 static void SetSystemRestorePoint (HWND hwndDlg, BOOL finalize)
 1913 {
 1914     static RESTOREPOINTINFO RestPtInfo;
 1915     static STATEMGRSTATUS SMgrStatus;
 1916     static BOOL failed = FALSE;
 1917     static BOOL (__stdcall *_SRSetRestorePoint)(PRESTOREPOINTINFO, PSTATEMGRSTATUS);
 1918 
 1919     if (!SystemRestoreDll) return;
 1920 
 1921     _SRSetRestorePoint = (BOOL (__stdcall *)(PRESTOREPOINTINFO, PSTATEMGRSTATUS))GetProcAddress (SystemRestoreDll,"SRSetRestorePointW");
 1922     if (_SRSetRestorePoint == 0)
 1923     {
 1924         FreeLibrary (SystemRestoreDll);
 1925         SystemRestoreDll = 0;
 1926         return;
 1927     }
 1928 
 1929     if (!finalize)
 1930     {
 1931         StatusMessage (hwndDlg, "CREATING_SYS_RESTORE");
 1932 
 1933         RestPtInfo.dwEventType = BEGIN_SYSTEM_CHANGE;
 1934         RestPtInfo.dwRestorePtType = bUninstall ? APPLICATION_UNINSTALL : APPLICATION_INSTALL | DEVICE_DRIVER_INSTALL;
 1935         RestPtInfo.llSequenceNumber = 0;
 1936         StringCbCopyW (RestPtInfo.szDescription, sizeof(RestPtInfo.szDescription), bUninstall ? L"VeraCrypt uninstallation" : L"VeraCrypt installation");
 1937 
 1938         if(!_SRSetRestorePoint (&RestPtInfo, &SMgrStatus))
 1939         {
 1940             StatusMessage (hwndDlg, "FAILED_SYS_RESTORE");
 1941             failed = TRUE;
 1942         }
 1943     }
 1944     else if (!failed)
 1945     {
 1946         RestPtInfo.dwEventType = END_SYSTEM_CHANGE;
 1947         RestPtInfo.llSequenceNumber = SMgrStatus.llSequenceNumber;
 1948 
 1949         if(!_SRSetRestorePoint(&RestPtInfo, &SMgrStatus))
 1950         {
 1951             StatusMessage (hwndDlg, "FAILED_SYS_RESTORE");
 1952         }
 1953     }
 1954 }
 1955 
 1956 void DoUninstall (void *arg)
 1957 {
 1958     HWND hwndDlg = (HWND) arg;
 1959     BOOL bOK = TRUE;
 1960     BOOL bTempSkipSysRestore = FALSE;
 1961 
 1962     if (!Rollback)
 1963         EnableWindow (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), FALSE);
 1964 
 1965     WaitCursor ();
 1966 
 1967     if (!Rollback)
 1968     {
 1969         ClearLogWindow (hwndDlg);
 1970     }
 1971 
 1972     if (DoDriverUnload (hwndDlg) == FALSE)
 1973     {
 1974         bOK = FALSE;
 1975         bTempSkipSysRestore = TRUE;     // Volumes are possibly mounted; defer System Restore point creation for this uninstall attempt.
 1976     }
 1977     else
 1978     {
 1979         if (!Rollback && bSystemRestore && !bTempSkipSysRestore)
 1980             SetSystemRestorePoint (hwndDlg, FALSE);
 1981 
 1982         if (DoServiceUninstall (hwndDlg, L"veracrypt") == FALSE)
 1983         {
 1984             bOK = FALSE;
 1985         }
 1986         else if (DoRegUninstall ((HWND) hwndDlg, FALSE) == FALSE)
 1987         {
 1988             bOK = FALSE;
 1989         }
 1990         else if (DoFilesInstall ((HWND) hwndDlg, InstallationPath) == FALSE)
 1991         {
 1992             bOK = FALSE;
 1993         }
 1994         else if (DoShortcutsUninstall (hwndDlg, InstallationPath) == FALSE)
 1995         {
 1996             bOK = FALSE;
 1997         }
 1998         else if (!DoApplicationDataUninstall (hwndDlg))
 1999         {
 2000             bOK = FALSE;
 2001         }
 2002         else
 2003         {
 2004             wchar_t temp[MAX_PATH];
 2005             FILE *f;
 2006 
 2007             // Deprecated service
 2008             DoServiceUninstall (hwndDlg, L"VeraCryptService");
 2009 
 2010             GetTempPath (ARRAYSIZE (temp), temp);
 2011             StringCbPrintfW (UninstallBatch, sizeof (UninstallBatch), L"%sVeraCrypt-Uninstall.bat", temp);
 2012 
 2013             UninstallBatch [ARRAYSIZE(UninstallBatch)-1] = 0;
 2014 
 2015             // Create uninstall batch
 2016             f = _wfopen (UninstallBatch, L"w");
 2017             if (!f)
 2018                 bOK = FALSE;
 2019             else
 2020             {
 2021                 fwprintf (f,L":loop\n"
 2022                     L"del \"%s%s\"\n"
 2023                     L"if exist \"%s%s\" goto loop\n"
 2024                     L"rmdir \"%s\"\n"
 2025                     L"del \"%s\"",
 2026                     InstallationPath, L"VeraCrypt Setup.exe",
 2027                     InstallationPath, L"VeraCrypt Setup.exe",
 2028                     InstallationPath,
 2029                     UninstallBatch
 2030                     );
 2031 
 2032                 CheckFileStreamWriteErrors (hwndDlg, f, UninstallBatch);
 2033                 fclose (f);
 2034             }
 2035         }
 2036     }
 2037 
 2038     NormalCursor ();
 2039 
 2040     if (Rollback)
 2041         return;
 2042 
 2043     if (bSystemRestore && !bTempSkipSysRestore)
 2044         SetSystemRestorePoint (hwndDlg, TRUE);
 2045 
 2046     if (bOK)
 2047         PostMessage (hwndDlg, TC_APPMSG_UNINSTALL_SUCCESS, 0, 0);
 2048     else
 2049         bUninstallInProgress = FALSE;
 2050 
 2051     EnableWindow (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), TRUE);
 2052     OutcomePrompt (hwndDlg, bOK);
 2053 }
 2054 
 2055 void DoInstall (void *arg)
 2056 {
 2057     HWND hwndDlg = (HWND) arg;
 2058     BOOL bOK = TRUE;
 2059     wchar_t path[MAX_PATH];
 2060 
 2061     BootEncryption bootEnc (hwndDlg);
 2062 
 2063     // Refresh the main GUI (wizard thread)
 2064     InvalidateRect (MainDlg, NULL, TRUE);
 2065 
 2066     ClearLogWindow (hwndDlg);
 2067 
 2068     if (mkfulldir (InstallationPath, TRUE) != 0)
 2069     {
 2070         if (mkfulldir (InstallationPath, FALSE) != 0)
 2071         {
 2072             wchar_t szTmp[TC_MAX_PATH];
 2073 
 2074             handleWin32Error (hwndDlg, SRC_POS);
 2075             StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("CANT_CREATE_FOLDER"), InstallationPath);
 2076             MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_ICONHAND);
 2077             Error ("INSTALL_FAILED", hwndDlg);
 2078             PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
 2079             return;
 2080         }
 2081     }
 2082 
 2083     UpdateProgressBarProc(2);
 2084 
 2085     if (DoDriverUnload (hwndDlg) == FALSE)
 2086     {
 2087         NormalCursor ();
 2088         PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
 2089         return;
 2090     }
 2091 
 2092     if (bUpgrade
 2093         && (IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L".exe")
 2094             || IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L"-x86.exe")
 2095             || IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L"-x64.exe")
 2096             || IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L" Format.exe")
 2097             || IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L" Format-x86.exe")
 2098             || IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L" Format-x64.exe")
 2099             || IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L"Expander.exe")
 2100             || IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L"Expander-x86.exe")
 2101             || IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L"Expander-x64.exe")
 2102             || IsFileInUse (wstring (InstallationPath) + L'\\' + _T(TC_APP_NAME) L" Setup.exe")
 2103             )
 2104         )
 2105     {
 2106         NormalCursor ();
 2107         Error ("CLOSE_TC_FIRST", hwndDlg);
 2108         PostMessage (MainDlg, TC_APPMSG_INSTALL_FAILURE, 0, 0);
 2109         return;
 2110     }
 2111 
 2112     UpdateProgressBarProc(12);
 2113 
 2114     if (bSystemRestore)
 2115         SetSystemRestorePoint (hwndDlg, FALSE);
 2116 
 2117     UpdateProgressBarProc(48);
 2118 
 2119     if (bDisableSwapFiles
 2120         && IsPagingFileActive (FALSE))
 2121     {
 2122         if (!DisablePagingFile())
 2123         {
 2124             handleWin32Error (hwndDlg, SRC_POS);
 2125             Error ("FAILED_TO_DISABLE_PAGING_FILES", hwndDlg);
 2126         }
 2127         else
 2128             bRestartRequired = TRUE;
 2129     }
 2130 
 2131     UpdateProgressBarProc(50);
 2132 
 2133     // Remove deprecated
 2134     DoServiceUninstall (hwndDlg, L"VeraCryptService");
 2135 
 2136     UpdateProgressBarProc(55);
 2137 
 2138     if (!SystemEncryptionUpdate)
 2139         DoRegUninstall ((HWND) hwndDlg, TRUE);
 2140 
 2141     UpdateProgressBarProc(61);
 2142 
 2143     GetWindowsDirectory (path, ARRAYSIZE (path));
 2144     StringCbCatW (path, sizeof (path), L"\\VeraCrypt Setup.exe");
 2145     StatDeleteFile (path, FALSE);
 2146 
 2147     if (UpdateProgressBarProc(63) && UnloadDriver && DoServiceUninstall (hwndDlg, L"veracrypt") == FALSE)
 2148     {
 2149         bOK = FALSE;
 2150     }
 2151     else if (UpdateProgressBarProc(72) && DoFilesInstall ((HWND) hwndDlg, InstallationPath) == FALSE)
 2152     {
 2153         bOK = FALSE;
 2154     }
 2155     else if (UpdateProgressBarProc(80) && DoRegInstall ((HWND) hwndDlg, InstallationPath, bRegisterFileExt) == FALSE)
 2156     {
 2157         bOK = FALSE;
 2158     }
 2159     else if (UpdateProgressBarProc(85) && UnloadDriver && DoDriverInstall (hwndDlg) == FALSE)
 2160     {
 2161         bOK = FALSE;
 2162     }
 2163     else if (UpdateProgressBarProc(90) && SystemEncryptionUpdate && UpgradeBootLoader (hwndDlg) == FALSE)
 2164     {
 2165         bOK = FALSE;
 2166     }
 2167     else if (UpdateProgressBarProc(93) && DoShortcutsInstall (hwndDlg, InstallationPath, bAddToStartMenu, bDesktopIcon) == FALSE)
 2168     {
 2169         bOK = FALSE;
 2170     }
 2171 
 2172     if (!UnloadDriver)
 2173         bRestartRequired = TRUE;
 2174 
 2175     try
 2176     {
 2177         bootEnc.RenameDeprecatedSystemLoaderBackup();
 2178     }
 2179     catch (...) { }
 2180 
 2181     if (bOK)
 2182         UpdateProgressBarProc(97);
 2183 
 2184     if (bSystemRestore)
 2185         SetSystemRestorePoint (hwndDlg, TRUE);
 2186 
 2187     if (bOK)
 2188     {
 2189         UpdateProgressBarProc(100);
 2190         UninstallBatch[0] = 0;
 2191         StatusMessage (hwndDlg, "INSTALL_COMPLETED");
 2192     }
 2193     else
 2194     {
 2195         UpdateProgressBarProc(0);
 2196 
 2197         if (!SystemEncryptionUpdate)
 2198         {
 2199             bUninstall = TRUE;
 2200             Rollback = TRUE;
 2201             Silent = TRUE;
 2202 
 2203             DoUninstall (hwndDlg);
 2204 
 2205             bUninstall = FALSE;
 2206             Rollback = FALSE;
 2207             Silent = FALSE;
 2208 
 2209             StatusMessage (hwndDlg, "ROLLBACK");
 2210         }
 2211         else
 2212         {
 2213             Warning ("SYS_ENC_UPGRADE_FAILED", hwndDlg);
 2214         }
 2215     }
 2216 
 2217     OutcomePrompt (hwndDlg, bOK);
 2218 
 2219     if (bOK && !bUninstall && !bDowngrade && !bRepairMode && !bDevm)
 2220     {
 2221         if (!IsHiddenOSRunning())   // A hidden OS user should not see the post-install notes twice (on decoy OS and then on hidden OS).
 2222         {
 2223             if (bRestartRequired || SystemEncryptionUpdate)
 2224             {
 2225                 // Restart required
 2226 
 2227                 if (bUpgrade)
 2228                 {
 2229                     SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_RELEASE_NOTES);
 2230                     if (bUpdateRescueDisk)
 2231                     {
 2232                         SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_RESCUE_DISK);
 2233                     }
 2234                 }
 2235                 else if (bPossiblyFirstTimeInstall)
 2236                 {
 2237                     SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_TUTORIAL);
 2238                 }
 2239             }
 2240             else
 2241             {
 2242                 // No restart will be required
 2243 
 2244                 if (bUpgrade)
 2245                 {
 2246                     bPromptReleaseNotes = TRUE;
 2247                 }
 2248                 else if (bPossiblyFirstTimeInstall)
 2249                 {
 2250                     bPromptTutorial = TRUE;
 2251                 }
 2252             }
 2253         }
 2254     }
 2255 
 2256     PostMessage (MainDlg, bOK ? TC_APPMSG_INSTALL_SUCCESS : TC_APPMSG_INSTALL_FAILURE, 0, 0);
 2257 }
 2258 
 2259 
 2260 void SetInstallationPath (HWND hwndDlg)
 2261 {
 2262     BOOL bInstallPathDetermined = FALSE;
 2263     
 2264     GetInstallationPath (hwndDlg, InstallationPath, ARRAYSIZE (InstallationPath), &bInstallPathDetermined);
 2265 
 2266     if (bInstallPathDetermined)
 2267     {
 2268         wchar_t mp[MAX_PATH];
 2269 
 2270         // Determine whether we were launched from the folder where VeraCrypt is installed
 2271         GetModuleFileName (NULL, mp, ARRAYSIZE (mp));
 2272         if (wcsncmp (InstallationPath, mp, min (wcslen(InstallationPath), wcslen(mp))) == 0)
 2273         {
 2274             // We were launched from the folder where VeraCrypt is installed
 2275 
 2276             if (!IsNonInstallMode() && !bDevm)
 2277                 bChangeMode = TRUE;
 2278         }
 2279     }
 2280 }
 2281 
 2282 
 2283 // Handler for uninstall only (install is handled by the wizard)
 2284 BOOL CALLBACK UninstallDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 2285 {
 2286     WORD lw = LOWORD (wParam);
 2287 
 2288     switch (msg)
 2289     {
 2290     case WM_INITDIALOG:
 2291 
 2292         MainDlg = hwndDlg;
 2293 
 2294         if (!CreateAppSetupMutex ())
 2295             AbortProcess ("TC_INSTALLER_IS_RUNNING");
 2296 
 2297         InitDialog (hwndDlg);
 2298         LocalizeDialog (hwndDlg, NULL);
 2299 
 2300         SetWindowTextW (hwndDlg, lpszTitle);
 2301 
 2302         // System Restore
 2303         SetCheckBox (hwndDlg, IDC_SYSTEM_RESTORE, bSystemRestore);
 2304         if (SystemRestoreDll == 0)
 2305         {
 2306             SetCheckBox (hwndDlg, IDC_SYSTEM_RESTORE, FALSE);
 2307             EnableWindow (GetDlgItem (hwndDlg, IDC_SYSTEM_RESTORE), FALSE);
 2308         }
 2309 
 2310         SetFocus (GetDlgItem (hwndDlg, IDC_UNINSTALL));
 2311 
 2312         return 1;
 2313 
 2314     case WM_SYSCOMMAND:
 2315         if (lw == IDC_ABOUT)
 2316         {
 2317             DialogBoxW (hInst, MAKEINTRESOURCEW (IDD_ABOUT_DLG), hwndDlg, (DLGPROC) AboutDlgProc);
 2318             return 1;
 2319         }
 2320         return 0;
 2321 
 2322     case WM_COMMAND:
 2323         if (lw == IDC_UNINSTALL)
 2324         {
 2325             if (bDone)
 2326             {
 2327                 bUninstallInProgress = FALSE;
 2328                 PostMessage (hwndDlg, WM_CLOSE, 0, 0);
 2329                 return 1;
 2330             }
 2331 
 2332             bUninstallInProgress = TRUE;
 2333 
 2334             WaitCursor ();
 2335 
 2336             if (bUninstall)
 2337                 _beginthread (DoUninstall, 0, (void *) hwndDlg);
 2338 
 2339             return 1;
 2340         }
 2341 
 2342         if (lw == IDC_SYSTEM_RESTORE)
 2343         {
 2344             bSystemRestore = IsButtonChecked (GetDlgItem (hwndDlg, IDC_SYSTEM_RESTORE));
 2345             return 1;
 2346         }
 2347 
 2348         if (lw == IDCANCEL)
 2349         {
 2350             PostMessage (hwndDlg, WM_CLOSE, 0, 0);
 2351             return 1;
 2352         }
 2353 
 2354         return 0;
 2355 
 2356     case TC_APPMSG_UNINSTALL_SUCCESS:
 2357         SetWindowTextW (GetDlgItem ((HWND) hwndDlg, IDC_UNINSTALL), GetString ("FINALIZE"));
 2358         NormalCursor ();
 2359         return 1;
 2360 
 2361     case WM_CLOSE:
 2362         if (bUninstallInProgress)
 2363         {
 2364             NormalCursor();
 2365             if (AskNoYes("CONFIRM_EXIT_UNIVERSAL", hwndDlg) == IDNO)
 2366             {
 2367                 return 1;
 2368             }
 2369             WaitCursor ();
 2370         }
 2371         EndDialog (hwndDlg, IDCANCEL);
 2372         return 1;
 2373     }
 2374 
 2375     return 0;
 2376 }
 2377 #endif
 2378 
 2379 typedef struct
 2380 {
 2381     LPCWSTR name;
 2382     int resourceid;
 2383     WORD langid;
 2384     LPCSTR internalId;
 2385     LPCWSTR langtag;
 2386 } tLanguageEntry;
 2387 
 2388 static tLanguageEntry g_languagesEntries[] = {
 2389     {L"العربية", IDR_LANG_AR, LANG_ARABIC, "ar", NULL},
 2390     {L"Čeština", IDR_LANG_CS, LANG_CZECH, "cs", NULL},
 2391     {L"Deutsch", IDR_LANG_DE, LANG_GERMAN, "de", NULL},
 2392     {L"English", IDR_LANGUAGE, LANG_ENGLISH, "en", NULL},
 2393     {L"Español", IDR_LANG_ES, LANG_SPANISH, "es", NULL},
 2394     {L"Français", IDR_LANG_FR, LANG_FRENCH, "fr", NULL},
 2395     {L"Italiano", IDR_LANG_IT, LANG_ITALIAN, "it", NULL},
 2396     {L"日本語", IDR_LANG_JA, LANG_JAPANESE, "ja", NULL},
 2397     {L"Nederlands", IDR_LANG_NL, LANG_DUTCH, "nl", NULL},
 2398     {L"Polski", IDR_LANG_PL, LANG_POLISH, "pl", NULL},
 2399     {L"Română", IDR_LANG_RO, LANG_ROMANIAN, "ro", NULL},
 2400     {L"Русский", IDR_LANG_RU, LANG_RUSSIAN, "ru", NULL},
 2401     {L"Tiếng Việt", IDR_LANG_VI, LANG_VIETNAMESE, "vi", NULL},
 2402     {L"简体中文", IDR_LANG_ZHCN, LANG_CHINESE, "zh-cn", L"zh-CN"},
 2403     {L"繁體中文", IDR_LANG_ZHHK, LANG_CHINESE, "zh-hk", L"zh-HK"},
 2404 };
 2405 
 2406 typedef int (WINAPI *LCIDToLocaleNameFn)(
 2407     LCID     Locale,
 2408     LPWSTR  lpName,
 2409     int      cchName,
 2410     DWORD    dwFlags);
 2411 
 2412 static void UpdateSelectLanguageDialog (HWND hwndDlg)
 2413 {
 2414     HWND hLangList = GetDlgItem (hwndDlg, IDC_LANGUAGES_LIST);
 2415     LPARAM nIndex = SendMessage (hLangList, CB_GETCURSEL, 0, 0);
 2416     int resourceid = (int) SendMessage (hLangList, CB_GETITEMDATA, nIndex, 0);
 2417     BOOL bVal;
 2418 
 2419     LoadLanguageFromResource (resourceid, TRUE, TRUE);
 2420 
 2421     bVal = LocalizationActive;
 2422     LocalizationActive = TRUE;
 2423     LocalizeDialog (hwndDlg, "IDD_INSTL_DLG");
 2424     InvalidateRect (hwndDlg, NULL, FALSE);
 2425     LocalizationActive = bVal;
 2426 }
 2427 
 2428 BOOL CALLBACK SelectLanguageDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 2429 {
 2430     WORD lw = LOWORD (wParam);
 2431 
 2432     switch (uMsg)
 2433     {
 2434     case WM_INITDIALOG:
 2435         {
 2436             char* preferredLanguage = GetPreferredLangId ();
 2437             if (strlen (preferredLanguage))
 2438             {
 2439                 // language already selected by user in current install
 2440                 // use it for the setup
 2441                 for (size_t i = 0; i < ARRAYSIZE (g_languagesEntries); i++)
 2442                 {
 2443                     if (0 == strcmp (preferredLanguage, g_languagesEntries[i].internalId))
 2444                     {
 2445                         LoadLanguageFromResource (g_languagesEntries[i].resourceid, FALSE, TRUE);
 2446                         break;
 2447                     }
 2448                 }
 2449                 EndDialog (hwndDlg, IDCANCEL);
 2450                 return FALSE;
 2451             }
 2452             else
 2453             {
 2454                 // Get the default UI language
 2455                 LCIDToLocaleNameFn LCIDToLocaleNamePtr = (LCIDToLocaleNameFn) GetProcAddress (GetModuleHandle (L"kernel32.dll"), "LCIDToLocaleName");
 2456                 WCHAR langtag[256];
 2457                 LANGID defaultLanguage = GetUserDefaultUILanguage ();
 2458                 WORD langid = (WORD) (defaultLanguage & 0x03FF); // primary language ID
 2459 
 2460                 InitDialog (hwndDlg);
 2461 
 2462                 LCIDToLocaleNamePtr (MAKELCID (defaultLanguage, 0), langtag, ARRAYSIZE (langtag), 0); // language tag (e.g. "en-US")
 2463                 int resourceid = IDR_LANGUAGE;
 2464                 for (size_t i = 0; i < ARRAYSIZE (g_languagesEntries); i++)
 2465                 {
 2466                     if (g_languagesEntries[i].langid == langid)
 2467                     {
 2468                         if (!g_languagesEntries[i].langtag || (0 == _wcsicmp (g_languagesEntries[i].langtag, langtag)))
 2469                         {
 2470                             resourceid = g_languagesEntries[i].resourceid;
 2471                             break;
 2472                         }
 2473                     }
 2474                 }
 2475 
 2476                 for (size_t i = 0; i < ARRAYSIZE (g_languagesEntries); i++)
 2477                 {
 2478                     AddComboPair (GetDlgItem (hwndDlg, IDC_LANGUAGES_LIST), g_languagesEntries[i].name, g_languagesEntries[i].resourceid);
 2479                 }
 2480 
 2481                 SelectAlgo (GetDlgItem (hwndDlg, IDC_LANGUAGES_LIST), &resourceid);
 2482 
 2483                 UpdateSelectLanguageDialog (hwndDlg);
 2484             }
 2485 
 2486         }
 2487         return TRUE;
 2488 
 2489     case WM_COMMAND:
 2490         if (CBN_SELCHANGE == HIWORD (wParam))
 2491         {
 2492             UpdateSelectLanguageDialog (hwndDlg);
 2493             return 1;
 2494         }
 2495 
 2496         if (lw == IDOK)
 2497         {
 2498             bUserSetLanguage = TRUE;
 2499             EndDialog (hwndDlg, IDOK);
 2500             return 1;
 2501         }
 2502 
 2503         if (lw == IDCANCEL)
 2504         {
 2505             SetPreferredLangId ("");
 2506             EndDialog (hwndDlg, IDCANCEL);
 2507             return 1;
 2508         }
 2509         return 0;
 2510     }
 2511 
 2512     return 0;
 2513 }
 2514 
 2515 
 2516 int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpszCommandLine, int nCmdShow)
 2517 {
 2518     atexit (localcleanup);
 2519 
 2520     SelfExtractStartupInit();
 2521 
 2522 #ifdef PORTABLE
 2523     lpszTitle = L"VeraCrypt Portable";
 2524 #else
 2525     lpszTitle = L"VeraCrypt Setup";
 2526 #endif
 2527     /* Call InitApp to initialize the common code */
 2528     InitApp (hInstance, NULL);
 2529 
 2530 #ifndef PORTABLE
 2531     if (IsAdmin () != TRUE)
 2532         if (MessageBoxW (NULL, GetString ("SETUP_ADMIN"), lpszTitle, MB_YESNO | MB_ICONQUESTION) != IDYES)
 2533         {
 2534             FinalizeApp ();
 2535             exit (1);
 2536         }
 2537 #endif
 2538     /* Setup directory */
 2539     {
 2540         wchar_t *s;
 2541         GetModuleFileName (NULL, SetupFilesDir, ARRAYSIZE (SetupFilesDir));
 2542         s = wcsrchr (SetupFilesDir, L'\\');
 2543         if (s)
 2544             s[1] = 0;
 2545     }
 2546 
 2547     /* Parse command line arguments */
 2548 
 2549     if (lpszCommandLine[0] == L'/')
 2550     {
 2551 #ifndef PORTABLE
 2552         if (lpszCommandLine[1] == L'u')
 2553         {
 2554             // Uninstall:   /u
 2555 
 2556             bUninstall = TRUE;
 2557         }
 2558         else if (lpszCommandLine[1] == L'c')
 2559         {
 2560             // Change:  /c
 2561 
 2562             bChangeMode = TRUE;
 2563         }
 2564         else
 2565 #endif
 2566         if (lpszCommandLine[1] == L'p')
 2567         {
 2568             // Create self-extracting package:  /p
 2569 
 2570             bMakePackage = TRUE;
 2571         }
 2572         else if (lpszCommandLine[1] == L'd')
 2573         {
 2574             // Dev mode:    /d
 2575             bDevm = TRUE;
 2576         }
 2577     }
 2578 
 2579     if (bMakePackage)
 2580     {
 2581         /* Create self-extracting package */
 2582 
 2583         MakeSelfExtractingPackage (NULL, SetupFilesDir);
 2584     }
 2585     else
 2586     {
 2587 #ifndef PORTABLE
 2588         SetInstallationPath (NULL);
 2589 #endif
 2590         if (bUninstall)
 2591         {
 2592             wchar_t path [TC_MAX_PATH];
 2593 
 2594             GetModuleFileName (NULL, path, ARRAYSIZE (path));
 2595             if (!VerifyModuleSignature (path))
 2596             {
 2597                 Error ("DIST_PACKAGE_CORRUPTED", NULL);
 2598                 exit (1);
 2599             }
 2600         }
 2601         else
 2602         {
 2603             if (IsSelfExtractingPackage())
 2604             {
 2605                 if (!VerifySelfPackageIntegrity())
 2606                 {
 2607                     // Package corrupted
 2608                     exit (1);
 2609                 }
 2610                 bDevm = FALSE;
 2611             }
 2612             else if (!bDevm)
 2613             {
 2614 #ifndef PORTABLE
 2615                 MessageBox (NULL, L"Error: This installer file does not contain any compressed files.\n\nTo create a self-extracting installation package (with embedded compressed files), run:\n\"VeraCrypt Setup.exe\" /p", L"VeraCrypt", MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
 2616 #else
 2617                 MessageBox (NULL, L"Error: This portable installer file does not contain any compressed files.\n\nTo create a self-extracting portable installation package (with embedded compressed files), run:\n\"VeraCrypt Portable.exe\" /p", L"VeraCrypt", MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
 2618 #endif
 2619                 FinalizeApp ();
 2620                 exit (1);
 2621             }
 2622 
 2623 #ifndef PORTABLE
 2624             if (bChangeMode)
 2625             {
 2626                 /* VeraCrypt is already installed on this system and we were launched from the Program Files folder */
 2627 
 2628                 char *tmpStr[] = {0, "SELECT_AN_ACTION", "REPAIR_REINSTALL", "UNINSTALL", "EXIT", 0};
 2629 
 2630                 // Ask the user to select either Repair or Unistallation
 2631                 switch (AskMultiChoice ((void **) tmpStr, FALSE, NULL))
 2632                 {
 2633                 case 1:
 2634                     bRepairMode = TRUE;
 2635                     break;
 2636                 case 2:
 2637                     bUninstall = TRUE;
 2638                     break;
 2639                 default:
 2640                     FinalizeApp ();
 2641                     exit (1);
 2642                 }
 2643             }
 2644 #endif
 2645         }
 2646 
 2647 #ifndef PORTABLE
 2648         // System Restore
 2649         if (IsSystemRestoreEnabled ())
 2650         {
 2651             wchar_t dllPath[MAX_PATH];
 2652             if (GetSystemDirectory (dllPath, MAX_PATH))
 2653             {
 2654                 StringCbCatW(dllPath, sizeof(dllPath), L"\\srclient.dll");
 2655             }
 2656             else
 2657                 StringCbCopyW(dllPath, sizeof(dllPath), L"C:\\Windows\\System32\\srclient.dll");
 2658             SystemRestoreDll = LoadLibrary (dllPath);
 2659         }
 2660         else
 2661             SystemRestoreDll = 0;
 2662 #endif
 2663 
 2664         if (!bUninstall)
 2665         {
 2666             if (!bDevm && !LocalizationActive && (nCurrentOS >= WIN_VISTA))
 2667             {
 2668                 BOOL bHasPreferredLanguage = (strlen (GetPreferredLangId ()) > 0)? TRUE : FALSE;
 2669                 if ((IDCANCEL == DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_INSTALL_LANGUAGE), NULL, (DLGPROC) SelectLanguageDialogProc, (LPARAM) 0 ))
 2670                     && !bHasPreferredLanguage
 2671                     )
 2672                 {
 2673                     // Language dialog cancelled by user: exit the installer
 2674                     FinalizeApp ();
 2675                     exit (1);
 2676                 }
 2677             }
 2678             /* Create the main dialog for install */
 2679 
 2680             DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_INSTL_DLG), NULL, (DLGPROC) MainDialogProc,
 2681                 (LPARAM)lpszCommandLine);
 2682         }
 2683 #ifndef PORTABLE
 2684         else
 2685         {
 2686             /* Create the main dialog for uninstall  */
 2687 
 2688             DialogBoxW (hInstance, MAKEINTRESOURCEW (IDD_UNINSTALL), NULL, (DLGPROC) UninstallDlgProc);
 2689 
 2690             if (UninstallBatch[0])
 2691             {
 2692                 STARTUPINFO si;
 2693                 PROCESS_INFORMATION pi;
 2694 
 2695                 ZeroMemory (&si, sizeof (si));
 2696                 si.cb = sizeof (si);
 2697                 si.dwFlags = STARTF_USESHOWWINDOW;
 2698                 si.wShowWindow = SW_HIDE;
 2699 
 2700                 if (!CreateProcess (UninstallBatch, NULL, NULL, NULL, FALSE, IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi))
 2701                     DeleteFile (UninstallBatch);
 2702                 else
 2703                 {
 2704                     CloseHandle (pi.hProcess);
 2705                     CloseHandle (pi.hThread);
 2706                 }
 2707             }
 2708         }
 2709 #endif
 2710     }
 2711     FinalizeApp ();
 2712     return 0;
 2713 }