VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common
diff options
context:
space:
mode:
authorMounir IDRASSI <mounir.idrassi@idrix.fr>2017-07-20 00:52:03 +0200
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2017-07-20 23:23:18 +0200
commit3021745f67164c2a19cafc0ed1eff7d35830f662 (patch)
treefec84eb925389e2ebf85af957240e6405215846e /src/Common
parentfe26ed8a5d224b133c48e2846b851d585460ad30 (diff)
downloadVeraCrypt-3021745f67164c2a19cafc0ed1eff7d35830f662.tar.gz
VeraCrypt-3021745f67164c2a19cafc0ed1eff7d35830f662.zip
Windows: better workaround for cases where ERROR_INVALID_PARAMETER is returned during system encryption which is due to 4096-bytes alignment of disk.
Diffstat (limited to 'src/Common')
-rw-r--r--src/Common/BootEncryption.cpp140
-rw-r--r--src/Common/BootEncryption.h3
2 files changed, 108 insertions, 35 deletions
diff --git a/src/Common/BootEncryption.cpp b/src/Common/BootEncryption.cpp
index 40e9e77b..f0fb414d 100644
--- a/src/Common/BootEncryption.cpp
+++ b/src/Common/BootEncryption.cpp
@@ -474,12 +474,12 @@ namespace VeraCrypt
#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(),
readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
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)
{
@@ -530,7 +530,45 @@ namespace VeraCrypt
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;
}
@@ -600,7 +638,63 @@ namespace VeraCrypt
}
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)
@@ -2134,21 +2228,10 @@ namespace VeraCrypt
memcpy (fileContent.data(), "\xEF\xBB\xBF", 3);
memcpy (&fileContent[dwOffset], pbData, dwDataLen);
- try
- {
- File f(pathESP + szFilePath, false, true);
- f.Write(fileContent.data(), dwSize);
- 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();
- }
+ File f(pathESP + szFilePath, false, true);
+ f.Write(fileContent.data(), dwSize);
+ f.Close();
+
}
EfiBoot::EfiBoot() {
@@ -2436,22 +2519,11 @@ namespace VeraCrypt
void EfiBoot::SaveFile(const wchar_t* name, byte* data, DWORD size) {
wstring path = EfiBootPartPath;
path += name;
- try
- {
- File f(path, false, true);
- f.Write(data, size);
- 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();
- }
+ File f(path, false, true);
+ f.Write(data, size);
+ f.Close();
+
}
void EfiBoot::GetFileSize(const wchar_t* name, unsigned __int64& size) {
diff --git a/src/Common/BootEncryption.h b/src/Common/BootEncryption.h
index 0f8e993b..f63ec541 100644
--- a/src/Common/BootEncryption.h
+++ b/src/Common/BootEncryption.h
@@ -37,7 +37,7 @@ namespace VeraCrypt
{
public:
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(); }
void CheckOpened (const char* srcPos) { if (!FileOpen) { SetLastError (LastError); throw SystemException (srcPos);} }
@@ -58,6 +58,7 @@ namespace VeraCrypt
bool IsDevice;
wstring Path;
DWORD LastError;
+ BYTE ReadBuffer[4096];
};