mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 19:08:26 -06:00
Windows: enhancements to the mechanism preserving file timestamps, especially for keyfiles.
This commit is contained in:
@@ -11238,10 +11238,8 @@ int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password
|
|||||||
else
|
else
|
||||||
StringCbCopyW (szCFDevice, sizeof(szCFDevice), szDiskFile);
|
StringCbCopyW (szCFDevice, sizeof(szCFDevice), szDiskFile);
|
||||||
|
|
||||||
if (preserveTimestamps)
|
|
||||||
write = TRUE;
|
|
||||||
|
|
||||||
context->HostFileHandle = CreateFile (szCFDevice, GENERIC_READ | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
context->HostFileHandle = CreateFile (szCFDevice, GENERIC_READ | (write ? GENERIC_WRITE : (!context->IsDevice && preserveTimestamps? FILE_WRITE_ATTRIBUTES : 0)), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
|
||||||
if (context->HostFileHandle == INVALID_HANDLE_VALUE)
|
if (context->HostFileHandle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
@@ -11263,6 +11261,13 @@ int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password
|
|||||||
// Remember the container modification/creation date and time
|
// Remember the container modification/creation date and time
|
||||||
if (!context->IsDevice && preserveTimestamps)
|
if (!context->IsDevice && preserveTimestamps)
|
||||||
{
|
{
|
||||||
|
// ensure that Last Access and Last Write timestamps are not modified
|
||||||
|
FILETIME ftLastAccessTime;
|
||||||
|
ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
|
||||||
|
ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
SetFileTime (context->HostFileHandle, NULL, &ftLastAccessTime, NULL);
|
||||||
|
|
||||||
if (GetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime) == 0)
|
if (GetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime) == 0)
|
||||||
context->TimestampsValid = FALSE;
|
context->TimestampsValid = FALSE;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -350,6 +350,19 @@ begin_format:
|
|||||||
nStatus = ERR_OS_ERROR;
|
nStatus = ERR_OS_ERROR;
|
||||||
goto 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);
|
DisableFileCompression (dev);
|
||||||
|
|
||||||
@@ -380,14 +393,6 @@ begin_format:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp)
|
|
||||||
{
|
|
||||||
if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
|
|
||||||
bTimeStampValid = FALSE;
|
|
||||||
else
|
|
||||||
bTimeStampValid = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (volParams->hwndDlg && volParams->bGuiMode) KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW);
|
if (volParams->hwndDlg && volParams->bGuiMode) KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW);
|
||||||
|
|
||||||
/* Volume header */
|
/* Volume header */
|
||||||
|
|||||||
@@ -149,50 +149,41 @@ void KeyFileCloneAll (KeyFile *firstKeyFile, KeyFile **outputKeyFile)
|
|||||||
|
|
||||||
static BOOL KeyFileProcess (unsigned __int8 *keyPool, unsigned __int32 keyPoolSize, KeyFile *keyFile)
|
static BOOL KeyFileProcess (unsigned __int8 *keyPool, unsigned __int32 keyPoolSize, KeyFile *keyFile)
|
||||||
{
|
{
|
||||||
FILE *f;
|
|
||||||
unsigned __int8 buffer[64 * 1024];
|
unsigned __int8 buffer[64 * 1024];
|
||||||
unsigned __int32 crc = 0xffffffff;
|
unsigned __int32 crc = 0xffffffff;
|
||||||
unsigned __int32 writePos = 0;
|
unsigned __int32 writePos = 0;
|
||||||
size_t bytesRead, totalRead = 0;
|
DWORD bytesRead, totalRead = 0;
|
||||||
int status = TRUE;
|
int status = TRUE;
|
||||||
|
|
||||||
HANDLE src;
|
HANDLE src;
|
||||||
FILETIME ftCreationTime;
|
BOOL bReadStatus = FALSE;
|
||||||
FILETIME ftLastWriteTime;
|
|
||||||
FILETIME ftLastAccessTime;
|
|
||||||
|
|
||||||
BOOL bTimeStampValid = FALSE;
|
|
||||||
|
|
||||||
/* Remember the last access time of the keyfile. It will be preserved in order to prevent
|
|
||||||
an adversary from determining which file may have been used as keyfile. */
|
|
||||||
src = CreateFile (keyFile->FileName,
|
src = CreateFile (keyFile->FileName,
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
GENERIC_READ | FILE_WRITE_ATTRIBUTES,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
|
||||||
if (src != INVALID_HANDLE_VALUE)
|
if (src != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
if (GetFileTime ((HANDLE) src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
|
/* We tell Windows not to update the Last Access timestamp in order to prevent
|
||||||
bTimeStampValid = TRUE;
|
an adversary from determining which file may have been used as keyfile. */
|
||||||
|
FILETIME ftLastAccessTime;
|
||||||
|
ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
|
||||||
|
ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
SetFileTime (src, NULL, &ftLastAccessTime, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* try to open without FILE_WRITE_ATTRIBUTES in case we are in a ReadOnly filesystem (e.g. CD) */
|
||||||
|
src = CreateFile (keyFile->FileName,
|
||||||
|
GENERIC_READ,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
if (src == INVALID_HANDLE_VALUE)
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
finally_do_arg (HANDLE, src,
|
while ((bReadStatus = ReadFile (src, buffer, sizeof (buffer), &bytesRead, NULL)) && (bytesRead > 0))
|
||||||
{
|
{
|
||||||
if (finally_arg != INVALID_HANDLE_VALUE)
|
DWORD i;
|
||||||
CloseHandle (finally_arg);
|
|
||||||
});
|
|
||||||
|
|
||||||
f = _wfopen (keyFile->FileName, L"rb");
|
|
||||||
if (f == NULL) return FALSE;
|
|
||||||
|
|
||||||
while ((bytesRead = fread (buffer, 1, sizeof (buffer), f)) > 0)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (ferror (f))
|
|
||||||
{
|
|
||||||
status = FALSE;
|
|
||||||
goto close;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < bytesRead; i++)
|
for (i = 0; i < bytesRead; i++)
|
||||||
{
|
{
|
||||||
@@ -211,7 +202,7 @@ static BOOL KeyFileProcess (unsigned __int8 *keyPool, unsigned __int32 keyPoolSi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ferror (f))
|
if (!bReadStatus)
|
||||||
{
|
{
|
||||||
status = FALSE;
|
status = FALSE;
|
||||||
}
|
}
|
||||||
@@ -223,13 +214,9 @@ static BOOL KeyFileProcess (unsigned __int8 *keyPool, unsigned __int32 keyPoolSi
|
|||||||
|
|
||||||
close:
|
close:
|
||||||
DWORD err = GetLastError();
|
DWORD err = GetLastError();
|
||||||
fclose (f);
|
|
||||||
|
|
||||||
if (bTimeStampValid && !IsFileOnReadOnlyFilesystem (keyFile->FileName))
|
CloseHandle (src);
|
||||||
{
|
burn (buffer, sizeof (buffer));
|
||||||
// Restore the keyfile timestamp
|
|
||||||
SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetLastError (err);
|
SetLastError (err);
|
||||||
return status;
|
return status;
|
||||||
|
|||||||
@@ -224,6 +224,19 @@ int ChangePwd (const wchar_t *lpszVolume, Password *oldPassword, int old_pkcs5,
|
|||||||
|
|
||||||
if (dev == INVALID_HANDLE_VALUE)
|
if (dev == INVALID_HANDLE_VALUE)
|
||||||
goto error;
|
goto error;
|
||||||
|
else if (!bDevice && 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;
|
||||||
|
}
|
||||||
|
|
||||||
if (bDevice)
|
if (bDevice)
|
||||||
{
|
{
|
||||||
@@ -313,13 +326,6 @@ int ChangePwd (const wchar_t *lpszVolume, Password *oldPassword, int old_pkcs5,
|
|||||||
|
|
||||||
SetRandomPoolEnrichedByUserStatus (FALSE); /* force the display of the random enriching dialog */
|
SetRandomPoolEnrichedByUserStatus (FALSE); /* force the display of the random enriching dialog */
|
||||||
|
|
||||||
if (!bDevice && bPreserveTimestamp)
|
|
||||||
{
|
|
||||||
if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
|
|
||||||
bTimeStampValid = FALSE;
|
|
||||||
else
|
|
||||||
bTimeStampValid = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
|
for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject,
|
|||||||
if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED)
|
if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED)
|
||||||
{
|
{
|
||||||
ntStatus = ZwCreateFile (&Extension->hDeviceFile,
|
ntStatus = ZwCreateFile (&Extension->hDeviceFile,
|
||||||
GENERIC_READ | SYNCHRONIZE,
|
GENERIC_READ | (!bRawDevice && mount->bPreserveTimestamp? FILE_WRITE_ATTRIBUTES : 0) | SYNCHRONIZE,
|
||||||
&oaFileAttributes,
|
&oaFileAttributes,
|
||||||
&IoStatusBlock,
|
&IoStatusBlock,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -318,6 +318,26 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject,
|
|||||||
NULL,
|
NULL,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS (ntStatus) && !bRawDevice && mount->bPreserveTimestamp)
|
||||||
|
{
|
||||||
|
/* try again without FILE_WRITE_ATTRIBUTES */
|
||||||
|
ntStatus = ZwCreateFile (&Extension->hDeviceFile,
|
||||||
|
GENERIC_READ | SYNCHRONIZE,
|
||||||
|
&oaFileAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
NULL,
|
||||||
|
FILE_ATTRIBUTE_NORMAL |
|
||||||
|
FILE_ATTRIBUTE_SYSTEM,
|
||||||
|
exclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
FILE_OPEN,
|
||||||
|
FILE_RANDOM_ACCESS |
|
||||||
|
FILE_WRITE_THROUGH |
|
||||||
|
(disableBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
|
||||||
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
if (NT_SUCCESS (ntStatus) && !mount->bMountReadOnly)
|
if (NT_SUCCESS (ntStatus) && !mount->bMountReadOnly)
|
||||||
mount->VolumeMountedReadOnlyAfterAccessDenied = TRUE;
|
mount->VolumeMountedReadOnlyAfterAccessDenied = TRUE;
|
||||||
|
|
||||||
@@ -362,6 +382,18 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject,
|
|||||||
Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime;
|
Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime;
|
||||||
Extension->fileLastChangeTime = FileBasicInfo.ChangeTime;
|
Extension->fileLastChangeTime = FileBasicInfo.ChangeTime;
|
||||||
Extension->bTimeStampValid = TRUE;
|
Extension->bTimeStampValid = TRUE;
|
||||||
|
|
||||||
|
// we tell the system not to update LastAccessTime, LastWriteTime, and ChangeTime
|
||||||
|
FileBasicInfo.CreationTime.QuadPart = 0;
|
||||||
|
FileBasicInfo.LastAccessTime.QuadPart = -1;
|
||||||
|
FileBasicInfo.LastWriteTime.QuadPart = -1;
|
||||||
|
FileBasicInfo.ChangeTime.QuadPart = -1;
|
||||||
|
|
||||||
|
ZwSetInformationFile (Extension->hDeviceFile,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&FileBasicInfo,
|
||||||
|
sizeof (FileBasicInfo),
|
||||||
|
FileBasicInformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
|
ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
|
||||||
|
|||||||
@@ -535,6 +535,27 @@ static int ExpandVolume (HWND hwndDlg, wchar_t *lpszVolume, Password *pVolumePas
|
|||||||
|
|
||||||
if (dev == INVALID_HANDLE_VALUE)
|
if (dev == INVALID_HANDLE_VALUE)
|
||||||
goto error;
|
goto error;
|
||||||
|
else if (!bDevice && bPreserveTimestamp)
|
||||||
|
{
|
||||||
|
// ensure that Last Access and Last Time timestamps are not modified
|
||||||
|
// in order to preserve plausible deniability of hidden volumes (last password change time is stored in the volume header).
|
||||||
|
ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
|
||||||
|
ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
SetFileTime (dev, NULL, &ftLastAccessTime, NULL);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
if (bDevice)
|
if (bDevice)
|
||||||
{
|
{
|
||||||
@@ -628,20 +649,6 @@ static int ExpandVolume (HWND hwndDlg, wchar_t *lpszVolume, Password *pVolumePas
|
|||||||
goto error;
|
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
|
// Seek the volume header
|
||||||
headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
|
headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
|
||||||
|
|||||||
@@ -3313,6 +3313,12 @@ BOOL IsSparseFile (HWND hwndDlg)
|
|||||||
|
|
||||||
if (bPreserveTimestamp)
|
if (bPreserveTimestamp)
|
||||||
{
|
{
|
||||||
|
FILETIME ftLastAccessTime;
|
||||||
|
ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
|
||||||
|
ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
SetFileTime (hFile, NULL, &ftLastAccessTime, NULL);
|
||||||
|
|
||||||
if (GetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0)
|
if (GetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0)
|
||||||
bTimeStampValid = FALSE;
|
bTimeStampValid = FALSE;
|
||||||
else
|
else
|
||||||
@@ -3352,6 +3358,12 @@ BOOL GetFileVolSize (HWND hwndDlg, unsigned __int64 *size)
|
|||||||
|
|
||||||
if (bPreserveTimestamp)
|
if (bPreserveTimestamp)
|
||||||
{
|
{
|
||||||
|
FILETIME ftLastAccessTime;
|
||||||
|
ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
|
||||||
|
ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
SetFileTime (hFile, NULL, &ftLastAccessTime, NULL);
|
||||||
|
|
||||||
if (GetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0)
|
if (GetFileTime (hFile, NULL, &ftLastAccessTime, NULL) == 0)
|
||||||
bTimeStampValid = FALSE;
|
bTimeStampValid = FALSE;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -10861,6 +10861,21 @@ int RestoreVolumeHeader (HWND hwndDlg, const wchar_t *lpszVolume)
|
|||||||
nStatus = ERR_OS_ERROR;
|
nStatus = ERR_OS_ERROR;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
else if (!bDevice && bPreserveTimestamp)
|
||||||
|
{
|
||||||
|
// ensure that Last Access timestamp is not modified
|
||||||
|
ftLastAccessTime.dwHighDateTime = 0xFFFFFFFF;
|
||||||
|
ftLastAccessTime.dwLowDateTime = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
SetFileTime (dev, NULL, &ftLastAccessTime, NULL);
|
||||||
|
|
||||||
|
/* Remember the container modification/creation date and time. */
|
||||||
|
|
||||||
|
if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
|
||||||
|
bTimeStampValid = FALSE;
|
||||||
|
else
|
||||||
|
bTimeStampValid = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Determine volume host size
|
// Determine volume host size
|
||||||
if (bDevice)
|
if (bDevice)
|
||||||
@@ -10931,15 +10946,6 @@ int RestoreVolumeHeader (HWND hwndDlg, const wchar_t *lpszVolume)
|
|||||||
hostSize = fileSize.QuadPart;
|
hostSize = fileSize.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bDevice && bPreserveTimestamp)
|
|
||||||
{
|
|
||||||
/* Remember the container modification/creation date and time. */
|
|
||||||
|
|
||||||
if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
|
|
||||||
bTimeStampValid = FALSE;
|
|
||||||
else
|
|
||||||
bTimeStampValid = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the volume header from the backup file */
|
/* Read the volume header from the backup file */
|
||||||
char buffer[TC_VOLUME_HEADER_GROUP_SIZE];
|
char buffer[TC_VOLUME_HEADER_GROUP_SIZE];
|
||||||
|
|||||||
Reference in New Issue
Block a user