mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 11:08:02 -06:00
Windows: better workaround for cases where ERROR_INVALID_PARAMETER is returned during system encryption which is due to 4096-bytes alignment of disk.
This commit is contained in:
@@ -474,12 +474,12 @@ namespace VeraCrypt
|
|||||||
|
|
||||||
#endif // SETUP
|
#endif // SETUP
|
||||||
|
|
||||||
File::File (wstring path, bool readOnly, bool create, bool useNormalAttributes) : Elevated (false), FileOpen (false), ReadOnly (readOnly), LastError(0)
|
File::File (wstring path, bool readOnly, bool create) : Elevated (false), FileOpen (false), ReadOnly (readOnly), LastError(0)
|
||||||
{
|
{
|
||||||
Handle = CreateFile (path.c_str(),
|
Handle = CreateFile (path.c_str(),
|
||||||
readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING,
|
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||||
useNormalAttributes? FILE_ATTRIBUTE_NORMAL : (FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH), NULL);
|
FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL);
|
||||||
|
|
||||||
if (Handle != INVALID_HANDLE_VALUE)
|
if (Handle != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
@@ -530,7 +530,45 @@ namespace VeraCrypt
|
|||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_sys_if (!ReadFile (Handle, buffer, size, &bytesRead, NULL));
|
if (!ReadFile (Handle, buffer, size, &bytesRead, NULL))
|
||||||
|
{
|
||||||
|
DWORD dwLastError = GetLastError();
|
||||||
|
if ((dwLastError == ERROR_INVALID_PARAMETER) && IsDevice && (size % 4096))
|
||||||
|
{
|
||||||
|
DWORD remainingSize = (size % 4096);
|
||||||
|
DWORD alignedSize = size - remainingSize;
|
||||||
|
LARGE_INTEGER offset;
|
||||||
|
|
||||||
|
if (alignedSize)
|
||||||
|
{
|
||||||
|
if (ReadFile (Handle, buffer, alignedSize, &bytesRead, NULL))
|
||||||
|
{
|
||||||
|
if (bytesRead < alignedSize)
|
||||||
|
return bytesRead;
|
||||||
|
|
||||||
|
buffer += alignedSize;
|
||||||
|
size -= alignedSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw SystemException (SRC_POS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ReadFile (Handle, ReadBuffer, 4096, &bytesRead, NULL))
|
||||||
|
{
|
||||||
|
DWORD effectiveSize = min (bytesRead, remainingSize);
|
||||||
|
memcpy (buffer, ReadBuffer, effectiveSize);
|
||||||
|
offset.QuadPart = - ((LONGLONG) bytesRead) + (LONGLONG) effectiveSize;
|
||||||
|
SetFilePointerEx (Handle, offset, NULL, FILE_CURRENT);
|
||||||
|
return alignedSize + effectiveSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw SystemException (SRC_POS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw SystemException (SRC_POS);
|
||||||
|
}
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,7 +638,63 @@ namespace VeraCrypt
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw_sys_if (!WriteFile (Handle, buffer, size, &bytesWritten, NULL) || bytesWritten != size);
|
if (!WriteFile (Handle, buffer, size, &bytesWritten, NULL))
|
||||||
|
{
|
||||||
|
DWORD dwLastError = GetLastError ();
|
||||||
|
if ((ERROR_INVALID_PARAMETER == dwLastError) && IsDevice && !ReadOnly && (size % 4096))
|
||||||
|
{
|
||||||
|
bool bSuccess = false;
|
||||||
|
DWORD remainingSize = (size % 4096);
|
||||||
|
DWORD alignedSize = size - remainingSize;
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
bytesWritten = 0;
|
||||||
|
if (alignedSize)
|
||||||
|
{
|
||||||
|
if (WriteFile (Handle, buffer, alignedSize, &bytesWritten, NULL))
|
||||||
|
{
|
||||||
|
throw_sys_if (bytesWritten != alignedSize);
|
||||||
|
buffer += alignedSize;
|
||||||
|
size -= alignedSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bytesWritten = 0;
|
||||||
|
dwLastError = GetLastError ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!alignedSize || (alignedSize && bytesWritten))
|
||||||
|
{
|
||||||
|
LARGE_INTEGER offset;
|
||||||
|
|
||||||
|
throw_sys_if (!ReadFile (Handle, ReadBuffer, 4096, &bytesRead, NULL) || (bytesRead != 4096));
|
||||||
|
offset.QuadPart = -4096;
|
||||||
|
throw_sys_if (!SetFilePointerEx (Handle, offset, NULL, FILE_CURRENT));
|
||||||
|
|
||||||
|
memcpy (ReadBuffer, buffer, remainingSize);
|
||||||
|
|
||||||
|
if (WriteFile (Handle, ReadBuffer, 4096, &bytesWritten, NULL))
|
||||||
|
{
|
||||||
|
throw_sys_if (bytesWritten != 4096);
|
||||||
|
bSuccess = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dwLastError = GetLastError ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
SetLastError (dwLastError);
|
||||||
|
throw SystemException (SRC_POS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw SystemException (SRC_POS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw_sys_if (bytesWritten != size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SystemException &e)
|
catch (SystemException &e)
|
||||||
@@ -2134,21 +2228,10 @@ namespace VeraCrypt
|
|||||||
memcpy (fileContent.data(), "\xEF\xBB\xBF", 3);
|
memcpy (fileContent.data(), "\xEF\xBB\xBF", 3);
|
||||||
memcpy (&fileContent[dwOffset], pbData, dwDataLen);
|
memcpy (&fileContent[dwOffset], pbData, dwDataLen);
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File f(pathESP + szFilePath, false, true);
|
File f(pathESP + szFilePath, false, true);
|
||||||
f.Write(fileContent.data(), dwSize);
|
f.Write(fileContent.data(), dwSize);
|
||||||
f.Close();
|
f.Close();
|
||||||
}
|
|
||||||
catch (SystemException &e)
|
|
||||||
{
|
|
||||||
if (e.ErrorCode != ERROR_INVALID_PARAMETER)
|
|
||||||
throw;
|
|
||||||
// try again with normal attributes
|
|
||||||
File f(pathESP + szFilePath, false, true, true);
|
|
||||||
f.Write(fileContent.data(), dwSize);
|
|
||||||
f.Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EfiBoot::EfiBoot() {
|
EfiBoot::EfiBoot() {
|
||||||
@@ -2436,22 +2519,11 @@ namespace VeraCrypt
|
|||||||
void EfiBoot::SaveFile(const wchar_t* name, byte* data, DWORD size) {
|
void EfiBoot::SaveFile(const wchar_t* name, byte* data, DWORD size) {
|
||||||
wstring path = EfiBootPartPath;
|
wstring path = EfiBootPartPath;
|
||||||
path += name;
|
path += name;
|
||||||
try
|
|
||||||
{
|
|
||||||
File f(path, false, true);
|
File f(path, false, true);
|
||||||
f.Write(data, size);
|
f.Write(data, size);
|
||||||
f.Close();
|
f.Close();
|
||||||
}
|
|
||||||
catch (SystemException &e)
|
|
||||||
{
|
|
||||||
if (e.ErrorCode != ERROR_INVALID_PARAMETER)
|
|
||||||
throw;
|
|
||||||
|
|
||||||
// try again with normal attributes
|
|
||||||
File f(path, false, true, true);
|
|
||||||
f.Write(data, size);
|
|
||||||
f.Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EfiBoot::GetFileSize(const wchar_t* name, unsigned __int64& size) {
|
void EfiBoot::GetFileSize(const wchar_t* name, unsigned __int64& size) {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace VeraCrypt
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
File () : Elevated (false), FileOpen (false), ReadOnly (false), FilePointerPosition(0), Handle(INVALID_HANDLE_VALUE), IsDevice(false), LastError(0) { }
|
File () : Elevated (false), FileOpen (false), ReadOnly (false), FilePointerPosition(0), Handle(INVALID_HANDLE_VALUE), IsDevice(false), LastError(0) { }
|
||||||
File (wstring path,bool readOnly = false, bool create = false, bool useNormalAttributes = false);
|
File (wstring path,bool readOnly = false, bool create = false);
|
||||||
virtual ~File () { Close(); }
|
virtual ~File () { Close(); }
|
||||||
|
|
||||||
void CheckOpened (const char* srcPos) { if (!FileOpen) { SetLastError (LastError); throw SystemException (srcPos);} }
|
void CheckOpened (const char* srcPos) { if (!FileOpen) { SetLastError (LastError); throw SystemException (srcPos);} }
|
||||||
@@ -58,6 +58,7 @@ namespace VeraCrypt
|
|||||||
bool IsDevice;
|
bool IsDevice;
|
||||||
wstring Path;
|
wstring Path;
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
|
BYTE ReadBuffer[4096];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user