WinStd
Additional templates and function helpers for Microsoft Windows using Standard C++ classes
Win.h
Go to the documentation of this file.
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 1991-2022 Amebis
4 Copyright © 2016 GÉANT
5*/
6
12
13#pragma once
14
15#include "Common.h"
16#include <string>
17#include <vector>
18
19#pragma warning(push)
20#pragma warning(disable: 4505) // Don't warn on unused code
21
24
26template<class _Traits, class _Ax>
27static DWORD GetModuleFileNameA(_In_opt_ HMODULE hModule, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
28{
29 assert(0); // TODO: Test this code.
30
31 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
32
33 // Try with stack buffer first.
34 DWORD dwResult = ::GetModuleFileNameA(hModule, szStackBuffer, _countof(szStackBuffer));
35 if (dwResult < _countof(szStackBuffer)) {
36 // Copy from stack.
37 sValue.assign(szStackBuffer, dwResult);
38 return dwResult;
39 } else {
40 for (DWORD dwCapacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(char);; dwCapacity *= 2) {
41 // Allocate on heap and retry.
42 std::unique_ptr<char[]> szBuffer(new char[dwCapacity]);
43 dwResult = ::GetModuleFileNameA(hModule, szBuffer.get(), dwCapacity);
44 if (dwResult < dwCapacity) {
45 sValue.assign(szBuffer.get(), dwResult);
46 return dwResult;
47 }
48 }
49 }
50}
51
57template<class _Traits, class _Ax>
58static DWORD GetModuleFileNameW(_In_opt_ HMODULE hModule, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
59{
60 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
61
62 // Try with stack buffer first.
63 DWORD dwResult = ::GetModuleFileNameW(hModule, szStackBuffer, _countof(szStackBuffer));
64 if (dwResult < _countof(szStackBuffer)) {
65 // Copy from stack.
66 sValue.assign(szStackBuffer, dwResult);
67 return dwResult;
68 } else {
69 for (DWORD dwCapacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t);; dwCapacity *= 2) {
70 // Allocate on heap and retry.
71 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwCapacity]);
72 dwResult = ::GetModuleFileNameW(hModule, szBuffer.get(), dwCapacity);
73 if (dwResult < dwCapacity) {
74 sValue.assign(szBuffer.get(), dwResult);
75 return dwResult;
76 }
77 }
78 }
79}
80
82template<class _Traits, class _Ax>
83static _Success_(return != 0) int GetWindowTextA(_In_ HWND hWnd, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
84{
85 assert(0); // TODO: Test this code.
86
87 int iResult;
88
89 // Query the final string length first.
90 iResult = ::GetWindowTextLengthA(hWnd);
91 if (iResult > 0) {
92 if (++iResult < WINSTD_STACK_BUFFER_BYTES/sizeof(char)) {
93 // Read string data to stack.
94 char szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
95 iResult = ::GetWindowTextA(hWnd, szBuffer, _countof(szBuffer));
96 sValue.assign(szBuffer, iResult);
97 } else {
98 // Allocate buffer on heap and read the string data into it.
99 std::unique_ptr<char[]> szBuffer(new char[++iResult]);
100 iResult = ::GetWindowTextA(hWnd, szBuffer.get(), iResult);
101 sValue.assign(szBuffer.get(), iResult);
102 }
103 return iResult;
104 }
105
106 sValue.clear();
107 return 0;
108}
109
115template<class _Traits, class _Ax>
116static _Success_(return != 0) int GetWindowTextW(_In_ HWND hWnd, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
117{
118 assert(0); // TODO: Test this code.
119
120 int iResult;
121
122 // Query the final string length first.
123 iResult = ::GetWindowTextLengthW(hWnd);
124 if (iResult > 0) {
125 if (++iResult < WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)) {
126 // Read string data to stack.
127 wchar_t szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
128 iResult = ::GetWindowTextW(hWnd, szBuffer, _countof(szBuffer));
129 sValue.assign(szBuffer, iResult);
130 } else {
131 // Allocate buffer on heap and read the string data into it.
132 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[++iResult]);
133 iResult = ::GetWindowTextW(hWnd, szBuffer.get(), iResult);
134 sValue.assign(szBuffer.get(), iResult);
135 }
136 return iResult;
137 }
138
139 sValue.clear();
140 return 0;
141}
142
144template<class _Ty, class _Ax>
145static _Success_(return != 0) BOOL GetFileVersionInfoA(_In_z_ LPCSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<_Ty, _Ax> &aValue) noexcept
146{
147 assert(0); // TODO: Test this code.
148
149 // Get version info size.
150 DWORD dwVerInfoSize = ::GetFileVersionInfoSizeA(lptstrFilename, &dwHandle);
151 if (dwVerInfoSize != 0) {
152 // Read version info.
153 aValue.resize((dwVerInfoSize + sizeof(_Ty) - 1) / sizeof(_Ty));
154 return ::GetFileVersionInfoA(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
155 } else
156 return FALSE;
157}
158
164template<class _Ty, class _Ax>
165static _Success_(return != 0) BOOL GetFileVersionInfoW(_In_z_ LPCWSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<_Ty, _Ax> &aValue) noexcept
166{
167 assert(0); // TODO: Test this code.
168
169 // Get version info size.
170 DWORD dwVerInfoSize = ::GetFileVersionInfoSizeW(lptstrFilename, &dwHandle);
171 if (dwVerInfoSize != 0) {
172 // Read version info.
173 aValue.resize((dwVerInfoSize + sizeof(_Ty) - 1) / sizeof(_Ty));
174 return ::GetFileVersionInfoW(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
175 } else
176 return FALSE;
177}
178
180template<class _Traits, class _Ax>
181static _Success_(return != 0) DWORD ExpandEnvironmentStringsA(_In_z_ LPCSTR lpSrc, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
182{
183 assert(0); // TODO: Test this code.
184
185 for (DWORD dwSizeOut = (DWORD)strlen(lpSrc) + 0x100;;) {
186 DWORD dwSizeIn = dwSizeOut;
187 std::unique_ptr<char[]> szBuffer(new char[(size_t)dwSizeIn + 2]); // Note: ANSI version requires one extra char.
188 dwSizeOut = ::ExpandEnvironmentStringsA(lpSrc, szBuffer.get(), dwSizeIn);
189 if (dwSizeOut == 0) {
190 // Error or zero-length input.
191 break;
192 } else if (dwSizeOut <= dwSizeIn) {
193 // The buffer was sufficient.
194 sValue.assign(szBuffer.get(), dwSizeOut - 1);
195 return dwSizeOut;
196 }
197 }
198
199 sValue.clear();
200 return 0;
201}
202
208template<class _Traits, class _Ax>
209static _Success_(return != 0) DWORD ExpandEnvironmentStringsW(_In_z_ LPCWSTR lpSrc, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
210{
211 for (DWORD dwSizeOut = (DWORD)wcslen(lpSrc) + 0x100;;) {
212 DWORD dwSizeIn = dwSizeOut;
213 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[(size_t)dwSizeIn + 1]);
214 dwSizeOut = ::ExpandEnvironmentStringsW(lpSrc, szBuffer.get(), dwSizeIn);
215 if (dwSizeOut == 0) {
216 // Error or zero-length input.
217 break;
218 } else if (dwSizeOut <= dwSizeIn) {
219 // The buffer was sufficient.
220 sValue.assign(szBuffer.get(), dwSizeOut - 1);
221 return dwSizeOut;
222 }
223 }
224
225 sValue.clear();
226 return 0;
227}
228
230template<class _Traits, class _Ax>
231static VOID GuidToStringA(_In_ LPCGUID lpGuid, _Out_ std::basic_string<char, _Traits, _Ax> &str) noexcept
232{
233 assert(0); // TODO: Test this code.
234
235 sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
236 lpGuid->Data1,
237 lpGuid->Data2,
238 lpGuid->Data3,
239 lpGuid->Data4[0], lpGuid->Data4[1],
240 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
241}
242
249template<class _Traits, class _Ax>
250static VOID GuidToStringW(_In_ LPCGUID lpGuid, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &str) noexcept
251{
252 assert(0); // TODO: Test this code.
253
254 sprintf(str, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
255 lpGuid->Data1,
256 lpGuid->Data2,
257 lpGuid->Data3,
258 lpGuid->Data4[0], lpGuid->Data4[1],
259 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
260}
261
263#ifdef _UNICODE
264#define GuidToString GuidToStringW
265#else
266#define GuidToString GuidToStringA
267#endif
268
270static _Success_(return) BOOL StringToGuidA(_In_z_ LPCSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCSTR *lpszGuidEnd = NULL) noexcept
271{
272 GUID g;
273 LPSTR lpszEnd;
274 unsigned long ulTmp;
275 unsigned long long ullTmp;
276
277 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
278 lpszGuid++;
279
280 g.Data1 = strtoul(lpszGuid, &lpszEnd, 16);
281 if (errno == ERANGE) return FALSE;
282 lpszGuid = lpszEnd;
283
284 if (*lpszGuid != '-') return FALSE;
285 lpszGuid++;
286
287 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
288 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
289 g.Data2 = static_cast<unsigned short>(ulTmp);
290 lpszGuid = lpszEnd;
291
292 if (*lpszGuid != '-') return FALSE;
293 lpszGuid++;
294
295 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
296 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
297 g.Data3 = static_cast<unsigned short>(ulTmp);
298 lpszGuid = lpszEnd;
299
300 if (*lpszGuid != '-') return FALSE;
301 lpszGuid++;
302
303 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
304 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
305 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
306 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
307 lpszGuid = lpszEnd;
308
309 if (*lpszGuid != '-') return FALSE;
310 lpszGuid++;
311
312 ullTmp = _strtoui64(lpszGuid, &lpszEnd, 16);
313 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
314 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
315 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
316 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
317 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
318 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
319 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
320 lpszGuid = lpszEnd;
321
322 if (*lpszGuid != '}') return FALSE;
323 lpszGuid++;
324
325 if (lpszGuidEnd)
326 *lpszGuidEnd = lpszGuid;
327
328 *lpGuid = g;
329 return TRUE;
330}
331
343static _Success_(return) BOOL StringToGuidW(_In_z_ LPCWSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCWSTR *lpszGuidEnd = NULL) noexcept
344{
345 GUID g;
346 LPWSTR lpszEnd;
347 unsigned long ulTmp;
348 unsigned long long ullTmp;
349
350 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
351 lpszGuid++;
352
353 g.Data1 = wcstoul(lpszGuid, &lpszEnd, 16);
354 if (errno == ERANGE) return FALSE;
355 lpszGuid = lpszEnd;
356
357 if (*lpszGuid != '-') return FALSE;
358 lpszGuid++;
359
360 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
361 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
362 g.Data2 = static_cast<unsigned short>(ulTmp);
363 lpszGuid = lpszEnd;
364
365 if (*lpszGuid != '-') return FALSE;
366 lpszGuid++;
367
368 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
369 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
370 g.Data3 = static_cast<unsigned short>(ulTmp);
371 lpszGuid = lpszEnd;
372
373 if (*lpszGuid != '-') return FALSE;
374 lpszGuid++;
375
376 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
377 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
378 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
379 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
380 lpszGuid = lpszEnd;
381
382 if (*lpszGuid != '-') return FALSE;
383 lpszGuid++;
384
385 ullTmp = _wcstoui64(lpszGuid, &lpszEnd, 16);
386 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
387 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
388 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
389 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
390 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
391 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
392 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
393 lpszGuid = lpszEnd;
394
395 if (*lpszGuid != '}') return FALSE;
396 lpszGuid++;
397
398 if (lpszGuidEnd)
399 *lpszGuidEnd = lpszGuid;
400
401 *lpGuid = g;
402 return TRUE;
403}
404
406#ifdef _UNICODE
407#define StringToGuid StringToGuidW
408#else
409#define StringToGuid StringToGuidA
410#endif
411
430template<class _Traits, class _Ax>
431static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCSTR pszName, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
432{
433 LSTATUS lResult;
434 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
435 DWORD dwSize = sizeof(aStackBuffer), dwType;
436
437 // Try with stack buffer first.
438 lResult = ::RegQueryValueExA(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
439 if (lResult == ERROR_SUCCESS) {
440 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
441 // The value is REG_SZ or REG_MULTI_SZ.
442 dwSize /= sizeof(CHAR);
443 sValue.assign(reinterpret_cast<LPCSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
444 } else if (dwType == REG_EXPAND_SZ) {
445 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
446 if (::ExpandEnvironmentStringsA(reinterpret_cast<LPCSTR>(aStackBuffer), sValue) == 0)
447 lResult = ::GetLastError();
448 } else {
449 // The value is not a string type.
450 lResult = ERROR_INVALID_DATA;
451 }
452 } else if (lResult == ERROR_MORE_DATA) {
453 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
454 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
455 std::unique_ptr<CHAR[]> szBuffer(new CHAR[dwSize / sizeof(CHAR)]);
456 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
457 dwSize /= sizeof(CHAR);
458 sValue.assign(szBuffer.get(), dwSize && szBuffer[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
459 }
460 } else if (dwType == REG_EXPAND_SZ) {
461 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
462 std::unique_ptr<CHAR[]> szBuffer(new CHAR[dwSize / sizeof(CHAR)]);
463 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
464 if (::ExpandEnvironmentStringsA(szBuffer.get(), sValue) == 0)
465 lResult = ::GetLastError();
466 }
467 } else {
468 // The value is not a string type.
469 lResult = ERROR_INVALID_DATA;
470 }
471 }
472
473 return lResult;
474}
475
494template<class _Traits, class _Ax>
495static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCWSTR pszName, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
496{
497 LSTATUS lResult;
498 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
499 DWORD dwSize = sizeof(aStackBuffer), dwType;
500
501 // Try with stack buffer first.
502 lResult = ::RegQueryValueExW(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
503 if (lResult == ERROR_SUCCESS) {
504 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
505 // The value is REG_SZ or REG_MULTI_SZ.
506 dwSize /= sizeof(WCHAR);
507 sValue.assign(reinterpret_cast<LPCWSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCWSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
508 } else if (dwType == REG_EXPAND_SZ) {
509 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
510 if (::ExpandEnvironmentStringsW(reinterpret_cast<LPCWSTR>(aStackBuffer), sValue) == 0)
511 lResult = ::GetLastError();
512 } else {
513 // The value is not a string type.
514 lResult = ERROR_INVALID_DATA;
515 }
516 } else if (lResult == ERROR_MORE_DATA) {
517 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
518 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
519 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[dwSize / sizeof(WCHAR)]);
520 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
521 dwSize /= sizeof(WCHAR);
522 sValue.assign(szBuffer.get(), dwSize && szBuffer[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
523 }
524 } else if (dwType == REG_EXPAND_SZ) {
525 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
526 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[dwSize / sizeof(WCHAR)]);
527 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
528 if (::ExpandEnvironmentStringsW(szBuffer.get(), sValue) == 0)
529 lResult = ::GetLastError();
530 }
531 } else {
532 // The value is not a string type.
533 lResult = ERROR_INVALID_DATA;
534 }
535 }
536
537 return lResult;
538}
539
541template<class _Ty, class _Ax>
542static LSTATUS RegQueryValueExA(_In_ HKEY hKey, _In_opt_z_ LPCSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
543{
544 LSTATUS lResult;
545 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
546 DWORD dwSize = sizeof(aStackBuffer);
547
548 // Try with stack buffer first.
549 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
550 if (lResult == ERROR_SUCCESS) {
551 // Copy from stack buffer.
552 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
553 memcpy(aData.data(), aStackBuffer, dwSize);
554 } else if (lResult == ERROR_MORE_DATA) {
555 // Allocate buffer on heap and retry.
556 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
557 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, NULL, aData.data(), &dwSize);
558 }
559
560 return lResult;
561}
562
568template<class _Ty, class _Ax>
569static LSTATUS RegQueryValueExW(_In_ HKEY hKey, _In_opt_z_ LPCWSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
570{
571 LSTATUS lResult;
572 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
573 DWORD dwSize = sizeof(aStackBuffer);
574
575 // Try with stack buffer first.
576 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
577 if (lResult == ERROR_SUCCESS) {
578 // Copy from stack buffer.
579 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
580 memcpy(aData.data(), aStackBuffer, dwSize);
581 } else if (lResult == ERROR_MORE_DATA) {
582 // Allocate buffer on heap and retry.
583 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
584 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, NULL, aData.data(), &dwSize);
585 }
586
587 return lResult;
588}
589
590#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
591
593template<class _Traits, class _Ax>
594static LSTATUS RegLoadMUIStringA(_In_ HKEY hKey, _In_opt_z_ LPCSTR pszValue, _Out_ std::basic_string<char, _Traits, _Ax> &sOut, _In_ DWORD Flags, _In_opt_z_ LPCSTR pszDirectory) noexcept
595{
596 // According to "Remarks" section in MSDN documentation of RegLoadMUIString(),
597 // this function is defined but not implemented as ANSI variation.
598 assert(0);
599 return ERROR_CALL_NOT_IMPLEMENTED;
600}
601
607template<class _Traits, class _Ax>
608static LSTATUS RegLoadMUIStringW(_In_ HKEY hKey, _In_opt_z_ LPCWSTR pszValue, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sOut, _In_ DWORD Flags, _In_opt_z_ LPCWSTR pszDirectory) noexcept
609{
610 LSTATUS lResult;
611 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
612 DWORD dwSize;
613
614 Flags &= ~REG_MUI_STRING_TRUNCATE;
615
616 // Try with stack buffer first.
617 lResult = RegLoadMUIStringW(hKey, pszValue, szStackBuffer, sizeof(szStackBuffer), &dwSize, Flags, pszDirectory);
618 if (lResult == ERROR_SUCCESS) {
619 // Copy from stack buffer.
620 sOut.assign(szStackBuffer, wcsnlen(szStackBuffer, dwSize/sizeof(wchar_t)));
621 } else if (lResult == ERROR_MORE_DATA) {
622 // Allocate buffer on heap and retry.
623 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[(dwSize + sizeof(wchar_t) - 1)/sizeof(wchar_t)]);
624 sOut.assign(szBuffer.get(), (lResult = RegLoadMUIStringW(hKey, pszValue, szBuffer.get(), dwSize, &dwSize, Flags, pszDirectory)) == ERROR_SUCCESS ? wcsnlen(szBuffer.get(), dwSize/sizeof(wchar_t)) : 0);
625 }
626
627 return lResult;
628}
629
630#endif
631
637template<class _Traits, class _Ax>
638static _Success_(return != 0) int WideCharToMultiByte(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_z_count_(cchWideChar) LPCWSTR lpWideCharStr, _In_ int cchWideChar, _Out_ std::basic_string<char, _Traits, _Ax> &sMultiByteStr, _In_opt_z_ LPCSTR lpDefaultChar, _Out_opt_ LPBOOL lpUsedDefaultChar) noexcept
639{
640 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
641
642 // Try to convert to stack buffer first.
643 int cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
644 if (cch) {
645 // Copy from stack. Be careful not to include zero terminator.
646 sMultiByteStr.assign(szStackBuffer, cchWideChar != -1 ? strnlen(szStackBuffer, cch) : (size_t)cch - 1);
647 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
648 // Query the required output size. Allocate buffer. Then convert again.
649 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
650 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
651 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szBuffer.get(), cch, lpDefaultChar, lpUsedDefaultChar);
652 sMultiByteStr.assign(szBuffer.get(), cchWideChar != -1 ? strnlen(szBuffer.get(), cch) : (size_t)cch - 1);
653 }
654
655 return cch;
656}
657
663template<class _Ax>
664static _Success_(return != 0) int WideCharToMultiByte(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_z_count_(cchWideChar) LPCWSTR lpWideCharStr, _In_ int cchWideChar, _Out_ std::vector<char, _Ax> &sMultiByteStr, _In_opt_z_ LPCSTR lpDefaultChar, _Out_opt_ LPBOOL lpUsedDefaultChar) noexcept
665{
666 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
667
668 // Try to convert to stack buffer first.
669 int cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
670 if (cch) {
671 // Copy from stack.
672 sMultiByteStr.assign(szStackBuffer, szStackBuffer + cch);
673 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
674 // Query the required output size. Allocate buffer. Then convert again.
675 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
676 sMultiByteStr.resize(cch);
677 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, sMultiByteStr.data(), cch, lpDefaultChar, lpUsedDefaultChar);
678 }
679
680 return cch;
681}
682
688template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
689static _Success_(return != 0) int WideCharToMultiByte(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_ std::basic_string<wchar_t, _Traits1, _Ax1> sWideCharStr, _Out_ std::basic_string<char, _Traits2, _Ax2> &sMultiByteStr, _In_opt_z_ LPCSTR lpDefaultChar, _Out_opt_ LPBOOL lpUsedDefaultChar) noexcept
690{
691 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
692
693 // Try to convert to stack buffer first.
694 int cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
695 if (cch) {
696 // Copy from stack.
697 sMultiByteStr.assign(szStackBuffer, cch);
698 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
699 // Query the required output size. Allocate buffer. Then convert again.
700 cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), NULL, 0, lpDefaultChar, lpUsedDefaultChar);
701 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
702 cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), szBuffer.get(), cch, lpDefaultChar, lpUsedDefaultChar);
703 sMultiByteStr.assign(szBuffer.get(), cch);
704 }
705
706 return cch;
707}
708
716template<class _Traits, class _Ax>
717static _Success_(return != 0) int SecureWideCharToMultiByte(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_z_count_(cchWideChar) LPCWSTR lpWideCharStr, _In_ int cchWideChar, _Out_ std::basic_string<char, _Traits, _Ax> &sMultiByteStr, _In_opt_z_ LPCSTR lpDefaultChar, _Out_opt_ LPBOOL lpUsedDefaultChar) noexcept
718{
719 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
720
721 // Try to convert to stack buffer first.
722 int cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
723 if (cch) {
724 // Copy from stack. Be careful not to include zero terminator.
725 sMultiByteStr.assign(szStackBuffer, cchWideChar != -1 ? strnlen(szStackBuffer, cch) : (size_t)cch - 1);
726 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
727 // Query the required output size. Allocate buffer. Then convert again.
728 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
729 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
730 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szBuffer.get(), cch, lpDefaultChar, lpUsedDefaultChar);
731 sMultiByteStr.assign(szBuffer.get(), cchWideChar != -1 ? strnlen(szBuffer.get(), cch) : (size_t)cch - 1);
732 SecureZeroMemory(szBuffer.get(), sizeof(CHAR)*cch);
733 }
734
735 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
736
737 return cch;
738}
739
747template<class _Ax>
748static _Success_(return != 0) int SecureWideCharToMultiByte(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_z_count_(cchWideChar) LPCWSTR lpWideCharStr, _In_ int cchWideChar, _Out_ std::vector<char, _Ax> &sMultiByteStr, _In_opt_z_ LPCSTR lpDefaultChar, _Out_opt_ LPBOOL lpUsedDefaultChar) noexcept
749{
750 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
751
752 // Try to convert to stack buffer first.
753 int cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
754 if (cch) {
755 // Copy from stack.
756 sMultiByteStr.assign(szStackBuffer, szStackBuffer + cch);
757 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
758 // Query the required output size. Allocate buffer. Then convert again.
759 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
760 sMultiByteStr.resize(cch);
761 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, sMultiByteStr.data(), cch, lpDefaultChar, lpUsedDefaultChar);
762 }
763
764 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
765
766 return cch;
767}
768
776template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
777static _Success_(return != 0) int SecureWideCharToMultiByte(_In_ UINT CodePage, _In_ DWORD dwFlags, _Out_ std::basic_string<wchar_t, _Traits1, _Ax1> sWideCharStr, _Out_ std::basic_string<char, _Traits2, _Ax2> &sMultiByteStr, _In_opt_z_ LPCSTR lpDefaultChar, _Out_opt_ LPBOOL lpUsedDefaultChar) noexcept
778{
779 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
780
781 // Try to convert to stack buffer first.
782 int cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
783 if (cch) {
784 // Copy from stack.
785 sMultiByteStr.assign(szStackBuffer, cch);
786 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
787 // Query the required output size. Allocate buffer. Then convert again.
788 cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), NULL, 0, lpDefaultChar, lpUsedDefaultChar);
789 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
790 cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), szBuffer.get(), cch, lpDefaultChar, lpUsedDefaultChar);
791 sMultiByteStr.assign(szBuffer.get(), cch);
792 SecureZeroMemory(szBuffer.get(), sizeof(CHAR)*cch);
793 }
794
795 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
796
797 return cch;
798}
799
805template<class _Traits, class _Ax>
806static _Success_(return != 0) int MultiByteToWideChar(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_z_count_(cbMultiByte) LPCSTR lpMultiByteStr, _In_ int cbMultiByte, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sWideCharStr) noexcept
807{
808 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
809
810 // Try to convert to stack buffer first.
811 int cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szStackBuffer, _countof(szStackBuffer));
812 if (cch) {
813 // Copy from stack.
814 sWideCharStr.assign(szStackBuffer, cbMultiByte != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
815 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
816 // Query the required output size. Allocate buffer. Then convert again.
817 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
818 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
819 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szBuffer.get(), cch);
820 sWideCharStr.assign(szBuffer.get(), cbMultiByte != -1 ? wcsnlen(szBuffer.get(), cch) : (size_t)cch - 1);
821 }
822
823 return cch;
824}
825
831template<class _Ax>
832static _Success_(return != 0) int MultiByteToWideChar(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_z_count_(cbMultiByte) LPCSTR lpMultiByteStr, _In_ int cbMultiByte, _Out_ std::vector<wchar_t, _Ax> &sWideCharStr) noexcept
833{
834 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
835
836 // Try to convert to stack buffer first.
837 int cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szStackBuffer, _countof(szStackBuffer));
838 if (cch) {
839 // Copy from stack.
840 sWideCharStr.assign(szStackBuffer, szStackBuffer + cch);
841 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
842 // Query the required output size. Allocate buffer. Then convert again.
843 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
844 sWideCharStr.resize(cch);
845 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, sWideCharStr.data(), cch);
846 }
847
848 return cch;
849}
850
856template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
857static _Success_(return != 0) int MultiByteToWideChar(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_ const std::basic_string<char, _Traits1, _Ax1> &sMultiByteStr, _Out_ std::basic_string<wchar_t, _Traits2, _Ax2> &sWideCharStr) noexcept
858{
859 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
860
861 // Try to convert to stack buffer first.
862 int cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), szStackBuffer, _countof(szStackBuffer));
863 if (cch) {
864 // Copy from stack.
865 sWideCharStr.assign(szStackBuffer, cch);
866 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
867 // Query the required output size. Allocate buffer. Then convert again.
868 cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), NULL, 0);
869 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
870 cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), szBuffer.get(), cch);
871 sWideCharStr.assign(szBuffer.get(), cch);
872 }
873
874 return cch;
875}
876
884template<class _Traits, class _Ax>
885static _Success_(return != 0) int SecureMultiByteToWideChar(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_z_count_(cbMultiByte) LPCSTR lpMultiByteStr, _In_ int cbMultiByte, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sWideCharStr) noexcept
886{
887 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
888
889 // Try to convert to stack buffer first.
890 int cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szStackBuffer, _countof(szStackBuffer));
891 if (cch) {
892 // Copy from stack.
893 sWideCharStr.assign(szStackBuffer, cbMultiByte != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
894 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
895 // Query the required output size. Allocate buffer. Then convert again.
896 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
897 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
898 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szBuffer.get(), cch);
899 sWideCharStr.assign(szBuffer.get(), cbMultiByte != -1 ? wcsnlen(szBuffer.get(), cch) : (size_t)cch - 1);
900 SecureZeroMemory(szBuffer.get(), sizeof(WCHAR)*cch);
901 }
902
903 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
904
905 return cch;
906}
907
915template<class _Ax>
916static _Success_(return != 0) int SecureMultiByteToWideChar(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_z_count_(cbMultiByte) LPCSTR lpMultiByteStr, _In_ int cbMultiByte, _Out_ std::vector<wchar_t, _Ax> &sWideCharStr) noexcept
917{
918 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
919
920 // Try to convert to stack buffer first.
921 int cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szStackBuffer, _countof(szStackBuffer));
922 if (cch) {
923 // Copy from stack.
924 sWideCharStr.assign(szStackBuffer, szStackBuffer + cch);
925 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
926 // Query the required output size. Allocate buffer. Then convert again.
927 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
928 sWideCharStr.resize(cch);
929 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, sWideCharStr.data(), cch);
930 }
931
932 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
933
934 return cch;
935}
936
944template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
945static _Success_(return != 0) int SecureMultiByteToWideChar(_In_ UINT CodePage, _In_ DWORD dwFlags, _In_ const std::basic_string<char, _Traits1, _Ax1> &sMultiByteStr, _Out_ std::basic_string<wchar_t, _Traits2, _Ax2> &sWideCharStr) noexcept
946{
947 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
948
949 // Try to convert to stack buffer first.
950 int cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), szStackBuffer, _countof(szStackBuffer));
951 if (cch) {
952 // Copy from stack.
953 sWideCharStr.assign(szStackBuffer, cch);
954 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
955 // Query the required output size. Allocate buffer. Then convert again.
956 cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), NULL, 0);
957 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
958 cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), szBuffer.get(), cch);
959 sWideCharStr.assign(szBuffer.get(), cch);
960 SecureZeroMemory(szBuffer.get(), sizeof(WCHAR)*cch);
961 }
962
963 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
964
965 return cch;
966}
967
973template<class _Traits, class _Ax>
974static _Success_(return > 0) int NormalizeString(_In_ NORM_FORM NormForm, _In_ LPCWSTR lpSrcString, _In_ int cwSrcLength, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sDstString) noexcept
975{
976 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
977
978 // Try to convert to stack buffer first.
979 int cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szStackBuffer, _countof(szStackBuffer));
980 if (cch > 0) {
981 // Copy from stack.
982 sDstString.assign(szStackBuffer, cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
983 } else {
984 switch (::GetLastError()) {
985 case ERROR_INSUFFICIENT_BUFFER:
986 for (int i = 10; i--;) {
987 // Allocate buffer. Then convert again.
988 cch = -cch;
989 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
990 cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szBuffer.get(), cch);
991 if (cch > 0) {
992 sDstString.assign(szBuffer.get(), cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
993 break;
994 }
995 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
996 sDstString.clear();
997 break;
998 }
999 }
1000 break;
1001
1002 case ERROR_SUCCESS:
1003 sDstString.clear();
1004 break;
1005 }
1006 }
1007
1008 return cch;
1009}
1010
1016template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
1017static _Success_(return > 0) int NormalizeString(_In_ NORM_FORM NormForm, _In_ const std::basic_string<wchar_t, _Traits1, _Ax1> &sSrcString, _Out_ std::basic_string<wchar_t, _Traits2, _Ax2> &sDstString) noexcept
1018{
1019 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
1020
1021 // Try to convert to stack buffer first.
1022 int cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szStackBuffer, _countof(szStackBuffer));
1023 if (cch > 0) {
1024 // Copy from stack.
1025 sDstString.assign(szStackBuffer, cch);
1026 } else {
1027 switch (::GetLastError()) {
1028 case ERROR_INSUFFICIENT_BUFFER:
1029 for (int i = 10; i--;) {
1030 // Allocate buffer. Then convert again.
1031 cch = -cch;
1032 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
1033 cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szBuffer.get(), cch);
1034 if (cch > 0) {
1035 sDstString.assign(szBuffer.get(), cch);
1036 break;
1037 }
1038 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
1039 sDstString.clear();
1040 break;
1041 }
1042 }
1043 break;
1044
1045 case ERROR_SUCCESS:
1046 sDstString.clear();
1047 break;
1048 }
1049 }
1050
1051 return cch;
1052}
1053
1055template<class _Traits, class _Ax>
1056static _Success_(return != 0) int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<char, _Traits, _Ax> &sBuffer) noexcept
1057{
1058 // Get read-only pointer to string resource.
1059 LPCSTR pszStr;
1060 int i = LoadStringA(hInstance, uID, reinterpret_cast<LPSTR>(&pszStr), 0);
1061 if (i) {
1062 sBuffer.assign(pszStr, i);
1063 return i;
1064 } else
1065 return 0;
1066}
1067
1073template<class _Traits, class _Ax>
1074static _Success_(return != 0) int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sBuffer) noexcept
1075{
1076 // Get read-only pointer to string resource.
1077 LPCWSTR pszStr;
1078 int i = LoadStringW(hInstance, uID, reinterpret_cast<LPWSTR>(&pszStr), 0);
1079 if (i) {
1080 sBuffer.assign(pszStr, i);
1081 return i;
1082 } else
1083 return 0;
1084}
1085
1091static VOID OutputDebugStrV(_In_z_ LPCSTR lpOutputString, _In_ va_list arg) noexcept
1092{
1093 std::string str;
1094 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
1095 OutputDebugStringA(str.c_str());
1096}
1097
1103static VOID OutputDebugStrV(_In_z_ LPCWSTR lpOutputString, _In_ va_list arg) noexcept
1104{
1105 std::wstring str;
1106 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
1107 OutputDebugStringW(str.c_str());
1108}
1109
1115static VOID OutputDebugStr(_In_z_ LPCSTR lpOutputString, ...) noexcept
1116{
1117 va_list arg;
1118 va_start(arg, lpOutputString);
1119 OutputDebugStrV(lpOutputString, arg);
1120 va_end(arg);
1121}
1122
1128static VOID OutputDebugStr(_In_z_ LPCWSTR lpOutputString, ...) noexcept
1129{
1130 va_list arg;
1131 va_start(arg, lpOutputString);
1132 OutputDebugStrV(lpOutputString, arg);
1133 va_end(arg);
1134}
1135
1137template<class _Traits, class _Ax>
1138static _Success_(return != 0) int GetDateFormatA(_In_ LCID Locale, _In_ DWORD dwFlags, _In_opt_ const SYSTEMTIME *lpDate, _In_opt_z_ LPCSTR lpFormat, _Out_ std::basic_string<char, _Traits, _Ax> &sDate) noexcept
1139{
1140 int iResult = GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
1141 if (iResult) {
1142 // Allocate buffer on heap and retry.
1143 std::unique_ptr<char[]> szBuffer(new char[iResult]);
1144 iResult = GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, szBuffer.get(), iResult);
1145 sDate.assign(szBuffer.get(), iResult ? iResult - 1 : 0);
1146 return iResult;
1147 }
1148
1149 return iResult;
1150}
1151
1157template<class _Traits, class _Ax>
1158static _Success_(return != 0) int GetDateFormatW(_In_ LCID Locale, _In_ DWORD dwFlags, _In_opt_ const SYSTEMTIME *lpDate, _In_opt_z_ LPCWSTR lpFormat, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sDate) noexcept
1159{
1160 int iResult = GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
1161 if (iResult) {
1162 // Allocate buffer on heap and retry.
1163 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[iResult]);
1164 iResult = GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, szBuffer.get(), iResult);
1165 sDate.assign(szBuffer.get(), iResult ? iResult - 1 : 0);
1166 return iResult;
1167 }
1168
1169 return iResult;
1170}
1171
1173template<class _Traits, class _Ax>
1174static _Success_(return != 0) BOOL LookupAccountSidA(_In_opt_z_ LPCSTR lpSystemName, _In_ PSID lpSid, _Out_opt_ std::basic_string<char, _Traits, _Ax> *sName, _Out_opt_ std::basic_string<char, _Traits, _Ax> *sReferencedDomainName, _Out_ PSID_NAME_USE peUse) noexcept
1175{
1176 assert(0); // TODO: Test this code.
1177
1178 DWORD dwNameLen = 0, dwRefDomainLen = 0;
1179
1180 if (LookupAccountSidA(lpSystemName, lpSid,
1181 NULL, &dwNameLen ,
1182 NULL, &dwRefDomainLen,
1183 peUse))
1184 {
1185 // Name and domain is blank.
1186 if (sName ) sName ->clear();
1187 if (sReferencedDomainName) sReferencedDomainName->clear();
1188 return TRUE;
1189 } else if (GetLastError() == ERROR_MORE_DATA) {
1190 // Allocate on heap and retry.
1191 std::unique_ptr<char[]> bufName (new char[dwNameLen ]);
1192 std::unique_ptr<char[]> bufRefDomain(new char[dwRefDomainLen]);
1193 if (LookupAccountSidA(lpSystemName, lpSid,
1194 bufName .get(), &dwNameLen ,
1195 bufRefDomain.get(), &dwRefDomainLen,
1196 peUse))
1197 {
1198 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
1199 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
1200 return TRUE;
1201 }
1202 }
1203
1204 return FALSE;
1205}
1206
1212template<class _Traits, class _Ax>
1213static _Success_(return != 0) BOOL LookupAccountSidW(_In_opt_z_ LPCWSTR lpSystemName, _In_ PSID lpSid, _Out_opt_ std::basic_string<wchar_t, _Traits, _Ax> *sName, _Out_opt_ std::basic_string<wchar_t, _Traits, _Ax> *sReferencedDomainName, _Out_ PSID_NAME_USE peUse) noexcept
1214{
1215 assert(0); // TODO: Test this code.
1216
1217 DWORD dwNameLen = 0, dwRefDomainLen = 0;
1218
1219 if (LookupAccountSidW(lpSystemName, lpSid,
1220 NULL, &dwNameLen ,
1221 NULL, &dwRefDomainLen,
1222 peUse))
1223 {
1224 // Name and domain is blank.
1225 if (sName ) sName ->clear();
1226 if (sReferencedDomainName) sReferencedDomainName->clear();
1227 return TRUE;
1228 } else if (GetLastError() == ERROR_MORE_DATA) {
1229 // Allocate on heap and retry.
1230 std::unique_ptr<wchar_t[]> bufName (new wchar_t[dwNameLen ]);
1231 std::unique_ptr<wchar_t[]> bufRefDomain(new wchar_t[dwRefDomainLen]);
1232 if (LookupAccountSidW(lpSystemName, lpSid,
1233 bufName .get(), &dwNameLen ,
1234 bufRefDomain.get(), &dwRefDomainLen,
1235 peUse))
1236 {
1237 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
1238 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
1239 return TRUE;
1240 }
1241 }
1242
1243 return FALSE;
1244}
1245
1251template<class _Ty>
1252static _Success_(return != 0) BOOL GetTokenInformation(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_ std::unique_ptr<_Ty> &TokenInformation) noexcept
1253{
1254 BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(BYTE)];
1255 DWORD dwSize;
1256
1257 if (GetTokenInformation(TokenHandle, TokenInformationClass, szStackBuffer, sizeof(szStackBuffer), &dwSize)) {
1258 // The stack buffer was big enough to retrieve complete data. Alloc and copy.
1259 TokenInformation.reset((_Ty*)(new BYTE[dwSize / sizeof(BYTE)]));
1260 if (!TokenInformation) {
1261 SetLastError(ERROR_OUTOFMEMORY);
1262 return FALSE;
1263 }
1264 memcpy(TokenInformation.get(), szStackBuffer, dwSize);
1265 return TRUE;
1266 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
1267 // The stack buffer was too small to retrieve complete data. Alloc and retry.
1268 TokenInformation.reset((_Ty*)(new BYTE[dwSize / sizeof(BYTE)]));
1269 if (!TokenInformation) {
1270 SetLastError(ERROR_OUTOFMEMORY);
1271 return FALSE;
1272 }
1273 return GetTokenInformation(TokenHandle, TokenInformationClass, TokenInformation.get(), dwSize, &dwSize);
1274 } else
1275 return FALSE;
1276}
1277
1283template<class _Traits, class _Ax>
1284static _Success_(return != 0) BOOL QueryFullProcessImageNameA(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<char, _Traits, _Ax>& sExeName)
1285{
1286 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(char)];
1287 DWORD dwSize = _countof(szStackBuffer);
1288
1289 // Try with stack buffer first.
1290 if (::QueryFullProcessImageNameA(hProcess, dwFlags, szStackBuffer, &dwSize)) {
1291 // Copy from stack.
1292 sExeName.assign(szStackBuffer, dwSize);
1293 return TRUE;
1294 }
1295 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(char); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
1296 // Allocate on heap and retry.
1297 std::unique_ptr<char[]> szBuffer(new char[dwCapacity]);
1298 dwSize = dwCapacity;
1299 if (::QueryFullProcessImageNameA(hProcess, dwFlags, szBuffer.get(), &dwSize)) {
1300 sExeName.assign(szBuffer.get(), dwSize);
1301 return TRUE;
1302 }
1303 }
1304 return FALSE;
1305}
1306
1312template<class _Traits, class _Ax>
1313static _Success_(return != 0) BOOL QueryFullProcessImageNameW(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<wchar_t, _Traits, _Ax>& sExeName)
1314{
1315 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t)];
1316 DWORD dwSize = _countof(szStackBuffer);
1317
1318 // Try with stack buffer first.
1319 if (::QueryFullProcessImageNameW(hProcess, dwFlags, szStackBuffer, &dwSize)) {
1320 // Copy from stack.
1321 sExeName.assign(szStackBuffer, dwSize);
1322 return TRUE;
1323 }
1324 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
1325 // Allocate on heap and retry.
1326 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwCapacity]);
1327 dwSize = dwCapacity;
1328 if (::QueryFullProcessImageNameW(hProcess, dwFlags, szBuffer.get(), &dwSize)) {
1329 sExeName.assign(szBuffer.get(), dwSize);
1330 return TRUE;
1331 }
1332 }
1333 return FALSE;
1334}
1335
1337
1338#pragma warning(pop)
1339
1340namespace winstd
1341{
1344
1348 template<HANDLE INVALID>
1349 class win_handle : public handle<HANDLE, INVALID>
1350 {
1352
1353 public:
1359 virtual ~win_handle()
1360 {
1361 if (m_h != invalid)
1362 free_internal();
1363 }
1364
1365 protected:
1371 void free_internal() noexcept override
1372 {
1373 CloseHandle(m_h);
1374 }
1375 };
1376
1382 class library : public handle<HMODULE, NULL>
1383 {
1385
1386 public:
1392 virtual ~library()
1393 {
1394 if (m_h != invalid)
1395 free_internal();
1396 }
1397
1398 protected:
1404 void free_internal() noexcept override
1405 {
1406 FreeLibrary(m_h);
1407 }
1408 };
1409
1416
1423
1430
1437
1444
1448 template <class _Ty> struct UnmapViewOfFile_delete
1449 {
1451
1456
1461
1465 void operator()(_Ty* _Ptr) const
1466 {
1467 if (!UnmapViewOfFile(_Ptr))
1468 throw win_runtime_error("UnmapViewOfFile failed");
1469 }
1470 };
1471
1475 template <class _Ty> struct UnmapViewOfFile_delete<_Ty[]>
1476 {
1478
1483
1487 void operator()(_Ty* _Ptr) const
1488 {
1489 if (!UnmapViewOfFile(_Ptr))
1490 throw win_runtime_error("UnmapViewOfFile failed");
1491 }
1492
1496 template<class _Other>
1497 void operator()(_Other*) const
1498 {
1499 if (!UnmapViewOfFile(_Ptr))
1500 throw win_runtime_error("UnmapViewOfFile failed");
1501 }
1502 };
1503
1511
1516 {
1519
1520 public:
1527 {
1528 __try {
1529 InitializeCriticalSection(&m_data);
1530 } __except(EXCEPTION_EXECUTE_HANDLER) {
1531 throw std::runtime_error("InitializeCriticalSection failed");
1532 }
1533 }
1534
1541 {
1542 DeleteCriticalSection(&m_data);
1543 }
1544
1550 operator LPCRITICAL_SECTION() noexcept
1551 {
1552 return &m_data;
1553 }
1554
1555 protected:
1556 CRITICAL_SECTION m_data;
1557 };
1558
1564 class find_file : public handle<HANDLE, INVALID_HANDLE_VALUE>
1565 {
1566 WINSTD_HANDLE_IMPL(find_file, INVALID_HANDLE_VALUE)
1567
1568 public:
1574 virtual ~find_file()
1575 {
1576 if (m_h != invalid)
1577 free_internal();
1578 }
1579
1580 protected:
1586 void free_internal() noexcept override
1587 {
1588 FindClose(m_h);
1589 }
1590 };
1591
1597 class heap : public handle<HANDLE, NULL>
1598 {
1600
1601 public:
1607 virtual ~heap()
1608 {
1609 if (m_h != invalid)
1610 free_internal();
1611 }
1612
1620 bool enumerate() noexcept
1621 {
1622 assert(m_h != invalid);
1623
1624 bool found = false;
1625
1626 // Lock the heap for exclusive access.
1627 HeapLock(m_h);
1628
1629 PROCESS_HEAP_ENTRY e;
1630 e.lpData = NULL;
1631 while (HeapWalk(m_h, &e) != FALSE) {
1632 if ((e.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
1634 _T("Allocated block%s%s\n")
1635 _T(" Data portion begins at: %#p\n Size: %d bytes\n")
1636 _T(" Overhead: %d bytes\n Region index: %d\n"),
1637 (e.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0 ? tstring_printf(_T(", movable with HANDLE %#p"), e.Block.hMem).c_str() : _T(""),
1638 (e.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0 ? _T(", DDESHARE") : _T(""),
1639 e.lpData,
1640 e.cbData,
1641 e.cbOverhead,
1642 e.iRegionIndex);
1643
1644 found = true;
1645 }
1646 }
1647
1648 const DWORD dwResult = GetLastError();
1649 if (dwResult != ERROR_NO_MORE_ITEMS)
1650 OutputDebugStr(_T("HeapWalk failed (error %u).\n"), dwResult);
1651
1652 // Unlock the heap.
1653 HeapUnlock(m_h);
1654
1655 return found;
1656 }
1657
1658 protected:
1664 void free_internal() noexcept override
1665 {
1666 enumerate();
1667 HeapDestroy(m_h);
1668 }
1669 };
1670
1674 template <class _Ty>
1676 {
1677 public:
1678 typedef typename _Ty value_type;
1679
1680 typedef _Ty *pointer;
1681 typedef _Ty& reference;
1682 typedef const _Ty *const_pointer;
1683 typedef const _Ty& const_reference;
1684
1685 typedef SIZE_T size_type;
1686 typedef ptrdiff_t difference_type;
1687
1691 template <class _Other>
1692 struct rebind
1693 {
1695 };
1696
1697 public:
1704 {
1705 }
1706
1712 template <class _Other>
1714 {
1715 }
1716
1725 {
1726 assert(m_heap);
1727 return (pointer)HeapAlloc(m_heap, 0, count * sizeof(_Ty));
1728 }
1729
1736 void deallocate(_In_ pointer ptr, _In_ size_type size)
1737 {
1738 UNREFERENCED_PARAMETER(size);
1739 assert(m_heap);
1740 HeapFree(m_heap, 0, ptr);
1741 }
1742
1749 void construct(_Inout_ pointer ptr, _In_ const _Ty& val)
1750 {
1751 ::new ((void*)ptr) _Ty(val);
1752 }
1753
1760 void construct(_Inout_ pointer ptr, _Inout_ _Ty&& val)
1761 {
1762 ::new ((void*)ptr) _Ty(std::forward<_Ty>(val));
1763 }
1764
1770 void destroy(_Inout_ pointer ptr)
1771 {
1772 ptr->_Ty::~_Ty();
1773 }
1774
1779 {
1780 return (SIZE_T)-1;
1781 }
1782
1783 public:
1784 HANDLE m_heap;
1785 };
1786
1791 {
1794
1795 public:
1803 actctx_activator(_In_ HANDLE hActCtx) noexcept
1804 {
1805 if (!ActivateActCtx(hActCtx, &m_cookie))
1806 m_cookie = 0;
1807 }
1808
1815 {
1816 if (m_cookie)
1817 DeactivateActCtx(0, m_cookie);
1818 }
1819
1820 protected:
1821 ULONG_PTR m_cookie;
1822 };
1823
1828 {
1831
1832 public:
1840 user_impersonator(_In_opt_ HANDLE hToken) noexcept
1841 {
1842 m_cookie = hToken && ImpersonateLoggedOnUser(hToken);
1843 }
1844
1851 {
1852 if (m_cookie)
1853 RevertToSelf();
1854 }
1855
1856 protected:
1858 };
1859
1864 {
1867
1868 public:
1876 console_ctrl_handler(_In_opt_ PHANDLER_ROUTINE HandlerRoutine) noexcept : m_handler(HandlerRoutine)
1877 {
1878 m_cookie = SetConsoleCtrlHandler(m_handler, TRUE);
1879 }
1880
1887 {
1888 if (m_cookie)
1889 SetConsoleCtrlHandler(m_handler, FALSE);
1890 }
1891
1892 protected:
1894 PHANDLER_ROUTINE m_handler;
1895 };
1896
1900 class vmemory : public handle<LPVOID, NULL>
1901 {
1903
1904 public:
1908 vmemory() noexcept : m_proc(NULL)
1909 {
1910 }
1911
1918 vmemory(_In_ handle_type h, _In_ HANDLE proc) noexcept :
1919 m_proc(proc),
1921 {
1922 }
1923
1929 vmemory(_Inout_ vmemory &&h) noexcept :
1930 m_proc(std::move(h.m_proc)),
1931 handle<LPVOID, NULL>(std::move(h))
1932 {
1933 }
1934
1940 virtual ~vmemory()
1941 {
1942 if (m_h != invalid)
1943 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
1944 }
1945
1951 vmemory& operator=(_Inout_ vmemory &&other) noexcept
1952 {
1953 if (this != std::addressof(other)) {
1954 (handle<handle_type, NULL>&&)*this = std::move(other);
1955 m_proc = std::move(other.m_proc);
1956 }
1957 return *this;
1958 }
1959
1968 void attach(_In_ HANDLE proc, _In_opt_ handle_type h) noexcept
1969 {
1970 m_proc = proc;
1971 if (m_h != invalid)
1972 free_internal();
1973 m_h = h;
1974 }
1975
1985 bool alloc(
1986 _In_ HANDLE hProcess,
1987 _In_opt_ LPVOID lpAddress,
1988 _In_ SIZE_T dwSize,
1989 _In_ DWORD flAllocationType,
1990 _In_ DWORD flProtect) noexcept
1991 {
1992 handle_type h = VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect);
1993 if (h != invalid) {
1994 attach(hProcess, h);
1995 return true;
1996 } else
1997 return false;
1998 }
1999
2000 protected:
2006 void free_internal() noexcept override
2007 {
2008 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
2009 }
2010
2011 protected:
2012 HANDLE m_proc;
2013 };
2014
2021 class reg_key : public handle<HKEY, NULL>
2022 {
2024
2025 public:
2031 virtual ~reg_key()
2032 {
2033 if (m_h != invalid)
2034 free_internal();
2035 }
2036
2046 bool delete_subkey(_In_z_ LPCTSTR szSubkey)
2047 {
2048 LSTATUS s;
2049
2050 s = RegDeleteKey(m_h, szSubkey);
2051 if (s == ERROR_SUCCESS || s == ERROR_FILE_NOT_FOUND)
2052 return true;
2053
2054 {
2055 reg_key k;
2056 handle_type h;
2057 s = RegOpenKeyEx(m_h, szSubkey, 0, KEY_ENUMERATE_SUB_KEYS, &h);
2058 if (s == ERROR_SUCCESS)
2059 k.attach(h);
2060 else {
2061 SetLastError(s);
2062 return false;
2063 }
2064 for (;;) {
2065 TCHAR szName[MAX_PATH];
2066 DWORD dwSize = _countof(szName);
2067 s = RegEnumKeyEx(k, 0, szName, &dwSize, NULL, NULL, NULL, NULL);
2068 if (s == ERROR_SUCCESS)
2069 k.delete_subkey(szName);
2070 else if (s == ERROR_NO_MORE_ITEMS)
2071 break;
2072 else {
2073 SetLastError(s);
2074 return false;
2075 }
2076 }
2077 }
2078
2079 s = RegDeleteKey(m_h, szSubkey);
2080 if (s == ERROR_SUCCESS)
2081 return true;
2082 else {
2083 SetLastError(s);
2084 return false;
2085 }
2086 }
2087
2088 protected:
2094 void free_internal() noexcept override
2095 {
2096 RegCloseKey(m_h);
2097 }
2098 };
2099
2103 class security_id : public handle<PSID, NULL>
2104 {
2106
2107 public:
2114 {
2115 if (m_h != invalid)
2116 free_internal();
2117 }
2118
2119 protected:
2125 void free_internal() noexcept override
2126 {
2127 FreeSid(m_h);
2128 }
2129 };
2130
2134 class process_information : public PROCESS_INFORMATION
2135 {
2138
2139 public:
2144 {
2145 hProcess = INVALID_HANDLE_VALUE;
2146 hThread = INVALID_HANDLE_VALUE;
2147 dwProcessId = 0;
2148 dwThreadId = 0;
2149 }
2150
2155 {
2156 #pragma warning(push)
2157 #pragma warning(disable: 6001) // Using uninitialized memory '*this'. << ???
2158
2159 if (hProcess != INVALID_HANDLE_VALUE)
2160 CloseHandle(hProcess);
2161
2162 if (hThread != INVALID_HANDLE_VALUE)
2163 CloseHandle(hThread);
2164
2165 #pragma warning(pop)
2166 }
2167 };
2168
2174 class event_log : public handle<HANDLE, NULL>
2175 {
2177
2178 public:
2184 virtual ~event_log()
2185 {
2186 if (m_h != invalid)
2187 free_internal();
2188 }
2189
2190 protected:
2196 void free_internal() noexcept override
2197 {
2198 DeregisterEventSource(m_h);
2199 }
2200 };
2201
2203}
2204
2207
2208#pragma warning(push)
2209#pragma warning(disable: 4505) // Don't warn on unused code
2210
2212static LSTATUS RegCreateKeyExA(
2213 _In_ HKEY hKey,
2214 _In_ LPCSTR lpSubKey,
2215 _Reserved_ DWORD Reserved,
2216 _In_opt_ LPSTR lpClass,
2217 _In_ DWORD dwOptions,
2218 _In_ REGSAM samDesired,
2219 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2220 _Inout_ winstd::reg_key &result,
2221 _Out_opt_ LPDWORD lpdwDisposition)
2222{
2223 HKEY h;
2224 LSTATUS s = RegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2225 if (s == ERROR_SUCCESS)
2226 result.attach(h);
2227 return s;
2228}
2229
2235static LSTATUS RegCreateKeyExW(
2236 _In_ HKEY hKey,
2237 _In_ LPCWSTR lpSubKey,
2238 _Reserved_ DWORD Reserved,
2239 _In_opt_ LPWSTR lpClass,
2240 _In_ DWORD dwOptions,
2241 _In_ REGSAM samDesired,
2242 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2243 _Inout_ winstd::reg_key &result,
2244 _Out_opt_ LPDWORD lpdwDisposition)
2245{
2246 HKEY h;
2247 LSTATUS s = RegCreateKeyExW(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2248 if (s == ERROR_SUCCESS)
2249 result.attach(h);
2250 return s;
2251}
2252
2254static LSTATUS RegOpenKeyExA(
2255 _In_ HKEY hKey,
2256 _In_opt_ LPCSTR lpSubKey,
2257 _In_opt_ DWORD ulOptions,
2258 _In_ REGSAM samDesired,
2259 _Inout_ winstd::reg_key &result)
2260{
2261 HKEY h;
2262 LSTATUS s = RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, &h);
2263 if (s == ERROR_SUCCESS)
2264 result.attach(h);
2265 return s;
2266}
2267
2277static LSTATUS RegOpenKeyExW(
2278 _In_ HKEY hKey,
2279 _In_opt_ LPCWSTR lpSubKey,
2280 _In_opt_ DWORD ulOptions,
2281 _In_ REGSAM samDesired,
2282 _Inout_ winstd::reg_key &result)
2283{
2284 HKEY h;
2285 LSTATUS s = RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, &h);
2286 if (s == ERROR_SUCCESS)
2287 result.attach(h);
2288 return s;
2289}
2290
2291#pragma warning(pop)
2292
General API.
Activates given activation context in constructor and deactivates it in destructor.
Definition: Win.h:1791
actctx_activator(HANDLE hActCtx) noexcept
Construct the activator and activates the given activation context.
Definition: Win.h:1803
virtual ~actctx_activator()
Deactivates activation context and destructs the activator.
Definition: Win.h:1814
ULONG_PTR m_cookie
Cookie for context deactivation.
Definition: Win.h:1821
Base template class to support string formatting using printf() style templates.
Definition: Common.h:1123
Console control handler stack management.
Definition: Win.h:1864
console_ctrl_handler(PHANDLER_ROUTINE HandlerRoutine) noexcept
Construct the console control handler object and pushes the given handler to the console control hand...
Definition: Win.h:1876
virtual ~console_ctrl_handler()
Pops console control handler from the console control handler stack.
Definition: Win.h:1886
PHANDLER_ROUTINE m_handler
Pointer to console control handler.
Definition: Win.h:1894
BOOL m_cookie
Did pushing the console control handler succeed?
Definition: Win.h:1893
Critical section wrapper.
Definition: Win.h:1516
CRITICAL_SECTION m_data
Critical section struct.
Definition: Win.h:1556
virtual ~critical_section()
Releases all resources used by an unowned critical section object.
Definition: Win.h:1540
critical_section()
Construct the object and initializes a critical section object.
Definition: Win.h:1526
Event log handle wrapper.
Definition: Win.h:2175
void free_internal() noexcept override
Closes an event log handle.
Definition: Win.h:2196
virtual ~event_log()
Closes an event log handle.
Definition: Win.h:2184
Find-file handle wrapper.
Definition: Win.h:1565
virtual ~find_file()
Closes a file search handle.
Definition: Win.h:1574
void free_internal() noexcept override
Closes a file search handle.
Definition: Win.h:1586
Base abstract template class to support generic object handle keeping.
Definition: Common.h:615
LPVOID handle_type
Datatype of the object handle this template class handles.
Definition: Common.h:620
handle_type m_h
Object handle.
Definition: Common.h:866
void attach(handle_type h) noexcept
Sets a new object handle for the class.
Definition: Common.h:829
HeapAlloc allocator.
Definition: Win.h:1676
SIZE_T size_type
An unsigned integral type that can represent the length of any sequence that an object of template cl...
Definition: Win.h:1685
_Ty value_type
A type that is managed by the allocator.
Definition: Win.h:1678
heap_allocator(const heap_allocator< _Other > &other)
Constructs allocator from another type.
Definition: Win.h:1713
HANDLE m_heap
Heap handle.
Definition: Win.h:1784
pointer allocate(size_type count)
Allocates a new memory block.
Definition: Win.h:1724
ptrdiff_t difference_type
A signed integral type that can represent the difference between values of pointers to the type of ob...
Definition: Win.h:1686
heap_allocator(HANDLE heap)
Constructs allocator.
Definition: Win.h:1703
_Ty & reference
A type that provides a reference to the type of object managed by the allocator.
Definition: Win.h:1681
void construct(pointer ptr, _Ty &&val)
Calls moving constructor for the element.
Definition: Win.h:1760
void deallocate(pointer ptr, size_type size)
Frees memory block.
Definition: Win.h:1736
size_type max_size() const
Returns maximum memory block size.
Definition: Win.h:1778
void construct(pointer ptr, const _Ty &val)
Calls copying constructor for the element.
Definition: Win.h:1749
const _Ty & const_reference
A type that provides a constant reference to type of object managed by the allocator.
Definition: Win.h:1683
const _Ty * const_pointer
A type that provides a constant pointer to the type of object managed by the allocator.
Definition: Win.h:1682
_Ty * pointer
A type that provides a pointer to the type of object managed by the allocator.
Definition: Win.h:1680
void destroy(pointer ptr)
Calls destructor for the element.
Definition: Win.h:1770
Heap handle wrapper.
Definition: Win.h:1598
bool enumerate() noexcept
Enumerates allocated heap blocks using OutputDebugString()
Definition: Win.h:1620
void free_internal() noexcept override
Destroys the heap.
Definition: Win.h:1664
virtual ~heap()
Destroys the heap.
Definition: Win.h:1607
Module handle wrapper.
Definition: Win.h:1383
void free_internal() noexcept override
Frees the module.
Definition: Win.h:1404
virtual ~library()
Frees the module.
Definition: Win.h:1392
PROCESS_INFORMATION struct wrapper.
Definition: Win.h:2135
~process_information()
Closes process and thread handles.
Definition: Win.h:2154
process_information() noexcept
Constructs blank PROCESS_INFORMATION.
Definition: Win.h:2143
Registry key wrapper class.
Definition: Win.h:2022
void free_internal() noexcept override
Closes a handle to the registry key.
Definition: Win.h:2094
bool delete_subkey(LPCTSTR szSubkey)
Deletes the specified registry subkey.
Definition: Win.h:2046
virtual ~reg_key()
Closes a handle to the registry key.
Definition: Win.h:2031
SID wrapper class.
Definition: Win.h:2104
void free_internal() noexcept override
Closes a handle to the SID.
Definition: Win.h:2125
virtual ~security_id()
Closes a handle to the SID.
Definition: Win.h:2113
Lets the calling thread impersonate the security context of a logged-on user.
Definition: Win.h:1828
BOOL m_cookie
Did impersonation succeed?
Definition: Win.h:1857
user_impersonator(HANDLE hToken) noexcept
Construct the impersonator and impersonates the given user.
Definition: Win.h:1840
virtual ~user_impersonator()
Reverts to current user and destructs the impersonator.
Definition: Win.h:1850
Memory in virtual address space of a process handle wrapper.
Definition: Win.h:1901
vmemory & operator=(vmemory &&other) noexcept
Move assignment.
Definition: Win.h:1951
bool alloc(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) noexcept
Reserves, commits, or changes the state of a region of memory within the virtual address space of a s...
Definition: Win.h:1985
void free_internal() noexcept override
Frees the memory.
Definition: Win.h:2006
void attach(HANDLE proc, handle_type h) noexcept
Sets a new memory handle for the class.
Definition: Win.h:1968
virtual ~vmemory()
Frees the memory.
Definition: Win.h:1940
vmemory(handle_type h, HANDLE proc) noexcept
Initializes a new class instance with an already available object handle.
Definition: Win.h:1918
vmemory() noexcept
Initializes a new class instance with the memory handle set to INVAL.
Definition: Win.h:1908
vmemory(vmemory &&h) noexcept
Move constructor.
Definition: Win.h:1929
HANDLE m_proc
Handle of memory's process.
Definition: Win.h:2012
Windows HANDLE wrapper class.
Definition: Win.h:1350
void free_internal() noexcept override
Closes an open object handle.
Definition: Win.h:1371
virtual ~win_handle()
Closes an open object handle.
Definition: Win.h:1359
Windows runtime error.
Definition: Common.h:1056
#define WINSTD_NONCOPYABLE(C)
Declares a class as non-copyable.
Definition: Common.h:74
#define WINSTD_STACK_BUFFER_BYTES
Size of the stack buffer in bytes used for initial system function call.
Definition: Common.h:101
#define WINSTD_NONMOVABLE(C)
Declares a class as non-movable.
Definition: Common.h:82
static int vsprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format, va_list arg)
Formats string using printf().
Definition: Common.h:259
static int sprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format,...)
Formats string using printf().
Definition: Common.h:292
#define WINSTD_HANDLE_IMPL(C, INVAL)
Implements default constructors and operators to prevent their auto-generation by compiler.
Definition: Common.h:171
static const HANDLE invalid
Invalid handle value.
Definition: Common.h:625
static int NormalizeString(NORM_FORM NormForm, LPCWSTR lpSrcString, int cwSrcLength, std::basic_string< wchar_t, _Traits, _Ax > &sDstString) noexcept
Normalizes characters of a text string according to Unicode 4.0 TR#15.
Definition: Win.h:974
static int SecureWideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, std::basic_string< char, _Traits, _Ax > &sMultiByteStr, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar) noexcept
Maps a UTF-16 (wide character) string to a std::string. The new character string is not necessarily f...
Definition: Win.h:717
static DWORD ExpandEnvironmentStringsA(LPCSTR lpSrc, std::basic_string< char, _Traits, _Ax > &sValue) noexcept
Expands environment-variable strings, replaces them with the values defined for the current user,...
Definition: Win.h:181
static BOOL StringToGuidA(LPCSTR lpszGuid, LPGUID lpGuid, LPCSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition: Win.h:270
static int GetWindowTextA(HWND hWnd, std::basic_string< char, _Traits, _Ax > &sValue) noexcept
Copies the text of the specified window's title bar (if it has one) into a std::wstring string.
Definition: Win.h:83
static LSTATUS RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions, REGSAM samDesired, CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes, winstd::reg_key &result, LPDWORD lpdwDisposition)
Creates the specified registry key. If the key already exists, the function opens it.
Definition: Win.h:2235
static int WINAPI LoadStringA(HINSTANCE hInstance, UINT uID, std::basic_string< char, _Traits, _Ax > &sBuffer) noexcept
Loads a string resource from the executable file associated with a specified module.
Definition: Win.h:1056
win_handle< INVALID_HANDLE_VALUE > file
File handle wrapper.
Definition: Win.h:1436
static BOOL GetFileVersionInfoA(LPCSTR lptstrFilename, __reserved DWORD dwHandle, std::vector< _Ty, _Ax > &aValue) noexcept
Retrieves version information for the specified file and stores it in a std::vector buffer.
Definition: Win.h:145
static int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, std::basic_string< wchar_t, _Traits, _Ax > &sWideCharStr) noexcept
Maps a character string to a UTF-16 (wide character) std::wstring. The character string is not necess...
Definition: Win.h:806
static LSTATUS RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, REGSAM samDesired, CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes, winstd::reg_key &result, LPDWORD lpdwDisposition)
Creates the specified registry key. If the key already exists, the function opens it.
Definition: Win.h:2212
static LSTATUS RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition: Win.h:2254
static LSTATUS RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition: Win.h:2277
static VOID GuidToStringA(LPCGUID lpGuid, std::basic_string< char, _Traits, _Ax > &str) noexcept
Formats GUID and stores it in a std::wstring string.
Definition: Win.h:231
static BOOL StringToGuidW(LPCWSTR lpszGuid, LPGUID lpGuid, LPCWSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition: Win.h:343
static LSTATUS RegLoadMUIStringW(HKEY hKey, LPCWSTR pszValue, std::basic_string< wchar_t, _Traits, _Ax > &sOut, DWORD Flags, LPCWSTR pszDirectory) noexcept
Loads the specified string from the specified key and subkey, and stores it in a std::wstring string.
Definition: Win.h:608
static BOOL LookupAccountSidA(LPCSTR lpSystemName, PSID lpSid, std::basic_string< char, _Traits, _Ax > *sName, std::basic_string< char, _Traits, _Ax > *sReferencedDomainName, PSID_NAME_USE peUse) noexcept
Retrieves the name of the account for this SID and the name of the first domain on which this SID is ...
Definition: Win.h:1174
static DWORD GetModuleFileNameW(HMODULE hModule, std::basic_string< wchar_t, _Traits, _Ax > &sValue) noexcept
Retrieves the fully qualified path for the file that contains the specified module and stores it in a...
Definition: Win.h:58
static BOOL LookupAccountSidW(LPCWSTR lpSystemName, PSID lpSid, std::basic_string< wchar_t, _Traits, _Ax > *sName, std::basic_string< wchar_t, _Traits, _Ax > *sReferencedDomainName, PSID_NAME_USE peUse) noexcept
Retrieves the name of the account for this SID and the name of the first domain on which this SID is ...
Definition: Win.h:1213
win_handle< INVALID_HANDLE_VALUE > process_snapshot
Process snapshot handle wrapper.
Definition: Win.h:1429
static DWORD GetModuleFileNameA(HMODULE hModule, std::basic_string< char, _Traits, _Ax > &sValue) noexcept
Retrieves the fully qualified path for the file that contains the specified module and stores it in a...
Definition: Win.h:27
static int GetDateFormatW(LCID Locale, DWORD dwFlags, const SYSTEMTIME *lpDate, LPCWSTR lpFormat, std::basic_string< wchar_t, _Traits, _Ax > &sDate) noexcept
Formats a date as a date string for a locale specified by the locale identifier. The function formats...
Definition: Win.h:1158
static int WINAPI LoadStringW(HINSTANCE hInstance, UINT uID, std::basic_string< wchar_t, _Traits, _Ax > &sBuffer) noexcept
Loads a string resource from the executable file associated with a specified module.
Definition: Win.h:1074
static BOOL GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, std::unique_ptr< _Ty > &TokenInformation) noexcept
Retrieves a specified type of information about an access token. The calling process must have approp...
Definition: Win.h:1252
static LSTATUS RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, __reserved LPDWORD lpReserved, LPDWORD lpType, std::vector< _Ty, _Ax > &aData) noexcept
Retrieves the type and data for the specified value name associated with an open registry key and sto...
Definition: Win.h:569
static BOOL GetFileVersionInfoW(LPCWSTR lptstrFilename, __reserved DWORD dwHandle, std::vector< _Ty, _Ax > &aValue) noexcept
Retrieves version information for the specified file and stores it in a std::vector buffer.
Definition: Win.h:165
win_handle< NULL > event
Event handle wrapper.
Definition: Win.h:1510
static LSTATUS RegLoadMUIStringA(HKEY hKey, LPCSTR pszValue, std::basic_string< char, _Traits, _Ax > &sOut, DWORD Flags, LPCSTR pszDirectory) noexcept
Loads the specified string from the specified key and subkey, and stores it in a std::wstring string.
Definition: Win.h:594
static VOID OutputDebugStr(LPCSTR lpOutputString,...) noexcept
Formats and sends a string to the debugger for display.
Definition: Win.h:1115
static BOOL QueryFullProcessImageNameA(HANDLE hProcess, DWORD dwFlags, std::basic_string< char, _Traits, _Ax > &sExeName)
Retrieves the full name of the executable image for the specified process.
Definition: Win.h:1284
win_handle< NULL > file_mapping
File mapping.
Definition: Win.h:1443
static int SecureMultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, std::basic_string< wchar_t, _Traits, _Ax > &sWideCharStr) noexcept
Maps a character string to a UTF-16 (wide character) std::wstring. The character string is not necess...
Definition: Win.h:885
static int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, std::basic_string< char, _Traits, _Ax > &sMultiByteStr, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar) noexcept
Maps a UTF-16 (wide character) string to a std::string. The new character string is not necessarily f...
Definition: Win.h:638
static BOOL QueryFullProcessImageNameW(HANDLE hProcess, DWORD dwFlags, std::basic_string< wchar_t, _Traits, _Ax > &sExeName)
Retrieves the full name of the executable image for the specified process.
Definition: Win.h:1313
win_handle< NULL > process
Process handle wrapper.
Definition: Win.h:1415
static LSTATUS RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, __reserved LPDWORD lpReserved, LPDWORD lpType, std::vector< _Ty, _Ax > &aData) noexcept
Retrieves the type and data for the specified value name associated with an open registry key and sto...
Definition: Win.h:542
static LSTATUS RegQueryStringValue(HKEY hReg, LPCSTR pszName, std::basic_string< char, _Traits, _Ax > &sValue) noexcept
Queries for a string value in the registry and stores it in a std::string string.
Definition: Win.h:431
static int GetWindowTextW(HWND hWnd, std::basic_string< wchar_t, _Traits, _Ax > &sValue) noexcept
Copies the text of the specified window's title bar (if it has one) into a std::wstring string.
Definition: Win.h:116
static int GetDateFormatA(LCID Locale, DWORD dwFlags, const SYSTEMTIME *lpDate, LPCSTR lpFormat, std::basic_string< char, _Traits, _Ax > &sDate) noexcept
Formats a date as a date string for a locale specified by the locale identifier. The function formats...
Definition: Win.h:1138
static DWORD ExpandEnvironmentStringsW(LPCWSTR lpSrc, std::basic_string< wchar_t, _Traits, _Ax > &sValue) noexcept
Expands environment-variable strings, replaces them with the values defined for the current user,...
Definition: Win.h:209
static VOID GuidToStringW(LPCGUID lpGuid, std::basic_string< wchar_t, _Traits, _Ax > &str) noexcept
Formats GUID and stores it in a std::wstring string.
Definition: Win.h:250
static VOID OutputDebugStrV(LPCSTR lpOutputString, va_list arg) noexcept
Formats and sends a string to the debugger for display.
Definition: Win.h:1091
win_handle< NULL > thread
Thread handle wrapper.
Definition: Win.h:1422
UnmapViewOfFile_delete()
Default construct.
Definition: Win.h:1482
void operator()(_Other *) const
Delete a pointer of another type.
Definition: Win.h:1497
void operator()(_Ty *_Ptr) const
Delete a pointer.
Definition: Win.h:1487
UnmapViewOfFile_delete< _Ty > _Myt
This type.
Definition: Win.h:1477
Deleter for unique_ptr using UnmapViewOfFile.
Definition: Win.h:1449
UnmapViewOfFile_delete(const UnmapViewOfFile_delete< _Ty2 > &)
Construct from another UnmapViewOfFile_delete.
Definition: Win.h:1460
void operator()(_Ty *_Ptr) const
Delete a pointer.
Definition: Win.h:1465
UnmapViewOfFile_delete< _Ty > _Myt
This type.
Definition: Win.h:1450
UnmapViewOfFile_delete()
Default construct.
Definition: Win.h:1455
A structure that enables an allocator for objects of one type to allocate storage for objects of anot...
Definition: Win.h:1693
heap_allocator< _Other > other
Other allocator type.
Definition: Win.h:1694