Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Crypto", "Crypto\Crypto.vcxproj", "{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Driver", "Driver\Driver.vcxproj", "{EF5EF444-18D0-40D7-8DFA-775EC4448602}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Format", "Format\Format.vcxproj", "{9DC1ABE2-D18B-48FB-81D2-8C50ADC57BCF}"
ProjectSection(ProjectDependencies) = postProject
{6316EE71-0210-4CA4-BCC7-CFB7A3C090FC} = {6316EE71-0210-4CA4-BCC7-CFB7A3C090FC}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mount", "Mount\Mount.vcxproj", "{E4C40F94-E7F9-4981-86E4-186B46F993F3}"
ProjectSection(ProjectDependencies) = postProject
{6316EE71-0210-4CA4-BCC7-CFB7A3C090FC} = {6316EE71-0210-4CA4-BCC7-CFB7A3C090FC}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Setup", "Setup\Setup.vcxproj", "{DF5F654D-BD44-4E31-B92E-B68074DC37A8}"
ProjectSection(ProjectDependencies) = postProject
{6316EE71-0210-4CA4-BCC7-CFB7A3C090FC} = {6316EE71-0210-4CA4-BCC7-CFB7A3C090FC}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Boot", "Boot\Windows\Boot.vcxproj", "{8B7F059F-E4C7-4E11-88F5-EE8B8433072E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExpandVolume", "ExpandVolume\ExpandVolume.vcxproj", "{9715FF1D-599B-4BBC-AD96-BEF6E08FF827}"
ProjectSection(ProjectDependencies) = postProject
{6316EE71-0210-4CA4-BCC7-CFB7A3C090FC} = {6316EE71-0210-4CA4-BCC7-CFB7A3C090FC}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zip", "Common\Zip.vcxproj", "{6316EE71-0210-4CA4-BCC7-CFB7A3C090FC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Portable", "Setup\Portable.vcxproj", "{60698D56-DB83-4D19-9C87-9DFB6A6F8C87}"
ProjectSection(ProjectDependencies) = postProject
{6316EE71-0210-4CA4-BCC7-CFB7A3C090FC} = {6316EE71-0210-4CA4-BCC7-CFB7A3C090FC}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
All Debug|Win32 = All Debug|Win32
All Debug|x64 = All Debug|x64
All|Win32 = All|Win32
All|x64 = All|x64
Boot Loader|Win32 = Boot Loader|Win32
Boot Loader|x64 = Boot Loader|x64
Boot|Win32 = Boot|Win32
Boot|x64 = Boot|x64
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Driver Debug|Win32 = Driver Debug|Win32
Driver Debug|x64 = Driver Debug|x64
Driver x64 Debug|Win32 = Driver x64 Debug|Win32
Driver x64 Debug|x64 = Driver x64 Debug|x64
Driver x64|Win32 = Driver x64|Win32
Driver x64|x64 = Driver x64|x64
Driver x86 Debug|Win32 = Driver x86 Debug|Win32
Driver x86 Debug|x64 = Driver x86 Debug|x64
Driver x86|Win32 = Driver x86|Win32
Driver x86|x64 = Driver x86|x64
Driver|Win32 = Driver|Win32
Driver|x64 = Driver|x64
Format Debug|Win32 = Format Debug|Win32
Format Debug|x64 = Format Debug|x64
Format|Win32 = Format|Win32
Format|x64 = Format|x64
Mount Debug|Win32 = Mount Debug|Win32
Mount Debug|x64 = Mount Debug|x64
Mount|Win32 = Mount|Win32
Mount|x64 = Mount|x64
Portable Debug|Win32 = Portable Debug|Win32
Portable Debug|x64 = Portable Debug|x64
Portable|Win32 = Portable|Win32
Portable|x64 = Portable|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
Setup Debug|Win32 = Setup Debug|Win32
Setup Debug|x64 = Setup Debug|x64
Setup|Win32 = Setup|Win32
Setup|x64 = Setup|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.All Debug|Win32.ActiveCfg = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.All Debug|Win32.Build.0 = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.All Debug|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.All Debug|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.All|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.All|Win32.Build.0 = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.All|x64.ActiveCfg = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.All|x64.Build.0 = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Boot Loader|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Boot Loader|x64.ActiveCfg = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Boot Loader|x64.Build.0 = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Boot|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Boot|x64.ActiveCfg = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Boot|x64.Build.0 = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Debug|Win32.ActiveCfg = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Debug|Win32.Build.0 = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Debug|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Debug|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver Debug|Win32.ActiveCfg = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver Debug|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver Debug|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x64 Debug|Win32.ActiveCfg = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x64 Debug|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x64 Debug|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x64|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x64|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x64|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x86 Debug|Win32.ActiveCfg = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x86 Debug|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x86 Debug|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x86|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x86|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver x86|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Driver|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Format Debug|Win32.ActiveCfg = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Format Debug|Win32.Build.0 = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Format Debug|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Format Debug|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Format|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Format|Win32.Build.0 = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Format|x64.ActiveCfg = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Format|x64.Build.0 = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Mount Debug|Win32.ActiveCfg = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Mount Debug|Win32.Build.0 = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Mount Debug|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Mount Debug|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Mount|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Mount|Win32.Build.0 = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Mount|x64.ActiveCfg = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Mount|x64.Build.0 = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Portable Debug|Win32.ActiveCfg = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Portable Debug|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Portable Debug|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Portable|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Portable|x64.ActiveCfg = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Portable|x64.Build.0 = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Release|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Release|Win32.Build.0 = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Release|x64.ActiveCfg = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Release|x64.Build.0 = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Setup Debug|Win32.ActiveCfg = Debug|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Setup Debug|x64.ActiveCfg = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Setup Debug|x64.Build.0 = Debug|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Setup|Win32.ActiveCfg = Release|Win32
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Setup|x64.ActiveCfg = Release|x64
{993245CF-6B70-47EE-91BB-39F8FC6DC0E7}.Setup|x64./*
Legal Notice: Some portions of the source code contained in this file were
derived from the source code of TrueCrypt 7.1a, which is
Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
governed by the TrueCrypt License 3.0, also from the source code of
Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
and which is governed by the 'License Agreement for Encryption for the Masses'
and also from the source code of extcv, which is Copyright (c) 2009-2010 Kih-Oskh
or Copyright (c) 2012-2013 Josef Schneider <josef@netpage.dk>
Modifications and additions to the original source code (contained in this file)
and all other portions of this file are Copyright (c) 2013-2016 IDRIX
and are governed by the Apache License 2.0 the full text of which is
contained in the file License.txt included in VeraCrypt binary and source
code distribution packages. */
#include "Tcdefs.h"
#include <time.h>
#include <math.h>
#include <dbt.h>
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
#include <windowsx.h>
#include <stdio.h>
#include "Apidrvr.h"
#include "Volumes.h"
#include "Crypto.h"
#include "Dlgcode.h"
#include "Language.h"
#include "Pkcs5.h"
#include "Random.h"
#include "Progress.h"
#include "InitDataArea.h"
#include "ExpandVolume.h"
#include "Resource.h"
#ifndef SRC_POS
#define SRC_POS (__FUNCTION__ ":" TC_TO_STRING(__LINE__))
#endif
#define DEBUG_EXPAND_VOLUME
#ifdef DEBUG_EXPAND_VOLUME
#define DebugAddProgressDlgStatus AddProgressDlgStatus
#else
#define DebugAddProgressDlgStatus(a,b)
#endif
HWND hCurPage; /* Handle to window with progress bar (used by FormatNoFs)*/
int nPbar; /* Control ID of progress bar (used by FormatNoFs) */
volatile BOOL bVolTransformThreadCancel = FALSE; /* TRUE if the user cancels/pauses volume expansion */
// internal functions
static int UpdateVolumeHeaderHostSize (wchar_t *lpszVolume, Password *pVolumePassword, HWND hwndDlg, uint64 newHostSize, uint64 *pDataSize, BOOL initFreeSpace);
static int FsctlExtendVolume(wchar_t * szVolume, LONGLONG nTotalSectors );
/*
MountVolTemp
Mounts a trucrypt volume temporarily (using any free drive number)
Parameters:
hwndDlg : HWND
[in] handle to parent window
volumePath : char *
[in] Pointer to a string that contains the volume path
driveNo : int *
[out] returns the drive number (0='A',...)
password : Password *
[in] Pointer to the volume password
Return value:
int with Truecrypt error code (ERR_SUCCESS on success)
*/
int MountVolTemp (HWND hwndDlg, wchar_t *volumePath, int *driveNo, Password *password, int pkcs5, int pim)
{
MountOptions mountOptions;
ZeroMemory (&mountOptions, sizeof (mountOptions));
*driveNo = GetLastAvailableDrive ();
if (*driveNo == -1)
{
*driveNo = -2;
return ERR_NO_FREE_DRIVES;
}
mountOptions.ReadOnly = FALSE;
mountOptions.Removable = ConfigReadInt ("MountVolumesRemovable", FALSE);
mountOptions.ProtectHiddenVolume = FALSE;
mountOptions.PreserveTimestamp = bPreserveTimestamp;
mountOptions.PartitionInInactiveSysEncScope = FALSE;
mountOptions.UseBackupHeader = FALSE;
if (MountVolume (hwndDlg, *driveNo, volumePath, password, pkcs5, pim, FALSE, FALSE, FALSE, TRUE, &mountOptions, FALSE, FALSE) < 1)
{
*driveNo = -3;
return ERR_VOL_MOUNT_FAILED;
}
return 0;
}
/*
FsctlExtendVolume
Expands a volume by sending the FSCTL_EXTEND_VOLUME ioctl command to the volume
Parameters:
szVolume : char *
[in] Pointer to a string that contains the volume GUID
nTotalSectors : LONGLONG
[in] specifies the total size of the volume, in sectors
Return value:
int with Truecrypt error code (ERR_SUCCESS on success)
Remarks: only supported by NTFS and RAW file systems
*/
static int FsctlExtendVolume(wchar_t * szVolume, LONGLONG nTotalSectors )
{
HANDLE hDevice; // handle to the volume to be extended
BOOL bResult; // results flag
DWORD nbytes; // discard results
DWORD dwError;
int nStatus = ERR_OS_ERROR;
hDevice = CreateFile(szVolume,
GENERIC_READ,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hDevice == INVALID_HANDLE_VALUE)
goto error;
bResult = DeviceIoControl(hDevice,
FSCTL_EXTEND_VOLUME,
&nTotalSectors, sizeof(nTotalSectors),
NULL, 0,
&nbytes,
(LPOVERLAPPED) NULL);
if (bResult)
nStatus = ERR_SUCCESS;
error:
dwError = GetLastError ();
if (hDevice != INVALID_HANDLE_VALUE)
CloseHandle (hDevice);
SetLastError (dwError);
return nStatus;
}
BOOL GetFileSystemType(const wchar_t *szFileName, enum EV_FileSystem *pFS)
{
wchar_t szFS[256];
wchar_t root[MAX_PATH];
*pFS = EV_FS_TYPE_RAW;
if (!GetVolumePathName (szFileName, root, ARRAYSIZE (root)))
return FALSE;
if ( GetVolumeInformation (root, NULL, 0, NULL, NULL, NULL, szFS, ARRAYSIZE(szFS)) )
{
if (!wcsncmp (szFS, L"NTFS", 4))
*pFS = EV_FS_TYPE_NTFS;
else if (!wcsncmp (szFS, L"FAT", 3)) // FAT16, FAT32
*pFS = EV_FS_TYPE_FAT;
else if (!_wcsnicmp (szFS, L"exFAT", 5)) // exFAT
*pFS = EV_FS_TYPE_EXFAT;
else
*pFS = EV_FS_TYPE_RAW;
}
else
{
return FALSE;
}
return TRUE;
}
/*
QueryVolumeInfo
Retrieves the free disk space and file size limit on the truecrypt volume host
Parameters:
hwndDlg : HWND
[in] handle to parent window
lpszVolume : char *
[in] Pointer to a string that contains the volume path
pHostSizeFree : uint64 *
[out] returns the free space available on the host (always zero for devices)
pSizeLimitFS : uint64 *
[out] returns the file size limit of the host file system
Return value:
int with TrueCrypt error code (ERR_SUCCESS on success)
*/
int QueryVolumeInfo (HWND hwndDlg, const wchar_t *lpszVolume, uint64 * pHostSizeFree, uint64 * pSizeLimitFS )
{
int nStatus = ERR_OS_ERROR;
wchar_t szDiskFile[TC_MAX_PATH], root[MAX_PATH];
BOOL bDevice;
enum EV_FileSystem fs;
*pSizeLimitFS = (uint64)-1;
CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), lpszVolume, &bDevice);
if (bDevice)
{
*pHostSizeFree=0;
return ERR_SUCCESS;
}
if (!GetVolumePathName (szDiskFile, root, ARRAYSIZE (root)))
{
nStatus = ERR_OS_ERROR;
goto error;
}
if( ! GetDiskFreeSpaceEx (root,(PULARGE_INTEGER)pHostSizeFree,NULL,NULL) )
{
nStatus = ERR_OS_ERROR;
goto error;
}
if ( ! GetFileSystemType(root,&fs) )
{
nStatus = ERR_OS_ERROR;
goto error;
}
/* file size limits
FAT16 / FAT32 : 4 GB minus 1 byte (2^32 bytes minus 1 byte)
exFAT: 128 PiB − 1 byte
NTFS : Architecturally : 16 exabytes minus 1 KB (26^4 bytes minus 1 KB)
Implementation (Windows Server 2008): 16 terabytes minus 64 KB (2^44 bytes minus 64 KB)
*/
switch (fs)
{
case EV_FS_TYPE_NTFS:
*pSizeLimitFS = 16 * BYTES_PER_TB - 64 * BYTES_PER_KB;
break;
case EV_FS_TYPE_EXFAT:
*pSizeLimitFS = 128 * BYTES_PER_PB - 1;
break;
case EV_FS_TYPE_FAT:
*pSizeLimitFS = 4 * BYTES_PER_GB - 1;
break;
default:
*pSizeLimitFS = (uint64)-1;
}
nStatus = ERR_SUCCESS;
error:
return nStatus;
}
BOOL GetNtfsNumberOfSectors(wchar_t * rootPath, uint64 * pNumberOfSectors, DWORD *pBytesPerSector)
{
HANDLE hDevice;
BOOL bResult;
DWORD nbytes, dwError;
size_t len;
NTFS_VOLUME_DATA_BUFFER ntfsvdb;
wchar_t szVolumeGUID[128];
// get volume name
if (!GetVolumeNameForVolumeMountPoint(rootPath,szVolumeGUID,ARRAYSIZE(szVolumeGUID)))
{
return FALSE;
}
// strip trailing backslash from volume GUID (otherwise it means root dir)
len = wcslen(szVolumeGUID);
if (len>0)
--len;
if (szVolumeGUID[len]==L'\\')
szVolumeGUID[len]=0;
hDevice = CreateFile(szVolumeGUID,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hDevice == INVALID_HANDLE_VALUE)
return (FALSE);
bResult = DeviceIoControl(hDevice,
FSCTL_GET_NTFS_VOLUME_DATA,
NULL, 0,
&ntfsvdb, sizeof(ntfsvdb),
&nbytes,
(LPOVERLAPPED) NULL);
if (bResult)
{
if (pNumberOfSectors)
*pNumberOfSectors = ntfsvdb.NumberSectors.QuadPart;
if (pBytesPerSector)
*pBytesPerSector = ntfsvdb.BytesPerSector;
}
dwError = GetLastError ();
CloseHandle(hDevice);
SetLastError (dwError);
return (bResult);
}
uint64 GetVolumeDataAreaSize (uint64 volumeSize, BOOL legacyVolume)
{
uint64 reservedSize;
if (legacyVolume)
reservedSize = TC_VOLUME_HEADER_SIZE_LEGACY;
else
reservedSize = TC_TOTAL_VOLUME_HEADERS_SIZE;
if (volumeSize < reservedSize)
return 0;
return volumeSize - reservedSize;
}
uint64 GetVolumeSizeByDataAreaSize (uint64 dataAreaSize, BOOL legacyVolume)
{
uint64 reservedSize;
if (legacyVolume)
reservedSize = TC_VOLUME_HEADER_SIZE_LEGACY;
else
reservedSize = TC_TOTAL_VOLUME_HEADERS_SIZE;
return dataAreaSize + reservedSize;
}
int ExtendFileSystem (HWND hwndDlg , wchar_t *lpszVolume, Password *pVolumePassword, int VolumePkcs5, int VolumePim, uint64 newDataAreaSize)
{
wchar_t szVolumeGUID[128];
int driveNo = -1;
wchar_t rootPath[] = L"A:\\";
enum EV_FileSystem fs;
DWORD dwError;
int nStatus = ERR_SUCCESS;
DWORD BytesPerSector;
// mount and resize file system
DebugAddProgressDlgStatus (hwndDlg, L"Mounting volume ...\r\n");
nStatus=MountVolTemp(hwndDlg, lpszVolume, &driveNo, pVolumePassword, VolumePkcs5, VolumePim);
if (nStatus!=ERR_SUCCESS)
{
driveNo = -1;
goto error;
}
rootPath[0] += driveNo;
if ( !GetFileSystemType(rootPath,&fs) )
{
dwError = GetLastError();
if (dwError == ERROR_UNRECOGNIZED_VOLUME)
{
// raw volume with unrecognized file system -> return with no error
nStatus = ERR_SUCCESS;
goto error;
}
nStatus = ERR_OS_ERROR;
goto error;
}
if (fs != EV_FS_TYPE_RAW && fs != EV_FS_TYPE_NTFS )
{
// FsctlExtendVolume only supports NTFS and RAW -> return with no error
nStatus = ERR_SUCCESS;
goto error;
}
// Get volume GUID
if (!GetVolumeNameForVolumeMountPoint(rootPath,szVolumeGUID,ARRAYSIZE(szVolumeGUID)))
{
nStatus = ERR_OS_ERROR;
goto error;
}
else
{
// strip trailing backslash from volume GUID (otherwise it means root dir)
size_t len = wcslen(szVolumeGUID);
if (len>0) --len;
if (szVolumeGUID[len]==L'\\') szVolumeGUID[len]=0;
}
// Get Sector Size
if ( !GetNtfsNumberOfSectors(rootPath, NULL, &BytesPerSector) )
{
nStatus = ERR_OS_ERROR;
goto error;
}
DebugAddProgressDlgStatus (hwndDlg, L"Extending file system ...\r\n");
// extend volume
nStatus = FsctlExtendVolume(szVolumeGUID, newDataAreaSize/BytesPerSector );
error:
dwError = GetLastError();
if (driveNo>=0)
{
DebugAddProgressDlgStatus (hwndDlg, L"Unmounting volume ...\r\n");
UnmountVolume (hwndDlg, driveNo, TRUE);
}
SetLastError (dwError);
return nStatus;
}
/*
ExpandVolume
Sets the volume size in the volume header (and backup header) to a larger value,
and resizes the filesystem within the volume (only NTFS supported)
Parameters:
hwndDlg : HWND
[in] handle to progress dialog
lpszVolume : char *
[in] Pointer to a string that contains the path to the truecrypt volume
pVolumePassword : Password *
[in] Pointer to the volume password
newHostSize : uint64
[in] new value of the volume host size (can be zero for devices,
which means the volume should use all space of the host device)
initFreeSpace : BOOL
[in] if true, the new volume space will be initalized with random data
Return value:
int with Truecrypt error code (ERR_SUCCESS on success)
Remarks: a lot of code is from TrueCrypt 'Common\Password.c' :: ChangePwd()
*/
static int ExpandVolume (HWND hwndDlg, wchar_t *lpszVolume, Password *pVolumePassword, int VolumePkcs5, int VolumePim, uint64 newHostSize, BOOL initFreeSpace)
{
int nDosLinkCreated = 1, nStatus = ERR_OS_ERROR;
wchar_t szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH];
wchar_t szDosDevice[TC_MAX_PATH];
char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
PCRYPTO_INFO cryptoInfo = NULL, ci = NULL;
void *dev = INVALID_HANDLE_VALUE;
DWORD dwError;
BOOL bDevice;
uint64 hostSize=0, newDataAreaSize, currentVolSize;
DWORD HostSectorSize;
FILETIME ftCreationTime;
FILETIME ftLastWriteTime;
FILETIME ftLastAccessTime;
BOOL bTimeStampValid = FALSE;
LARGE_INTEGER headerOffset;
BOOL backupHeader;
byte *wipeBuffer = NULL;
uint32 workChunkSize = TC_VOLUME_HEADER_GROUP_SIZE;
if (pVolumePassword->Length == 0) return -1;
WaitCursor ();
CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), lpszVolume, &bDevice);
if (bDevice == FALSE)
{
wcscpy (szCFDevice, szDiskFile);
}
else
{
nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, sizeof(szDosDevice), szCFDevice, sizeof(szCFDevice), FALSE);
if (nDosLinkCreated != 0) // note: nStatus == ERR_OS_ERROR
goto error;
}
dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (dev == INVALID_HANDLE_VALUE)
goto error;
if (bDevice)
{
/* This is necessary to determine the hidden volume header offset */
if (dev == INVALID_HANDLE_VALUE)
{
goto error;
}
else
{
PARTITION_INFORMATION diskInfo;
DWORD dwResult;
BOOL bResult;
bResult = GetPartitionInfo (lpszVolume, &diskInfo);
if (bResult)
{
hostSize = diskInfo.PartitionLength.QuadPart;
HostSectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME; //TO DO: get the real host disk sector size
}
else
{
DISK_GEOMETRY driveInfo;
bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
&driveInfo, sizeof (driveInfo), &dwResult, NULL);
if (!bResult)
goto error;
hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector *
driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder;
HostSectorSize = driveInfo.BytesPerSector;
}
if (hostSize == 0)
{
nStatus = ERR_VOL_SIZE_WRONG;
goto error;
}
}
}
else
{
LARGE_INTEGER fileSize;
if (!GetFileSizeEx (dev, &fileSize))
{
nStatus = ERR_OS_ERROR;
goto error;
}
hostSize = fileSize.QuadPart;
HostSectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME; //TO DO: get the real host disk sector size
}
if (Randinit ())
{
if (CryptoAPILastError == ERROR_SUCCESS)
nStatus = ERR_RAND_INIT_FAILED;
else
nStatus = ERR_CAPI_INIT_FAILED;
goto error;
}
if (!bDevice && bPreserveTimestamp)
{
/* Remember the container modification/creation date and time, (used to reset file date and time of
file-hosted volumes after password change (or attempt to), in order to preserve plausible deniability
of hidden volumes (last password change time is stored in the volume header). */
if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
{
bTimeStampValid = FALSE;
MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_PW"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
}
else
bTimeStampValid = TRUE;
}
// Seek the volume header
headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
{
nStatus = ERR_OS_ERROR;
goto error;
}
/* Read in volume header */
nStatus = _lread ((HFILE) dev, buffer, sizeof (buffer));
if (nStatus != sizeof (buffer))
{
// Windows may report EOF when reading sectors from the last cluster of a device formatted as NTFS
memset (buffer, 0, sizeof (buffer));
}
/* Try to decrypt the header */
nStatus = ReadVolumeHeader (FALSE, buffer, pVolumePassword, VolumePkcs5, VolumePim, FALSE, &cryptoInfo, NULL);
if (nStatus == ERR_CIPHER_INIT_WEAK_KEY)
nStatus = 0; // We can ignore this error here
if (nStatus != 0)
{
cryptoInfo = NULL;
goto error;
}
if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
{
nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;
goto error;
}
if (bDevice && newHostSize == 0)
{
// this means we shall take all host space as new volume size
newHostSize = hostSize;
}
if ( newHostSize % cryptoInfo->SectorSize != 0 || newHostSize > TC_MAX_VOLUME_SIZE || (bDevice && newHostSize > hostSize) )
{
// 1. must be multiple of sector size
// 2. truecrypt volume size limit
// 3. for devices volume size can't be larger than host size
cryptoInfo = NULL;
nStatus = ERR_PARAMETER_INCORRECT;
goto error;
}
newDataAreaSize = GetVolumeDataAreaSize (newHostSize, cryptoInfo->LegacyVolume);
if (cryptoInfo->LegacyVolume)
{
if (bDevice)
{
if (initFreeSpace)
{
// unsupported
cryptoInfo = NULL;
nStatus = ERR_PARAMETER_INCORRECT;
goto error;
}
else
{
// note: dummy value (only used for parameter checks)
cryptoInfo->VolumeSize.Value = newDataAreaSize - TC_MINVAL_FS_EXPAND;
}
}
else
{
cryptoInfo->VolumeSize.Value = GetVolumeDataAreaSize (hostSize, TRUE);
}
}
currentVolSize = GetVolumeSizeByDataAreaSize (cryptoInfo->VolumeSize.Value, cryptoInfo->LegacyVolume);
if ( newDataAreaSize < cryptoInfo->VolumeSize.Value + TC_MINVAL_FS_EXPAND )
{
// shrinking a volume or enlarging by less then TC_MINVAL_FS_EXPAND is not allowed
cryptoInfo = NULL;
nStatus = ERR_PARAMETER_INCORRECT;
goto error;
}
InitProgressBar ( newHostSize, currentVolSize, FALSE, FALSE, FALSE, TRUE);
if (bVolTransformThreadCancel)
{
SetLastError(0);
nStatus = ERR_USER_ABORT;
goto error;
}
if (!bDevice) {
LARGE_INTEGER liNewSize;
liNewSize.QuadPart=(LONGLONG)newHostSize;
// Preallocate the file
if (!SetFilePointerEx (dev, liNewSize, NULL, FILE_BEGIN)
|| !SetEndOfFile (dev)
|| SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
{
nStatus = ERR_OS_ERROR;
goto error;
}
}
if (initFreeSpace)
{
uint64 startSector;
int64 num_sectors;
// fill new space with random data
startSector = currentVolSize/HostSectorSize ;
num_sectors = (newHostSize/HostSectorSize) - startSector;
if (bDevice && !StartFormatWriteThread())
{
nStatus = ERR_OS_ERROR;
goto error;
}
DebugAddProgressDlgStatus(hwndDlg, L"Writing random data to new space ...\r\n");
SetFormatSectorSize(HostSectorSize);
nStatus = FormatNoFs (hwndDlg, startSector, num_sectors, dev, cryptoInfo, FALSE);
dwError = GetLastError();
StopFormatWriteThread();
SetLastError (dwError);
}
else
{
UpdateProgressBar(newHostSize);
}
if (nStatus != ERR_SUCCESS)
{
dwError = GetLastError();
DebugAddProgressDlgStatus(hwndDlg, L"Error: failed to write random data ...\r\n");
if ( !bDevice ) {
// restore original size of the container file
LARGE_INTEGER liOldSize;
liOldSize.QuadPart=(LONGLONG)hostSize;
if (!SetFilePointerEx (dev, liOldSize, NULL, FILE_BEGIN) || !SetEndOfFile (dev))
{
DebugAddProgressDlgStatus(hwndDlg, L"Warning: failed to restore original size of the container file\r\n");
}
}
SetLastError (dwError);
goto error;
}
RandSetHashFunction (cryptoInfo->pkcs5);
// Re-encrypt the volume header forn non-legacy volumes: backup header first
backupHeader = TRUE;
headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET + newHostSize - TC_VOLUME_HEADER_GROUP_SIZE;
/* note: updating the header is not neccessary for legay volumes */
while ( !cryptoInfo->LegacyVolume )
{
if (backupHeader)
DebugAddProgressDlgStatus(hwndDlg, L"Writing re-encrypted backup header ...\r\n");
else
DebugAddProgressDlgStatus(hwndDlg, L"Writing re-encrypted primary header ...\r\n");
// Prepare new volume header
nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
buffer,
cryptoInfo->ea,
cryptoInfo->mode,
pVolumePassword,
cryptoInfo->pkcs5,
VolumePim,
(char*)(cryptoInfo->master_keydata),
&ci,
newDataAreaSize,
0, // hiddenVolumeSize
cryptoInfo->EncryptedAreaStart.Value,
newDataAreaSize,
cryptoInfo->RequiredProgramVersion,
cryptoInfo->HeaderFlags,
cryptoInfo->SectorSize,
FALSE ); // use slow poll
if (ci != NULL)
crypto_close (ci);
if (nStatus != 0)
goto error;
if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
{
nStatus = ERR_OS_ERROR;
goto error;
}
if (!WriteEffectiveVolumeHeader (bDevice, dev, buffer))
{
nStatus = ERR_OS_ERROR;
goto error;
}
if ( ( backupHeader && !initFreeSpace )
|| ( bDevice
&& !cryptoInfo->LegacyVolume
&& !cryptoInfo->hiddenVolume
&& cryptoInfo->HeaderVersion == 4 // BUG in TrueCrypt: doing this only for v4 make no sense
&& (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0
&& (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0 )
)
{
//DebugAddProgressDlgStatus(hwndDlg, L"WriteRandomDataToReservedHeaderAreas() ...\r\n");
PCRYPTO_INFO dummyInfo = NULL;
LARGE_INTEGER hiddenOffset;
nStatus = WriteRandomDataToReservedHeaderAreas (hwndDlg, dev, cryptoInfo, newDataAreaSize, !backupHeader, backupHeader);
if (nStatus != ERR_SUCCESS)
goto error;
// write fake hidden volume header to protect against attacks that use statistical entropy
// analysis to detect presence of hidden volumes
hiddenOffset.QuadPart = headerOffset.QuadPart + TC_HIDDEN_VOLUME_HEADER_OFFSET;
nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
buffer,
cryptoInfo->ea,
cryptoInfo->mode,
NULL,
0,
0,
NULL,
&dummyInfo,
newDataAreaSize,
newDataAreaSize, // hiddenVolumeSize
cryptoInfo->EncryptedAreaStart.Value,
newDataAreaSize,
cryptoInfo->RequiredProgramVersion,
cryptoInfo->HeaderFlags,
cryptoInfo->SectorSize,
FALSE ); // use slow poll
if (nStatus != ERR_SUCCESS)
goto error;
crypto_close (dummyInfo);
if (!SetFilePointerEx ((HANDLE) dev, hiddenOffset, NULL, FILE_BEGIN))
{
nStatus = ERR_OS_ERROR;
goto error;
}
if (!WriteEffectiveVolumeHeader (bDevice, dev, buffer))
{
nStatus = ERR_OS_ERROR;
goto error;
}
}
FlushFileBuffers (dev);
if (!backupHeader)
break;
backupHeader = FALSE;
headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET; // offset for main header
}
/* header successfully updated */
nStatus = ERR_SUCCESS;
if (bVolTransformThreadCancel)
{
nStatus = ERR_USER_ABORT;
goto error;
}
/* wipe old backup header */
if ( !cryptoInfo->LegacyVolume )
{
byte wipeRandChars [TC_WIPE_RAND_CHAR_COUNT];
byte wipeRandCharsUpdate [TC_WIPE_RAND_CHAR_COUNT];
byte wipePass;
UINT64_STRUCT unitNo;
LARGE_INTEGER offset;
WipeAlgorithmId wipeAlgorithm = TC_WIPE_35_GUTMANN;
if ( !RandgetBytes (hwndDlg, wipeRandChars, TC_WIPE_RAND_CHAR_COUNT, TRUE)
|| !RandgetBytes (hwndDlg, wipeRandCharsUpdate, TC_WIPE_RAND_CHAR_COUNT, TRUE)
)
{
nStatus = ERR_OS_ERROR;
goto error;
}
DebugAddProgressDlgStatus(hwndDlg, L"Wiping old backup header ...\r\n");
wipeBuffer = (byte *) TCalloc (workChunkSize);
if (!wipeBuffer)
{
nStatus = ERR_OUTOFMEMORY;
goto error;
}
offset.QuadPart = currentVolSize - TC_VOLUME_HEADER_GROUP_SIZE;
unitNo.Value = offset.QuadPart;
for (wipePass = 1; wipePass <= GetWipePassCount (wipeAlgorithm); ++wipePass)
{
if (!WipeBuffer (wipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, workChunkSize))
{
ULONG i;
for (i = 0; i < workChunkSize; ++i)
{
wipeBuffer[i] = wipePass;
}
EncryptDataUnits (wipeBuffer, &unitNo, workChunkSize / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo);
memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate));
}
if ( !SetFilePointerEx (dev, offset, NULL, FILE_BEGIN)
|| _lwrite ((HFILE)dev, (LPCSTR)wipeBuffer, workChunkSize) == HFILE_ERROR
)
{
// Write error
DebugAddProgressDlgStatus(hwndDlg, L"Warning: Failed to wipe old backup header\r\n");
MessageBoxW (hwndDlg, L"WARNING: Failed to wipe old backup header!\n\nIt may be possible to use the current volume password to decrypt the old backup header even after a future password change.\n", lpszTitle, MB_OK | MB_ICONEXCLAMATION);
if (wipePass == 1)
continue; // retry once
// non-critical error - it's better to continue
nStatus = ERR_SUCCESS;
goto error;
}
FlushFileBuffers(dev);
// we don't check FlushFileBuffers() return code, because it fails for devices
// (same implementation in password.c - a bug or not ???)
}
burn (wipeRandChars, TC_WIPE_RAND_CHAR_COUNT);
burn (wipeRandCharsUpdate, TC_WIPE_RAND_CHAR_COUNT);
}
error:
dwError = GetLastError ();
if (wipeBuffer)
{
burn (wipeBuffer, workChunkSize);
TCfree (wipeBuffer);
wipeBuffer = NULL;
}
burn (buffer, sizeof (buffer));
if (cryptoInfo != NULL)
crypto_close (cryptoInfo);
if (bTimeStampValid)
{
// Restore the container timestamp (to preserve plausible deniability of possible hidden volume).
if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
}
if (dev != INVALID_HANDLE_VALUE)
CloseHandle ((HANDLE) dev);
if (nDosLinkCreated == 0)
RemoveFakeDosName (szDiskFile, szDosDevice);
RandStop (FALSE);
if (bVolTransformThreadCancel)
nStatus = ERR_USER_ABORT;
SetLastError (dwError);
if (nStatus == ERR_SUCCESS)
{
nStatus = ExtendFileSystem (hwndDlg, lpszVolume, pVolumePassword, VolumePkcs5, VolumePim, newDataAreaSize);
}
return nStatus;
}
void __cdecl volTransformThreadFunction (void *pExpandDlgParam)
{
int nStatus;
EXPAND_VOL_THREAD_PARAMS *pParam=(EXPAND_VOL_THREAD_PARAMS *)pExpandDlgParam;
HWND hwndDlg = (HWND) pParam->hwndDlg;
nStatus = ExpandVolume (hwndDlg, (wchar_t*)pParam->szVolumeName, pParam->pVolumePassword,
pParam->VolumePkcs5, pParam->VolumePim, pParam->newSize, pParam->bInitFreeSpace );
if (nStatus!=ERR_SUCCESS && nStatus!=ERR_USER_ABORT)
handleError (hwndDlg, nStatus, SRC_POS);
bVolTransformThreadCancel = FALSE;
PostMessage (hwndDlg, TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED, 0, nStatus);
_endthread ();
}