VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/Format.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/Format.c')
-rw-r--r--src/Common/Format.c65
1 files changed, 54 insertions, 11 deletions
diff --git a/src/Common/Format.c b/src/Common/Format.c
index 6c3e2fff..7eff80e6 100644
--- a/src/Common/Format.c
+++ b/src/Common/Format.c
@@ -191,61 +191,61 @@ begin_format:
DWORD dwResult;
int nPass;
if (FakeDosNameForDevice (volParams->volumePath, dosDev, sizeof(dosDev), devName, sizeof(devName), FALSE) != 0)
return ERR_OS_ERROR;
if (IsDeviceMounted (devName))
{
if ((dev = DismountDrive (devName, volParams->volumePath)) == INVALID_HANDLE_VALUE)
{
Error ("FORMAT_CANT_DISMOUNT_FILESYS", hwndDlg);
nStatus = ERR_DONT_REPORT;
goto error;
}
/* Gain "raw" access to the partition (it contains a live filesystem and the filesystem driver
would otherwise prevent us from writing to hidden sectors). */
if (!DeviceIoControl (dev,
FSCTL_ALLOW_EXTENDED_DASD_IO,
NULL,
0,
NULL,
0,
&dwResult,
NULL))
{
bFailedRequiredDASD = TRUE;
}
}
- else if (IsOSAtLeast (WIN_VISTA) && driveLetter == -1)
+ else if (driveLetter == -1)
{
// Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition
// to which no drive letter has been assigned under the system. This problem can be worked
// around by assigning a drive letter to the partition temporarily.
wchar_t szDriveLetter[] = { L'A', L':', 0 };
wchar_t rootPath[] = { L'A', L':', L'\\', 0 };
wchar_t uniqVolName[MAX_PATH+1] = { 0 };
int tmpDriveLetter = -1;
BOOL bResult = FALSE;
tmpDriveLetter = GetFirstAvailableDrive ();
if (tmpDriveLetter != -1)
{
rootPath[0] += (wchar_t) tmpDriveLetter;
szDriveLetter[0] += (wchar_t) tmpDriveLetter;
if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath))
{
bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);
DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
szDriveLetter,
volParams->volumePath);
if (bResult
&& SetVolumeMountPoint (rootPath, uniqVolName))
{
// The drive letter can be removed now
@@ -318,137 +318,180 @@ begin_format:
char buf [2 * TC_MAX_VOLUME_SECTOR_SIZE];
DWORD bw;
// Perform pseudo "quick format" so that the filesystem driver does not prevent us from
// formatting hidden sectors
memset (buf, 0, sizeof (buf));
if (!WriteFile (dev, buf, sizeof (buf), &bw, NULL))
{
nStatus = ERR_OS_ERROR;
goto error;
}
FlushFileBuffers (dev);
CloseHandle (dev);
dev = INVALID_HANDLE_VALUE;
}
}
if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL))
{
Error ("FORMAT_CANT_DISMOUNT_FILESYS", hwndDlg);
nStatus = ERR_DONT_REPORT;
goto error;
}
}
else
{
/* File-hosted volume */
BOOL speedupFileCreation = FALSE;
+ BOOL delayedSpeedupFileCreation = FALSE;
// speedup for file creation only makes sens when using quick format for non hidden volumes
if (!volParams->hiddenVol && !bInstantRetryOtherFilesys && volParams->quickFormat && volParams->fastCreateFile)
{
// we set required privileges to speedup file creation before we create the file so that the file handle inherits the privileges
if (!SetPrivilege(SE_MANAGE_VOLUME_NAME, TRUE))
{
DWORD dwLastError = GetLastError();
- if (Silent || (MessageBoxW(hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_MANAGE_VOLUME"), lpszTitle, MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) == IDNO))
+ if (!IsAdmin () && IsUacSupported ())
+ {
+ speedupFileCreation = TRUE;
+ delayedSpeedupFileCreation = TRUE;
+ }
+ else if (Silent || (MessageBoxW(hwndDlg, GetString ("ADMIN_PRIVILEGES_WARN_MANAGE_VOLUME"), lpszTitle, MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) == IDNO))
{
SetLastError(dwLastError);
nStatus = ERR_OS_ERROR;
goto error;
}
}
else
{
speedupFileCreation = TRUE;
}
}
dev = CreateFile (volParams->volumePath, GENERIC_READ | GENERIC_WRITE,
(volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
if (dev == INVALID_HANDLE_VALUE)
{
nStatus = ERR_OS_ERROR;
goto error;
}
else if (volParams->hiddenVol && bPreserveTimestamp)
{
// ensure that Last Access and Last Write timestamps are not modified
ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
SetFileTime (dev, NULL, &ftLastAccessTime, NULL);
if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
bTimeStampValid = FALSE;
else
bTimeStampValid = TRUE;
}
DisableFileCompression (dev);
if (!volParams->hiddenVol && !bInstantRetryOtherFilesys)
{
LARGE_INTEGER volumeSize;
volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
if (volParams->sparseFileSwitch && volParams->quickFormat)
{
// Create as sparse file container
DWORD tmp;
if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL))
{
nStatus = ERR_OS_ERROR;
goto error;
}
}
- // Preallocate the file
- if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
- || !SetEndOfFile (dev))
+ if (!delayedSpeedupFileCreation)
{
- nStatus = ERR_OS_ERROR;
- goto error;
+ // Preallocate the file
+ if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
+ || !SetEndOfFile (dev))
+ {
+ nStatus = ERR_OS_ERROR;
+ goto error;
+ }
}
if (speedupFileCreation)
{
// accelerate file creation by telling Windows not to fill all file content with zeros
// this has security issues since it will put existing disk content into file container
// We use this mechanism only when switch /fastCreateFile specific and when quick format
// also specified and which is documented to have security issues.
- // we don't check returned status because failure is not issue for us
- if (!SetFileValidData (dev, volumeSize.QuadPart))
+ if (delayedSpeedupFileCreation)
+ {
+ // in case of delayed speedup we need to set the file size to a minimal value before performing the real preallocation through UAC
+ LARGE_INTEGER minimalSize;
+ DWORD dwOpStatus;
+ // 16K
+ minimalSize.QuadPart = 16 * 1024;
+ if (!SetFilePointerEx (dev, minimalSize, NULL, FILE_BEGIN)
+ || !SetEndOfFile (dev))
+ {
+ nStatus = ERR_OS_ERROR;
+ goto error;
+ }
+
+ FlushFileBuffers (dev);
+ CloseHandle (dev);
+ dev = INVALID_HANDLE_VALUE;
+
+ dwOpStatus = UacFastFileCreation (volParams->hwndDlg, volParams->volumePath, volumeSize.QuadPart);
+ if (dwOpStatus != 0)
+ {
+ SetLastError(dwOpStatus);
+ nStatus = ERR_OS_ERROR;
+ goto error;
+ }
+
+ // open again the file now that it was created
+ dev = CreateFile (volParams->volumePath, GENERIC_READ | GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (dev == INVALID_HANDLE_VALUE)
+ {
+ nStatus = ERR_OS_ERROR;
+ goto error;
+ }
+ }
+ else if (!SetFileValidData (dev, volumeSize.QuadPart))
{
nStatus = ERR_OS_ERROR;
goto error;
}
}
if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
{
nStatus = ERR_OS_ERROR;
goto error;
}
}
}
if (volParams->hwndDlg && volParams->bGuiMode) KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW);
/* Volume header */
// Hidden volume setup
if (volParams->hiddenVol)
{
LARGE_INTEGER headerOffset;
// Check hidden volume size
if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE)
{
nStatus = ERR_VOL_SIZE_WRONG;
goto error;
}
@@ -462,61 +505,61 @@ begin_format:
nStatus = ERR_OS_ERROR;
goto error;
}
}
else if (bInstantRetryOtherFilesys)
{
// The previous file system format failed and the user wants to try again with a different file system.
// The volume header had been written successfully so we need to seek to the byte after the header.
LARGE_INTEGER offset;
offset.QuadPart = TC_VOLUME_DATA_OFFSET;
if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
{
nStatus = ERR_OS_ERROR;
goto error;
}
}
if (!bInstantRetryOtherFilesys)
{
// Write the volume header
if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, header))
{
nStatus = ERR_OS_ERROR;
goto error;
}
// To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data
if (!volParams->bDevice && !volParams->hiddenVol)
{
- byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
+ uint8 buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
DWORD bytesWritten;
ZeroMemory (buf, sizeof (buf));
if (!WriteFile (dev, buf, sizeof (buf), &bytesWritten, NULL))
{
nStatus = ERR_OS_ERROR;
goto error;
}
if (bytesWritten != sizeof (buf))
{
nStatus = ERR_PARAMETER_INCORRECT;
goto error;
}
}
}
if (volParams->hiddenVol)
{
// Calculate data area position of hidden volume
cryptoInfo->hiddenVolumeOffset = dataOffset;
// Validate the offset
if (dataOffset % FormatSectorSize != 0)
{
nStatus = ERR_VOL_SIZE_WRONG;
goto error;
}
volParams->quickFormat = TRUE; // To entirely format a hidden volume would be redundant
@@ -1322,61 +1365,61 @@ BOOL WriteSector (void *dev, char *sector,
char *write_buf, int *write_buf_cnt,
unsigned __int64 *nSecNo, unsigned __int64 startSector, PCRYPTO_INFO cryptoInfo)
{
static __int32 updateTime = 0;
(*nSecNo)++;
memcpy (write_buf + *write_buf_cnt, sector, FormatSectorSize);
(*write_buf_cnt) += FormatSectorSize;
if (*write_buf_cnt == FormatWriteBufferSize && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo))
return FALSE;
if (GetTickCount () - updateTime > 25)
{
if (UpdateProgressBar ((*nSecNo - startSector) * FormatSectorSize))
return FALSE;
updateTime = GetTickCount ();
}
return TRUE;
}
static volatile BOOL WriteThreadRunning;
static volatile BOOL WriteThreadExitRequested;
static HANDLE WriteThreadHandle;
-static byte *WriteThreadBuffer;
+static uint8 *WriteThreadBuffer;
static HANDLE WriteBufferEmptyEvent;
static HANDLE WriteBufferFullEvent;
static volatile HANDLE WriteRequestHandle;
static volatile int WriteRequestSize;
static volatile DWORD WriteRequestResult;
static void __cdecl FormatWriteThreadProc (void *arg)
{
DWORD bytesWritten;
SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
while (!WriteThreadExitRequested)
{
if (WaitForSingleObject (WriteBufferFullEvent, INFINITE) == WAIT_FAILED)
{
handleWin32Error (NULL, SRC_POS);
break;
}
if (WriteThreadExitRequested)
break;
if (!WriteFile (WriteRequestHandle, WriteThreadBuffer, WriteRequestSize, &bytesWritten, NULL))
WriteRequestResult = GetLastError();
else
WriteRequestResult = ERROR_SUCCESS;