1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#include "cru/common/platform/win/Win32FileStream.h"
#include "cru/common/io/OpenFileFlag.h"
#include "cru/common/platform/win/Exception.h"
#include <Windows.h>
#include <winnt.h>
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;
} else {
dwCreationDisposition = OPEN_ALWAYS;
}
} else {
dwCreationDisposition = OPEN_EXISTING;
}
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.");
}
}
Win32FileStream::~Win32FileStream() {
Close();
delete p_;
}
bool Win32FileStream::CanSeek() { return true; }
Index Win32FileStream::Seek(Index offset, SeekOrigin origin) {
CheckClosed();
DWORD dwMoveMethod = 0;
if (origin == SeekOrigin::Current) {
dwMoveMethod = FILE_CURRENT;
} else if (origin == SeekOrigin::End) {
dwMoveMethod = FILE_END;
} else {
dwMoveMethod = FILE_BEGIN;
}
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.");
}
return n_new_offset.QuadPart;
}
bool Win32FileStream::CanRead() { return true; }
Index Win32FileStream::Read(std::byte* buffer, Index offset, Index size) {
CheckClosed();
DWORD dwRead;
if (::ReadFile(p_->handle, buffer + offset, size, &dwRead, nullptr) == 0) {
throw Win32Error(u"Failed to call ReadFile.");
}
return dwRead;
}
bool Win32FileStream::CanWrite() { return true; }
Index Win32FileStream::Write(const std::byte* buffer, Index offset,
Index size) {
CheckClosed();
DWORD dwWritten;
if (::WriteFile(p_->handle, buffer + offset, size, &dwWritten, nullptr) ==
0) {
throw Win32Error(u"Failed to call WriteFile.");
}
return dwWritten;
}
void Win32FileStream::Close() {
if (closed_) return;
::CloseHandle(p_->handle);
closed_ = true;
}
void Win32FileStream::CheckClosed() {
if (closed_) throw Exception(u"Stream is closed.");
}
} // namespace cru::platform::win
|