-
Notifications
You must be signed in to change notification settings - Fork 43
/
win32util.h
177 lines (156 loc) · 5.32 KB
/
win32util.h
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#ifndef _WIN32UTIL_H
#define _WIN32UTIL_H
#include <cstdio>
#include <stdexcept>
#include <string>
#include <vector>
#include <memory>
#include <io.h>
#include <fcntl.h>
#include <share.h>
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <shlwapi.h>
#pragma warning(push)
#pragma warning(disable: 4091)
#include <shlobj.h>
#pragma warning(pop)
#include "util.h"
#define HR(expr) (void)(win32::throwIfError((expr), #expr))
namespace win32 {
class Timer {
DWORD m_ticks;
public:
Timer() { m_ticks = GetTickCount(); };
double ellapsed() {
return (static_cast<double>(GetTickCount()) - m_ticks) / 1000.0;
}
};
void throw_error(const std::wstring& msg, DWORD error);
inline void throw_error(const std::string& msg, DWORD error)
{
throw_error(strutil::us2w(msg), error);
}
inline void throwIfError(HRESULT expr, const char *msg)
{
if (FAILED(expr)) throw_error(msg, expr);
}
inline std::wstring GetFullPathNameX(const std::wstring &path)
{
DWORD length = GetFullPathNameW(path.c_str(), 0, 0, 0);
std::vector<wchar_t> vec(length);
length = GetFullPathNameW(path.c_str(), static_cast<DWORD>(vec.size()),
&vec[0], 0);
return std::wstring(&vec[0], &vec[length]);
}
inline std::wstring PathReplaceExtension(const std::wstring &path,
const wchar_t *ext)
{
const wchar_t *beg = path.c_str();
const wchar_t *end = PathFindExtensionW(beg);
std::wstring s(beg, end);
//if (ext[0] != L'.') s.push_back(L'.');
s += ext;
return s;
}
// XXX: limited to MAX_PATH
inline std::wstring PathCombineX(const std::wstring &basedir,
const std::wstring &filename)
{
wchar_t buffer[MAX_PATH];
PathCombineW(buffer, basedir.c_str(), filename.c_str());
return buffer;
}
inline std::wstring GetModuleFileNameX(HMODULE module)
{
std::vector<wchar_t> buffer(32);
DWORD cclen = GetModuleFileNameW(module, &buffer[0],
static_cast<DWORD>(buffer.size()));
while (cclen >= buffer.size() - 1) {
buffer.resize(buffer.size() * 2);
cclen = GetModuleFileNameW(module, &buffer[0],
static_cast<DWORD>(buffer.size()));
}
return std::wstring(&buffer[0], &buffer[cclen]);
}
inline bool MakeSureDirectoryPathExistsX(const std::wstring &path)
{
// SHCreateDirectoryEx() doesn't work with relative path
std::wstring fullpath = GetFullPathNameX(path);
std::vector<wchar_t> buf(fullpath.begin(), fullpath.end());
buf.push_back(0);
wchar_t *pos = PathFindFileNameW(buf.data());
*pos = 0;
int rc = SHCreateDirectoryExW(nullptr, buf.data(), nullptr);
return rc == ERROR_SUCCESS;
}
inline std::wstring get_module_directory(HMODULE module=0)
{
std::wstring path = GetModuleFileNameX(module);
const wchar_t *fpos = PathFindFileNameW(path.c_str());
return path.substr(0, fpos - path.c_str());
}
inline std::wstring prefixed_path(const wchar_t *path)
{
std::wstring fullpath = GetFullPathNameX(path);
if (fullpath.size() < 256)
return fullpath;
if (fullpath.size() > 2 && fullpath.substr(0, 2) == L"\\\\")
fullpath.insert(2, L"?\\UNC\\");
else
fullpath.insert(0, L"\\\\?\\");
return fullpath;
}
inline FILE *wfopenx(const wchar_t *path, const wchar_t *mode)
{
std::wstring fullpath = win32::prefixed_path(path);
int share = _SH_DENYRW;
if (std::wcschr(mode, L'r') && !std::wcschr(mode, L'+'))
share = _SH_DENYWR;
FILE *fp = _wfsopen(fullpath.c_str(), mode, share);
if (!fp) {
if (_doserrno) throw_error(fullpath.c_str(), _doserrno);
util::throw_crt_error(fullpath);
}
return fp;
}
inline std::shared_ptr<FILE> fopen(const std::wstring &path,
const wchar_t *mode)
{
auto noop_close = [](FILE *){};
if (path != L"-")
return std::shared_ptr<FILE>(wfopenx(path.c_str(), mode),
std::fclose);
else if (std::wcschr(mode, L'r'))
return std::shared_ptr<FILE>(stdin, noop_close);
else
return std::shared_ptr<FILE>(stdout, noop_close);
}
inline HANDLE get_handle(int fd)
{
return reinterpret_cast<HANDLE>(_get_osfhandle(fd));
}
inline bool is_seekable(HANDLE fh)
{
return GetFileType(fh) == FILE_TYPE_DISK;
}
inline bool is_seekable(int fd)
{
return is_seekable(get_handle(fd));
}
FILE *tmpfile(const wchar_t *prefix);
char *load_with_mmap(const wchar_t *path, uint64_t *size);
int create_named_pipe(const wchar_t *path);
std::string get_dll_version_for_locale(HMODULE hDll, WORD langid);
bool is_same_file(HANDLE ha, HANDLE hb);
inline bool is_same_file(int fda, int fdb)
{
return is_same_file(get_handle(fda), get_handle(fdb));
}
}
#endif