Annotation of truecrypt/main/userinterface.cpp, revision 1.1.1.2

1.1       root        1: /*
                      2:  Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
                      3: 
                      4:  Governed by the TrueCrypt License 2.4 the full text of which is contained
                      5:  in the file License.txt included in TrueCrypt binary and source code
                      6:  distribution packages.
                      7: */
                      8: 
                      9: #include "System.h"
                     10: #include <set>
                     11: #include <typeinfo>
                     12: #include <wx/apptrait.h>
                     13: #include <wx/cmdline.h>
                     14: #include "Platform/PlatformTest.h"
                     15: #ifdef TC_UNIX
                     16: #include "Platform/Unix/Process.h"
                     17: #endif
                     18: #include "Volume/EncryptionTest.h"
                     19: #include "Application.h"
                     20: #include "FavoriteVolume.h"
                     21: #include "UserInterface.h"
                     22: 
                     23: namespace TrueCrypt
                     24: {
                     25:        UserInterface::UserInterface ()
                     26:        {
                     27:        }
                     28: 
                     29:        UserInterface::~UserInterface ()
                     30:        {
                     31:                Core->WarningEvent.Disconnect (this);
                     32:                Core->VolumeMountedEvent.Disconnect (this);
                     33:        }
                     34: 
                     35:        void UserInterface::CloseExplorerWindows (shared_ptr <VolumeInfo> mountedVolume) const
                     36:        {
                     37: #ifdef TC_WINDOWS
                     38:                struct Args
                     39:                {
                     40:                        HWND ExplorerWindow;
                     41:                        string DriveRootPath;
                     42:                };
                     43: 
                     44:                struct Enumerator
                     45:                {
                     46:                        static BOOL CALLBACK ChildWindows (HWND hwnd, LPARAM argsLP)
                     47:                        {
                     48:                                Args *args = reinterpret_cast <Args *> (argsLP);
                     49:                                
                     50:                                char s[4096];
                     51:                                SendMessageA (hwnd, WM_GETTEXT, sizeof (s), (LPARAM) s);
                     52: 
                     53:                                if (strstr (s, args->DriveRootPath.c_str()) != NULL)
                     54:                                {
                     55:                                        PostMessage (args->ExplorerWindow, WM_CLOSE, 0, 0);
                     56:                                        return FALSE;
                     57:                                }
                     58: 
                     59:                                return TRUE;
                     60:                        }
                     61: 
                     62:                        static BOOL CALLBACK TopLevelWindows (HWND hwnd, LPARAM argsLP)
                     63:                        {
                     64:                                Args *args = reinterpret_cast <Args *> (argsLP);
                     65: 
                     66:                                char s[4096];
                     67:                                GetClassNameA (hwnd, s, sizeof s);
                     68:                                if (strcmp (s, "CabinetWClass") == 0)
                     69:                                {
                     70:                                        GetWindowTextA (hwnd, s, sizeof s);
                     71:                                        if (strstr (s, args->DriveRootPath.c_str()) != NULL)
                     72:                                        {
                     73:                                                PostMessage (hwnd, WM_CLOSE, 0, 0);
                     74:                                                return TRUE;
                     75:                                        }
                     76: 
                     77:                                        args->ExplorerWindow = hwnd;
                     78:                                        EnumChildWindows (hwnd, ChildWindows, argsLP);
                     79:                                }
                     80: 
                     81:                                return TRUE;
                     82:                        }
                     83:                };
                     84: 
                     85:                Args args;
                     86: 
                     87:                string mountPoint = mountedVolume->MountPoint;
                     88:                if (mountPoint.size() < 2 || mountPoint[1] != ':')
                     89:                        return;
                     90: 
                     91:                args.DriveRootPath = string() + mountPoint[0] + string (":\\");
                     92:                
                     93:                EnumWindows (Enumerator::TopLevelWindows, (LPARAM) &args);
                     94: #endif
                     95:        }
                     96: 
                     97:        void UserInterface::DismountAllVolumes (bool ignoreOpenFiles, bool interactive) const
                     98:        {
                     99:                try
                    100:                {
                    101:                        VolumeInfoList mountedVolumes = Core->GetMountedVolumes();
                    102: 
                    103:                        if (mountedVolumes.size() < 1)
                    104:                                ShowInfo (LangString["NO_VOLUMES_MOUNTED"]);
                    105: 
                    106:                        BusyScope busy (this);
                    107:                        DismountVolumes (mountedVolumes, ignoreOpenFiles, interactive);
                    108:                }
                    109:                catch (exception &e)
                    110:                {
                    111:                        ShowError (e);
                    112:                }
                    113:        }
                    114: 
                    115:        void UserInterface::DismountVolume (shared_ptr <VolumeInfo> volume, bool ignoreOpenFiles, bool interactive) const
                    116:        {
                    117:                VolumeInfoList volumes;
                    118:                volumes.push_back (volume);
                    119: 
                    120:                DismountVolumes (volumes, ignoreOpenFiles, interactive);
                    121:        }
                    122: 
                    123:        void UserInterface::DismountVolumes (VolumeInfoList volumes, bool ignoreOpenFiles, bool interactive) const
                    124:        {
                    125:                BusyScope busy (this);
                    126: 
                    127:                wxString message;
                    128:                bool twoPassMode = volumes.size() > 1;
                    129:                bool volumesInUse = false;
                    130:                bool firstPass = true;
                    131: 
                    132: #ifdef TC_WINDOWS
                    133:                if (Preferences.CloseExplorerWindowsOnDismount)
                    134:                {
                    135:                        foreach (shared_ptr <VolumeInfo> volume, volumes)
                    136:                                CloseExplorerWindows (volume);
                    137:                }
                    138: #endif
                    139:                while (!volumes.empty())
                    140:                {
                    141:                        VolumeInfoList volumesLeft;
                    142:                        foreach (shared_ptr <VolumeInfo> volume, volumes)
                    143:                        {
                    144:                                try
                    145:                                {
                    146:                                        BusyScope busy (this);
                    147:                                        Core->DismountVolume (volume, ignoreOpenFiles);
                    148:                                }
                    149:                                catch (MountedVolumeInUse&)
                    150:                                {
                    151:                                        if (!firstPass)
                    152:                                                throw;
                    153: 
                    154:                                        if (twoPassMode || !interactive)
                    155:                                        {
                    156:                                                volumesInUse = true;
                    157:                                                volumesLeft.push_back (volume);
                    158:                                                continue;
                    159:                                        }
                    160:                                        else
                    161:                                        {
                    162:                                                if (AskYesNo (StringFormatter (LangString["UNMOUNT_LOCK_FAILED"], wstring (volume->Path)), true, true))
                    163:                                                {
                    164:                                                        BusyScope busy (this);
                    165:                                                        Core->DismountVolume (volume, true);
                    166:                                                }
                    167:                                                else
                    168:                                                        throw UserAbort (SRC_POS);
                    169:                                        }
                    170:                                }
                    171:                                catch (...)
                    172:                                {
                    173:                                        if (twoPassMode && firstPass)
                    174:                                                volumesLeft.push_back (volume);
                    175:                                        else
                    176:                                                throw;
                    177:                                }
                    178: 
                    179:                                if (volume->HiddenVolumeProtectionTriggered)
                    180:                                        ShowWarning (StringFormatter (LangString["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"], wstring (volume->Path)));
                    181: 
                    182:                                if (Preferences.Verbose)
                    183:                                {
                    184:                                        if (!message.IsEmpty())
                    185:                                                message += L'\n';
                    186:                                        message += StringFormatter (_("Volume \"{0}\" has been dismounted."), wstring (volume->Path));
                    187:                                }
                    188:                        }
                    189: 
                    190:                        if (twoPassMode && firstPass)
                    191:                        {
                    192:                                volumes = volumesLeft;
                    193: 
                    194:                                if (volumesInUse && interactive)
                    195:                                {
                    196:                                        if (AskYesNo (LangString["UNMOUNTALL_LOCK_FAILED"], true, true))
                    197:                                                ignoreOpenFiles = true;
                    198:                                        else
                    199:                                                throw UserAbort (SRC_POS);
                    200:                                }
                    201:                        }
                    202:                        else
                    203:                                break;
                    204: 
                    205:                        firstPass = false;
                    206:                }
                    207: 
                    208:                if (Preferences.Verbose && !message.IsEmpty())
                    209:                        ShowInfo (message);
                    210:        }
                    211:        
                    212:        wxString UserInterface::ExceptionToMessage (const exception &ex) const
                    213:        {
                    214:                wxString message;
                    215:                
                    216:                const Exception *e = dynamic_cast <const Exception *> (&ex);
                    217:                if (e)
                    218:                {
                    219:                        message = ExceptionToString (*e);
                    220: 
                    221:                        // System exception
                    222:                        const SystemException *sysEx = dynamic_cast <const SystemException *> (&ex);
                    223:                        if (sysEx)
                    224:                        {
                    225:                                if (!message.IsEmpty())
                    226:                                {
                    227:                                        message += L"\n\n";
                    228:                                }
                    229: 
                    230:                                message += wxString (sysEx->SystemText()).Trim (true);
                    231:                        }
                    232: 
                    233:                        if (!message.IsEmpty())
                    234:                        {
                    235:                                // Subject
                    236:                                if (!e->GetSubject().empty())
                    237:                                {
                    238:                                        message = message.Trim (true);
                    239: 
                    240:                                        if (message.EndsWith (L"."))
                    241:                                                message.Truncate (message.size() - 1);
                    242: 
                    243:                                        if (!message.EndsWith (L":"))
                    244:                                                message << L":\n";
                    245:                                        else
                    246:                                                message << L"\n";
                    247: 
                    248:                                        message << e->GetSubject();
                    249:                                }
                    250: #ifdef DEBUG
                    251:                                if (sysEx && sysEx->what())
                    252:                                        message << L"\n\n" << StringConverter::ToWide (sysEx->what());
                    253: #endif
                    254:                                return message;
                    255:                        }
                    256:                }
                    257: 
                    258:                // bad_alloc
                    259:                const bad_alloc *outOfMemory = dynamic_cast <const bad_alloc *> (&ex);
                    260:                if (outOfMemory)
                    261:                        return _("Out of memory.");
                    262: 
                    263:                // Unresolved exceptions
                    264:                string typeName (StringConverter::GetTypeName (typeid (ex)));
                    265:                size_t pos = typeName.find ("TrueCrypt::");
                    266:                if (pos != string::npos)
                    267:                {
                    268:                        return StringConverter::ToWide (typeName.substr (pos + string ("TrueCrypt::").size()))
                    269:                                + L" at " + StringConverter::ToWide (ex.what());
                    270:                }
                    271: 
                    272:                return StringConverter::ToWide (typeName) + L" at " + StringConverter::ToWide (ex.what());
                    273:        }
                    274: 
                    275:        wxString UserInterface::ExceptionToString (const Exception &ex) const
                    276:        {
                    277:                // Error messages
                    278:                const ErrorMessage *errMsgEx = dynamic_cast <const ErrorMessage *> (&ex);
                    279:                if (errMsgEx)
                    280:                        return wstring (*errMsgEx).c_str();
                    281: 
                    282:                // ExecutedProcessFailed
                    283:                const ExecutedProcessFailed *execEx = dynamic_cast <const ExecutedProcessFailed *> (&ex);
                    284:                if (execEx)
                    285:                {
                    286:                        wstring errOutput;
                    287: 
                    288:                        // ElevationFailed
                    289:                        if (dynamic_cast <const ElevationFailed*> (&ex))
                    290:                                errOutput += wxString (_("Failed to obtain administrator privileges")) + (StringConverter::Trim (execEx->GetErrorOutput()).empty() ? L". " : L": ");
                    291: 
                    292:                        errOutput += StringConverter::ToWide (execEx->GetErrorOutput());
                    293: 
                    294:                        if (errOutput.empty())
                    295:                                return errOutput + StringFormatter (_("Command \"{0}\" returned error {1}."), execEx->GetCommand(), execEx->GetExitCode());
                    296: 
                    297:                        return wxString (errOutput).Trim (true);
                    298:                }
                    299: 
                    300:                // PasswordIncorrect 
                    301:                if (dynamic_cast <const PasswordIncorrect *> (&ex))
                    302:                {
                    303:                        wxString message = ExceptionTypeToString (typeid (ex));
                    304: 
                    305:                        if (wxGetKeyState (WXK_CAPITAL))
                    306:                                message += wxString (L"\n\n") + LangString["CAPSLOCK_ON"];
                    307: 
                    308:                        return message;
                    309:                }
                    310: 
                    311:                // Other library exceptions
                    312:                return ExceptionTypeToString (typeid (ex));
                    313:        }
                    314: 
                    315:        wxString UserInterface::ExceptionTypeToString (const std::type_info &ex) const
                    316:        {
                    317: #define EX2MSG(exception, message) do { if (ex == typeid (exception)) return (message); } while (false)
                    318:                EX2MSG (DriveLetterUnavailable,                         LangString["DRIVE_LETTER_UNAVAILABLE"]);
                    319:                EX2MSG (ExternalException,                                      LangString["EXCEPTION_OCCURRED"]);
                    320:                EX2MSG (InsufficientData,                                       _("Not enough data available."));
                    321:                EX2MSG (HigherVersionRequired,                          LangString["NEW_VERSION_REQUIRED"]);
                    322:                EX2MSG (MissingArgument,                                        _("A required argument is missing."));
                    323:                EX2MSG (MissingVolumeData,                                      _("Volume data missing."));
                    324:                EX2MSG (MountPointRequired,                                     _("Mount point required."));
                    325:                EX2MSG (MountPointUnavailable,                          _("Mount point is already in use."));
                    326:                EX2MSG (NoDriveLetterAvailable,                         LangString["NO_FREE_DRIVES"]);
                    327:                EX2MSG (NoLoopbackDeviceAvailable,                      _("No loopback device available."));
                    328:                EX2MSG (PasswordEmpty,                                          _("No password or keyfile specified."));
                    329:                EX2MSG (PasswordIncorrect,                                      LangString["PASSWORD_WRONG"]);
                    330:                EX2MSG (PasswordKeyfilesIncorrect,                      LangString["PASSWORD_OR_KEYFILE_WRONG"]);
                    331:                EX2MSG (PasswordTooLong,                                        StringFormatter (_("Password is longer than {0} characters."), VolumePassword::MaxSize));
                    332:                EX2MSG (ProtectionPasswordIncorrect,            _("Incorrect keyfile(s) and/or password to the protected hidden volume or the hidden volume does not exist."));
                    333:                EX2MSG (ProtectionPasswordKeyfilesIncorrect,    _("Incorrect password to the protected hidden volume or the hidden volume does not exist."));
                    334:                EX2MSG (RootDeviceUnavailable,                          LangString["NODRIVER"]);
                    335:                EX2MSG (StringConversionFailed,                         _("Invalid characters encountered."));
                    336:                EX2MSG (StringFormatterException,                       _("Error while parsing formatted string."));
                    337:                EX2MSG (UnportablePassword,                                     LangString["UNSUPPORTED_CHARS_IN_PWD"]);
                    338:                EX2MSG (UnsupportedSectorSize,                                  LangString["LARGE_SECTOR_UNSUPPORTED"]);
                    339:                EX2MSG (VolumeAlreadyMounted,                           LangString["VOL_ALREADY_MOUNTED"]);
                    340:                EX2MSG (VolumeHostInUse,                                        _("The host file/device is already in use."));
                    341:                EX2MSG (VolumeSlotUnavailable,                          _("Volume slot unavailable."));
                    342: 
                    343: #undef EX2MSG
                    344:                return L"";
                    345:        }
                    346: 
                    347:        void UserInterface::Init ()
                    348:        {
                    349:                SetAppName (Application::GetName());
                    350:                SetClassName (Application::GetName());
                    351: 
                    352:                LangString.Init();
                    353:                Core->Init();
                    354: 
                    355:                wxCmdLineParser parser;
                    356:                parser.SetCmdLine (argc, argv);
                    357:                CmdLine.reset (new CommandLineInterface (parser, InterfaceType));
                    358:                SetPreferences (CmdLine->Preferences);
                    359: 
                    360:                Core->SetApplicationExecutablePath (Application::GetExecutablePath());
                    361: 
                    362:                if (!Preferences.NonInteractive)
                    363:                {
                    364:                        Core->SetAdminPasswordCallback (GetAdminPasswordRequestHandler());
                    365:                }
                    366:                else
                    367:                {
                    368:                        struct AdminPasswordRequestHandler : public GetStringFunctor
                    369:                        {
                    370:                                virtual string operator() ()
                    371:                                {
                    372:                                        throw ElevationFailed (SRC_POS, "sudo", 1, "");
                    373:                                }
                    374:                        };
                    375: 
                    376:                        Core->SetAdminPasswordCallback (shared_ptr <GetStringFunctor> (new AdminPasswordRequestHandler));
                    377:                }
                    378: 
                    379:                Core->WarningEvent.Connect (EventConnector <UserInterface> (this, &UserInterface::OnWarning));
                    380:                Core->VolumeMountedEvent.Connect (EventConnector <UserInterface> (this, &UserInterface::OnVolumeMounted));
                    381:        }
                    382:        
                    383:        void UserInterface::ListMountedVolumes (const VolumeInfoList &volumes) const
                    384:        {
                    385:                if (volumes.size() < 1)
                    386:                        throw_err (LangString["NO_VOLUMES_MOUNTED"]);
                    387: 
                    388:                wxString message;
                    389: 
                    390:                foreach_ref (const VolumeInfo &volume, volumes)
                    391:                {
                    392:                        message << volume.SlotNumber << L": " << StringConverter::QuoteSpaces (volume.Path);
                    393: 
                    394:                        if (!volume.VirtualDevice.IsEmpty())
                    395:                                message << L' ' << wstring (volume.VirtualDevice);
                    396:                        else
                    397:                                message << L" - ";
                    398: 
                    399:                        if (!volume.MountPoint.IsEmpty())
                    400:                                message << L' ' << StringConverter::QuoteSpaces (volume.MountPoint);
                    401:                        else
                    402:                                message << L" - ";
                    403: 
                    404:                        if (Preferences.Verbose)
                    405:                                message << L' ' << SizeToString (volume.Size);
                    406: 
                    407:                        message << L'\n';
                    408:                }
                    409: 
                    410:                ShowString (message);
                    411:        }
                    412:        
                    413:        VolumeInfoList UserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const
                    414:        {
                    415:                BusyScope busy (this);
                    416: 
                    417:                VolumeInfoList newMountedVolumes;
                    418: 
                    419:                if (!options.MountPoint)
                    420:                        options.MountPoint.reset (new DirectoryPath);
                    421: 
                    422:                Core->CoalesceSlotNumberAndMountPoint (options);
                    423: 
                    424:                bool sharedAccessAllowed = options.SharedAccessAllowed;
                    425:                bool someVolumesShared = false;
                    426: 
                    427:                HostDeviceList devices;
                    428:                foreach (shared_ptr <HostDevice> device, Core->GetHostDevices (true))
                    429:                {
                    430:                        devices.push_back (device);
                    431: 
                    432:                        foreach (shared_ptr <HostDevice> partition, device->Partitions)
                    433:                                devices.push_back (partition);
                    434:                }
                    435: 
                    436:                set <wstring> mountedVolumes;
                    437:                foreach_ref (const VolumeInfo &v, Core->GetMountedVolumes())
                    438:                        mountedVolumes.insert (v.Path);
                    439: 
                    440:                bool protectedVolumeMounted = false;
                    441:                bool legacyVolumeMounted = false;
                    442: 
                    443:                foreach_ref (const HostDevice &device, devices)
                    444:                {
                    445:                        if (mountedVolumes.find (wstring (device.Path)) != mountedVolumes.end())
                    446:                                continue;
                    447: 
                    448:                        Yield();
                    449:                        options.SlotNumber = Core->GetFirstFreeSlotNumber (options.SlotNumber);
                    450:                        options.MountPoint.reset (new DirectoryPath);
                    451:                        options.Path.reset (new VolumePath (device.Path));
                    452: 
                    453:                        try
                    454:                        {
                    455:                                try
                    456:                                {
                    457:                                        options.SharedAccessAllowed = sharedAccessAllowed;
                    458:                                        newMountedVolumes.push_back (Core->MountVolume (options));
                    459:                                }
                    460:                                catch (VolumeHostInUse&)
                    461:                                {
                    462:                                        if (!sharedAccessAllowed)
                    463:                                        {
                    464:                                                try
                    465:                                                {
                    466:                                                        options.SharedAccessAllowed = true;
                    467:                                                        newMountedVolumes.push_back (Core->MountVolume (options));
                    468:                                                        someVolumesShared = true;
                    469:                                                }
                    470:                                                catch (VolumeHostInUse&)
                    471:                                                {
                    472:                                                        continue;
                    473:                                                }
                    474:                                        }
                    475:                                        else
                    476:                                                continue;
                    477:                                }
                    478: 
                    479:                                if (newMountedVolumes.back()->Protection == VolumeProtection::HiddenVolumeReadOnly)
                    480:                                        protectedVolumeMounted = true;
                    481: 
                    482:                                if (newMountedVolumes.back()->EncryptionAlgorithmMinBlockSize == 8)
                    483:                                        legacyVolumeMounted = true;
                    484:                        }
                    485:                        catch (DriverError&) { }
                    486:                        catch (MissingVolumeData&) { }
                    487:                        catch (PasswordException&) { }
                    488:                        catch (SystemException&) { }
                    489:                }
                    490: 
                    491:                if (newMountedVolumes.empty())
                    492:                {
                    493:                        ShowWarning (LangString [options.Keyfiles && !options.Keyfiles->empty() ? "PASSWORD_OR_KEYFILE_WRONG_AUTOMOUNT" : "PASSWORD_WRONG_AUTOMOUNT"]);
                    494:                }
                    495:                else
                    496:                {
                    497:                        if (someVolumesShared)
                    498:                                ShowWarning ("DEVICE_IN_USE_INFO");
                    499: 
                    500:                        if (legacyVolumeMounted)
                    501:                                ShowWarning ("WARN_64_BIT_BLOCK_CIPHER");
                    502: 
                    503:                        if (protectedVolumeMounted)
                    504:                                ShowInfo (LangString[newMountedVolumes.size() > 1 ? "HIDVOL_PROT_WARN_AFTER_MOUNT_PLURAL" : "HIDVOL_PROT_WARN_AFTER_MOUNT"]);
                    505:                }
                    506: 
                    507:                return newMountedVolumes;
                    508:        }
                    509: 
                    510:        VolumeInfoList UserInterface::MountAllFavoriteVolumes (MountOptions &options) const
                    511:        {
                    512:                BusyScope busy (this);
                    513:                
                    514:                VolumeInfoList newMountedVolumes;
                    515:                foreach_ref (const FavoriteVolume &favorite, FavoriteVolume::LoadList())
                    516:                {
                    517:                        shared_ptr <VolumeInfo> mountedVolume = Core->GetMountedVolume (favorite.Path);
                    518:                        if (mountedVolume)
                    519:                        {
                    520:                                if (mountedVolume->MountPoint != favorite.MountPoint)
                    521:                                        ShowInfo (StringFormatter (LangString["VOLUME_ALREADY_MOUNTED"], wstring (favorite.Path)));
                    522:                                continue;
                    523:                        }
                    524: 
                    525:                        favorite.ToMountOptions (options);
                    526: 
                    527:                        if (Preferences.NonInteractive)
                    528:                        {
                    529:                                BusyScope busy (this);
                    530:                                newMountedVolumes.push_back (Core->MountVolume (options));
                    531:                        }
                    532:                        else
                    533:                        {
                    534:                                try
                    535:                                {
                    536:                                        BusyScope busy (this);
                    537:                                        newMountedVolumes.push_back (Core->MountVolume (options));
                    538:                                }
                    539:                                catch (...)
                    540:                                {
                    541:                                        shared_ptr <VolumeInfo> volume = MountVolume (options);
                    542:                                        if (!volume)
                    543:                                                break;
                    544:                                        newMountedVolumes.push_back (volume);
                    545:                                }
                    546:                        }
                    547:                }
                    548: 
                    549:                return newMountedVolumes;
                    550:        }
                    551: 
                    552:        shared_ptr <VolumeInfo> UserInterface::MountVolume (MountOptions &options) const
                    553:        {
                    554:                shared_ptr <VolumeInfo> volume;
                    555: 
                    556:                try
                    557:                {
                    558:                        volume = Core->MountVolume (options);
                    559:                }
                    560:                catch (VolumeHostInUse&)
                    561:                {
                    562:                        if (options.SharedAccessAllowed)
                    563:                                throw_err (LangString["FILE_IN_USE_FAILED"]);
                    564: 
                    565:                        if (!AskYesNo (StringFormatter (LangString["VOLUME_HOST_IN_USE"], wstring (*options.Path)), false, true))
                    566:                                throw UserAbort (SRC_POS);
                    567: 
                    568:                        try
                    569:                        {
                    570:                                options.SharedAccessAllowed = true;
                    571:                                volume = Core->MountVolume (options);
                    572:                        }
                    573:                        catch (VolumeHostInUse&)
                    574:                        {
                    575:                                throw_err (LangString["FILE_IN_USE_FAILED"]);
                    576:                        }
                    577:                }
                    578: 
                    579:                if (volume->EncryptionAlgorithmMinBlockSize == 8)
                    580:                        ShowWarning ("WARN_64_BIT_BLOCK_CIPHER");
                    581: 
                    582:                if (VolumeHasUnrecommendedExtension (*options.Path))
                    583:                        ShowWarning ("EXE_FILE_EXTENSION_MOUNT_WARNING");
                    584: 
                    585:                if (options.Protection == VolumeProtection::HiddenVolumeReadOnly)
                    586:                        ShowInfo ("HIDVOL_PROT_WARN_AFTER_MOUNT");
                    587: 
                    588:                return volume;
                    589:        }
                    590: 
                    591:        void UserInterface::OnUnhandledException ()
                    592:        {
                    593:                try
                    594:                {
                    595:                        throw;
                    596:                }
                    597:                catch (UserAbort&)
                    598:                {
                    599:                }
                    600:                catch (exception &e)
                    601:                {
                    602:                        ShowError (e);
                    603:                }
                    604:                catch (...)
                    605:                {
                    606:                        ShowError (_("Unknown exception occurred."));
                    607:                }
                    608: 
                    609:                Yield();
                    610:                Application::SetExitCode (1);
                    611:        }
                    612: 
                    613:        void UserInterface::OnVolumeMounted (EventArgs &args)
                    614:        {
                    615:                shared_ptr <VolumeInfo> mountedVolume = (dynamic_cast <VolumeEventArgs &> (args)).mVolume;
                    616: 
                    617:                if (Preferences.OpenExplorerWindowAfterMount && !mountedVolume->MountPoint.IsEmpty())
                    618:                        OpenExplorerWindow (mountedVolume->MountPoint);
                    619:        }
                    620:        
                    621:        void UserInterface::OnWarning (EventArgs &args)
                    622:        {
                    623:                ExceptionEventArgs &e = dynamic_cast <ExceptionEventArgs &> (args);
                    624:                ShowWarning (e.mException);
                    625:        }
                    626: 
                    627:        void UserInterface::OpenExplorerWindow (const DirectoryPath &path)
                    628:        {
                    629:                if (path.IsEmpty())
                    630:                        return;
                    631: 
                    632:                list <string> args;
                    633: 
                    634: #ifdef TC_WINDOWS
                    635: 
                    636:                wstring p (Directory::AppendSeparator (path));
                    637:                SHFILEINFO fInfo;
                    638:                SHGetFileInfo (p.c_str(), 0, &fInfo, sizeof (fInfo), 0); // Force explorer to discover the drive
                    639:                ShellExecute (GetTopWindow() ? static_cast <HWND> (GetTopWindow()->GetHandle()) : nullptr, L"open", p.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
                    640: 
                    641: #elif defined (TC_MACOSX)
                    642: 
                    643:                args.push_back (string (path));
                    644:                Process::Execute ("open", args);
                    645: 
                    646: #else
                    647:                // MIME handler for directory seems to be unavailable through wxWidgets
                    648:                if (GetTraits()->GetDesktopEnvironment() == L"GNOME")
                    649:                {
                    650:                        args.push_back ("--no-default-window");
                    651:                        args.push_back ("--no-desktop");
                    652:                        args.push_back (string (path));
                    653:                        try
                    654:                        {
                    655:                                Process::Execute ("nautilus", args, 2000);
                    656:                        }
                    657:                        catch (TimeOut&) { }
                    658:                }
                    659:                else if (GetTraits()->GetDesktopEnvironment() == L"KDE")
                    660:                {
                    661:                        args.push_back ("openURL");
                    662:                        args.push_back (string (path));
                    663:                        try
                    664:                        {
                    665:                                Process::Execute ("kfmclient", args, 2000);
                    666:                        }
                    667:                        catch (TimeOut&) { }
                    668:                }
                    669: #endif
                    670:        }
                    671: 
                    672:        bool UserInterface::ProcessCommandLine ()
                    673:        {
                    674:                CommandLineInterface &cmdLine = *CmdLine;
                    675: 
                    676:                switch (cmdLine.ArgCommand)
                    677:                {
                    678:                case CommandId::None:
                    679:                        return false;
                    680: 
                    681:                case CommandId::AutoMountDevices:
                    682:                case CommandId::AutoMountFavorites:
                    683:                case CommandId::AutoMountDevicesFavorites:
                    684:                case CommandId::MountVolume:
                    685:                        {
                    686:                                cmdLine.ArgMountOptions.Path = cmdLine.ArgVolumePath;
                    687:                                cmdLine.ArgMountOptions.MountPoint = cmdLine.ArgMountPoint;
                    688:                                cmdLine.ArgMountOptions.Password = cmdLine.ArgPassword;
                    689:                                cmdLine.ArgMountOptions.Keyfiles = cmdLine.ArgKeyfiles;
                    690:                                cmdLine.ArgMountOptions.SharedAccessAllowed = cmdLine.ArgForce;
                    691: 
                    692:                                VolumeInfoList mountedVolumes;
                    693:                                switch (cmdLine.ArgCommand)
                    694:                                {
                    695:                                case CommandId::AutoMountDevices:
                    696:                                case CommandId::AutoMountFavorites:
                    697:                                case CommandId::AutoMountDevicesFavorites:
                    698:                                        {
                    699:                                                if (cmdLine.ArgCommand == CommandId::AutoMountDevices || cmdLine.ArgCommand == CommandId::AutoMountDevicesFavorites)
                    700:                                                {
                    701:                                                        if (Preferences.NonInteractive)
                    702:                                                                mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (cmdLine.ArgMountOptions);
                    703:                                                        else
                    704:                                                                mountedVolumes = MountAllDeviceHostedVolumes (cmdLine.ArgMountOptions);
                    705:                                                }
                    706: 
                    707:                                                if (cmdLine.ArgCommand == CommandId::AutoMountFavorites || cmdLine.ArgCommand == CommandId::AutoMountDevicesFavorites)
                    708:                                                {
                    709:                                                        foreach (shared_ptr <VolumeInfo> v, MountAllFavoriteVolumes(cmdLine.ArgMountOptions))
                    710:                                                                mountedVolumes.push_back (v);
                    711:                                                }
                    712:                                        }
                    713:                                        break;
                    714: 
                    715: 
                    716:                                        break;
                    717: 
                    718:                                case CommandId::MountVolume:
                    719:                                        if (Preferences.OpenExplorerWindowAfterMount)
                    720:                                        {
                    721:                                                // Open explorer window for an already mounted volume
                    722:                                                shared_ptr <VolumeInfo> mountedVolume = Core->GetMountedVolume (*cmdLine.ArgMountOptions.Path);
                    723:                                                if (mountedVolume && !mountedVolume->MountPoint.IsEmpty())
                    724:                                                {
                    725:                                                        OpenExplorerWindow (mountedVolume->MountPoint);
                    726:                                                        break;
                    727:                                                }
                    728:                                        }
                    729: 
                    730:                                        if (Preferences.NonInteractive)
                    731:                                        {
                    732:                                                // Volume path
                    733:                                                if (!cmdLine.ArgMountOptions.Path)
                    734:                                                        throw MissingArgument (SRC_POS);
                    735: 
                    736:                                                mountedVolumes.push_back (Core->MountVolume (cmdLine.ArgMountOptions));
                    737:                                        }
                    738:                                        else
                    739:                                        {
                    740:                                                shared_ptr <VolumeInfo> volume = MountVolume (cmdLine.ArgMountOptions);
                    741:                                                if (!volume)
                    742:                                                {
                    743:                                                        Application::SetExitCode (1);
                    744:                                                        throw UserAbort (SRC_POS);
                    745:                                                }
                    746:                                                mountedVolumes.push_back (volume);
                    747:                                        }
                    748:                                        break;
                    749: 
                    750:                                default:
                    751:                                        throw ParameterIncorrect (SRC_POS);
                    752:                                }
                    753: 
                    754:                                if (Preferences.Verbose && !mountedVolumes.empty())
                    755:                                {
                    756:                                        wxString message;
                    757:                                        foreach_ref (const VolumeInfo &volume, mountedVolumes)
                    758:                                        {
                    759:                                                if (!message.IsEmpty())
                    760:                                                        message += L'\n';
                    761:                                                message += StringFormatter (_("Volume \"{0}\" has been mounted."), wstring (volume.Path));
                    762:                                        }
                    763:                                        ShowInfo (message);
                    764:                                }
                    765:                        }
                    766:                        return true;
                    767: 
                    768:                case CommandId::ChangePassword:
                    769:                        ChangePassword (cmdLine.ArgVolumePath, cmdLine.ArgPassword, cmdLine.ArgKeyfiles, cmdLine.ArgNewPassword, cmdLine.ArgNewKeyfiles);
                    770:                        return true;
                    771: 
                    772:                case CommandId::DismountVolumes:
                    773:                        DismountVolumes (cmdLine.ArgVolumes, cmdLine.ArgForce, !Preferences.NonInteractive);
                    774:                        return true;
                    775: 
                    776:                case CommandId::DisplayVersion:
                    777:                        ShowString (Application::GetName() + L" " + StringConverter::ToWide (Version::String()) + L"\n");
                    778:                        return true;
                    779: 
                    780:                case CommandId::Help:
                    781:                        ShowString (L"\nExamples:\n\nMount a volume:\ntruecrypt volume.tc /media/truecrypt1\n\n"
1.1.1.2 ! root      782:                                        L"Dismount a volume:\ntruecrypt -d volume.tc\n\n"
        !           783:                                        L"Dismount all mounted volumes:\ntruecrypt -d\n\n"
1.1       root      784:                                        );
                    785:                        return true;
                    786: 
                    787:                case CommandId::ListVolumes:
                    788:                        ListMountedVolumes (cmdLine.ArgVolumes);
                    789:                        return true;
                    790: 
                    791:                case CommandId::Test:
                    792:                        Test();
                    793:                        return true;
                    794: 
                    795:                default:
                    796:                        throw ParameterIncorrect (SRC_POS);
                    797:                }
                    798: 
                    799:                return false;
                    800:        }
                    801: 
                    802:        void UserInterface::SetPreferences (const UserPreferences &preferences)
                    803:        {
                    804:                Preferences = preferences;
                    805:                PreferencesUpdatedEvent.Raise();
                    806:        }
                    807: 
                    808:        void UserInterface::ShowError (const exception &ex) const
                    809:        {
                    810:                if (!dynamic_cast <const UserAbort*> (&ex))
                    811:                        DoShowError (ExceptionToMessage (ex));
                    812:        }
                    813: 
                    814:        wxString UserInterface::SizeToString (uint64 size) const
                    815:        {
                    816:                wstringstream s;
                    817:                if (size > 1024ULL*1024*1024*1024*1024*99)
                    818:                        s << size/1024/1024/1024/1024/1024 << L" " << LangString["PB"].c_str();
                    819:                else if (size > 1024ULL*1024*1024*1024*1024)
                    820:                        return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024/1024/1024), LangString["PB"].c_str());
                    821:                else if (size > 1024ULL*1024*1024*1024*99)
                    822:                        s << size/1024/1024/1024/1024 << L" " << LangString["TB"].c_str();
                    823:                else if (size > 1024ULL*1024*1024*1024)
                    824:                        return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024/1024), LangString["TB"].c_str());
                    825:                else if (size > 1024ULL*1024*1024*99)
                    826:                        s << size/1024/1024/1024 << L" " << LangString["GB"].c_str();
                    827:                else if (size > 1024ULL*1024*1024)
                    828:                        return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024), LangString["GB"].c_str());
                    829:                else if (size > 1024ULL*1024*99)
                    830:                        s << size/1024/1024 << L" " << LangString["MB"].c_str();
                    831:                else if (size > 1024ULL*1024)
                    832:                        return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024), LangString["MB"].c_str());
                    833:                else if (size > 1024ULL)
                    834:                        s << size/1024 << L" " << LangString["KB"].c_str();
                    835:                else
                    836:                        s << size << L" " << LangString["BYTE"].c_str();
                    837: 
                    838:                return s.str();
                    839:        }
                    840: 
                    841:        wxString UserInterface::SpeedToString (uint64 speed) const
                    842:        {
                    843:                wstringstream s;
                    844: 
                    845:                if (speed > 1024ULL*1024*1024*1024*1024*99)
                    846:                        s << speed/1024/1024/1024/1024/1024 << L" " << LangString["PB_PER_SEC"].c_str();
                    847:                else if (speed > 1024ULL*1024*1024*1024*1024)
                    848:                        return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024/1024/1024), LangString["PB_PER_SEC"].c_str());
                    849:                else if (speed > 1024ULL*1024*1024*1024*99)
                    850:                        s << speed/1024/1024/1024/1024 << L" " << LangString["TB"].c_str();
                    851:                else if (speed > 1024ULL*1024*1024*1024)
                    852:                        return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024/1024), LangString["TB_PER_SEC"].c_str());
                    853:                else if (speed > 1024ULL*1024*1024*99)
                    854:                        s << speed/1024/1024/1024 << L" " << LangString["GB"].c_str();
                    855:                else if (speed > 1024ULL*1024*1024)
                    856:                        return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024), LangString["GB_PER_SEC"].c_str());
                    857:                else if (speed > 1024ULL*1024*99)
                    858:                        s << speed/1024/1024 << L" " << LangString["MB"].c_str();
                    859:                else if (speed > 1024ULL*1024)
                    860:                        return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024), LangString["MB_PER_SEC"].c_str());
                    861:                else if (speed > 1024ULL)
                    862:                        s << speed/1024 << L" " << LangString["KB_PER_SEC"].c_str();
                    863:                else
                    864:                        s << speed << L" " << LangString["B_PER_SEC"].c_str();
                    865: 
                    866:                return s.str();
                    867:        }
                    868: 
                    869:        void UserInterface::Test () const
                    870:        {
                    871:                if (!PlatformTest::TestAll())
                    872:                        throw TestFailed (SRC_POS);
                    873: 
                    874:                EncryptionTest::TestAll();
                    875: 
                    876:                // StringFormatter
                    877:                if (StringFormatter (L"{9} {8} {7} {6} {5} {4} {3} {2} {1} {0} {{0}}", "1", L"2", '3', L'4', 5, 6, 7, 8, 9, 10) != L"10 9 8 7 6 5 4 3 2 1 {0}")
                    878:                        throw TestFailed (SRC_POS);
                    879:                try
                    880:                {
                    881:                        StringFormatter (L"{0} {1}", 1);
                    882:                        throw TestFailed (SRC_POS);
                    883:                }
                    884:                catch (StringFormatterException&) { }
                    885: 
                    886:                try
                    887:                {
                    888:                        StringFormatter (L"{0} {1} {1}", 1, 2, 3);
                    889:                        throw TestFailed (SRC_POS);
                    890:                }
                    891:                catch (StringFormatterException&) { }
                    892: 
                    893:                try
                    894:                {
                    895:                        StringFormatter (L"{0} 1}", 1, 2);
                    896:                        throw TestFailed (SRC_POS);
                    897:                }
                    898:                catch (StringFormatterException&) { }
                    899: 
                    900:                try
                    901:                {
                    902:                        StringFormatter (L"{0} {1", 1, 2);
                    903:                        throw TestFailed (SRC_POS);
                    904:                }
                    905:                catch (StringFormatterException&) { }
                    906: 
                    907:                ShowInfo ("TESTS_PASSED");
                    908:        }
                    909:        
                    910:        bool UserInterface::VolumeHasUnrecommendedExtension (const VolumePath &path) const
                    911:        {
                    912:                wxString ext = wxFileName (wxString (wstring (path)).Lower()).GetExt();
                    913:                return ext.IsSameAs (L"exe") || ext.IsSameAs (L"sys") || ext.IsSameAs (L"dll");
                    914:        }
                    915: 
                    916:        wxString UserInterface::VolumeTimeToString (VolumeTime volumeTime) const
                    917:        {
                    918:                wxString dateStr = VolumeTimeToDateTime (volumeTime).Format();
                    919: 
                    920: #ifdef TC_WINDOWS
                    921: 
                    922:                FILETIME ft;
                    923:                *(unsigned __int64 *)(&ft) = volumeTime;
                    924:                SYSTEMTIME st;
                    925:                FileTimeToSystemTime (&ft, &st);
                    926: 
                    927:                wchar_t wstr[1024];
                    928:                if (GetDateFormat (LOCALE_USER_DEFAULT, 0, &st, 0, wstr, array_capacity (wstr)) != 0)
                    929:                {
                    930:                        dateStr = wstr;
                    931:                        GetTimeFormat (LOCALE_USER_DEFAULT, 0, &st, 0, wstr, array_capacity (wstr));
                    932:                        dateStr += wxString (L" ") + wstr;
                    933:                }
                    934: #endif
                    935:                return dateStr;
                    936:        }
                    937: 
                    938:        wxString UserInterface::VolumeTypeToString (VolumeType::Enum type, VolumeProtection::Enum protection) const
                    939:        {
                    940:                switch (type)
                    941:                {
                    942:                case VolumeType::Normal:
                    943:                        return LangString[protection == VolumeProtection::HiddenVolumeReadOnly ? "OUTER" : "NORMAL"];
                    944: 
                    945:                case VolumeType::Hidden:
                    946:                        return LangString["HIDDEN"];
                    947: 
                    948:                default:
                    949:                        return L"?";
                    950:                }
                    951:        }
                    952: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.