Annotation of truecrypt/common/bootencryption.cpp, revision 1.1

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 "Tcdefs.h"
        !            10: #include "Platform/Finally.h"
        !            11: #include "Platform/ForEach.h"
        !            12: #include <Setupapi.h>
        !            13: #include <devguid.h>
        !            14: #include <io.h>
        !            15: #include <shlobj.h>
        !            16: #include <atlbase.h>
        !            17: #include "BootEncryption.h"
        !            18: #include "Boot/Windows/BootCommon.h"
        !            19: #include "Common/Resource.h"
        !            20: #include "Crc.h"
        !            21: #include "Crypto.h"
        !            22: #include "Dlgcode.h"
        !            23: #include "Endian.h"
        !            24: #include "Random.h"
        !            25: #include "Registry.h"
        !            26: #include "Volumes.h"
        !            27: 
        !            28: #ifdef VOLFORMAT
        !            29: #include "Format/FormatCom.h"
        !            30: #elif defined (TCMOUNT)
        !            31: #include "Mount/MainCom.h"
        !            32: #endif
        !            33: 
        !            34: namespace TrueCrypt
        !            35: {
        !            36: #if !defined (SETUP)
        !            37: 
        !            38:        class Elevator
        !            39:        {
        !            40:        public:
        !            41:                static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize)
        !            42:                {
        !            43:                        Elevate();
        !            44: 
        !            45:                        CComBSTR inputBstr;
        !            46:                        if (input && inputBstr.AppendBytes ((const char *) input, inputSize) != S_OK)
        !            47:                                throw ParameterIncorrect (SRC_POS);
        !            48: 
        !            49:                        CComBSTR outputBstr;
        !            50:                        if (output && outputBstr.AppendBytes ((const char *) output, outputSize) != S_OK)
        !            51:                                throw ParameterIncorrect (SRC_POS);
        !            52: 
        !            53:                        DWORD result = ElevatedComInstance->CallDriver (ioctl, inputBstr, &outputBstr);
        !            54:                        if (result != ERROR_SUCCESS)
        !            55:                        {
        !            56:                                SetLastError (result);
        !            57:                                throw SystemException();
        !            58:                        }
        !            59:                }
        !            60: 
        !            61:                static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone)
        !            62:                {
        !            63:                        Elevate();
        !            64: 
        !            65:                        CComBSTR bufferBstr;
        !            66:                        if (bufferBstr.AppendBytes ((const char *) buffer, size) != S_OK)
        !            67:                                throw ParameterIncorrect (SRC_POS);
        !            68:                        DWORD result = ElevatedComInstance->ReadWriteFile (write, device, CComBSTR (filePath.c_str()), &bufferBstr, offset, size, sizeDone);
        !            69: 
        !            70:                        if (result != ERROR_SUCCESS)
        !            71:                        {
        !            72:                                SetLastError (result);
        !            73:                                throw SystemException();
        !            74:                        }
        !            75: 
        !            76:                        if (!write)
        !            77:                                memcpy (buffer, (BYTE *) bufferBstr.m_str, size);
        !            78:                }
        !            79: 
        !            80:                static void RegisterFilterDriver (bool registerDriver)
        !            81:                {
        !            82:                        Elevate();
        !            83: 
        !            84:                        DWORD result = ElevatedComInstance->RegisterFilterDriver (registerDriver ? TRUE : FALSE);
        !            85:                        if (result != ERROR_SUCCESS)
        !            86:                        {
        !            87:                                SetLastError (result);
        !            88:                                throw SystemException();
        !            89:                        }
        !            90:                }
        !            91: 
        !            92:                static void Release ()
        !            93:                {
        !            94:                        if (ElevatedComInstance)
        !            95:                        {
        !            96:                                ElevatedComInstance->Release();
        !            97:                                ElevatedComInstance = nullptr;
        !            98:                                CoUninitialize ();
        !            99:                        }
        !           100:                }
        !           101: 
        !           102:                static void SetDriverServiceStartType (DWORD startType)
        !           103:                {
        !           104:                        Elevate();
        !           105: 
        !           106:                        DWORD result = ElevatedComInstance->SetDriverServiceStartType (startType);
        !           107:                        if (result != ERROR_SUCCESS)
        !           108:                        {
        !           109:                                SetLastError (result);
        !           110:                                throw SystemException();
        !           111:                        }
        !           112:                }
        !           113: 
        !           114:        protected:
        !           115:                static void Elevate ()
        !           116:                {
        !           117:                        if (IsAdmin())
        !           118:                        {
        !           119:                                SetLastError (ERROR_ACCESS_DENIED);
        !           120:                                throw SystemException();
        !           121:                        }
        !           122: 
        !           123:                        if (!ElevatedComInstance)
        !           124:                        {
        !           125:                                CoInitialize (NULL);
        !           126:                                ElevatedComInstance = GetElevatedInstance (GetActiveWindow() ? GetActiveWindow() : MainDlg);
        !           127:                        }
        !           128:                }
        !           129:                
        !           130: #if defined (TCMOUNT)
        !           131:                static ITrueCryptMainCom *ElevatedComInstance;
        !           132: #elif defined (VOLFORMAT)
        !           133:                static ITrueCryptFormatCom *ElevatedComInstance;
        !           134: #endif
        !           135:        };
        !           136: 
        !           137: #if defined (TCMOUNT)
        !           138:        ITrueCryptMainCom *Elevator::ElevatedComInstance;
        !           139: #elif defined (VOLFORMAT)
        !           140:        ITrueCryptFormatCom *Elevator::ElevatedComInstance;
        !           141: #endif
        !           142: 
        !           143: #else // SETUP
        !           144:        
        !           145:        class Elevator
        !           146:        {
        !           147:        public:
        !           148:                static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) { throw ParameterIncorrect (SRC_POS); }
        !           149:                static void ReadWriteFile (BOOL write, BOOL device, const string &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) { throw ParameterIncorrect (SRC_POS); }
        !           150:                static void RegisterFilterDriver (bool registerDriver) { throw ParameterIncorrect (SRC_POS); }
        !           151:                static void Release () { }
        !           152:                static void SetDriverServiceStartType (DWORD startType) { throw ParameterIncorrect (SRC_POS); }
        !           153:        };
        !           154: 
        !           155: #endif // SETUP
        !           156: 
        !           157: 
        !           158:        File::File (string path, bool readOnly, bool create) : Elevated (false), FileOpen (false)
        !           159:        {
        !           160:                Handle = CreateFile (path.c_str(),
        !           161:                        readOnly ? FILE_READ_DATA : FILE_READ_DATA | FILE_WRITE_DATA,
        !           162:                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING,
        !           163:                        FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL);
        !           164: 
        !           165:                try
        !           166:                {
        !           167:                        throw_sys_if (Handle == INVALID_HANDLE_VALUE);
        !           168:                }
        !           169:                catch (SystemException &)
        !           170:                {
        !           171:                        if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
        !           172:                                Elevated = true;
        !           173:                        else
        !           174:                                throw;
        !           175:                }
        !           176: 
        !           177:                FileOpen = true;
        !           178:                FilePointerPosition = 0;
        !           179:                IsDevice = false;
        !           180:                Path = path;
        !           181:        }
        !           182: 
        !           183:        void File::Close ()
        !           184:        {
        !           185:                if (FileOpen)
        !           186:                {
        !           187:                        if (!Elevated)
        !           188:                                CloseHandle (Handle);
        !           189: 
        !           190:                        FileOpen = false;
        !           191:                }
        !           192:        }
        !           193: 
        !           194:        DWORD File::Read (byte *buffer, DWORD size)
        !           195:        {
        !           196:                DWORD bytesRead;
        !           197: 
        !           198:                if (Elevated)
        !           199:                {
        !           200:                        DWORD bytesRead;
        !           201: 
        !           202:                        Elevator::ReadWriteFile (false, IsDevice, Path, buffer, FilePointerPosition, size, &bytesRead);
        !           203:                        FilePointerPosition += bytesRead;
        !           204:                        return bytesRead;
        !           205:                }
        !           206: 
        !           207:                throw_sys_if (!ReadFile (Handle, buffer, size, &bytesRead, NULL));
        !           208:                return bytesRead;
        !           209:        }
        !           210: 
        !           211:        void File::SeekAt (int64 position)
        !           212:        {
        !           213:                if (Elevated)
        !           214:                {
        !           215:                        FilePointerPosition = position;
        !           216:                }
        !           217:                else
        !           218:                {
        !           219:                        LARGE_INTEGER pos;
        !           220:                        pos.QuadPart = position;
        !           221:                        throw_sys_if (!SetFilePointerEx (Handle, pos, NULL, FILE_BEGIN));
        !           222:                }
        !           223:        }
        !           224: 
        !           225:        void File::Write (byte *buffer, DWORD size)
        !           226:        {
        !           227:                DWORD bytesWritten;
        !           228:                
        !           229:                if (Elevated)
        !           230:                {
        !           231:                        Elevator::ReadWriteFile (true, IsDevice, Path, buffer, FilePointerPosition, size, &bytesWritten);
        !           232:                        FilePointerPosition += bytesWritten;
        !           233:                        throw_sys_if (bytesWritten != size);
        !           234:                }
        !           235:                else
        !           236:                {
        !           237:                        throw_sys_if (!WriteFile (Handle, buffer, size, &bytesWritten, NULL) || bytesWritten != size);
        !           238:                }
        !           239:        }
        !           240: 
        !           241:        void Show (HWND parent, const string &str)
        !           242:        {
        !           243:                MessageBox (parent, str.c_str(), NULL, 0);
        !           244:        }
        !           245: 
        !           246: 
        !           247:        Device::Device (string path, bool readOnly)
        !           248:        {
        !           249:                 FileOpen = false;
        !           250:                 Elevated = false;
        !           251: 
        !           252:                Handle = CreateFile ((string ("\\\\.\\") + path).c_str(),
        !           253:                        readOnly ? FILE_READ_DATA : FILE_READ_DATA | FILE_WRITE_DATA,
        !           254:                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
        !           255:                        FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL);
        !           256: 
        !           257:                try
        !           258:                {
        !           259:                        throw_sys_if (Handle == INVALID_HANDLE_VALUE);
        !           260:                }
        !           261:                catch (SystemException &)
        !           262:                {
        !           263:                        if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
        !           264:                                Elevated = true;
        !           265:                        else
        !           266:                                throw;
        !           267:                }
        !           268: 
        !           269:                FileOpen = true;
        !           270:                FilePointerPosition = 0;
        !           271:                IsDevice = true;
        !           272:                Path = path;
        !           273:        }
        !           274: 
        !           275: 
        !           276:        BootEncryption::~BootEncryption ()
        !           277:        {
        !           278:                if (RescueIsoImage)
        !           279:                        delete RescueIsoImage;
        !           280: 
        !           281:                Elevator::Release();
        !           282:        }
        !           283: 
        !           284: 
        !           285:        void BootEncryption::CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize)
        !           286:        {
        !           287:                try
        !           288:                {
        !           289:                        DWORD bytesReturned;
        !           290:                        throw_sys_if (!DeviceIoControl (hDriver, ioctl, input, inputSize, output, outputSize, &bytesReturned, NULL));
        !           291:                }
        !           292:                catch (SystemException &)
        !           293:                {
        !           294:                        if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
        !           295:                                Elevator::CallDriver (ioctl, input, inputSize, output, outputSize);
        !           296:                        else
        !           297:                                throw;
        !           298:                }
        !           299:        }
        !           300: 
        !           301: 
        !           302:        DWORD BootEncryption::GetDriverServiceStartType ()
        !           303:        {
        !           304:                DWORD startType;
        !           305:                throw_sys_if (!ReadLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", &startType));
        !           306:                return startType;
        !           307:        }
        !           308: 
        !           309: 
        !           310:        void BootEncryption::SetDriverServiceStartType (DWORD startType)
        !           311:        {
        !           312:                if (!IsAdmin() && IsUacSupported())
        !           313:                {
        !           314:                        Elevator::SetDriverServiceStartType (startType);
        !           315:                        return;
        !           316:                }
        !           317: 
        !           318:                BOOL startOnBoot = (startType == SERVICE_BOOT_START);
        !           319: 
        !           320:                SC_HANDLE serviceManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
        !           321:                throw_sys_if (!serviceManager);
        !           322: 
        !           323:                finally_do_arg (SC_HANDLE, serviceManager, { CloseServiceHandle (finally_arg); });
        !           324: 
        !           325:                SC_HANDLE service = OpenService (serviceManager, "truecrypt", SERVICE_CHANGE_CONFIG);
        !           326:                throw_sys_if (!service);
        !           327: 
        !           328:                finally_do_arg (SC_HANDLE, service, { CloseServiceHandle (finally_arg); });
        !           329: 
        !           330:                throw_sys_if (!ChangeServiceConfig (service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
        !           331:                        startOnBoot ? SERVICE_ERROR_SEVERE : SERVICE_ERROR_NORMAL, NULL,
        !           332:                        startOnBoot ? "Filter" : NULL,
        !           333:                        NULL, NULL, NULL, NULL, NULL));
        !           334: 
        !           335:                // ChangeServiceConfig() rejects SERVICE_BOOT_START with ERROR_INVALID_PARAMETER
        !           336:                throw_sys_if (!WriteLocalMachineRegistryDword ("SYSTEM\\CurrentControlSet\\Services\\truecrypt", "Start", startType));
        !           337:        }
        !           338: 
        !           339: 
        !           340:        void BootEncryption::ProbeRealSystemDriveSize ()
        !           341:        {
        !           342:                if (RealSystemDriveSizeValid)
        !           343:                        return;
        !           344: 
        !           345:                GetSystemDriveConfiguration();
        !           346: 
        !           347:                ProbeRealDriveSizeRequest request;
        !           348:                _snwprintf (request.DeviceName, array_capacity (request.DeviceName), L"%hs", DriveConfig.DrivePartition.DevicePath.c_str());
        !           349:                
        !           350:                CallDriver (TC_IOCTL_PROBE_REAL_DRIVE_SIZE, &request, sizeof (request), &request, sizeof (request));
        !           351:                DriveConfig.DrivePartition.Info.PartitionLength = request.RealDriveSize;
        !           352: 
        !           353:                RealSystemDriveSizeValid = TRUE;
        !           354:        }
        !           355: 
        !           356: 
        !           357:        PartitionList BootEncryption::GetDrivePartitions (int driveNumber)
        !           358:        {
        !           359:                PartitionList partList;
        !           360: 
        !           361:                for (int partNumber = 0; partNumber < 64; ++partNumber)
        !           362:                {
        !           363:                        stringstream partPath;
        !           364:                        partPath << "\\Device\\Harddisk" << driveNumber << "\\Partition" << partNumber;
        !           365: 
        !           366:                        DISK_PARTITION_INFO_STRUCT diskPartInfo;
        !           367:                        _snwprintf (diskPartInfo.deviceName, array_capacity (diskPartInfo.deviceName), L"%hs", partPath.str().c_str());
        !           368: 
        !           369:                        try
        !           370:                        {
        !           371:                                CallDriver (TC_IOCTL_GET_DRIVE_PARTITION_INFO, &diskPartInfo, sizeof (diskPartInfo), &diskPartInfo, sizeof (diskPartInfo));
        !           372:                        }
        !           373:                        catch (...)
        !           374:                        {
        !           375:                                continue;
        !           376:                        }
        !           377: 
        !           378:                        Partition part;
        !           379:                        part.DevicePath = partPath.str();
        !           380:                        part.Number = partNumber;
        !           381:                        part.Info = diskPartInfo.partInfo;
        !           382:                        part.IsGPT = diskPartInfo.IsGPT;
        !           383: 
        !           384:                        // Mount point
        !           385:                        wstringstream ws;
        !           386:                        ws << partPath.str().c_str();
        !           387:                        int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) ws.str().c_str());
        !           388: 
        !           389:                        if (driveNumber >= 0)
        !           390:                        {
        !           391:                                part.MountPoint += (char) (driveNumber + 'A');
        !           392:                                part.MountPoint += ":";
        !           393:                        }
        !           394:                        partList.push_back (part);
        !           395:                }
        !           396: 
        !           397:                return partList;
        !           398:        }
        !           399:        
        !           400: 
        !           401:        DISK_GEOMETRY BootEncryption::GetDriveGeometry (int driveNumber)
        !           402:        {
        !           403:                stringstream devName;
        !           404:                devName << "\\Device\\Harddisk" << driveNumber << "\\Partition0";
        !           405: 
        !           406:                DISK_GEOMETRY geometry;
        !           407:                throw_sys_if (!::GetDriveGeometry ((char *) devName.str().c_str(), &geometry));
        !           408:                return geometry;
        !           409:        }
        !           410: 
        !           411:        
        !           412:        string BootEncryption::GetWindowsDirectory ()
        !           413:        {
        !           414:                char buf[MAX_PATH];
        !           415:                if (GetSystemDirectory (buf, sizeof (buf)) > 0)
        !           416:                        return string (buf);
        !           417: 
        !           418:                return string();
        !           419:        }
        !           420:        
        !           421: 
        !           422:        uint16 BootEncryption::GetInstalledBootLoaderVersion ()
        !           423:        {
        !           424:                uint16 version;
        !           425:                CallDriver (TC_IOCTL_GET_BOOT_LOADER_VERSION, NULL, 0, &version, sizeof (version));
        !           426:                return version;
        !           427:        }
        !           428: 
        !           429: 
        !           430:        BootEncryptionStatus BootEncryption::GetStatus ()
        !           431:        {
        !           432:                /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */
        !           433: 
        !           434:                BootEncryptionStatus status;
        !           435:                CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS, NULL, 0, &status, sizeof (status));
        !           436:                return status;
        !           437:        }
        !           438: 
        !           439: 
        !           440:        void BootEncryption::GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties)
        !           441:        {
        !           442:                if (properties == NULL)
        !           443:                        throw ParameterIncorrect (SRC_POS);
        !           444: 
        !           445:                CallDriver (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES, NULL, 0, properties, sizeof (*properties));
        !           446:        }
        !           447: 
        !           448: 
        !           449:        SystemDriveConfiguration BootEncryption::GetSystemDriveConfiguration ()
        !           450:        {
        !           451:                if (DriveConfigValid)
        !           452:                        return DriveConfig;
        !           453: 
        !           454:                SystemDriveConfiguration config;
        !           455: 
        !           456:                string winDir = GetWindowsDirectory();
        !           457: 
        !           458:                // Scan all drives
        !           459:                for (int driveNumber = 0; driveNumber < 32; ++driveNumber)
        !           460:                {
        !           461:                        bool windowsFound = false;
        !           462:                        config.SystemLoaderPresent = false;
        !           463: 
        !           464:                        PartitionList partitions = GetDrivePartitions (driveNumber);
        !           465:                        foreach (const Partition &part, partitions)
        !           466:                        {
        !           467:                                if (_access ((part.MountPoint + "\\bootmgr").c_str(), 0) == 0 || _access ((part.MountPoint + "\\ntldr").c_str(), 0) == 0)
        !           468:                                        config.SystemLoaderPresent = true;
        !           469: 
        !           470:                                if (!windowsFound && !part.MountPoint.empty() && winDir.find (part.MountPoint) == 0)
        !           471:                                {
        !           472:                                        config.SystemPartition = part;
        !           473:                                        windowsFound = true;
        !           474:                                }
        !           475:                        }
        !           476: 
        !           477:                        if (windowsFound)
        !           478:                        {
        !           479:                                config.DriveNumber = driveNumber;
        !           480: 
        !           481:                                stringstream ss;
        !           482:                                ss << "PhysicalDrive" << driveNumber;
        !           483:                                config.DevicePath = ss.str();
        !           484: 
        !           485:                                config.DrivePartition = partitions.front();
        !           486:                                partitions.pop_front();
        !           487:                                config.Partitions = partitions;
        !           488: 
        !           489:                                config.InitialUnallocatedSpace = 0x7fffFFFFffffFFFFull;
        !           490:                                config.TotalUnallocatedSpace = config.DrivePartition.Info.PartitionLength.QuadPart;
        !           491: 
        !           492:                                foreach (const Partition &part, config.Partitions)
        !           493:                                {
        !           494:                                        if (part.Info.StartingOffset.QuadPart < config.InitialUnallocatedSpace)
        !           495:                                                config.InitialUnallocatedSpace = part.Info.StartingOffset.QuadPart;
        !           496: 
        !           497:                                        config.TotalUnallocatedSpace -= part.Info.PartitionLength.QuadPart;
        !           498:                                }
        !           499: 
        !           500:                                DriveConfig = config;
        !           501:                                DriveConfigValid = TRUE;
        !           502:                                return DriveConfig;
        !           503:                        }
        !           504:                }
        !           505: 
        !           506:                throw ParameterIncorrect (SRC_POS);
        !           507:        }
        !           508: 
        !           509: 
        !           510:        bool BootEncryption::SystemPartitionCoversWholeDrive ()
        !           511:        {
        !           512:                SystemDriveConfiguration config = GetSystemDriveConfiguration();
        !           513: 
        !           514:                return config.Partitions.size() == 1
        !           515:                        && config.SystemPartition.Info.PartitionLength.QuadPart * 1000 / config.DrivePartition.Info.PartitionLength.QuadPart >= 995;
        !           516:        }
        !           517: 
        !           518: 
        !           519:        void BootEncryption::InstallBootLoader ()
        !           520:        {
        !           521:                Device device (GetSystemDriveConfiguration().DevicePath);
        !           522:                DWORD size;
        !           523: 
        !           524:                // MBR
        !           525:                byte *bootSecImg = MapResource ("BIN", IDR_BOOT_SECTOR, &size);
        !           526:                if (!bootSecImg || size != SECTOR_SIZE)
        !           527:                        throw ParameterIncorrect (SRC_POS);
        !           528: 
        !           529:                byte bootSecBuf[SECTOR_SIZE];
        !           530: 
        !           531:                device.SeekAt (0);
        !           532:                device.Read (bootSecBuf, sizeof (bootSecBuf));
        !           533: 
        !           534:                memcpy (bootSecBuf, bootSecImg, TC_MAX_MBR_BOOT_CODE_SIZE);
        !           535: 
        !           536:                device.SeekAt (0);
        !           537:                device.Write (bootSecBuf, size);
        !           538: 
        !           539:                byte bootSecVerificationBuf[SECTOR_SIZE];
        !           540:                device.SeekAt (0);
        !           541:                device.Read (bootSecVerificationBuf, size);
        !           542: 
        !           543:                if (memcmp (bootSecBuf, bootSecVerificationBuf, size) != 0)
        !           544:                        throw ErrorException ("ERROR_MBR_PROTECTED");
        !           545: 
        !           546:                // Boot loader
        !           547:                byte bootLoaderBuf[TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET - SECTOR_SIZE];
        !           548:                byte *bootLoader = MapResource ("BIN", IDR_BOOT_LOADER, &size);
        !           549: 
        !           550:                if (!bootLoader || size > sizeof (bootLoaderBuf))
        !           551:                        throw ParameterIncorrect (SRC_POS);
        !           552: 
        !           553:                ZeroMemory (bootLoaderBuf, sizeof (bootLoaderBuf));
        !           554:                memcpy (bootLoaderBuf, bootLoader, size);
        !           555: 
        !           556:                device.SeekAt (SECTOR_SIZE);
        !           557:                device.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
        !           558:        }
        !           559: 
        !           560: 
        !           561:        string BootEncryption::GetSystemLoaderBackupPath ()
        !           562:        {
        !           563:                char pathBuf[MAX_PATH];
        !           564: 
        !           565:                throw_sys_if (!SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, pathBuf)));
        !           566:                
        !           567:                string path = string (pathBuf) + "\\" TC_APP_NAME;
        !           568:                CreateDirectory (path.c_str(), NULL);
        !           569: 
        !           570:                return path + '\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME;
        !           571:        }
        !           572: 
        !           573:        void BootEncryption::CreateRescueIsoImage (bool initialSetup, const string &isoImagePath)
        !           574:        {
        !           575:                BootEncryptionStatus encStatus = GetStatus();
        !           576:                if (encStatus.SetupInProgress)
        !           577:                        throw ParameterIncorrect (SRC_POS);
        !           578: 
        !           579:                Buffer imageBuf (RescueIsoImageSize);
        !           580:                
        !           581:                byte *image = imageBuf.Ptr();
        !           582:                memset (image, 0, RescueIsoImageSize);
        !           583: 
        !           584:                // Primary volume descriptor
        !           585:                int offset = 0x8000;
        !           586: 
        !           587:                // Boot record volume descriptor
        !           588:                strcpy ((char *)image + 0x8801, "CD001\001EL TORITO SPECIFICATION");
        !           589:                image[0x8800 + 0x47] = 0x19;
        !           590: 
        !           591:                // Validation entry
        !           592:                image[0xc800] = 1;
        !           593:                offset = 0xc800 + 0x1c;
        !           594:                image[offset++] = 0xaa;
        !           595:                image[offset++] = 0x55;
        !           596:                image[offset++] = 0x55;
        !           597:                image[offset] = 0xaa;
        !           598: 
        !           599:                // Initial entry
        !           600:                offset = 0xc820;
        !           601:                image[offset++] = 0x88;
        !           602:                image[offset++] = 2;
        !           603:                image[0xc820 + 6] = 1;
        !           604:                image[0xc820 + 8] = TC_CD_BOOT_LOADER_SECTOR;
        !           605: 
        !           606:                // TrueCrypt Boot Loader
        !           607:                DWORD size;
        !           608:                byte *bootSecResourceImg = MapResource ("BIN", IDR_BOOT_SECTOR, &size);
        !           609:                if (!bootSecResourceImg || size != SECTOR_SIZE)
        !           610:                        throw ParameterIncorrect (SRC_POS);
        !           611: 
        !           612:                byte bootSecImg[SECTOR_SIZE];
        !           613:                memcpy (bootSecImg, bootSecResourceImg, sizeof (bootSecImg));
        !           614: 
        !           615:                bootSecImg[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK;
        !           616:                memcpy (image + TC_CD_BOOTSECTOR_OFFSET, bootSecImg, SECTOR_SIZE);
        !           617: 
        !           618:                byte *bootLoader = MapResource ("BIN", IDR_BOOT_LOADER, &size);
        !           619:                if (!bootLoader)
        !           620:                        throw ParameterIncorrect (SRC_POS);
        !           621: 
        !           622:                memcpy (image + TC_CD_BOOTSECTOR_OFFSET + SECTOR_SIZE, bootLoader, size);
        !           623:                
        !           624:                // Volume header
        !           625:                if (initialSetup)
        !           626:                {
        !           627:                        if (!RescueVolumeHeaderValid)
        !           628:                                throw ParameterIncorrect (SRC_POS);
        !           629: 
        !           630:                        memcpy (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, RescueVolumeHeader, HEADER_SIZE);
        !           631:                }
        !           632:                else
        !           633:                {
        !           634:                        Device bootDevice (GetSystemDriveConfiguration().DevicePath, true);
        !           635:                        bootDevice.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
        !           636:                        bootDevice.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, HEADER_SIZE);
        !           637:                }
        !           638: 
        !           639:                // Original system loader
        !           640:                try
        !           641:                {
        !           642:                        File sysBakFile (GetSystemLoaderBackupPath(), true);
        !           643:                        sysBakFile.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE);
        !           644:                        
        !           645:                        image[TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER;
        !           646:                }
        !           647:                catch (Exception &e)
        !           648:                {
        !           649:                        e.Show (ParentWindow);
        !           650:                        Warning ("SYS_LOADER_UNAVAILABLE_FOR_RESCUE_DISK");
        !           651:                }
        !           652:                
        !           653:                RescueIsoImage = new byte[RescueIsoImageSize];
        !           654:                if (!RescueIsoImage)
        !           655:                        throw bad_alloc();
        !           656:                memcpy (RescueIsoImage, image, RescueIsoImageSize);
        !           657: 
        !           658:                if (!isoImagePath.empty())
        !           659:                {
        !           660:                        File isoFile (isoImagePath, false, true);
        !           661:                        isoFile.Write (image, RescueIsoImageSize);
        !           662:                }
        !           663:        }
        !           664: 
        !           665: 
        !           666:        bool BootEncryption::VerifyRescueDisk ()
        !           667:        {
        !           668:                if (!RescueIsoImage)
        !           669:                        throw ParameterIncorrect (SRC_POS);
        !           670: 
        !           671:                for (char drive = 'Z'; drive >= 'D'; --drive)
        !           672:                {
        !           673:                        try
        !           674:                        {
        !           675:                                string path = "X:";
        !           676:                                path[0] = drive;
        !           677: 
        !           678:                                Device driveDevice (path, true);
        !           679:                                size_t verifiedSectorCount = (TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET + TC_BOOT_LOADER_AREA_SIZE) / 2048;
        !           680:                                Buffer buffer ((verifiedSectorCount + 1) * 2048);
        !           681: 
        !           682:                                DWORD bytesRead = driveDevice.Read (buffer.Ptr(), buffer.Size());
        !           683:                                if (bytesRead != buffer.Size())
        !           684:                                        continue;
        !           685: 
        !           686:                                if (memcmp (buffer.Ptr(), RescueIsoImage, buffer.Size()) == 0)
        !           687:                                        return true;
        !           688:                        }
        !           689:                        catch (...) { }
        !           690:                }
        !           691: 
        !           692:                return false;
        !           693:        }
        !           694: 
        !           695: 
        !           696: #ifndef SETUP
        !           697: 
        !           698:        void BootEncryption::CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5)
        !           699:        {
        !           700:                PCRYPTO_INFO cryptoInfo = NULL;
        !           701:                
        !           702:                throw_sys_if (Randinit () != 0);
        !           703:                throw_sys_if (VolumeWriteHeader (TRUE, (char *) VolumeHeader, ea, mode, password, pkcs5, NULL, 0, &cryptoInfo,
        !           704:                        volumeSize, 0, encryptedAreaStart, 0, FALSE) != 0);
        !           705: 
        !           706:                finally_do_arg (PCRYPTO_INFO*, &cryptoInfo, { crypto_close (*finally_arg); });
        !           707: 
        !           708:                // Initial rescue disk assumes encryption of the drive has been completed (EncryptedAreaLength == volumeSize)
        !           709:                memcpy (RescueVolumeHeader, VolumeHeader, sizeof (RescueVolumeHeader));
        !           710:                VolumeReadHeader (TRUE, (char *) RescueVolumeHeader, password, NULL, cryptoInfo);
        !           711: 
        !           712:                DecryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
        !           713: 
        !           714:                if (GetHeaderField32 (RescueVolumeHeader, TC_HEADER_OFFSET_MAGIC) != 0x54525545)
        !           715:                        throw ParameterIncorrect (SRC_POS);
        !           716: 
        !           717:                byte *fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH;
        !           718:                mputInt64 (fieldPos, volumeSize);
        !           719:                
        !           720:                EncryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
        !           721: 
        !           722:                VolumeHeaderValid = true;
        !           723:                RescueVolumeHeaderValid = true;
        !           724:        }
        !           725: 
        !           726: 
        !           727:        void BootEncryption::InstallVolumeHeader ()
        !           728:        {
        !           729:                if (!VolumeHeaderValid)
        !           730:                        throw ParameterIncorrect (SRC_POS);
        !           731: 
        !           732:                Device device (GetSystemDriveConfiguration().DevicePath);
        !           733: 
        !           734:                device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
        !           735:                device.Write ((byte *) VolumeHeader, sizeof (VolumeHeader));
        !           736:        }
        !           737: 
        !           738: 
        !           739:        // For synchronous operations use AbortSetupWait()
        !           740:        void BootEncryption::AbortSetup ()
        !           741:        {
        !           742:                CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
        !           743:        }
        !           744: 
        !           745: 
        !           746:        // For asynchronous operations use AbortSetup()
        !           747:        void BootEncryption::AbortSetupWait ()
        !           748:        {
        !           749:                CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
        !           750: 
        !           751:                BootEncryptionStatus encStatus = GetStatus();
        !           752: 
        !           753:                while (encStatus.SetupInProgress)
        !           754:                {
        !           755:                        Sleep (TC_ABORT_TRANSFORM_WAIT_INTERVAL);
        !           756:                        encStatus = GetStatus();
        !           757:                }
        !           758:        }
        !           759: 
        !           760: 
        !           761:        void BootEncryption::BackupSystemLoader ()
        !           762:        {
        !           763:                Device device (GetSystemDriveConfiguration().DevicePath, true);
        !           764:        
        !           765:                byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE];
        !           766: 
        !           767:                device.SeekAt (0);
        !           768:                device.Read (bootLoaderBuf, sizeof (bootLoaderBuf));
        !           769: 
        !           770:                // Prevent TrueCrypt loader from being backed up
        !           771:                for (size_t i = 0; i < sizeof (bootLoaderBuf) - strlen (TC_APP_NAME); ++i)
        !           772:                {
        !           773:                        if (memcmp (bootLoaderBuf + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0)
        !           774:                        {
        !           775:                                if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED") == IDNO)
        !           776:                                        throw UserAbort (SRC_POS);
        !           777:                                return;
        !           778:                        }
        !           779:                }
        !           780: 
        !           781:                File backupFile (GetSystemLoaderBackupPath(), false, true);
        !           782:                backupFile.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
        !           783:        }
        !           784: 
        !           785: 
        !           786:        void BootEncryption::RestoreSystemLoader ()
        !           787:        {
        !           788:                byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * SECTOR_SIZE];
        !           789: 
        !           790:                File backupFile (GetSystemLoaderBackupPath(), true);
        !           791:                
        !           792:                if (backupFile.Read (bootLoaderBuf, sizeof (bootLoaderBuf)) != sizeof (bootLoaderBuf))
        !           793:                        throw ParameterIncorrect (SRC_POS);
        !           794: 
        !           795:                Device device (GetSystemDriveConfiguration().DevicePath);
        !           796:                device.SeekAt (0);
        !           797:                device.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
        !           798:        }
        !           799: 
        !           800: 
        !           801:        void BootEncryption::RegisterFilterDriver (bool registerDriver)
        !           802:        {
        !           803:                if (!IsAdmin() && IsUacSupported())
        !           804:                {
        !           805:                        Elevator::RegisterFilterDriver (registerDriver);
        !           806:                        return;
        !           807:                }
        !           808: 
        !           809:                HKEY classRegKey = SetupDiOpenClassRegKey (&GUID_DEVCLASS_DISKDRIVE, KEY_READ | KEY_WRITE);
        !           810:                throw_sys_if (classRegKey == INVALID_HANDLE_VALUE);
        !           811:                finally_do_arg (HKEY, classRegKey, { RegCloseKey (finally_arg); });
        !           812: 
        !           813:                if (registerDriver)
        !           814:                {
        !           815:                        // Place our filter in front of others already registered
        !           816:                        size_t strSize = strlen ("truecrypt") + 1;
        !           817:                        byte regKeyBuf[65536];
        !           818:                        DWORD size = sizeof (regKeyBuf) - strSize;
        !           819: 
        !           820:                        // SetupInstallFromInfSection() does not support prepending of values so we have to modify the registry directly
        !           821:                        strncpy ((char *) regKeyBuf, "truecrypt", sizeof (regKeyBuf));
        !           822: 
        !           823:                        if (RegQueryValueEx (classRegKey, "UpperFilters", NULL, NULL, regKeyBuf + strSize, &size) != ERROR_SUCCESS)
        !           824:                                size = 1;
        !           825: 
        !           826:                        throw_sys_if (RegSetValueEx (classRegKey, "UpperFilters", 0, REG_MULTI_SZ, regKeyBuf, strSize + size) != ERROR_SUCCESS);
        !           827:                }
        !           828:                else
        !           829:                {
        !           830:                        // Deregister filter
        !           831:                        char tempPath[MAX_PATH];
        !           832:                        GetTempPath (sizeof (tempPath), tempPath);
        !           833:                        string infFileName = string (tempPath) + "\\truecrypt_filter.inf";
        !           834: 
        !           835:                        finally_do_arg (string, infFileName, { DeleteFile (finally_arg.c_str()); });
        !           836:                        File infFile (infFileName, false, true);
        !           837: 
        !           838:                        string infTxt = "[truecrypt]\r\nDelReg=truecrypt_reg\r\n\r\n"
        !           839:                                                        "[truecrypt_reg]\r\nHKR,,\"UpperFilters\",0x00018002,\"truecrypt\"\r\n";
        !           840: 
        !           841:                        infFile.Write ((byte *) infTxt.c_str(), infTxt.size());
        !           842:                        infFile.Close();
        !           843: 
        !           844:                        HINF hInf = SetupOpenInfFile (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
        !           845:                        throw_sys_if (hInf == INVALID_HANDLE_VALUE);
        !           846:                        finally_do_arg (HINF, hInf, { SetupCloseInfFile (finally_arg); });
        !           847: 
        !           848:                        throw_sys_if (!SetupInstallFromInfSection (ParentWindow, hInf, "truecrypt", SPINST_REGISTRY, classRegKey, NULL, 0, NULL, NULL, NULL, NULL));
        !           849:                }
        !           850:        }
        !           851: 
        !           852: 
        !           853:        void BootEncryption::CheckRequirements ()
        !           854:        {
        !           855:                if (nCurrentOS == WIN_2000)
        !           856:                        throw ErrorException ("SYS_ENCRYPTION_UNSUPPORTED_ON_CURRENT_OS");
        !           857: 
        !           858:                if (IsNonInstallMode())
        !           859:                        throw ErrorException ("FEATURE_REQUIRES_INSTALLATION");
        !           860: 
        !           861:                SystemDriveConfiguration config = GetSystemDriveConfiguration ();
        !           862: 
        !           863:                if (config.SystemPartition.IsGPT)
        !           864:                        throw ErrorException ("GPT_BOOT_DRIVE_UNSUPPORTED");
        !           865: 
        !           866:                if (config.InitialUnallocatedSpace < TC_BOOT_LOADER_AREA_SIZE)
        !           867:                        throw ErrorException ("NO_SPACE_FOR_BOOT_LOADER");
        !           868: 
        !           869:                DISK_GEOMETRY geometry = GetDriveGeometry (config.DriveNumber);
        !           870: 
        !           871:                if (geometry.BytesPerSector != SECTOR_SIZE)
        !           872:                        throw ErrorException ("LARGE_SECTOR_UNSUPPORTED");
        !           873: 
        !           874:                if (geometry.SectorsPerTrack < 63)
        !           875:                        throw ErrorException ("UNSUPPORTED_BOOT_DRIVE_GEOMETRY");
        !           876: 
        !           877:                if (!config.SystemLoaderPresent)
        !           878:                        throw ErrorException ("WINDOWS_NOT_ON_BOOT_DRIVE_ERROR");
        !           879:        }
        !           880: 
        !           881: 
        !           882:        void BootEncryption::Deinstall ()
        !           883:        {
        !           884:                BootEncryptionStatus encStatus = GetStatus();
        !           885: 
        !           886:                if (encStatus.DriveEncrypted || encStatus.DriveMounted)
        !           887:                        throw ParameterIncorrect (SRC_POS);
        !           888: 
        !           889:                SystemDriveConfiguration config = GetSystemDriveConfiguration ();
        !           890: 
        !           891:                if (encStatus.VolumeHeaderPresent)
        !           892:                {
        !           893:                        // Verify CRC of header salt
        !           894:                        Device device (config.DevicePath, true);
        !           895:                        byte header[SECTOR_SIZE];
        !           896: 
        !           897:                        device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
        !           898:                        device.Read (header, sizeof (header));
        !           899: 
        !           900:                        if (encStatus.VolumeHeaderSaltCrc32 != GetCrc32 ((byte *) header, PKCS5_SALT_SIZE))
        !           901:                                throw ParameterIncorrect (SRC_POS);
        !           902:                }
        !           903: 
        !           904:                RegisterFilterDriver (false);
        !           905:                SetDriverServiceStartType (SERVICE_SYSTEM_START);
        !           906: 
        !           907:                try
        !           908:                {
        !           909:                        RestoreSystemLoader ();
        !           910:                }
        !           911:                catch (Exception &e)
        !           912:                {
        !           913:                        e.Show (ParentWindow);
        !           914:                        throw ErrorException ("SYS_LOADER_RESTORE_FAILED");
        !           915:                }
        !           916:        }
        !           917: 
        !           918: 
        !           919:        int BootEncryption::ChangePassword (Password *oldPassword, Password *newPassword, int pkcs5)
        !           920:        {
        !           921:                if (GetStatus().SetupInProgress)
        !           922:                        throw ParameterIncorrect (SRC_POS);
        !           923: 
        !           924:                SystemDriveConfiguration config = GetSystemDriveConfiguration ();
        !           925: 
        !           926:                char header[HEADER_SIZE];
        !           927:                Device device (config.DevicePath);
        !           928: 
        !           929:                // Only one algorithm is currently supported
        !           930:                if (pkcs5 != 0)
        !           931:                        throw ParameterIncorrect (SRC_POS);
        !           932: 
        !           933:                device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
        !           934:                device.Read ((byte *) header, sizeof (header));
        !           935: 
        !           936:                PCRYPTO_INFO cryptoInfo = NULL;
        !           937:                
        !           938:                int status = VolumeReadHeader (TRUE, header, oldPassword, &cryptoInfo, NULL);
        !           939:                finally_do_arg (PCRYPTO_INFO, cryptoInfo, { if (finally_arg) crypto_close (finally_arg); });
        !           940: 
        !           941:                if (status != 0)
        !           942:                {
        !           943:                        handleError (ParentWindow, status);
        !           944:                        return status;
        !           945:                }
        !           946: 
        !           947:                // Change the PKCS-5 PRF if requested by user
        !           948:                if (pkcs5 != 0)
        !           949:                        cryptoInfo->pkcs5 = pkcs5;
        !           950: 
        !           951:                throw_sys_if (Randinit () != 0);
        !           952: 
        !           953:                /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using 
        !           954:                techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
        !           955:                to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
        !           956:                times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
        !           957:                impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
        !           958:                valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
        !           959:                recommends. During each pass we will write a valid working header. Each pass will use the same master
        !           960:                key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
        !           961:                item that will be different for each pass will be the salt. This is sufficient to cause each "version"
        !           962:                of the header to differ substantially and in a random manner from the versions written during the
        !           963:                other passes. */
        !           964: 
        !           965:                bool headerUpdated = false;
        !           966:                int result = ERR_SUCCESS;
        !           967: 
        !           968:                try
        !           969:                {
        !           970:                        for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
        !           971:                        {
        !           972:                                PCRYPTO_INFO tmpCryptoInfo = NULL;
        !           973: 
        !           974:                                status = VolumeWriteHeader (TRUE,
        !           975:                                        header,
        !           976:                                        cryptoInfo->ea,
        !           977:                                        cryptoInfo->mode,
        !           978:                                        newPassword,
        !           979:                                        cryptoInfo->pkcs5,
        !           980:                                        (char *) cryptoInfo->master_keydata,
        !           981:                                        cryptoInfo->volume_creation_time,
        !           982:                                        &tmpCryptoInfo,
        !           983:                                        cryptoInfo->VolumeSize.Value,
        !           984:                                        cryptoInfo->hiddenVolumeSize,
        !           985:                                        cryptoInfo->EncryptedAreaStart.Value,
        !           986:                                        cryptoInfo->EncryptedAreaLength.Value,
        !           987:                                        wipePass < PRAND_DISK_WIPE_PASSES - 1);
        !           988: 
        !           989:                                if (tmpCryptoInfo)
        !           990:                                        crypto_close (tmpCryptoInfo);
        !           991: 
        !           992:                                if (status != 0)
        !           993:                                {
        !           994:                                        handleError (ParentWindow, status);
        !           995:                                        return status;
        !           996:                                }
        !           997: 
        !           998:                                device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
        !           999:                                device.Write ((byte *) header, sizeof (header));
        !          1000:                                headerUpdated = true;
        !          1001:                        }
        !          1002:                }
        !          1003:                catch (Exception &e)
        !          1004:                {
        !          1005:                        e.Show (ParentWindow);
        !          1006:                        result = ERR_OS_ERROR;
        !          1007:                }
        !          1008: 
        !          1009:                if (headerUpdated)
        !          1010:                {
        !          1011:                        ReopenBootVolumeHeaderRequest reopenRequest;
        !          1012:                        reopenRequest.VolumePassword = *newPassword;
        !          1013:                        finally_do_arg (ReopenBootVolumeHeaderRequest*, &reopenRequest, { burn (finally_arg, sizeof (*finally_arg)); });
        !          1014: 
        !          1015:                        CallDriver (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, &reopenRequest, sizeof (reopenRequest));
        !          1016:                }
        !          1017: 
        !          1018:                return result;
        !          1019:        }
        !          1020: 
        !          1021: 
        !          1022:        void BootEncryption::CheckEncryptionSetupResult ()
        !          1023:        {
        !          1024:                CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT);
        !          1025:        }
        !          1026: 
        !          1027: 
        !          1028:        void BootEncryption::Install ()
        !          1029:        {
        !          1030:                BootEncryptionStatus encStatus = GetStatus();
        !          1031:                if (encStatus.DriveMounted)
        !          1032:                        throw ParameterIncorrect (SRC_POS);
        !          1033: 
        !          1034:                try
        !          1035:                {
        !          1036:                        InstallBootLoader ();
        !          1037:                        InstallVolumeHeader ();
        !          1038: 
        !          1039:                        SetDriverServiceStartType (SERVICE_BOOT_START);
        !          1040: 
        !          1041:                        try
        !          1042:                        {
        !          1043:                                RegisterFilterDriver (false);
        !          1044:                        }
        !          1045:                        catch (...) { }
        !          1046: 
        !          1047:                        RegisterFilterDriver (true);
        !          1048:                }
        !          1049:                catch (Exception &)
        !          1050:                {
        !          1051:                        try
        !          1052:                        {
        !          1053:                                RestoreSystemLoader ();
        !          1054:                        }
        !          1055:                        catch (Exception &e)
        !          1056:                        {
        !          1057:                                e.Show (ParentWindow);
        !          1058:                        }
        !          1059: 
        !          1060:                        throw;
        !          1061:                }
        !          1062:        }
        !          1063: 
        !          1064: 
        !          1065:        void BootEncryption::PrepareInstallation (bool systemPartitionOnly, Password &password, int ea, int mode, int pkcs5, const string &rescueIsoImagePath)
        !          1066:        {
        !          1067:                if (!systemPartitionOnly && !RealSystemDriveSizeValid)
        !          1068:                        ProbeRealSystemDriveSize();
        !          1069: 
        !          1070:                BootEncryptionStatus encStatus = GetStatus();
        !          1071:                if (encStatus.DriveMounted)
        !          1072:                        throw ParameterIncorrect (SRC_POS);
        !          1073: 
        !          1074:                CheckRequirements ();
        !          1075: 
        !          1076:                SystemDriveConfiguration config = GetSystemDriveConfiguration();
        !          1077:                BackupSystemLoader ();
        !          1078: 
        !          1079:                uint64 volumeSize;
        !          1080:                uint64 encryptedAreaStart;
        !          1081: 
        !          1082:                if (systemPartitionOnly)
        !          1083:                {
        !          1084:                        volumeSize = config.SystemPartition.Info.PartitionLength.QuadPart;
        !          1085:                        encryptedAreaStart = config.SystemPartition.Info.StartingOffset.QuadPart;
        !          1086:                }
        !          1087:                else
        !          1088:                {
        !          1089:                        volumeSize = config.DrivePartition.Info.PartitionLength.QuadPart - TC_BOOT_LOADER_AREA_SIZE;
        !          1090:                        encryptedAreaStart = config.DrivePartition.Info.StartingOffset.QuadPart + TC_BOOT_LOADER_AREA_SIZE;
        !          1091:                }
        !          1092: 
        !          1093:                CreateVolumeHeader (volumeSize, encryptedAreaStart, &password, ea, mode, pkcs5);
        !          1094:                
        !          1095:                if (!rescueIsoImagePath.empty())
        !          1096:                        CreateRescueIsoImage (true, rescueIsoImagePath);
        !          1097:        }
        !          1098:        
        !          1099: 
        !          1100:        void BootEncryption::StartDecryption ()
        !          1101:        {
        !          1102:                BootEncryptionStatus encStatus = GetStatus();
        !          1103: 
        !          1104:                if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
        !          1105:                        throw ParameterIncorrect (SRC_POS);
        !          1106: 
        !          1107:                BootEncryptionSetupRequest request;
        !          1108:                ZeroMemory (&request, sizeof (request));
        !          1109:                
        !          1110:                request.SetupMode = SetupDecryption;
        !          1111: 
        !          1112:                CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
        !          1113:        }
        !          1114: 
        !          1115: 
        !          1116:        void BootEncryption::StartEncryption (WipeAlgorithmId wipeAlgorithm)
        !          1117:        {
        !          1118:                BootEncryptionStatus encStatus = GetStatus();
        !          1119: 
        !          1120:                if (!encStatus.DeviceFilterActive || !encStatus.DriveMounted || encStatus.SetupInProgress)
        !          1121:                        throw ParameterIncorrect (SRC_POS);
        !          1122: 
        !          1123:                BootEncryptionSetupRequest request;
        !          1124:                ZeroMemory (&request, sizeof (request));
        !          1125:                
        !          1126:                request.SetupMode = SetupEncryption;
        !          1127:                request.WipeAlgorithm = wipeAlgorithm;
        !          1128: 
        !          1129:                CallDriver (TC_IOCTL_BOOT_ENCRYPTION_SETUP, &request, sizeof (request), NULL, 0);
        !          1130:        }
        !          1131: 
        !          1132: 
        !          1133:        bool BootEncryption::RestartComputer (void)
        !          1134:        {
        !          1135:                TOKEN_PRIVILEGES tokenPrivil; 
        !          1136:                HANDLE hTkn; 
        !          1137: 
        !          1138:                if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hTkn))
        !          1139:                {
        !          1140:                        return false; 
        !          1141:                }
        !          1142: 
        !          1143:                LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &tokenPrivil.Privileges[0].Luid); 
        !          1144:                tokenPrivil.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
        !          1145:                tokenPrivil.PrivilegeCount = 1;    
        !          1146: 
        !          1147:                AdjustTokenPrivileges (hTkn, false, &tokenPrivil, 0, (PTOKEN_PRIVILEGES) NULL, 0); 
        !          1148:                if (GetLastError() != ERROR_SUCCESS) 
        !          1149:                        return false; 
        !          1150: 
        !          1151:                if (!ExitWindowsEx (EWX_REBOOT | EWX_FORCE, 
        !          1152:                        SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED)) 
        !          1153:                        return false; 
        !          1154: 
        !          1155:                return true;
        !          1156:        }
        !          1157: 
        !          1158:        
        !          1159: #endif // !SETUP
        !          1160: 
        !          1161: }

unix.superglobalmegacorp.com

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