winapi_common
file.cpp
1 // Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
2 // This file is part of the "winapi-common" project.
3 // For details, see https://github.com/egor-tensin/winapi-common.
4 // Distributed under the MIT License.
5 
6 #include <winapi/error.hpp>
7 #include <winapi/file.hpp>
8 #include <winapi/handle.hpp>
9 #include <winapi/path.hpp>
10 #include <winapi/utf8.hpp>
11 
12 #include <cstddef>
13 #include <cstdint>
14 #include <cstring>
15 #include <stdexcept>
16 #include <string>
17 
18 namespace winapi {
19 namespace {
20 
21 std::wstring to_system_path(const std::string& path) {
22  return widen(path);
23 }
24 
25 std::wstring to_system_path(const CanonicalPath& path) {
26  return widen(R"(\\?\)" + path.get());
27 }
28 
29 struct CreateFileParams {
30  static CreateFileParams read() {
31  CreateFileParams params;
32  params.dwDesiredAccess = GENERIC_READ;
33  params.dwShareMode = FILE_SHARE_READ;
34  params.dwCreationDisposition = OPEN_EXISTING;
35  return params;
36  }
37 
38  static CreateFileParams read_attributes() {
39  auto params = read();
40  params.dwDesiredAccess = FILE_READ_ATTRIBUTES;
41  params.dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
42  return params;
43  }
44 
45  static CreateFileParams write() {
46  CreateFileParams params;
47  params.dwDesiredAccess = GENERIC_WRITE;
48  params.dwShareMode = FILE_SHARE_READ;
49  params.dwCreationDisposition = OPEN_ALWAYS;
50  return params;
51  }
52 
53  DWORD dwDesiredAccess = 0;
54  DWORD dwShareMode = 0;
55  DWORD dwCreationDisposition = 0;
56 
57 private:
58  CreateFileParams() = default;
59 };
60 
61 File open_file(const std::wstring& path, const CreateFileParams& params) {
62  SECURITY_ATTRIBUTES attributes;
63  std::memset(&attributes, 0, sizeof(attributes));
64  attributes.nLength = sizeof(attributes);
65  attributes.bInheritHandle = TRUE;
66 
67  const auto handle = ::CreateFileW(path.c_str(),
68  params.dwDesiredAccess,
69  params.dwShareMode,
70  &attributes,
71  params.dwCreationDisposition,
72  FILE_ATTRIBUTE_NORMAL,
73  NULL);
74 
75  if (handle == INVALID_HANDLE_VALUE) {
76  throw error::windows(GetLastError(), "CreateFileW");
77  }
78 
79  return File{Handle{handle}};
80 }
81 
82 void remove_file(const std::wstring& path) {
83  const auto ret = ::DeleteFileW(path.c_str());
84 
85  if (!ret) {
86  throw error::windows(GetLastError(), "DeleteFileW");
87  }
88 }
89 
90 } // namespace
91 
92 File File::open_r(const std::string& path) {
93  return open_file(to_system_path(path), CreateFileParams::read());
94 }
95 
97  return open_file(to_system_path(path), CreateFileParams::read());
98 }
99 
100 File File::open_read_attributes(const std::string& path) {
101  return open_file(to_system_path(path), CreateFileParams::read_attributes());
102 }
103 
105  return open_file(to_system_path(path), CreateFileParams::read_attributes());
106 }
107 
108 File File::open_w(const std::string& path) {
109  return open_file(to_system_path(path), CreateFileParams::write());
110 }
111 
113  return open_file(to_system_path(path), CreateFileParams::write());
114 }
115 
116 void File::remove(const std::string& path) {
117  remove_file(to_system_path(path));
118 }
119 
120 void File::remove(const CanonicalPath& path) {
121  remove_file(to_system_path(path));
122 }
123 
124 std::size_t File::get_size() const {
125  LARGE_INTEGER size;
126 
127  if (!GetFileSizeEx(get(), &size))
128  throw error::windows(GetLastError(), "GetFileSizeEx");
129 
130  if (size.QuadPart < 0 || size.QuadPart > SIZE_MAX)
131  throw std::runtime_error{"invalid file size"};
132  return static_cast<std::size_t>(size.QuadPart);
133 }
134 
135 bool operator==(const FILE_ID_128& a, const FILE_ID_128& b) {
136  return 0 == std::memcmp(a.Identifier, b.Identifier, sizeof(a.Identifier));
137 }
138 
140  FILE_ID_INFO id;
141 
142  if (!GetFileInformationByHandleEx(get(), FileIdInfo, &id, sizeof(id)))
143  throw error::windows(GetLastError(), "GetFileInformationByHandleEx");
144 
145  return {id};
146 }
147 
148 } // namespace winapi
Absolute, canonical path.
Definition: path.hpp:13
File I/O.
Definition: file.hpp:29
static File open_w(const std::string &)
Definition: file.cpp:108
static void remove(const std::string &)
Definition: file.cpp:116
static File open_read_attributes(const std::string &)
Definition: file.cpp:100
static File open_r(const std::string &)
Definition: file.cpp:92
std::size_t get_size() const
Definition: file.cpp:124
ID query_id() const
Definition: file.cpp:139
Make std::system_error work with GetLastError().