aboutsummaryrefslogtreecommitdiff
path: root/src/common/platform/win/Win32FileStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/platform/win/Win32FileStream.cpp')
-rw-r--r--src/common/platform/win/Win32FileStream.cpp101
1 files changed, 52 insertions, 49 deletions
diff --git a/src/common/platform/win/Win32FileStream.cpp b/src/common/platform/win/Win32FileStream.cpp
index 92420bbe..a118dc02 100644
--- a/src/common/platform/win/Win32FileStream.cpp
+++ b/src/common/platform/win/Win32FileStream.cpp
@@ -1,50 +1,48 @@
#include "cru/common/platform/win/Win32FileStream.h"
+#include "Win32FileStreamPrivate.h"
#include "cru/common/io/OpenFileFlag.h"
#include "cru/common/platform/win/Exception.h"
#include <Windows.h>
+#include <coml2api.h>
+#include <shlwapi.h>
#include <winnt.h>
+#include <filesystem>
namespace cru::platform::win {
using namespace cru::io;
-namespace details {
-struct Win32FileStreamPrivate {
- HANDLE handle;
-};
-} // namespace details
-
Win32FileStream::Win32FileStream(String path, OpenFileFlag flags)
- : path_(std::move(path)), flags_(flags) {
- p_ = new details::Win32FileStreamPrivate();
-
- DWORD dwDesiredAccess = 0;
- if (flags & OpenFileFlags::Read) {
- dwDesiredAccess |= GENERIC_READ;
- }
- if (flags & OpenFileFlags::Write) {
- dwDesiredAccess |= GENERIC_WRITE;
- }
-
- DWORD dwCreationDisposition = 0;
- if (flags & OpenFileFlags::Create) {
- if (flags & OpenFileFlags::ThrowOnExist) {
- dwCreationDisposition = CREATE_NEW;
+ : path_(std::move(path)),
+ flags_(flags),
+ p_(new details::Win32FileStreamPrivate()) {
+ DWORD grfMode = STGM_SHARE_DENY_NONE;
+ if (flags & io::OpenFileFlags::Read) {
+ if (flags & io::OpenFileFlags::Write) {
+ grfMode |= STGM_READWRITE;
} else {
- dwCreationDisposition = OPEN_ALWAYS;
+ grfMode |= STGM_READ;
}
} else {
- dwCreationDisposition = OPEN_EXISTING;
+ if (flags & io::OpenFileFlags::Write) {
+ grfMode |= STGM_WRITE;
+ } else {
+ throw Exception(u"Stream must be readable or writable.");
+ }
}
- p_->handle = ::CreateFileW(
- path_.WinCStr(), dwDesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE,
- nullptr, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
-
- if (p_->handle == INVALID_HANDLE_VALUE) {
- throw Win32Error(u"Failed to call CreateFileW.");
+ if (flags & io::OpenFileFlags::Truncate) {
+ grfMode |= STGM_CREATE;
}
+
+ IStream* stream;
+
+ ThrowIfFailed(SHCreateStreamOnFileEx(
+ path_.WinCStr(), grfMode, FILE_ATTRIBUTE_NORMAL,
+ flags & io::OpenFileFlags::Create ? TRUE : FALSE, NULL, &stream));
+
+ p_->stream_ = stream;
}
Win32FileStream::~Win32FileStream() {
@@ -57,22 +55,21 @@ bool Win32FileStream::CanSeek() { return true; }
Index Win32FileStream::Seek(Index offset, SeekOrigin origin) {
CheckClosed();
- DWORD dwMoveMethod = 0;
+ DWORD dwOrigin = 0;
if (origin == SeekOrigin::Current) {
- dwMoveMethod = FILE_CURRENT;
+ dwOrigin = STREAM_SEEK_CUR;
} else if (origin == SeekOrigin::End) {
- dwMoveMethod = FILE_END;
+ dwOrigin = STREAM_SEEK_END;
} else {
- dwMoveMethod = FILE_BEGIN;
+ dwOrigin = STREAM_SEEK_SET;
}
LARGE_INTEGER n_offset;
n_offset.QuadPart = offset;
- LARGE_INTEGER n_new_offset;
- if (!::SetFilePointerEx(p_->handle, n_offset, &n_new_offset, dwMoveMethod)) {
- throw Win32Error(u"Failed to call SetFilePointerEx.");
- }
+ ULARGE_INTEGER n_new_offset;
+
+ ThrowIfFailed(p_->stream_->Seek(n_offset, dwOrigin, &n_new_offset));
return n_new_offset.QuadPart;
}
@@ -80,34 +77,40 @@ Index Win32FileStream::Seek(Index offset, SeekOrigin origin) {
bool Win32FileStream::CanRead() { return true; }
Index Win32FileStream::Read(std::byte* buffer, Index offset, Index size) {
+ if (size < 0) {
+ throw Exception(u"Size must be greater than 0.");
+ }
+
CheckClosed();
- DWORD dwRead;
- if (::ReadFile(p_->handle, buffer + offset, size, &dwRead, nullptr) == 0) {
- throw Win32Error(u"Failed to call ReadFile.");
- }
- return dwRead;
+ ULONG n_read;
+ ThrowIfFailed(p_->stream_->Read(buffer + offset, size, &n_read));
+ return n_read;
}
bool Win32FileStream::CanWrite() { return true; }
Index Win32FileStream::Write(const std::byte* buffer, Index offset,
Index size) {
+ if (size < 0) {
+ throw Exception(u"Size must be greater than 0.");
+ }
+
CheckClosed();
- DWORD dwWritten;
- if (::WriteFile(p_->handle, buffer + offset, size, &dwWritten, nullptr) ==
- 0) {
- throw Win32Error(u"Failed to call WriteFile.");
- }
+ ULONG n_written;
+ ThrowIfFailed(p_->stream_->Write(buffer + offset, size, &n_written));
- return dwWritten;
+ return n_written;
}
void Win32FileStream::Close() {
if (closed_) return;
- ::CloseHandle(p_->handle);
+ if (p_->stream_) {
+ p_->stream_->Release();
+ p_->stream_ = nullptr;
+ }
closed_ = true;
}