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