VeraCrypt
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
@@ -473,14 +473,14 @@ 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)
{
FileOpen = true;
@@ -529,9 +529,47 @@ namespace VeraCrypt
FilePointerPosition += 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;
}
void File::SeekAt (int64 position)
@@ -599,9 +637,65 @@ namespace VeraCrypt
throw_sys_if (bytesWritten != size);
}
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)
{
@@ -2133,23 +2227,12 @@ namespace VeraCrypt
if (bAddUTF8BOM)
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() {
ZeroMemory(EfiBootPartPath, sizeof(EfiBootPartPath));
@@ -2435,24 +2518,13 @@ 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) {
wstring path = EfiBootPartPath;
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
@@ -36,9 +36,9 @@ namespace VeraCrypt
class File
{
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);} }
void Close ();
@@ -57,8 +57,9 @@ namespace VeraCrypt
HANDLE Handle;
bool IsDevice;
wstring Path;
DWORD LastError;
+ BYTE ReadBuffer[4096];
};
class Device : public File