WinStd
Windows Win32 API using Standard C++
Loading...
Searching...
No Matches
Win.h
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 1991-2022 Amebis
4 Copyright © 2016 GÉANT
5*/
6
8
9#pragma once
10
11#include "Common.h"
12#include <tlhelp32.h>
13#include <string>
14#include <vector>
15
16#pragma warning(push)
17#pragma warning(disable: 4505) // Don't warn on unused code
18
21
23template<class _Traits, class _Ax>
24static DWORD GetModuleFileNameA(_In_opt_ HMODULE hModule, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
25{
26 assert(0); // TODO: Test this code.
27
28 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
29
30 // Try with stack buffer first.
31 DWORD dwResult = ::GetModuleFileNameA(hModule, szStackBuffer, _countof(szStackBuffer));
32 if (dwResult < _countof(szStackBuffer)) {
33 // Copy from stack.
34 sValue.assign(szStackBuffer, dwResult);
35 return dwResult;
36 } else {
37 for (DWORD dwCapacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(char);; dwCapacity *= 2) {
38 // Allocate on heap and retry.
39 std::unique_ptr<char[]> szBuffer(new char[dwCapacity]);
40 dwResult = ::GetModuleFileNameA(hModule, szBuffer.get(), dwCapacity);
41 if (dwResult < dwCapacity) {
42 sValue.assign(szBuffer.get(), dwResult);
43 return dwResult;
44 }
45 }
46 }
47}
48
54template<class _Traits, class _Ax>
55static DWORD GetModuleFileNameW(_In_opt_ HMODULE hModule, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
56{
57 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
58
59 // Try with stack buffer first.
60 DWORD dwResult = ::GetModuleFileNameW(hModule, szStackBuffer, _countof(szStackBuffer));
61 if (dwResult < _countof(szStackBuffer)) {
62 // Copy from stack.
63 sValue.assign(szStackBuffer, dwResult);
64 return dwResult;
65 } else {
66 for (DWORD dwCapacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t);; dwCapacity *= 2) {
67 // Allocate on heap and retry.
68 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwCapacity]);
69 dwResult = ::GetModuleFileNameW(hModule, szBuffer.get(), dwCapacity);
70 if (dwResult < dwCapacity) {
71 sValue.assign(szBuffer.get(), dwResult);
72 return dwResult;
73 }
74 }
75 }
76}
77
79template<class _Traits, class _Ax>
80static _Success_(return != 0) int GetWindowTextA(_In_ HWND hWnd, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
81{
82 assert(0); // TODO: Test this code.
83
84 int iResult;
85
86 // Query the final string length first.
87 iResult = ::GetWindowTextLengthA(hWnd);
88 if (iResult > 0) {
89 if (++iResult < WINSTD_STACK_BUFFER_BYTES/sizeof(char)) {
90 // Read string data to stack.
91 char szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
92 iResult = ::GetWindowTextA(hWnd, szBuffer, _countof(szBuffer));
93 sValue.assign(szBuffer, iResult);
94 } else {
95 // Allocate buffer on heap and read the string data into it.
96 std::unique_ptr<char[]> szBuffer(new char[++iResult]);
97 iResult = ::GetWindowTextA(hWnd, szBuffer.get(), iResult);
98 sValue.assign(szBuffer.get(), iResult);
99 }
100 return iResult;
101 }
102
103 sValue.clear();
104 return 0;
105}
106
112template<class _Traits, class _Ax>
113static _Success_(return != 0) int GetWindowTextW(_In_ HWND hWnd, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
114{
115 assert(0); // TODO: Test this code.
116
117 int iResult;
118
119 // Query the final string length first.
120 iResult = ::GetWindowTextLengthW(hWnd);
121 if (iResult > 0) {
122 if (++iResult < WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)) {
123 // Read string data to stack.
124 wchar_t szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
125 iResult = ::GetWindowTextW(hWnd, szBuffer, _countof(szBuffer));
126 sValue.assign(szBuffer, iResult);
127 } else {
128 // Allocate buffer on heap and read the string data into it.
129 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[++iResult]);
130 iResult = ::GetWindowTextW(hWnd, szBuffer.get(), iResult);
131 sValue.assign(szBuffer.get(), iResult);
132 }
133 return iResult;
134 }
135
136 sValue.clear();
137 return 0;
138}
139
141template<class _Ty, class _Ax>
142static _Success_(return != 0) BOOL GetFileVersionInfoA(_In_z_ LPCSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<_Ty, _Ax> &aValue) noexcept
143{
144 assert(0); // TODO: Test this code.
145
146 // Get version info size.
147 DWORD dwVerInfoSize = ::GetFileVersionInfoSizeA(lptstrFilename, &dwHandle);
148 if (dwVerInfoSize != 0) {
149 // Read version info.
150 aValue.resize((dwVerInfoSize + sizeof(_Ty) - 1) / sizeof(_Ty));
151 return ::GetFileVersionInfoA(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
152 } else
153 return FALSE;
154}
155
161template<class _Ty, class _Ax>
162static _Success_(return != 0) BOOL GetFileVersionInfoW(_In_z_ LPCWSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<_Ty, _Ax> &aValue) noexcept
163{
164 assert(0); // TODO: Test this code.
165
166 // Get version info size.
167 DWORD dwVerInfoSize = ::GetFileVersionInfoSizeW(lptstrFilename, &dwHandle);
168 if (dwVerInfoSize != 0) {
169 // Read version info.
170 aValue.resize((dwVerInfoSize + sizeof(_Ty) - 1) / sizeof(_Ty));
171 return ::GetFileVersionInfoW(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
172 } else
173 return FALSE;
174}
175
177template<class _Traits, class _Ax>
178static _Success_(return != 0) DWORD ExpandEnvironmentStringsA(_In_z_ LPCSTR lpSrc, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
179{
180 assert(0); // TODO: Test this code.
181
182 for (DWORD dwSizeOut = (DWORD)strlen(lpSrc) + 0x100;;) {
183 DWORD dwSizeIn = dwSizeOut;
184 std::unique_ptr<char[]> szBuffer(new char[(size_t)dwSizeIn + 2]); // Note: ANSI version requires one extra char.
185 dwSizeOut = ::ExpandEnvironmentStringsA(lpSrc, szBuffer.get(), dwSizeIn);
186 if (dwSizeOut == 0) {
187 // Error or zero-length input.
188 break;
189 } else if (dwSizeOut <= dwSizeIn) {
190 // The buffer was sufficient.
191 sValue.assign(szBuffer.get(), dwSizeOut - 1);
192 return dwSizeOut;
193 }
194 }
195
196 sValue.clear();
197 return 0;
198}
199
205template<class _Traits, class _Ax>
206static _Success_(return != 0) DWORD ExpandEnvironmentStringsW(_In_z_ LPCWSTR lpSrc, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
207{
208 for (DWORD dwSizeOut = (DWORD)wcslen(lpSrc) + 0x100;;) {
209 DWORD dwSizeIn = dwSizeOut;
210 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[(size_t)dwSizeIn + 1]);
211 dwSizeOut = ::ExpandEnvironmentStringsW(lpSrc, szBuffer.get(), dwSizeIn);
212 if (dwSizeOut == 0) {
213 // Error or zero-length input.
214 break;
215 } else if (dwSizeOut <= dwSizeIn) {
216 // The buffer was sufficient.
217 sValue.assign(szBuffer.get(), dwSizeOut - 1);
218 return dwSizeOut;
219 }
220 }
221
222 sValue.clear();
223 return 0;
224}
225
227template<class _Traits, class _Ax>
228static VOID GuidToStringA(_In_ LPCGUID lpGuid, _Out_ std::basic_string<char, _Traits, _Ax> &str) noexcept
229{
230 assert(0); // TODO: Test this code.
231
232 sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
233 lpGuid->Data1,
234 lpGuid->Data2,
235 lpGuid->Data3,
236 lpGuid->Data4[0], lpGuid->Data4[1],
237 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
238}
239
246template<class _Traits, class _Ax>
247static VOID GuidToStringW(_In_ LPCGUID lpGuid, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &str) noexcept
248{
249 assert(0); // TODO: Test this code.
250
251 sprintf(str, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
252 lpGuid->Data1,
253 lpGuid->Data2,
254 lpGuid->Data3,
255 lpGuid->Data4[0], lpGuid->Data4[1],
256 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
257}
258
260#ifdef _UNICODE
261#define GuidToString GuidToStringW
262#else
263#define GuidToString GuidToStringA
264#endif
265
267static _Success_(return) BOOL StringToGuidA(_In_z_ LPCSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCSTR *lpszGuidEnd = NULL) noexcept
268{
269 GUID g;
270 LPSTR lpszEnd;
271 unsigned long ulTmp;
272 unsigned long long ullTmp;
273
274 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
275 lpszGuid++;
276
277 g.Data1 = strtoul(lpszGuid, &lpszEnd, 16);
278 if (errno == ERANGE) return FALSE;
279 lpszGuid = lpszEnd;
280
281 if (*lpszGuid != '-') return FALSE;
282 lpszGuid++;
283
284 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
285 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
286 g.Data2 = static_cast<unsigned short>(ulTmp);
287 lpszGuid = lpszEnd;
288
289 if (*lpszGuid != '-') return FALSE;
290 lpszGuid++;
291
292 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
293 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
294 g.Data3 = static_cast<unsigned short>(ulTmp);
295 lpszGuid = lpszEnd;
296
297 if (*lpszGuid != '-') return FALSE;
298 lpszGuid++;
299
300 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
301 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
302 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
303 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
304 lpszGuid = lpszEnd;
305
306 if (*lpszGuid != '-') return FALSE;
307 lpszGuid++;
308
309 ullTmp = _strtoui64(lpszGuid, &lpszEnd, 16);
310 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
311 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
312 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
313 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
314 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
315 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
316 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
317 lpszGuid = lpszEnd;
318
319 if (*lpszGuid != '}') return FALSE;
320 lpszGuid++;
321
322 if (lpszGuidEnd)
323 *lpszGuidEnd = lpszGuid;
324
325 *lpGuid = g;
326 return TRUE;
327}
328
340static _Success_(return) BOOL StringToGuidW(_In_z_ LPCWSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCWSTR *lpszGuidEnd = NULL) noexcept
341{
342 GUID g;
343 LPWSTR lpszEnd;
344 unsigned long ulTmp;
345 unsigned long long ullTmp;
346
347 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
348 lpszGuid++;
349
350 g.Data1 = wcstoul(lpszGuid, &lpszEnd, 16);
351 if (errno == ERANGE) return FALSE;
352 lpszGuid = lpszEnd;
353
354 if (*lpszGuid != '-') return FALSE;
355 lpszGuid++;
356
357 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
358 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
359 g.Data2 = static_cast<unsigned short>(ulTmp);
360 lpszGuid = lpszEnd;
361
362 if (*lpszGuid != '-') return FALSE;
363 lpszGuid++;
364
365 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
366 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
367 g.Data3 = static_cast<unsigned short>(ulTmp);
368 lpszGuid = lpszEnd;
369
370 if (*lpszGuid != '-') return FALSE;
371 lpszGuid++;
372
373 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
374 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
375 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
376 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
377 lpszGuid = lpszEnd;
378
379 if (*lpszGuid != '-') return FALSE;
380 lpszGuid++;
381
382 ullTmp = _wcstoui64(lpszGuid, &lpszEnd, 16);
383 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
384 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
385 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
386 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
387 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
388 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
389 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
390 lpszGuid = lpszEnd;
391
392 if (*lpszGuid != '}') return FALSE;
393 lpszGuid++;
394
395 if (lpszGuidEnd)
396 *lpszGuidEnd = lpszGuid;
397
398 *lpGuid = g;
399 return TRUE;
400}
401
403#ifdef _UNICODE
404#define StringToGuid StringToGuidW
405#else
406#define StringToGuid StringToGuidA
407#endif
408
427template<class _Traits, class _Ax>
428static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCSTR pszName, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
429{
430 LSTATUS lResult;
431 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
432 DWORD dwSize = sizeof(aStackBuffer), dwType;
433
434 // Try with stack buffer first.
435 lResult = ::RegQueryValueExA(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
436 if (lResult == ERROR_SUCCESS) {
437 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
438 // The value is REG_SZ or REG_MULTI_SZ.
439 dwSize /= sizeof(CHAR);
440 sValue.assign(reinterpret_cast<LPCSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
441 } else if (dwType == REG_EXPAND_SZ) {
442 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
443 if (::ExpandEnvironmentStringsA(reinterpret_cast<LPCSTR>(aStackBuffer), sValue) == 0)
444 lResult = ::GetLastError();
445 } else {
446 // The value is not a string type.
447 lResult = ERROR_INVALID_DATA;
448 }
449 } else if (lResult == ERROR_MORE_DATA) {
450 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
451 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
452 std::unique_ptr<CHAR[]> szBuffer(new CHAR[dwSize / sizeof(CHAR)]);
453 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
454 dwSize /= sizeof(CHAR);
455 sValue.assign(szBuffer.get(), dwSize && szBuffer[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
456 }
457 } else if (dwType == REG_EXPAND_SZ) {
458 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
459 std::unique_ptr<CHAR[]> szBuffer(new CHAR[dwSize / sizeof(CHAR)]);
460 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
461 if (::ExpandEnvironmentStringsA(szBuffer.get(), sValue) == 0)
462 lResult = ::GetLastError();
463 }
464 } else {
465 // The value is not a string type.
466 lResult = ERROR_INVALID_DATA;
467 }
468 }
469
470 return lResult;
471}
472
491template<class _Traits, class _Ax>
492static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCWSTR pszName, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
493{
494 LSTATUS lResult;
495 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
496 DWORD dwSize = sizeof(aStackBuffer), dwType;
497
498 // Try with stack buffer first.
499 lResult = ::RegQueryValueExW(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
500 if (lResult == ERROR_SUCCESS) {
501 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
502 // The value is REG_SZ or REG_MULTI_SZ.
503 dwSize /= sizeof(WCHAR);
504 sValue.assign(reinterpret_cast<LPCWSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCWSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
505 } else if (dwType == REG_EXPAND_SZ) {
506 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
507 if (::ExpandEnvironmentStringsW(reinterpret_cast<LPCWSTR>(aStackBuffer), sValue) == 0)
508 lResult = ::GetLastError();
509 } else {
510 // The value is not a string type.
511 lResult = ERROR_INVALID_DATA;
512 }
513 } else if (lResult == ERROR_MORE_DATA) {
514 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
515 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
516 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[dwSize / sizeof(WCHAR)]);
517 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
518 dwSize /= sizeof(WCHAR);
519 sValue.assign(szBuffer.get(), dwSize && szBuffer[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
520 }
521 } else if (dwType == REG_EXPAND_SZ) {
522 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
523 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[dwSize / sizeof(WCHAR)]);
524 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
525 if (::ExpandEnvironmentStringsW(szBuffer.get(), sValue) == 0)
526 lResult = ::GetLastError();
527 }
528 } else {
529 // The value is not a string type.
530 lResult = ERROR_INVALID_DATA;
531 }
532 }
533
534 return lResult;
535}
536
538template<class _Ty, class _Ax>
539static LSTATUS RegQueryValueExA(_In_ HKEY hKey, _In_opt_z_ LPCSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
540{
541 LSTATUS lResult;
542 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
543 DWORD dwSize = sizeof(aStackBuffer);
544
545 // Try with stack buffer first.
546 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
547 if (lResult == ERROR_SUCCESS) {
548 // Copy from stack buffer.
549 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
550 memcpy(aData.data(), aStackBuffer, dwSize);
551 } else if (lResult == ERROR_MORE_DATA) {
552 // Allocate buffer on heap and retry.
553 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
554 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, NULL, reinterpret_cast<LPBYTE>(aData.data()), &dwSize);
555 }
556
557 return lResult;
558}
559
565template<class _Ty, class _Ax>
566static LSTATUS RegQueryValueExW(_In_ HKEY hKey, _In_opt_z_ LPCWSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
567{
568 LSTATUS lResult;
569 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
570 DWORD dwSize = sizeof(aStackBuffer);
571
572 // Try with stack buffer first.
573 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
574 if (lResult == ERROR_SUCCESS) {
575 // Copy from stack buffer.
576 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
577 memcpy(aData.data(), aStackBuffer, dwSize);
578 } else if (lResult == ERROR_MORE_DATA) {
579 // Allocate buffer on heap and retry.
580 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
581 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, NULL, reinterpret_cast<LPBYTE>(aData.data()), &dwSize);
582 }
583
584 return lResult;
585}
586
587#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
588
590template<class _Traits, class _Ax>
591static 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
592{
593 // According to "Remarks" section in MSDN documentation of RegLoadMUIString(),
594 // this function is defined but not implemented as ANSI variation.
595 assert(0);
596 return ERROR_CALL_NOT_IMPLEMENTED;
597}
598
604template<class _Traits, class _Ax>
605static 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
606{
607 LSTATUS lResult;
608 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
609 DWORD dwSize;
610
611 Flags &= ~REG_MUI_STRING_TRUNCATE;
612
613 // Try with stack buffer first.
614 lResult = RegLoadMUIStringW(hKey, pszValue, szStackBuffer, sizeof(szStackBuffer), &dwSize, Flags, pszDirectory);
615 if (lResult == ERROR_SUCCESS) {
616 // Copy from stack buffer.
617 sOut.assign(szStackBuffer, wcsnlen(szStackBuffer, dwSize/sizeof(wchar_t)));
618 } else if (lResult == ERROR_MORE_DATA) {
619 // Allocate buffer on heap and retry.
620 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[(dwSize + sizeof(wchar_t) - 1)/sizeof(wchar_t)]);
621 sOut.assign(szBuffer.get(), (lResult = RegLoadMUIStringW(hKey, pszValue, szBuffer.get(), dwSize, &dwSize, Flags, pszDirectory)) == ERROR_SUCCESS ? wcsnlen(szBuffer.get(), dwSize/sizeof(wchar_t)) : 0);
622 }
623
624 return lResult;
625}
626
627#endif
628
634template<class _Traits, class _Ax>
635static _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
636{
637 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
638
639 // Try to convert to stack buffer first.
640 int cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
641 if (cch) {
642 // Copy from stack. Be careful not to include zero terminator.
643 sMultiByteStr.assign(szStackBuffer, cchWideChar != -1 ? strnlen(szStackBuffer, cch) : (size_t)cch - 1);
644 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
645 // Query the required output size. Allocate buffer. Then convert again.
646 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
647 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
648 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szBuffer.get(), cch, lpDefaultChar, lpUsedDefaultChar);
649 sMultiByteStr.assign(szBuffer.get(), cchWideChar != -1 ? strnlen(szBuffer.get(), cch) : (size_t)cch - 1);
650 }
651
652 return cch;
653}
654
660template<class _Ax>
661static _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
662{
663 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
664
665 // Try to convert to stack buffer first.
666 int cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
667 if (cch) {
668 // Copy from stack.
669 sMultiByteStr.assign(szStackBuffer, szStackBuffer + cch);
670 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
671 // Query the required output size. Allocate buffer. Then convert again.
672 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
673 sMultiByteStr.resize(cch);
674 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, sMultiByteStr.data(), cch, lpDefaultChar, lpUsedDefaultChar);
675 }
676
677 return cch;
678}
679
685template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
686static _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
687{
688 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
689
690 // Try to convert to stack buffer first.
691 int cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
692 if (cch) {
693 // Copy from stack.
694 sMultiByteStr.assign(szStackBuffer, cch);
695 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
696 // Query the required output size. Allocate buffer. Then convert again.
697 cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), NULL, 0, lpDefaultChar, lpUsedDefaultChar);
698 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
699 cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), szBuffer.get(), cch, lpDefaultChar, lpUsedDefaultChar);
700 sMultiByteStr.assign(szBuffer.get(), cch);
701 }
702
703 return cch;
704}
705
713template<class _Traits, class _Ax>
714static _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
715{
716 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
717
718 // Try to convert to stack buffer first.
719 int cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
720 if (cch) {
721 // Copy from stack. Be careful not to include zero terminator.
722 sMultiByteStr.assign(szStackBuffer, cchWideChar != -1 ? strnlen(szStackBuffer, cch) : (size_t)cch - 1);
723 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
724 // Query the required output size. Allocate buffer. Then convert again.
725 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
726 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
727 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szBuffer.get(), cch, lpDefaultChar, lpUsedDefaultChar);
728 sMultiByteStr.assign(szBuffer.get(), cchWideChar != -1 ? strnlen(szBuffer.get(), cch) : (size_t)cch - 1);
729 SecureZeroMemory(szBuffer.get(), sizeof(CHAR)*cch);
730 }
731
732 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
733
734 return cch;
735}
736
744template<class _Ax>
745static _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
746{
747 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
748
749 // Try to convert to stack buffer first.
750 int cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
751 if (cch) {
752 // Copy from stack.
753 sMultiByteStr.assign(szStackBuffer, szStackBuffer + cch);
754 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
755 // Query the required output size. Allocate buffer. Then convert again.
756 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, lpDefaultChar, lpUsedDefaultChar);
757 sMultiByteStr.resize(cch);
758 cch = ::WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, sMultiByteStr.data(), cch, lpDefaultChar, lpUsedDefaultChar);
759 }
760
761 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
762
763 return cch;
764}
765
773template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
774static _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
775{
776 CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
777
778 // Try to convert to stack buffer first.
779 int cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), szStackBuffer, _countof(szStackBuffer), lpDefaultChar, lpUsedDefaultChar);
780 if (cch) {
781 // Copy from stack.
782 sMultiByteStr.assign(szStackBuffer, cch);
783 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
784 // Query the required output size. Allocate buffer. Then convert again.
785 cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), NULL, 0, lpDefaultChar, lpUsedDefaultChar);
786 std::unique_ptr<CHAR[]> szBuffer(new CHAR[cch]);
787 cch = ::WideCharToMultiByte(CodePage, dwFlags, sWideCharStr.c_str(), (int)sWideCharStr.length(), szBuffer.get(), cch, lpDefaultChar, lpUsedDefaultChar);
788 sMultiByteStr.assign(szBuffer.get(), cch);
789 SecureZeroMemory(szBuffer.get(), sizeof(CHAR)*cch);
790 }
791
792 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
793
794 return cch;
795}
796
802template<class _Traits, class _Ax>
803static _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
804{
805 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
806
807 // Try to convert to stack buffer first.
808 int cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szStackBuffer, _countof(szStackBuffer));
809 if (cch) {
810 // Copy from stack.
811 sWideCharStr.assign(szStackBuffer, cbMultiByte != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
812 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
813 // Query the required output size. Allocate buffer. Then convert again.
814 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
815 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
816 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szBuffer.get(), cch);
817 sWideCharStr.assign(szBuffer.get(), cbMultiByte != -1 ? wcsnlen(szBuffer.get(), cch) : (size_t)cch - 1);
818 }
819
820 return cch;
821}
822
828template<class _Ax>
829static _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
830{
831 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
832
833 // Try to convert to stack buffer first.
834 int cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szStackBuffer, _countof(szStackBuffer));
835 if (cch) {
836 // Copy from stack.
837 sWideCharStr.assign(szStackBuffer, szStackBuffer + cch);
838 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
839 // Query the required output size. Allocate buffer. Then convert again.
840 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
841 sWideCharStr.resize(cch);
842 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, sWideCharStr.data(), cch);
843 }
844
845 return cch;
846}
847
853template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
854static _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
855{
856 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
857
858 // Try to convert to stack buffer first.
859 int cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), szStackBuffer, _countof(szStackBuffer));
860 if (cch) {
861 // Copy from stack.
862 sWideCharStr.assign(szStackBuffer, cch);
863 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
864 // Query the required output size. Allocate buffer. Then convert again.
865 cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), NULL, 0);
866 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
867 cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), szBuffer.get(), cch);
868 sWideCharStr.assign(szBuffer.get(), cch);
869 }
870
871 return cch;
872}
873
881template<class _Traits, class _Ax>
882static _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
883{
884 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
885
886 // Try to convert to stack buffer first.
887 int cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szStackBuffer, _countof(szStackBuffer));
888 if (cch) {
889 // Copy from stack.
890 sWideCharStr.assign(szStackBuffer, cbMultiByte != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
891 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
892 // Query the required output size. Allocate buffer. Then convert again.
893 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
894 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
895 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szBuffer.get(), cch);
896 sWideCharStr.assign(szBuffer.get(), cbMultiByte != -1 ? wcsnlen(szBuffer.get(), cch) : (size_t)cch - 1);
897 SecureZeroMemory(szBuffer.get(), sizeof(WCHAR)*cch);
898 }
899
900 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
901
902 return cch;
903}
904
912template<class _Ax>
913static _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
914{
915 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
916
917 // Try to convert to stack buffer first.
918 int cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, szStackBuffer, _countof(szStackBuffer));
919 if (cch) {
920 // Copy from stack.
921 sWideCharStr.assign(szStackBuffer, szStackBuffer + cch);
922 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
923 // Query the required output size. Allocate buffer. Then convert again.
924 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
925 sWideCharStr.resize(cch);
926 cch = ::MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, sWideCharStr.data(), cch);
927 }
928
929 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
930
931 return cch;
932}
933
941template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
942static _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
943{
944 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
945
946 // Try to convert to stack buffer first.
947 int cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), szStackBuffer, _countof(szStackBuffer));
948 if (cch) {
949 // Copy from stack.
950 sWideCharStr.assign(szStackBuffer, cch);
951 } else if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
952 // Query the required output size. Allocate buffer. Then convert again.
953 cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), NULL, 0);
954 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
955 cch = ::MultiByteToWideChar(CodePage, dwFlags, sMultiByteStr.c_str(), (int)sMultiByteStr.length(), szBuffer.get(), cch);
956 sWideCharStr.assign(szBuffer.get(), cch);
957 SecureZeroMemory(szBuffer.get(), sizeof(WCHAR)*cch);
958 }
959
960 SecureZeroMemory(szStackBuffer, sizeof(szStackBuffer));
961
962 return cch;
963}
964
970template<class _Traits, class _Ax>
971static _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
972{
973 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
974
975 // Try to convert to stack buffer first.
976 int cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szStackBuffer, _countof(szStackBuffer));
977 if (cch > 0) {
978 // Copy from stack.
979 sDstString.assign(szStackBuffer, cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
980 } else {
981 switch (::GetLastError()) {
982 case ERROR_INSUFFICIENT_BUFFER:
983 for (int i = 10; i--;) {
984 // Allocate buffer. Then convert again.
985 cch = -cch;
986 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
987 cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szBuffer.get(), cch);
988 if (cch > 0) {
989 sDstString.assign(szBuffer.get(), cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
990 break;
991 }
992 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
993 sDstString.clear();
994 break;
995 }
996 }
997 break;
998
999 case ERROR_SUCCESS:
1000 sDstString.clear();
1001 break;
1002 }
1003 }
1004
1005 return cch;
1006}
1007
1013template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
1014static _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
1015{
1016 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
1017
1018 // Try to convert to stack buffer first.
1019 int cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szStackBuffer, _countof(szStackBuffer));
1020 if (cch > 0) {
1021 // Copy from stack.
1022 sDstString.assign(szStackBuffer, cch);
1023 } else {
1024 switch (::GetLastError()) {
1025 case ERROR_INSUFFICIENT_BUFFER:
1026 for (int i = 10; i--;) {
1027 // Allocate buffer. Then convert again.
1028 cch = -cch;
1029 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
1030 cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szBuffer.get(), cch);
1031 if (cch > 0) {
1032 sDstString.assign(szBuffer.get(), cch);
1033 break;
1034 }
1035 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
1036 sDstString.clear();
1037 break;
1038 }
1039 }
1040 break;
1041
1042 case ERROR_SUCCESS:
1043 sDstString.clear();
1044 break;
1045 }
1046 }
1047
1048 return cch;
1049}
1050
1052template<class _Traits, class _Ax>
1053static _Success_(return != 0) int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<char, _Traits, _Ax> &sBuffer) noexcept
1054{
1055 // Get read-only pointer to string resource.
1056 LPCSTR pszStr;
1057 int i = LoadStringA(hInstance, uID, reinterpret_cast<LPSTR>(&pszStr), 0);
1058 if (i) {
1059 sBuffer.assign(pszStr, i);
1060 return i;
1061 } else
1062 return 0;
1063}
1064
1070template<class _Traits, class _Ax>
1071static _Success_(return != 0) int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sBuffer) noexcept
1072{
1073 // Get read-only pointer to string resource.
1074 LPCWSTR pszStr;
1075 int i = LoadStringW(hInstance, uID, reinterpret_cast<LPWSTR>(&pszStr), 0);
1076 if (i) {
1077 sBuffer.assign(pszStr, i);
1078 return i;
1079 } else
1080 return 0;
1081}
1082
1088static VOID OutputDebugStrV(_In_z_ LPCSTR lpOutputString, _In_ va_list arg) noexcept
1089{
1090 std::string str;
1091 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
1092 OutputDebugStringA(str.c_str());
1093}
1094
1100static VOID OutputDebugStrV(_In_z_ LPCWSTR lpOutputString, _In_ va_list arg) noexcept
1101{
1102 std::wstring str;
1103 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
1104 OutputDebugStringW(str.c_str());
1105}
1106
1112static VOID OutputDebugStr(_In_z_ LPCSTR lpOutputString, ...) noexcept
1113{
1114 va_list arg;
1115 va_start(arg, lpOutputString);
1116 OutputDebugStrV(lpOutputString, arg);
1117 va_end(arg);
1118}
1119
1125static VOID OutputDebugStr(_In_z_ LPCWSTR lpOutputString, ...) noexcept
1126{
1127 va_list arg;
1128 va_start(arg, lpOutputString);
1129 OutputDebugStrV(lpOutputString, arg);
1130 va_end(arg);
1131}
1132
1134template<class _Traits, class _Ax>
1135static _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
1136{
1137 int iResult = GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
1138 if (iResult) {
1139 // Allocate buffer on heap and retry.
1140 std::unique_ptr<char[]> szBuffer(new char[iResult]);
1141 iResult = GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, szBuffer.get(), iResult);
1142 sDate.assign(szBuffer.get(), iResult ? iResult - 1 : 0);
1143 return iResult;
1144 }
1145
1146 return iResult;
1147}
1148
1154template<class _Traits, class _Ax>
1155static _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
1156{
1157 int iResult = GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
1158 if (iResult) {
1159 // Allocate buffer on heap and retry.
1160 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[iResult]);
1161 iResult = GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, szBuffer.get(), iResult);
1162 sDate.assign(szBuffer.get(), iResult ? iResult - 1 : 0);
1163 return iResult;
1164 }
1165
1166 return iResult;
1167}
1168
1170template<class _Traits, class _Ax>
1171static _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
1172{
1173 assert(0); // TODO: Test this code.
1174
1175 DWORD dwNameLen = 0, dwRefDomainLen = 0;
1176
1177 if (LookupAccountSidA(lpSystemName, lpSid,
1178 NULL, &dwNameLen ,
1179 NULL, &dwRefDomainLen,
1180 peUse))
1181 {
1182 // Name and domain is blank.
1183 if (sName ) sName ->clear();
1184 if (sReferencedDomainName) sReferencedDomainName->clear();
1185 return TRUE;
1186 } else if (GetLastError() == ERROR_MORE_DATA) {
1187 // Allocate on heap and retry.
1188 std::unique_ptr<char[]> bufName (new char[dwNameLen ]);
1189 std::unique_ptr<char[]> bufRefDomain(new char[dwRefDomainLen]);
1190 if (LookupAccountSidA(lpSystemName, lpSid,
1191 bufName .get(), &dwNameLen ,
1192 bufRefDomain.get(), &dwRefDomainLen,
1193 peUse))
1194 {
1195 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
1196 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
1197 return TRUE;
1198 }
1199 }
1200
1201 return FALSE;
1202}
1203
1209template<class _Traits, class _Ax>
1210static _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
1211{
1212 assert(0); // TODO: Test this code.
1213
1214 DWORD dwNameLen = 0, dwRefDomainLen = 0;
1215
1216 if (LookupAccountSidW(lpSystemName, lpSid,
1217 NULL, &dwNameLen ,
1218 NULL, &dwRefDomainLen,
1219 peUse))
1220 {
1221 // Name and domain is blank.
1222 if (sName ) sName ->clear();
1223 if (sReferencedDomainName) sReferencedDomainName->clear();
1224 return TRUE;
1225 } else if (GetLastError() == ERROR_MORE_DATA) {
1226 // Allocate on heap and retry.
1227 std::unique_ptr<wchar_t[]> bufName (new wchar_t[dwNameLen ]);
1228 std::unique_ptr<wchar_t[]> bufRefDomain(new wchar_t[dwRefDomainLen]);
1229 if (LookupAccountSidW(lpSystemName, lpSid,
1230 bufName .get(), &dwNameLen ,
1231 bufRefDomain.get(), &dwRefDomainLen,
1232 peUse))
1233 {
1234 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
1235 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
1236 return TRUE;
1237 }
1238 }
1239
1240 return FALSE;
1241}
1242
1248static _Success_(return != FALSE) BOOL CreateWellKnownSid(_In_ WELL_KNOWN_SID_TYPE WellKnownSidType, _In_opt_ PSID DomainSid, _Inout_ std::unique_ptr<SID> &Sid)
1249{
1250 BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES];
1251 DWORD dwSize = sizeof(szStackBuffer);
1252
1253 if (CreateWellKnownSid(WellKnownSidType, DomainSid, szStackBuffer, &dwSize)) {
1254 // The stack buffer was big enough to retrieve complete data. Alloc and copy.
1255 Sid.reset((SID*)new BYTE[dwSize]);
1256 memcpy(Sid.get(), szStackBuffer, dwSize);
1257 return TRUE;
1258 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
1259 // The stack buffer was too small to retrieve complete data. Alloc and retry.
1260 Sid.reset((SID*)new BYTE[dwSize]);
1261 return CreateWellKnownSid(WellKnownSidType, DomainSid, Sid.get(), &dwSize);
1262 } else
1263 return FALSE;
1264}
1265
1271template<class _Ty>
1272static _Success_(return != 0) BOOL GetTokenInformation(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_ std::unique_ptr<_Ty> &TokenInformation) noexcept
1273{
1274 BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES];
1275 DWORD dwSize;
1276
1277 if (GetTokenInformation(TokenHandle, TokenInformationClass, szStackBuffer, sizeof(szStackBuffer), &dwSize)) {
1278 // The stack buffer was big enough to retrieve complete data. Alloc and copy.
1279 TokenInformation.reset((_Ty*)(new BYTE[dwSize]));
1280 memcpy(TokenInformation.get(), szStackBuffer, dwSize);
1281 return TRUE;
1282 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
1283 // The stack buffer was too small to retrieve complete data. Alloc and retry.
1284 TokenInformation.reset((_Ty*)(new BYTE[dwSize]));
1285 return GetTokenInformation(TokenHandle, TokenInformationClass, TokenInformation.get(), dwSize, &dwSize);
1286 } else
1287 return FALSE;
1288}
1289
1295template<class _Traits, class _Ax>
1296static _Success_(return != 0) BOOL QueryFullProcessImageNameA(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<char, _Traits, _Ax>& sExeName)
1297{
1298 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(char)];
1299 DWORD dwSize = _countof(szStackBuffer);
1300
1301 // Try with stack buffer first.
1302 if (::QueryFullProcessImageNameA(hProcess, dwFlags, szStackBuffer, &dwSize)) {
1303 // Copy from stack.
1304 sExeName.assign(szStackBuffer, dwSize);
1305 return TRUE;
1306 }
1307 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(char); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
1308 // Allocate on heap and retry.
1309 std::unique_ptr<char[]> szBuffer(new char[dwCapacity]);
1310 dwSize = dwCapacity;
1311 if (::QueryFullProcessImageNameA(hProcess, dwFlags, szBuffer.get(), &dwSize)) {
1312 sExeName.assign(szBuffer.get(), dwSize);
1313 return TRUE;
1314 }
1315 }
1316 return FALSE;
1317}
1318
1324template<class _Traits, class _Ax>
1325static _Success_(return != 0) BOOL QueryFullProcessImageNameW(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<wchar_t, _Traits, _Ax>& sExeName)
1326{
1327 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t)];
1328 DWORD dwSize = _countof(szStackBuffer);
1329
1330 // Try with stack buffer first.
1331 if (::QueryFullProcessImageNameW(hProcess, dwFlags, szStackBuffer, &dwSize)) {
1332 // Copy from stack.
1333 sExeName.assign(szStackBuffer, dwSize);
1334 return TRUE;
1335 }
1336 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
1337 // Allocate on heap and retry.
1338 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwCapacity]);
1339 dwSize = dwCapacity;
1340 if (::QueryFullProcessImageNameW(hProcess, dwFlags, szBuffer.get(), &dwSize)) {
1341 sExeName.assign(szBuffer.get(), dwSize);
1342 return TRUE;
1343 }
1344 }
1345 return FALSE;
1346}
1347
1349
1350#pragma warning(pop)
1351
1352namespace winstd
1353{
1356
1360 template<HANDLE INVALID>
1361 class win_handle : public handle<HANDLE, INVALID>
1362 {
1364
1365 public:
1371 virtual ~win_handle()
1372 {
1373 if (m_h != invalid)
1374 free_internal();
1375 }
1376
1377 protected:
1383 void free_internal() noexcept override
1384 {
1385 CloseHandle(m_h);
1386 }
1387 };
1388
1394 class library : public handle<HMODULE, NULL>
1395 {
1397
1398 public:
1404 virtual ~library()
1405 {
1406 if (m_h != invalid)
1407 free_internal();
1408 }
1409
1410 protected:
1416 void free_internal() noexcept override
1417 {
1418 FreeLibrary(m_h);
1419 }
1420 };
1421
1428
1435
1442
1450
1457
1461 template <class _Ty> struct UnmapViewOfFile_delete
1462 {
1464
1469
1474
1478 void operator()(_Ty* _Ptr) const
1479 {
1480 if (!UnmapViewOfFile(_Ptr))
1481 throw win_runtime_error("UnmapViewOfFile failed");
1482 }
1483 };
1484
1488 template <class _Ty> struct UnmapViewOfFile_delete<_Ty[]>
1489 {
1491
1496
1500 void operator()(_Ty* _Ptr) const
1501 {
1502 if (!UnmapViewOfFile(_Ptr))
1503 throw win_runtime_error("UnmapViewOfFile failed");
1504 }
1505
1509 template<class _Other>
1510 void operator()(_Other*) const
1511 {
1512 if (!UnmapViewOfFile(_Ptr))
1513 throw win_runtime_error("UnmapViewOfFile failed");
1514 }
1515 };
1516
1524
1529 {
1532
1533 public:
1540 {
1541 InitializeCriticalSection(&m_data);
1542 }
1543
1550 {
1551 DeleteCriticalSection(&m_data);
1552 }
1553
1559 operator LPCRITICAL_SECTION() noexcept
1560 {
1561 return &m_data;
1562 }
1563
1564 protected:
1565 CRITICAL_SECTION m_data;
1566 };
1567
1573 class find_file : public handle<HANDLE, INVALID_HANDLE_VALUE>
1574 {
1575 WINSTD_HANDLE_IMPL(find_file, INVALID_HANDLE_VALUE)
1576
1577 public:
1583 virtual ~find_file()
1584 {
1585 if (m_h != invalid)
1586 free_internal();
1587 }
1588
1589 protected:
1595 void free_internal() noexcept override
1596 {
1597 FindClose(m_h);
1598 }
1599 };
1600
1606 class heap : public handle<HANDLE, NULL>
1607 {
1609
1610 public:
1616 virtual ~heap()
1617 {
1618 if (m_h != invalid)
1619 free_internal();
1620 }
1621
1629 bool enumerate() noexcept
1630 {
1631 assert(m_h != invalid);
1632
1633 bool found = false;
1634
1635 // Lock the heap for exclusive access.
1636 HeapLock(m_h);
1637
1638 PROCESS_HEAP_ENTRY e;
1639 e.lpData = NULL;
1640 while (HeapWalk(m_h, &e) != FALSE) {
1641 if ((e.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
1643 _T("Allocated block%s%s\n")
1644 _T(" Data portion begins at: %#p\n Size: %d bytes\n")
1645 _T(" Overhead: %d bytes\n Region index: %d\n"),
1646 (e.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0 ? tstring_printf(_T(", movable with HANDLE %#p"), e.Block.hMem).c_str() : _T(""),
1647 (e.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0 ? _T(", DDESHARE") : _T(""),
1648 e.lpData,
1649 e.cbData,
1650 e.cbOverhead,
1651 e.iRegionIndex);
1652
1653 found = true;
1654 }
1655 }
1656
1657 const DWORD dwResult = GetLastError();
1658 if (dwResult != ERROR_NO_MORE_ITEMS)
1659 OutputDebugStr(_T("HeapWalk failed (error %u).\n"), dwResult);
1660
1661 // Unlock the heap.
1662 HeapUnlock(m_h);
1663
1664 return found;
1665 }
1666
1667 protected:
1673 void free_internal() noexcept override
1674 {
1675 enumerate();
1676 HeapDestroy(m_h);
1677 }
1678 };
1679
1683 template <class _Ty>
1685 {
1686 public:
1687 typedef typename _Ty value_type;
1688
1689 typedef _Ty *pointer;
1690 typedef _Ty& reference;
1691 typedef const _Ty *const_pointer;
1692 typedef const _Ty& const_reference;
1693
1694 typedef SIZE_T size_type;
1695 typedef ptrdiff_t difference_type;
1696
1700 template <class _Other>
1701 struct rebind
1702 {
1704 };
1705
1706 public:
1713 {
1714 }
1715
1721 template <class _Other>
1723 {
1724 }
1725
1734 {
1735 assert(m_heap);
1736 return (pointer)HeapAlloc(m_heap, 0, count * sizeof(_Ty));
1737 }
1738
1745 void deallocate(_In_ pointer ptr, _In_ size_type size)
1746 {
1747 UNREFERENCED_PARAMETER(size);
1748 assert(m_heap);
1749 HeapFree(m_heap, 0, ptr);
1750 }
1751
1758 void construct(_Inout_ pointer ptr, _In_ const _Ty& val)
1759 {
1760 ::new ((void*)ptr) _Ty(val);
1761 }
1762
1769 void construct(_Inout_ pointer ptr, _Inout_ _Ty&& val)
1770 {
1771 ::new ((void*)ptr) _Ty(std::forward<_Ty>(val));
1772 }
1773
1779 void destroy(_Inout_ pointer ptr)
1780 {
1781 ptr->_Ty::~_Ty();
1782 }
1783
1788 {
1789 return (SIZE_T)-1;
1790 }
1791
1792 public:
1793 HANDLE m_heap;
1794 };
1795
1800 {
1803
1804 public:
1812 actctx_activator(_In_ HANDLE hActCtx) noexcept
1813 {
1814 if (!ActivateActCtx(hActCtx, &m_cookie))
1815 m_cookie = 0;
1816 }
1817
1824 {
1825 if (m_cookie)
1826 DeactivateActCtx(0, m_cookie);
1827 }
1828
1829 protected:
1830 ULONG_PTR m_cookie;
1831 };
1832
1837 {
1838 public:
1842 impersonator() noexcept : m_cookie(FALSE) {}
1843
1850 {
1851 if (m_cookie)
1852 RevertToSelf();
1853 }
1854
1858 operator bool () const { return m_cookie; }
1859
1860 protected:
1862 };
1863
1868 {
1871
1872 public:
1880 user_impersonator(_In_opt_ HANDLE hToken) noexcept
1881 {
1882 m_cookie = hToken && ImpersonateLoggedOnUser(hToken);
1883 }
1884 };
1885
1890 {
1893
1894 public:
1899 {
1900 TOKEN_PRIVILEGES privileges = { 1, {{{ 0, 0 }, SE_PRIVILEGE_ENABLED }} };
1901 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid) ||
1902 !ImpersonateSelf(SecurityImpersonation))
1903 return;
1904
1905 {
1906 HANDLE h;
1907 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &h))
1908 goto revert;
1909 win_handle<INVALID_HANDLE_VALUE> thread_token(h);
1910 if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL))
1911 goto revert;
1912 process_snapshot process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1913 if (!process_snapshot)
1914 goto revert;
1915 PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32) };
1916 if (!Process32First(process_snapshot, &entry))
1917 goto revert;
1918 while (_tcsicmp(entry.szExeFile, TEXT("winlogon.exe")) != 0)
1919 if (!Process32Next(process_snapshot, &entry))
1920 goto revert;
1921 process winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
1922 if (!winlogon_process)
1923 goto revert;
1924 if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &h))
1925 goto revert;
1926 win_handle<INVALID_HANDLE_VALUE> winlogon_token(h);
1927 if (!DuplicateToken(winlogon_token, SecurityImpersonation, &h))
1928 goto revert;
1929 win_handle<INVALID_HANDLE_VALUE> duplicated_token(h);
1930 if (!SetThreadToken(NULL, duplicated_token))
1931 goto revert;
1932 }
1933
1934 m_cookie = TRUE;
1935 return;
1936
1937 revert:
1938 DWORD dwResult = GetLastError();
1939 RevertToSelf();
1940 SetLastError(dwResult);
1941 }
1942 };
1943
1948 {
1951
1952 public:
1960 console_ctrl_handler(_In_opt_ PHANDLER_ROUTINE HandlerRoutine) noexcept : m_handler(HandlerRoutine)
1961 {
1962 m_cookie = SetConsoleCtrlHandler(m_handler, TRUE);
1963 }
1964
1971 {
1972 if (m_cookie)
1973 SetConsoleCtrlHandler(m_handler, FALSE);
1974 }
1975
1976 protected:
1978 PHANDLER_ROUTINE m_handler;
1979 };
1980
1984 class vmemory : public handle<LPVOID, NULL>
1985 {
1987
1988 public:
1992 vmemory() noexcept : m_proc(NULL)
1993 {
1994 }
1995
2002 vmemory(_In_ handle_type h, _In_ HANDLE proc) noexcept :
2003 m_proc(proc),
2005 {
2006 }
2007
2013 vmemory(_Inout_ vmemory &&h) noexcept :
2014 m_proc(std::move(h.m_proc)),
2015 handle<LPVOID, NULL>(std::move(h))
2016 {
2017 }
2018
2024 virtual ~vmemory()
2025 {
2026 if (m_h != invalid)
2027 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
2028 }
2029
2035 vmemory& operator=(_Inout_ vmemory &&other) noexcept
2036 {
2037 if (this != std::addressof(other)) {
2038 (handle<handle_type, NULL>&&)*this = std::move(other);
2039 m_proc = std::move(other.m_proc);
2040 }
2041 return *this;
2042 }
2043
2052 void attach(_In_ HANDLE proc, _In_opt_ handle_type h) noexcept
2053 {
2054 m_proc = proc;
2055 if (m_h != invalid)
2056 free_internal();
2057 m_h = h;
2058 }
2059
2069 bool alloc(
2070 _In_ HANDLE hProcess,
2071 _In_opt_ LPVOID lpAddress,
2072 _In_ SIZE_T dwSize,
2073 _In_ DWORD flAllocationType,
2074 _In_ DWORD flProtect) noexcept
2075 {
2076 handle_type h = VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect);
2077 if (h != invalid) {
2078 attach(hProcess, h);
2079 return true;
2080 } else
2081 return false;
2082 }
2083
2084 protected:
2090 void free_internal() noexcept override
2091 {
2092 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
2093 }
2094
2095 protected:
2096 HANDLE m_proc;
2097 };
2098
2105 class reg_key : public handle<HKEY, NULL>
2106 {
2108
2109 public:
2115 virtual ~reg_key()
2116 {
2117 if (m_h != invalid)
2118 free_internal();
2119 }
2120
2130 bool delete_subkey(_In_z_ LPCTSTR szSubkey)
2131 {
2132 LSTATUS s;
2133
2134 s = RegDeleteKey(m_h, szSubkey);
2135 if (s == ERROR_SUCCESS || s == ERROR_FILE_NOT_FOUND)
2136 return true;
2137
2138 {
2139 reg_key k;
2140 handle_type h;
2141 s = RegOpenKeyEx(m_h, szSubkey, 0, KEY_ENUMERATE_SUB_KEYS, &h);
2142 if (s == ERROR_SUCCESS)
2143 k.attach(h);
2144 else {
2145 SetLastError(s);
2146 return false;
2147 }
2148 for (;;) {
2149 TCHAR szName[MAX_PATH];
2150 DWORD dwSize = _countof(szName);
2151 s = RegEnumKeyEx(k, 0, szName, &dwSize, NULL, NULL, NULL, NULL);
2152 if (s == ERROR_SUCCESS)
2153 k.delete_subkey(szName);
2154 else if (s == ERROR_NO_MORE_ITEMS)
2155 break;
2156 else {
2157 SetLastError(s);
2158 return false;
2159 }
2160 }
2161 }
2162
2163 s = RegDeleteKey(m_h, szSubkey);
2164 if (s == ERROR_SUCCESS)
2165 return true;
2166 else {
2167 SetLastError(s);
2168 return false;
2169 }
2170 }
2171
2172 protected:
2178 void free_internal() noexcept override
2179 {
2180 RegCloseKey(m_h);
2181 }
2182 };
2183
2187 class security_id : public handle<PSID, NULL>
2188 {
2190
2191 public:
2198 {
2199 if (m_h != invalid)
2200 free_internal();
2201 }
2202
2203 protected:
2209 void free_internal() noexcept override
2210 {
2211 FreeSid(m_h);
2212 }
2213 };
2214
2218 class process_information : public PROCESS_INFORMATION
2219 {
2222
2223 public:
2228 {
2229 hProcess = INVALID_HANDLE_VALUE;
2230 hThread = INVALID_HANDLE_VALUE;
2231 dwProcessId = 0;
2232 dwThreadId = 0;
2233 }
2234
2239 {
2240 #pragma warning(push)
2241 #pragma warning(disable: 6001) // Using uninitialized memory '*this'. << ???
2242
2243 if (hProcess != INVALID_HANDLE_VALUE)
2244 CloseHandle(hProcess);
2245
2246 if (hThread != INVALID_HANDLE_VALUE)
2247 CloseHandle(hThread);
2248
2249 #pragma warning(pop)
2250 }
2251 };
2252
2258 class event_log : public handle<HANDLE, NULL>
2259 {
2261
2262 public:
2268 virtual ~event_log()
2269 {
2270 if (m_h != invalid)
2271 free_internal();
2272 }
2273
2274 protected:
2280 void free_internal() noexcept override
2281 {
2282 DeregisterEventSource(m_h);
2283 }
2284 };
2285
2289 class sc_handle : public handle<SC_HANDLE, NULL>
2290 {
2292
2293 public:
2299 virtual ~sc_handle()
2300 {
2301 if (m_h != invalid)
2302 free_internal();
2303 }
2304
2305 protected:
2311 void free_internal() noexcept override
2312 {
2313 CloseServiceHandle(m_h);
2314 }
2315 };
2316
2318}
2319
2322
2323#pragma warning(push)
2324#pragma warning(disable: 4505) // Don't warn on unused code
2325
2327static LSTATUS RegCreateKeyExA(
2328 _In_ HKEY hKey,
2329 _In_ LPCSTR lpSubKey,
2330 _Reserved_ DWORD Reserved,
2331 _In_opt_ LPSTR lpClass,
2332 _In_ DWORD dwOptions,
2333 _In_ REGSAM samDesired,
2334 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2335 _Inout_ winstd::reg_key &result,
2336 _Out_opt_ LPDWORD lpdwDisposition)
2337{
2338 HKEY h;
2339 LSTATUS s = RegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2340 if (s == ERROR_SUCCESS)
2341 result.attach(h);
2342 return s;
2343}
2344
2350static LSTATUS RegCreateKeyExW(
2351 _In_ HKEY hKey,
2352 _In_ LPCWSTR lpSubKey,
2353 _Reserved_ DWORD Reserved,
2354 _In_opt_ LPWSTR lpClass,
2355 _In_ DWORD dwOptions,
2356 _In_ REGSAM samDesired,
2357 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2358 _Inout_ winstd::reg_key &result,
2359 _Out_opt_ LPDWORD lpdwDisposition)
2360{
2361 HKEY h;
2362 LSTATUS s = RegCreateKeyExW(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2363 if (s == ERROR_SUCCESS)
2364 result.attach(h);
2365 return s;
2366}
2367
2369static LSTATUS RegOpenKeyExA(
2370 _In_ HKEY hKey,
2371 _In_opt_ LPCSTR lpSubKey,
2372 _In_opt_ DWORD ulOptions,
2373 _In_ REGSAM samDesired,
2374 _Inout_ winstd::reg_key &result)
2375{
2376 HKEY h;
2377 LSTATUS s = RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, &h);
2378 if (s == ERROR_SUCCESS)
2379 result.attach(h);
2380 return s;
2381}
2382
2388static LSTATUS RegOpenKeyExW(
2389 _In_ HKEY hKey,
2390 _In_opt_ LPCWSTR lpSubKey,
2391 _In_opt_ DWORD ulOptions,
2392 _In_ REGSAM samDesired,
2393 _Inout_ winstd::reg_key &result)
2394{
2395 HKEY h;
2396 LSTATUS s = RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, &h);
2397 if (s == ERROR_SUCCESS)
2398 result.attach(h);
2399 return s;
2400}
2401
2407static BOOL OpenProcessToken(_In_ HANDLE ProcessHandle, _In_ DWORD DesiredAccess, _Inout_ winstd::win_handle<NULL> &TokenHandle)
2408{
2409 HANDLE h;
2410 if (OpenProcessToken(ProcessHandle, DesiredAccess, &h)) {
2411 TokenHandle.attach(h);
2412 return TRUE;
2413 }
2414 return FALSE;
2415}
2416
2422static BOOL DuplicateTokenEx(_In_ HANDLE hExistingToken, _In_ DWORD dwDesiredAccess, _In_opt_ LPSECURITY_ATTRIBUTES lpTokenAttributes, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ TOKEN_TYPE TokenType, _Inout_ winstd::win_handle<NULL> &NewToken)
2423{
2424 HANDLE h;
2425 if (DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, &h)) {
2426 NewToken.attach(h);
2427 return TRUE;
2428 }
2429 return FALSE;
2430}
2431
2432#pragma warning(pop)
2433
Activates given activation context in constructor and deactivates it in destructor.
Definition: Win.h:1800
actctx_activator(HANDLE hActCtx) noexcept
Construct the activator and activates the given activation context.
Definition: Win.h:1812
virtual ~actctx_activator()
Deactivates activation context and destructs the activator.
Definition: Win.h:1823
ULONG_PTR m_cookie
Cookie for context deactivation.
Definition: Win.h:1830
Base template class to support string formatting using printf() style templates.
Definition: Common.h:1080
Console control handler stack management.
Definition: Win.h:1948
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:1960
virtual ~console_ctrl_handler()
Pops console control handler from the console control handler stack.
Definition: Win.h:1970
PHANDLER_ROUTINE m_handler
Pointer to console control handler.
Definition: Win.h:1978
BOOL m_cookie
Did pushing the console control handler succeed?
Definition: Win.h:1977
Critical section wrapper.
Definition: Win.h:1529
critical_section() noexcept
Construct the object and initializes a critical section object.
Definition: Win.h:1539
CRITICAL_SECTION m_data
Critical section struct.
Definition: Win.h:1565
virtual ~critical_section()
Releases all resources used by an unowned critical section object.
Definition: Win.h:1549
Event log handle wrapper.
Definition: Win.h:2259
void free_internal() noexcept override
Closes an event log handle.
Definition: Win.h:2280
virtual ~event_log()
Closes an event log handle.
Definition: Win.h:2268
Find-file handle wrapper.
Definition: Win.h:1574
virtual ~find_file()
Closes a file search handle.
Definition: Win.h:1583
void free_internal() noexcept override
Closes a file search handle.
Definition: Win.h:1595
Base abstract template class to support generic object handle keeping.
Definition: Common.h:569
LPVOID handle_type
Datatype of the object handle this template class handles.
Definition: Common.h:574
handle_type m_h
Object handle.
Definition: Common.h:823
void attach(handle_type h) noexcept
Sets a new object handle for the class.
Definition: Common.h:786
HeapAlloc allocator.
Definition: Win.h:1685
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:1694
_Ty value_type
A type that is managed by the allocator.
Definition: Win.h:1687
heap_allocator(const heap_allocator< _Other > &other)
Constructs allocator from another type.
Definition: Win.h:1722
HANDLE m_heap
Heap handle.
Definition: Win.h:1793
pointer allocate(size_type count)
Allocates a new memory block.
Definition: Win.h:1733
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:1695
heap_allocator(HANDLE heap)
Constructs allocator.
Definition: Win.h:1712
_Ty & reference
A type that provides a reference to the type of object managed by the allocator.
Definition: Win.h:1690
void construct(pointer ptr, _Ty &&val)
Calls moving constructor for the element.
Definition: Win.h:1769
void deallocate(pointer ptr, size_type size)
Frees memory block.
Definition: Win.h:1745
size_type max_size() const
Returns maximum memory block size.
Definition: Win.h:1787
void construct(pointer ptr, const _Ty &val)
Calls copying constructor for the element.
Definition: Win.h:1758
const _Ty & const_reference
A type that provides a constant reference to type of object managed by the allocator.
Definition: Win.h:1692
const _Ty * const_pointer
A type that provides a constant pointer to the type of object managed by the allocator.
Definition: Win.h:1691
_Ty * pointer
A type that provides a pointer to the type of object managed by the allocator.
Definition: Win.h:1689
void destroy(pointer ptr)
Calls destructor for the element.
Definition: Win.h:1779
Heap handle wrapper.
Definition: Win.h:1607
bool enumerate() noexcept
Enumerates allocated heap blocks using OutputDebugString()
Definition: Win.h:1629
void free_internal() noexcept override
Destroys the heap.
Definition: Win.h:1673
virtual ~heap()
Destroys the heap.
Definition: Win.h:1616
Base class for thread impersonation of another security context.
Definition: Win.h:1837
virtual ~impersonator()
Reverts to current user and destructs the impersonator.
Definition: Win.h:1849
impersonator() noexcept
Construct the impersonator.
Definition: Win.h:1842
BOOL m_cookie
Did impersonation succeed?
Definition: Win.h:1861
Module handle wrapper.
Definition: Win.h:1395
void free_internal() noexcept override
Frees the module.
Definition: Win.h:1416
virtual ~library()
Frees the module.
Definition: Win.h:1404
PROCESS_INFORMATION struct wrapper.
Definition: Win.h:2219
~process_information()
Closes process and thread handles.
Definition: Win.h:2238
process_information() noexcept
Constructs blank PROCESS_INFORMATION.
Definition: Win.h:2227
Registry key wrapper class.
Definition: Win.h:2106
void free_internal() noexcept override
Closes a handle to the registry key.
Definition: Win.h:2178
bool delete_subkey(LPCTSTR szSubkey)
Deletes the specified registry subkey.
Definition: Win.h:2130
virtual ~reg_key()
Closes a handle to the registry key.
Definition: Win.h:2115
SC_HANDLE wrapper class.
Definition: Win.h:2290
void free_internal() noexcept override
Closes an open object handle.
Definition: Win.h:2311
virtual ~sc_handle()
Closes an open object handle.
Definition: Win.h:2299
SID wrapper class.
Definition: Win.h:2188
void free_internal() noexcept override
Closes a handle to the SID.
Definition: Win.h:2209
virtual ~security_id()
Closes a handle to the SID.
Definition: Win.h:2197
Lets the calling thread impersonate the security context of the SYSTEM user.
Definition: Win.h:1890
system_impersonator() noexcept
Construct the impersonator and impersonates the SYSTEM user.
Definition: Win.h:1898
Lets the calling thread impersonate the security context of a logged-on user.
Definition: Win.h:1868
user_impersonator(HANDLE hToken) noexcept
Construct the impersonator and impersonates the given user.
Definition: Win.h:1880
Memory in virtual address space of a process handle wrapper.
Definition: Win.h:1985
vmemory & operator=(vmemory &&other) noexcept
Move assignment.
Definition: Win.h:2035
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:2069
void free_internal() noexcept override
Frees the memory.
Definition: Win.h:2090
void attach(HANDLE proc, handle_type h) noexcept
Sets a new memory handle for the class.
Definition: Win.h:2052
virtual ~vmemory()
Frees the memory.
Definition: Win.h:2024
vmemory(handle_type h, HANDLE proc) noexcept
Initializes a new class instance with an already available object handle.
Definition: Win.h:2002
vmemory() noexcept
Initializes a new class instance with the memory handle set to INVAL.
Definition: Win.h:1992
vmemory(vmemory &&h) noexcept
Move constructor.
Definition: Win.h:2013
HANDLE m_proc
Handle of memory's process.
Definition: Win.h:2096
Windows HANDLE wrapper class.
Definition: Win.h:1362
void free_internal() noexcept override
Closes an open object handle.
Definition: Win.h:1383
virtual ~win_handle()
Closes an open object handle.
Definition: Win.h:1371
Windows runtime error.
Definition: Common.h:1013
#define WINSTD_NONCOPYABLE(C)
Declares a class as non-copyable.
Definition: Common.h:66
#define WINSTD_STACK_BUFFER_BYTES
Size of the stack buffer in bytes used for initial system function call.
Definition: Common.h:93
#define WINSTD_NONMOVABLE(C)
Declares a class as non-movable.
Definition: Common.h:74
static int vsprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format, va_list arg)
Formats string using printf().
Definition: Common.h:251
static int sprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format,...)
Formats string using printf().
Definition: Common.h:284
#define WINSTD_HANDLE_IMPL(C, INVAL)
Implements default constructors and operators to prevent their auto-generation by compiler.
Definition: Common.h:163
static const HANDLE invalid
Invalid handle value.
Definition: Common.h:579
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:971
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:714
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:178
static BOOL StringToGuidA(LPCSTR lpszGuid, LPGUID lpGuid, LPCSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition: Win.h:267
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:80
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:2350
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:1053
win_handle< INVALID_HANDLE_VALUE > file
File handle wrapper.
Definition: Win.h:1449
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:142
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:803
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:2327
static LSTATUS RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition: Win.h:2369
static LSTATUS RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition: Win.h:2388
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:228
static BOOL StringToGuidW(LPCWSTR lpszGuid, LPGUID lpGuid, LPCWSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition: Win.h:340
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:605
static BOOL OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, winstd::win_handle< NULL > &TokenHandle)
Opens the access token associated with a process.
Definition: Win.h:2407
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:1171
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:55
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:1210
win_handle< INVALID_HANDLE_VALUE > process_snapshot
Process snapshot handle wrapper.
Definition: Win.h:1441
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:24
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:1155
static BOOL CreateWellKnownSid(WELL_KNOWN_SID_TYPE WellKnownSidType, PSID DomainSid, std::unique_ptr< SID > &Sid)
Creates a SID for predefined aliases.
Definition: Win.h:1248
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:1071
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:1272
static BOOL DuplicateTokenEx(HANDLE hExistingToken, DWORD dwDesiredAccess, LPSECURITY_ATTRIBUTES lpTokenAttributes, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, TOKEN_TYPE TokenType, winstd::win_handle< NULL > &NewToken)
Creates a new access token that duplicates an existing token. This function can create either a prima...
Definition: Win.h:2422
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:566
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:162
win_handle< NULL > event
Event handle wrapper.
Definition: Win.h:1523
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:591
static VOID OutputDebugStr(LPCSTR lpOutputString,...) noexcept
Formats and sends a string to the debugger for display.
Definition: Win.h:1112
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:1296
win_handle< NULL > file_mapping
File mapping.
Definition: Win.h:1456
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:882
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:635
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:1325
win_handle< NULL > process
Process handle wrapper.
Definition: Win.h:1427
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:539
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:428
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:113
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:1135
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:206
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:247
static VOID OutputDebugStrV(LPCSTR lpOutputString, va_list arg) noexcept
Formats and sends a string to the debugger for display.
Definition: Win.h:1088
win_handle< NULL > thread
Thread handle wrapper.
Definition: Win.h:1434
UnmapViewOfFile_delete()
Default construct.
Definition: Win.h:1495
void operator()(_Other *) const
Delete a pointer of another type.
Definition: Win.h:1510
void operator()(_Ty *_Ptr) const
Delete a pointer.
Definition: Win.h:1500
UnmapViewOfFile_delete< _Ty > _Myt
This type.
Definition: Win.h:1490
Deleter for unique_ptr using UnmapViewOfFile.
Definition: Win.h:1462
UnmapViewOfFile_delete(const UnmapViewOfFile_delete< _Ty2 > &)
Construct from another UnmapViewOfFile_delete.
Definition: Win.h:1473
void operator()(_Ty *_Ptr) const
Delete a pointer.
Definition: Win.h:1478
UnmapViewOfFile_delete< _Ty > _Myt
This type.
Definition: Win.h:1463
UnmapViewOfFile_delete()
Default construct.
Definition: Win.h:1468
A structure that enables an allocator for objects of one type to allocate storage for objects of anot...
Definition: Win.h:1702
heap_allocator< _Other > other
Other allocator type.
Definition: Win.h:1703