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 <winsvc.h>
15#include <string>
16#include <vector>
17
18#pragma warning(push)
19#pragma warning(disable: 4505) // Don't warn on unused code
20
23
25template<class _Traits, class _Ax>
26static DWORD GetModuleFileNameA(_In_opt_ HMODULE hModule, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
27{
28 assert(0); // TODO: Test this code.
29
30 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
31
32 // Try with stack buffer first.
33 DWORD dwResult = ::GetModuleFileNameA(hModule, szStackBuffer, _countof(szStackBuffer));
34 if (dwResult < _countof(szStackBuffer)) {
35 // Copy from stack.
36 sValue.assign(szStackBuffer, dwResult);
37 return dwResult;
38 } else {
39 for (DWORD dwCapacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(char);; dwCapacity *= 2) {
40 // Allocate on heap and retry.
41 std::unique_ptr<char[]> szBuffer(new char[dwCapacity]);
42 dwResult = ::GetModuleFileNameA(hModule, szBuffer.get(), dwCapacity);
43 if (dwResult < dwCapacity) {
44 sValue.assign(szBuffer.get(), dwResult);
45 return dwResult;
46 }
47 }
48 }
49}
50
56template<class _Traits, class _Ax>
57static DWORD GetModuleFileNameW(_In_opt_ HMODULE hModule, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
58{
59 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
60
61 // Try with stack buffer first.
62 DWORD dwResult = ::GetModuleFileNameW(hModule, szStackBuffer, _countof(szStackBuffer));
63 if (dwResult < _countof(szStackBuffer)) {
64 // Copy from stack.
65 sValue.assign(szStackBuffer, dwResult);
66 return dwResult;
67 } else {
68 for (DWORD dwCapacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t);; dwCapacity *= 2) {
69 // Allocate on heap and retry.
70 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwCapacity]);
71 dwResult = ::GetModuleFileNameW(hModule, szBuffer.get(), dwCapacity);
72 if (dwResult < dwCapacity) {
73 sValue.assign(szBuffer.get(), dwResult);
74 return dwResult;
75 }
76 }
77 }
78}
79
81template<class _Traits, class _Ax>
82static _Success_(return != 0) int GetWindowTextA(_In_ HWND hWnd, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
83{
84 assert(0); // TODO: Test this code.
85
86 int iResult;
87
88 // Query the final string length first.
89 iResult = ::GetWindowTextLengthA(hWnd);
90 if (iResult > 0) {
91 if (++iResult < WINSTD_STACK_BUFFER_BYTES/sizeof(char)) {
92 // Read string data to stack.
93 char szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
94 iResult = ::GetWindowTextA(hWnd, szBuffer, _countof(szBuffer));
95 sValue.assign(szBuffer, iResult);
96 } else {
97 // Allocate buffer on heap and read the string data into it.
98 std::unique_ptr<char[]> szBuffer(new char[++iResult]);
99 iResult = ::GetWindowTextA(hWnd, szBuffer.get(), iResult);
100 sValue.assign(szBuffer.get(), iResult);
101 }
102 return iResult;
103 }
104
105 sValue.clear();
106 return 0;
107}
108
114template<class _Traits, class _Ax>
115static _Success_(return != 0) int GetWindowTextW(_In_ HWND hWnd, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
116{
117 assert(0); // TODO: Test this code.
118
119 int iResult;
120
121 // Query the final string length first.
122 iResult = ::GetWindowTextLengthW(hWnd);
123 if (iResult > 0) {
124 if (++iResult < WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)) {
125 // Read string data to stack.
126 wchar_t szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
127 iResult = ::GetWindowTextW(hWnd, szBuffer, _countof(szBuffer));
128 sValue.assign(szBuffer, iResult);
129 } else {
130 // Allocate buffer on heap and read the string data into it.
131 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[++iResult]);
132 iResult = ::GetWindowTextW(hWnd, szBuffer.get(), iResult);
133 sValue.assign(szBuffer.get(), iResult);
134 }
135 return iResult;
136 }
137
138 sValue.clear();
139 return 0;
140}
141
143template<class _Ty, class _Ax>
144static _Success_(return != 0) BOOL GetFileVersionInfoA(_In_z_ LPCSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<_Ty, _Ax> &aValue) noexcept
145{
146 assert(0); // TODO: Test this code.
147
148 // Get version info size.
149 DWORD dwVerInfoSize = ::GetFileVersionInfoSizeA(lptstrFilename, &dwHandle);
150 if (dwVerInfoSize != 0) {
151 // Read version info.
152 aValue.resize((dwVerInfoSize + sizeof(_Ty) - 1) / sizeof(_Ty));
153 return ::GetFileVersionInfoA(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
154 } else
155 return FALSE;
156}
157
163template<class _Ty, class _Ax>
164static _Success_(return != 0) BOOL GetFileVersionInfoW(_In_z_ LPCWSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<_Ty, _Ax> &aValue) noexcept
165{
166 assert(0); // TODO: Test this code.
167
168 // Get version info size.
169 DWORD dwVerInfoSize = ::GetFileVersionInfoSizeW(lptstrFilename, &dwHandle);
170 if (dwVerInfoSize != 0) {
171 // Read version info.
172 aValue.resize((dwVerInfoSize + sizeof(_Ty) - 1) / sizeof(_Ty));
173 return ::GetFileVersionInfoW(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
174 } else
175 return FALSE;
176}
177
179template<class _Traits, class _Ax>
180static _Success_(return != 0) DWORD ExpandEnvironmentStringsA(_In_z_ LPCSTR lpSrc, _Out_ std::basic_string<char, _Traits, _Ax> &sValue)
181{
182 assert(0); // TODO: Test this code.
183
184 for (SIZE_T sSizeOut = SIZETAdd(strlen(lpSrc), 0x100);;) {
185 if (sSizeOut > DWORD_MAX)
186 throw std::invalid_argument("String too big");
187 DWORD dwSizeIn = static_cast<DWORD>(sSizeOut);
188 std::unique_ptr<char[]> szBuffer(new char[(size_t)dwSizeIn + 2]); // Note: ANSI version requires one extra char.
189 sSizeOut = ::ExpandEnvironmentStringsA(lpSrc, szBuffer.get(), dwSizeIn);
190 if (sSizeOut == 0) {
191 // Error or zero-length input.
192 break;
193 } else if (sSizeOut <= dwSizeIn) {
194 // The buffer was sufficient.
195 sValue.assign(szBuffer.get(), sSizeOut - 1);
196 return static_cast<DWORD>(sSizeOut);
197 }
198 }
199
200 sValue.clear();
201 return 0;
202}
203
209template<class _Traits, class _Ax>
210static _Success_(return != 0) DWORD ExpandEnvironmentStringsW(_In_z_ LPCWSTR lpSrc, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
211{
212 for (SIZE_T sSizeOut = SIZETAdd(wcslen(lpSrc), 0x100);;) {
213 if (sSizeOut > DWORD_MAX)
214 throw std::invalid_argument("String too big");
215 DWORD dwSizeIn = static_cast<DWORD>(sSizeOut);
216 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[(size_t)dwSizeIn + 1]);
217 sSizeOut = ::ExpandEnvironmentStringsW(lpSrc, szBuffer.get(), dwSizeIn);
218 if (sSizeOut == 0) {
219 // Error or zero-length input.
220 break;
221 } else if (sSizeOut <= dwSizeIn) {
222 // The buffer was sufficient.
223 sValue.assign(szBuffer.get(), sSizeOut - 1);
224 return static_cast<DWORD>(sSizeOut);
225 }
226 }
227
228 sValue.clear();
229 return 0;
230}
231
233template<class _Traits, class _Ax>
234static VOID GuidToStringA(_In_ LPCGUID lpGuid, _Out_ std::basic_string<char, _Traits, _Ax> &str) noexcept
235{
236 assert(0); // TODO: Test this code.
237
238 sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
239 lpGuid->Data1,
240 lpGuid->Data2,
241 lpGuid->Data3,
242 lpGuid->Data4[0], lpGuid->Data4[1],
243 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
244}
245
252template<class _Traits, class _Ax>
253static VOID GuidToStringW(_In_ LPCGUID lpGuid, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &str) noexcept
254{
255 assert(0); // TODO: Test this code.
256
257 sprintf(str, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
258 lpGuid->Data1,
259 lpGuid->Data2,
260 lpGuid->Data3,
261 lpGuid->Data4[0], lpGuid->Data4[1],
262 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
263}
264
266#ifdef _UNICODE
267#define GuidToString GuidToStringW
268#else
269#define GuidToString GuidToStringA
270#endif
271
273static _Success_(return) BOOL StringToGuidA(_In_z_ LPCSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCSTR *lpszGuidEnd = NULL) noexcept
274{
275 GUID g;
276 LPSTR lpszEnd;
277 unsigned long ulTmp;
278 unsigned long long ullTmp;
279
280 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
281 lpszGuid++;
282
283 g.Data1 = strtoul(lpszGuid, &lpszEnd, 16);
284 if (errno == ERANGE) return FALSE;
285 lpszGuid = lpszEnd;
286
287 if (*lpszGuid != '-') return FALSE;
288 lpszGuid++;
289
290 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
291 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
292 g.Data2 = static_cast<unsigned short>(ulTmp);
293 lpszGuid = lpszEnd;
294
295 if (*lpszGuid != '-') return FALSE;
296 lpszGuid++;
297
298 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
299 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
300 g.Data3 = static_cast<unsigned short>(ulTmp);
301 lpszGuid = lpszEnd;
302
303 if (*lpszGuid != '-') return FALSE;
304 lpszGuid++;
305
306 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
307 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
308 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
309 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
310 lpszGuid = lpszEnd;
311
312 if (*lpszGuid != '-') return FALSE;
313 lpszGuid++;
314
315 ullTmp = _strtoui64(lpszGuid, &lpszEnd, 16);
316 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
317 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
318 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
319 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
320 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
321 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
322 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
323 lpszGuid = lpszEnd;
324
325 if (*lpszGuid != '}') return FALSE;
326 lpszGuid++;
327
328 if (lpszGuidEnd)
329 *lpszGuidEnd = lpszGuid;
330
331 *lpGuid = g;
332 return TRUE;
333}
334
346static _Success_(return) BOOL StringToGuidW(_In_z_ LPCWSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCWSTR *lpszGuidEnd = NULL) noexcept
347{
348 GUID g;
349 LPWSTR lpszEnd;
350 unsigned long ulTmp;
351 unsigned long long ullTmp;
352
353 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
354 lpszGuid++;
355
356 g.Data1 = wcstoul(lpszGuid, &lpszEnd, 16);
357 if (errno == ERANGE) return FALSE;
358 lpszGuid = lpszEnd;
359
360 if (*lpszGuid != '-') return FALSE;
361 lpszGuid++;
362
363 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
364 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
365 g.Data2 = static_cast<unsigned short>(ulTmp);
366 lpszGuid = lpszEnd;
367
368 if (*lpszGuid != '-') return FALSE;
369 lpszGuid++;
370
371 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
372 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
373 g.Data3 = static_cast<unsigned short>(ulTmp);
374 lpszGuid = lpszEnd;
375
376 if (*lpszGuid != '-') return FALSE;
377 lpszGuid++;
378
379 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
380 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
381 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
382 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
383 lpszGuid = lpszEnd;
384
385 if (*lpszGuid != '-') return FALSE;
386 lpszGuid++;
387
388 ullTmp = _wcstoui64(lpszGuid, &lpszEnd, 16);
389 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
390 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
391 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
392 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
393 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
394 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
395 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
396 lpszGuid = lpszEnd;
397
398 if (*lpszGuid != '}') return FALSE;
399 lpszGuid++;
400
401 if (lpszGuidEnd)
402 *lpszGuidEnd = lpszGuid;
403
404 *lpGuid = g;
405 return TRUE;
406}
407
409#ifdef _UNICODE
410#define StringToGuid StringToGuidW
411#else
412#define StringToGuid StringToGuidA
413#endif
414
433template<class _Traits, class _Ax>
434static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCSTR pszName, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
435{
436 LSTATUS lResult;
437 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
438 DWORD dwSize = sizeof(aStackBuffer), dwType;
439
440 // Try with stack buffer first.
441 lResult = ::RegQueryValueExA(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
442 if (lResult == ERROR_SUCCESS) {
443 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
444 // The value is REG_SZ or REG_MULTI_SZ.
445 dwSize /= sizeof(CHAR);
446 sValue.assign(reinterpret_cast<LPCSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
447 } else if (dwType == REG_EXPAND_SZ) {
448 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
449 if (::ExpandEnvironmentStringsA(reinterpret_cast<LPCSTR>(aStackBuffer), sValue) == 0)
450 lResult = ::GetLastError();
451 } else {
452 // The value is not a string type.
453 lResult = ERROR_INVALID_DATA;
454 }
455 } else if (lResult == ERROR_MORE_DATA) {
456 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
457 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
458 std::unique_ptr<CHAR[]> szBuffer(new CHAR[dwSize / sizeof(CHAR)]);
459 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
460 dwSize /= sizeof(CHAR);
461 sValue.assign(szBuffer.get(), dwSize && szBuffer[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
462 }
463 } else if (dwType == REG_EXPAND_SZ) {
464 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
465 std::unique_ptr<CHAR[]> szBuffer(new CHAR[dwSize / sizeof(CHAR)]);
466 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
467 if (::ExpandEnvironmentStringsA(szBuffer.get(), sValue) == 0)
468 lResult = ::GetLastError();
469 }
470 } else {
471 // The value is not a string type.
472 lResult = ERROR_INVALID_DATA;
473 }
474 }
475
476 return lResult;
477}
478
497template<class _Traits, class _Ax>
498static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCWSTR pszName, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
499{
500 LSTATUS lResult;
501 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
502 DWORD dwSize = sizeof(aStackBuffer), dwType;
503
504 // Try with stack buffer first.
505 lResult = ::RegQueryValueExW(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
506 if (lResult == ERROR_SUCCESS) {
507 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
508 // The value is REG_SZ or REG_MULTI_SZ.
509 dwSize /= sizeof(WCHAR);
510 sValue.assign(reinterpret_cast<LPCWSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCWSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
511 } else if (dwType == REG_EXPAND_SZ) {
512 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
513 if (::ExpandEnvironmentStringsW(reinterpret_cast<LPCWSTR>(aStackBuffer), sValue) == 0)
514 lResult = ::GetLastError();
515 } else {
516 // The value is not a string type.
517 lResult = ERROR_INVALID_DATA;
518 }
519 } else if (lResult == ERROR_MORE_DATA) {
520 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
521 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
522 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[dwSize / sizeof(WCHAR)]);
523 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
524 dwSize /= sizeof(WCHAR);
525 sValue.assign(szBuffer.get(), dwSize && szBuffer[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
526 }
527 } else if (dwType == REG_EXPAND_SZ) {
528 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
529 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[dwSize / sizeof(WCHAR)]);
530 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
531 if (::ExpandEnvironmentStringsW(szBuffer.get(), sValue) == 0)
532 lResult = ::GetLastError();
533 }
534 } else {
535 // The value is not a string type.
536 lResult = ERROR_INVALID_DATA;
537 }
538 }
539
540 return lResult;
541}
542
544template<class _Ty, class _Ax>
545static LSTATUS RegQueryValueExA(_In_ HKEY hKey, _In_opt_z_ LPCSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
546{
547 LSTATUS lResult;
548 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
549 DWORD dwSize = sizeof(aStackBuffer);
550
551 // Try with stack buffer first.
552 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
553 if (lResult == ERROR_SUCCESS) {
554 // Copy from stack buffer.
555 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
556 memcpy(aData.data(), aStackBuffer, dwSize);
557 } else if (lResult == ERROR_MORE_DATA) {
558 // Allocate buffer on heap and retry.
559 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
560 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, NULL, reinterpret_cast<LPBYTE>(aData.data()), &dwSize);
561 }
562
563 return lResult;
564}
565
571template<class _Ty, class _Ax>
572static LSTATUS RegQueryValueExW(_In_ HKEY hKey, _In_opt_z_ LPCWSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
573{
574 LSTATUS lResult;
575 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
576 DWORD dwSize = sizeof(aStackBuffer);
577
578 // Try with stack buffer first.
579 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
580 if (lResult == ERROR_SUCCESS) {
581 // Copy from stack buffer.
582 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
583 memcpy(aData.data(), aStackBuffer, dwSize);
584 } else if (lResult == ERROR_MORE_DATA) {
585 // Allocate buffer on heap and retry.
586 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
587 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, NULL, reinterpret_cast<LPBYTE>(aData.data()), &dwSize);
588 }
589
590 return lResult;
591}
592
593#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
594
596template<class _Traits, class _Ax>
597static 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
598{
599 // According to "Remarks" section in MSDN documentation of RegLoadMUIString(),
600 // this function is defined but not implemented as ANSI variation.
601 assert(0);
602 return ERROR_CALL_NOT_IMPLEMENTED;
603}
604
610template<class _Traits, class _Ax>
611static 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
612{
613 LSTATUS lResult;
614 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
615 DWORD dwSize;
616
617 Flags &= ~REG_MUI_STRING_TRUNCATE;
618
619 // Try with stack buffer first.
620 lResult = RegLoadMUIStringW(hKey, pszValue, szStackBuffer, sizeof(szStackBuffer), &dwSize, Flags, pszDirectory);
621 if (lResult == ERROR_SUCCESS) {
622 // Copy from stack buffer.
623 sOut.assign(szStackBuffer, wcsnlen(szStackBuffer, dwSize/sizeof(wchar_t)));
624 } else if (lResult == ERROR_MORE_DATA) {
625 // Allocate buffer on heap and retry.
626 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[(dwSize + sizeof(wchar_t) - 1)/sizeof(wchar_t)]);
627 sOut.assign(szBuffer.get(), (lResult = RegLoadMUIStringW(hKey, pszValue, szBuffer.get(), dwSize, &dwSize, Flags, pszDirectory)) == ERROR_SUCCESS ? wcsnlen(szBuffer.get(), dwSize/sizeof(wchar_t)) : 0);
628 }
629
630 return lResult;
631}
632
633#endif
634
640template<class _Traits, class _Ax>
641static _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
642{
643 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
644
645 // Try to convert to stack buffer first.
646 int cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szStackBuffer, _countof(szStackBuffer));
647 if (cch > 0) {
648 // Copy from stack.
649 sDstString.assign(szStackBuffer, cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
650 } else {
651 switch (::GetLastError()) {
652 case ERROR_INSUFFICIENT_BUFFER:
653 for (int i = 10; i--;) {
654 // Allocate buffer. Then convert again.
655 cch = -cch;
656 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
657 cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szBuffer.get(), cch);
658 if (cch > 0) {
659 sDstString.assign(szBuffer.get(), cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
660 break;
661 }
662 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
663 sDstString.clear();
664 break;
665 }
666 }
667 break;
668
669 case ERROR_SUCCESS:
670 sDstString.clear();
671 break;
672 }
673 }
674
675 return cch;
676}
677
683template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
684static _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
685{
686 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
687
688 // Try to convert to stack buffer first.
689 int cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szStackBuffer, _countof(szStackBuffer));
690 if (cch > 0) {
691 // Copy from stack.
692 sDstString.assign(szStackBuffer, cch);
693 } else {
694 switch (::GetLastError()) {
695 case ERROR_INSUFFICIENT_BUFFER:
696 for (int i = 10; i--;) {
697 // Allocate buffer. Then convert again.
698 cch = -cch;
699 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
700 cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szBuffer.get(), cch);
701 if (cch > 0) {
702 sDstString.assign(szBuffer.get(), cch);
703 break;
704 }
705 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
706 sDstString.clear();
707 break;
708 }
709 }
710 break;
711
712 case ERROR_SUCCESS:
713 sDstString.clear();
714 break;
715 }
716 }
717
718 return cch;
719}
720
722template<class _Traits, class _Ax>
723static _Success_(return != 0) int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<char, _Traits, _Ax> &sBuffer) noexcept
724{
725 // Get read-only pointer to string resource.
726 LPCSTR pszStr;
727 int i = LoadStringA(hInstance, uID, reinterpret_cast<LPSTR>(&pszStr), 0);
728 if (i) {
729 sBuffer.assign(pszStr, i);
730 return i;
731 } else
732 return 0;
733}
734
740template<class _Traits, class _Ax>
741static _Success_(return != 0) int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sBuffer) noexcept
742{
743 // Get read-only pointer to string resource.
744 LPCWSTR pszStr;
745 int i = LoadStringW(hInstance, uID, reinterpret_cast<LPWSTR>(&pszStr), 0);
746 if (i) {
747 sBuffer.assign(pszStr, i);
748 return i;
749 } else
750 return 0;
751}
752
758static VOID OutputDebugStrV(_In_z_ LPCSTR lpOutputString, _In_ va_list arg) noexcept
759{
760 std::string str;
761 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
762 OutputDebugStringA(str.c_str());
763}
764
770static VOID OutputDebugStrV(_In_z_ LPCWSTR lpOutputString, _In_ va_list arg) noexcept
771{
772 std::wstring str;
773 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
774 OutputDebugStringW(str.c_str());
775}
776
782static VOID OutputDebugStr(_In_z_ LPCSTR lpOutputString, ...) noexcept
783{
784 va_list arg;
785 va_start(arg, lpOutputString);
786 OutputDebugStrV(lpOutputString, arg);
787 va_end(arg);
788}
789
795static VOID OutputDebugStr(_In_z_ LPCWSTR lpOutputString, ...) noexcept
796{
797 va_list arg;
798 va_start(arg, lpOutputString);
799 OutputDebugStrV(lpOutputString, arg);
800 va_end(arg);
801}
802
804template<class _Traits, class _Ax>
805static _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
806{
807 int iResult = GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
808 if (iResult) {
809 // Allocate buffer on heap and retry.
810 std::unique_ptr<char[]> szBuffer(new char[iResult]);
811 iResult = GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, szBuffer.get(), iResult);
812 sDate.assign(szBuffer.get(), iResult ? iResult - 1 : 0);
813 return iResult;
814 }
815
816 return iResult;
817}
818
824template<class _Traits, class _Ax>
825static _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
826{
827 int iResult = GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
828 if (iResult) {
829 // Allocate buffer on heap and retry.
830 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[iResult]);
831 iResult = GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, szBuffer.get(), iResult);
832 sDate.assign(szBuffer.get(), iResult ? iResult - 1 : 0);
833 return iResult;
834 }
835
836 return iResult;
837}
838
840template<class _Traits, class _Ax>
841static _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
842{
843 assert(0); // TODO: Test this code.
844
845 DWORD dwNameLen = 0, dwRefDomainLen = 0;
846
847 if (LookupAccountSidA(lpSystemName, lpSid,
848 NULL, &dwNameLen ,
849 NULL, &dwRefDomainLen,
850 peUse))
851 {
852 // Name and domain is blank.
853 if (sName ) sName ->clear();
854 if (sReferencedDomainName) sReferencedDomainName->clear();
855 return TRUE;
856 } else if (GetLastError() == ERROR_MORE_DATA) {
857 // Allocate on heap and retry.
858 std::unique_ptr<char[]> bufName (new char[dwNameLen ]);
859 std::unique_ptr<char[]> bufRefDomain(new char[dwRefDomainLen]);
860 if (LookupAccountSidA(lpSystemName, lpSid,
861 bufName .get(), &dwNameLen ,
862 bufRefDomain.get(), &dwRefDomainLen,
863 peUse))
864 {
865 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
866 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
867 return TRUE;
868 }
869 }
870
871 return FALSE;
872}
873
879template<class _Traits, class _Ax>
880static _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
881{
882 assert(0); // TODO: Test this code.
883
884 DWORD dwNameLen = 0, dwRefDomainLen = 0;
885
886 if (LookupAccountSidW(lpSystemName, lpSid,
887 NULL, &dwNameLen ,
888 NULL, &dwRefDomainLen,
889 peUse))
890 {
891 // Name and domain is blank.
892 if (sName ) sName ->clear();
893 if (sReferencedDomainName) sReferencedDomainName->clear();
894 return TRUE;
895 } else if (GetLastError() == ERROR_MORE_DATA) {
896 // Allocate on heap and retry.
897 std::unique_ptr<wchar_t[]> bufName (new wchar_t[dwNameLen ]);
898 std::unique_ptr<wchar_t[]> bufRefDomain(new wchar_t[dwRefDomainLen]);
899 if (LookupAccountSidW(lpSystemName, lpSid,
900 bufName .get(), &dwNameLen ,
901 bufRefDomain.get(), &dwRefDomainLen,
902 peUse))
903 {
904 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
905 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
906 return TRUE;
907 }
908 }
909
910 return FALSE;
911}
912
918static _Success_(return != FALSE) BOOL CreateWellKnownSid(_In_ WELL_KNOWN_SID_TYPE WellKnownSidType, _In_opt_ PSID DomainSid, _Inout_ std::unique_ptr<SID> &Sid)
919{
920 BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES];
921 DWORD dwSize = sizeof(szStackBuffer);
922
923 if (CreateWellKnownSid(WellKnownSidType, DomainSid, szStackBuffer, &dwSize)) {
924 // The stack buffer was big enough to retrieve complete data. Alloc and copy.
925 Sid.reset((SID*)new BYTE[dwSize]);
926 memcpy(Sid.get(), szStackBuffer, dwSize);
927 return TRUE;
928 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
929 // The stack buffer was too small to retrieve complete data. Alloc and retry.
930 Sid.reset((SID*)new BYTE[dwSize]);
931 return CreateWellKnownSid(WellKnownSidType, DomainSid, Sid.get(), &dwSize);
932 } else
933 return FALSE;
934}
935
941template<class _Ty>
942static _Success_(return != 0) BOOL GetTokenInformation(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_ std::unique_ptr<_Ty> &TokenInformation) noexcept
943{
944 BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES];
945 DWORD dwSize;
946
947 if (GetTokenInformation(TokenHandle, TokenInformationClass, szStackBuffer, sizeof(szStackBuffer), &dwSize)) {
948 // The stack buffer was big enough to retrieve complete data. Alloc and copy.
949 TokenInformation.reset((_Ty*)(new BYTE[dwSize]));
950 memcpy(TokenInformation.get(), szStackBuffer, dwSize);
951 return TRUE;
952 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
953 // The stack buffer was too small to retrieve complete data. Alloc and retry.
954 TokenInformation.reset((_Ty*)(new BYTE[dwSize]));
955 return GetTokenInformation(TokenHandle, TokenInformationClass, TokenInformation.get(), dwSize, &dwSize);
956 } else
957 return FALSE;
958}
959
965template<class _Traits, class _Ax>
966static _Success_(return != 0) BOOL QueryFullProcessImageNameA(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<char, _Traits, _Ax>& sExeName)
967{
968 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(char)];
969 DWORD dwSize = _countof(szStackBuffer);
970
971 // Try with stack buffer first.
972 if (::QueryFullProcessImageNameA(hProcess, dwFlags, szStackBuffer, &dwSize)) {
973 // Copy from stack.
974 sExeName.assign(szStackBuffer, dwSize);
975 return TRUE;
976 }
977 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(char); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
978 // Allocate on heap and retry.
979 std::unique_ptr<char[]> szBuffer(new char[dwCapacity]);
980 dwSize = dwCapacity;
981 if (::QueryFullProcessImageNameA(hProcess, dwFlags, szBuffer.get(), &dwSize)) {
982 sExeName.assign(szBuffer.get(), dwSize);
983 return TRUE;
984 }
985 }
986 return FALSE;
987}
988
994template<class _Traits, class _Ax>
995static _Success_(return != 0) BOOL QueryFullProcessImageNameW(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<wchar_t, _Traits, _Ax>& sExeName)
996{
997 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t)];
998 DWORD dwSize = _countof(szStackBuffer);
999
1000 // Try with stack buffer first.
1001 if (::QueryFullProcessImageNameW(hProcess, dwFlags, szStackBuffer, &dwSize)) {
1002 // Copy from stack.
1003 sExeName.assign(szStackBuffer, dwSize);
1004 return TRUE;
1005 }
1006 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
1007 // Allocate on heap and retry.
1008 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwCapacity]);
1009 dwSize = dwCapacity;
1010 if (::QueryFullProcessImageNameW(hProcess, dwFlags, szBuffer.get(), &dwSize)) {
1011 sExeName.assign(szBuffer.get(), dwSize);
1012 return TRUE;
1013 }
1014 }
1015 return FALSE;
1016}
1017
1019
1020#pragma warning(pop)
1021
1022namespace winstd
1023{
1026
1030 template<HANDLE INVALID>
1031 class win_handle : public handle<HANDLE, INVALID>
1032 {
1033 WINSTD_HANDLE_IMPL(win_handle, HANDLE, INVALID)
1034
1035 public:
1041 virtual ~win_handle()
1042 {
1043 if (m_h != invalid)
1044 free_internal();
1045 }
1046
1047 protected:
1053 void free_internal() noexcept override
1054 {
1055 CloseHandle(m_h);
1056 }
1057 };
1058
1064 class library : public handle<HMODULE, NULL>
1065 {
1066 WINSTD_HANDLE_IMPL(library, HMODULE, NULL)
1067
1068 public:
1074 virtual ~library()
1075 {
1076 if (m_h != invalid)
1077 free_internal();
1078 }
1079
1080 protected:
1086 void free_internal() noexcept override
1087 {
1088 FreeLibrary(m_h);
1089 }
1090 };
1091
1098
1105
1112
1119
1127
1134
1139 {
1143 void operator()(void* _Ptr) const
1144 {
1145 if (!UnmapViewOfFile(_Ptr))
1146 throw win_runtime_error("UnmapViewOfFile failed");
1147 }
1148 };
1149
1157
1162 {
1165
1166 public:
1173 {
1174 InitializeCriticalSection(&m_data);
1175 }
1176
1183 {
1184 DeleteCriticalSection(&m_data);
1185 }
1186
1192 operator LPCRITICAL_SECTION() noexcept
1193 {
1194 return &m_data;
1195 }
1196
1197 protected:
1198 CRITICAL_SECTION m_data;
1199 };
1200
1206 class find_file : public handle<HANDLE, INVALID_HANDLE_VALUE>
1207 {
1208 WINSTD_HANDLE_IMPL(find_file, HANDLE, INVALID_HANDLE_VALUE)
1209
1210 public:
1216 virtual ~find_file()
1217 {
1218 if (m_h != invalid)
1219 free_internal();
1220 }
1221
1222 protected:
1228 void free_internal() noexcept override
1229 {
1230 FindClose(m_h);
1231 }
1232 };
1233
1239 class heap : public handle<HANDLE, NULL>
1240 {
1241 WINSTD_HANDLE_IMPL(heap, HANDLE, NULL)
1242
1243 public:
1249 virtual ~heap()
1250 {
1251 if (m_h != invalid)
1252 free_internal();
1253 }
1254
1262 bool enumerate() noexcept
1263 {
1264 assert(m_h != invalid);
1265
1266 bool found = false;
1267
1268 // Lock the heap for exclusive access.
1269 HeapLock(m_h);
1270
1271 PROCESS_HEAP_ENTRY e;
1272 e.lpData = NULL;
1273 while (HeapWalk(m_h, &e) != FALSE) {
1274 if ((e.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
1276 _T("Allocated block%s%s\n")
1277 _T(" Data portion begins at: %#p\n Size: %d bytes\n")
1278 _T(" Overhead: %d bytes\n Region index: %d\n"),
1279 (e.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0 ? tstring_printf(_T(", movable with HANDLE %#p"), e.Block.hMem).c_str() : _T(""),
1280 (e.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0 ? _T(", DDESHARE") : _T(""),
1281 e.lpData,
1282 e.cbData,
1283 e.cbOverhead,
1284 e.iRegionIndex);
1285
1286 found = true;
1287 }
1288 }
1289
1290 const DWORD dwResult = GetLastError();
1291 if (dwResult != ERROR_NO_MORE_ITEMS)
1292 OutputDebugStr(_T("HeapWalk failed (error %u).\n"), dwResult);
1293
1294 // Unlock the heap.
1295 HeapUnlock(m_h);
1296
1297 return found;
1298 }
1299
1300 protected:
1306 void free_internal() noexcept override
1307 {
1308 enumerate();
1309 HeapDestroy(m_h);
1310 }
1311 };
1312
1316 template <class _Ty>
1318 {
1319 public:
1320 typedef typename _Ty value_type;
1321
1322 typedef _Ty *pointer;
1323 typedef _Ty& reference;
1324 typedef const _Ty *const_pointer;
1325 typedef const _Ty& const_reference;
1326
1327 typedef SIZE_T size_type;
1328 typedef ptrdiff_t difference_type;
1329
1333 template <class _Other>
1334 struct rebind
1335 {
1337 };
1338
1339 public:
1346 {
1347 }
1348
1354 template <class _Other>
1356 {
1357 }
1358
1367 {
1368 assert(m_heap);
1369 return (pointer)HeapAlloc(m_heap, 0, count * sizeof(_Ty));
1370 }
1371
1378 void deallocate(_In_ pointer ptr, _In_ size_type size)
1379 {
1380 UNREFERENCED_PARAMETER(size);
1381 assert(m_heap);
1382 HeapFree(m_heap, 0, ptr);
1383 }
1384
1391 void construct(_Inout_ pointer ptr, _In_ const _Ty& val)
1392 {
1393 ::new ((void*)ptr) _Ty(val);
1394 }
1395
1402 void construct(_Inout_ pointer ptr, _Inout_ _Ty&& val)
1403 {
1404 ::new ((void*)ptr) _Ty(std::forward<_Ty>(val));
1405 }
1406
1412 void destroy(_Inout_ pointer ptr)
1413 {
1414 ptr->_Ty::~_Ty();
1415 }
1416
1421 {
1422 return (SIZE_T)-1;
1423 }
1424
1425 public:
1426 HANDLE m_heap;
1427 };
1428
1433 {
1436
1437 public:
1445 actctx_activator(_In_ HANDLE hActCtx) noexcept
1446 {
1447 if (!ActivateActCtx(hActCtx, &m_cookie))
1448 m_cookie = 0;
1449 }
1450
1457 {
1458 if (m_cookie)
1459 DeactivateActCtx(0, m_cookie);
1460 }
1461
1462 protected:
1463 ULONG_PTR m_cookie;
1464 };
1465
1470 {
1471 public:
1475 impersonator() noexcept : m_cookie(FALSE) {}
1476
1483 {
1484 if (m_cookie)
1485 RevertToSelf();
1486 }
1487
1491 operator bool () const { return m_cookie; }
1492
1493 protected:
1495 };
1496
1501 {
1504
1505 public:
1513 user_impersonator(_In_opt_ HANDLE hToken) noexcept
1514 {
1515 m_cookie = hToken && ImpersonateLoggedOnUser(hToken);
1516 }
1517 };
1518
1523 {
1526
1527 public:
1532 {
1533 TOKEN_PRIVILEGES privileges = { 1, {{{ 0, 0 }, SE_PRIVILEGE_ENABLED }} };
1534 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid) ||
1535 !ImpersonateSelf(SecurityImpersonation))
1536 return;
1537
1538 {
1539 HANDLE h;
1540 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &h))
1541 goto revert;
1542 win_handle<INVALID_HANDLE_VALUE> thread_token(h);
1543 if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL))
1544 goto revert;
1545 process_snapshot process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1546 if (!process_snapshot)
1547 goto revert;
1548 PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32) };
1549 if (!Process32First(process_snapshot, &entry))
1550 goto revert;
1551 while (_tcsicmp(entry.szExeFile, TEXT("winlogon.exe")) != 0)
1552 if (!Process32Next(process_snapshot, &entry))
1553 goto revert;
1554 process winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
1555 if (!winlogon_process)
1556 goto revert;
1557 if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &h))
1558 goto revert;
1559 win_handle<INVALID_HANDLE_VALUE> winlogon_token(h);
1560 if (!DuplicateToken(winlogon_token, SecurityImpersonation, &h))
1561 goto revert;
1562 win_handle<INVALID_HANDLE_VALUE> duplicated_token(h);
1563 if (!SetThreadToken(NULL, duplicated_token))
1564 goto revert;
1565 }
1566
1567 m_cookie = TRUE;
1568 return;
1569
1570 revert:
1571 DWORD dwResult = GetLastError();
1572 RevertToSelf();
1573 SetLastError(dwResult);
1574 }
1575 };
1576
1581 {
1582 public:
1588 clipboard_opener(_In_opt_ HWND hWndNewOwner = NULL)
1589 {
1590 if (!OpenClipboard(hWndNewOwner))
1591 throw win_runtime_error("OpenClipboard failed");
1592 }
1593
1600 {
1601 CloseClipboard();
1602 }
1603 };
1604
1609 {
1612
1613 public:
1621 console_ctrl_handler(_In_opt_ PHANDLER_ROUTINE HandlerRoutine) noexcept : m_handler(HandlerRoutine)
1622 {
1623 m_cookie = SetConsoleCtrlHandler(m_handler, TRUE);
1624 }
1625
1632 {
1633 if (m_cookie)
1634 SetConsoleCtrlHandler(m_handler, FALSE);
1635 }
1636
1637 protected:
1639 PHANDLER_ROUTINE m_handler;
1640 };
1641
1645 class vmemory : public handle<LPVOID, NULL>
1646 {
1648
1649 public:
1653 vmemory() noexcept : m_proc(NULL)
1654 {
1655 }
1656
1663 vmemory(_In_ handle_type h, _In_ HANDLE proc) noexcept :
1664 m_proc(proc),
1666 {
1667 }
1668
1674 vmemory(_Inout_ vmemory &&h) noexcept :
1675 m_proc(std::move(h.m_proc)),
1676 handle<LPVOID, NULL>(std::move(h))
1677 {
1678 }
1679
1685 virtual ~vmemory()
1686 {
1687 if (m_h != invalid)
1688 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
1689 }
1690
1696 vmemory& operator=(_Inout_ vmemory &&other) noexcept
1697 {
1698 if (this != std::addressof(other)) {
1699 (handle<handle_type, NULL>&&)*this = std::move(other);
1700 m_proc = std::move(other.m_proc);
1701 }
1702 return *this;
1703 }
1704
1713 void attach(_In_ HANDLE proc, _In_opt_ handle_type h) noexcept
1714 {
1715 m_proc = proc;
1716 if (m_h != invalid)
1717 free_internal();
1718 m_h = h;
1719 }
1720
1730 bool alloc(
1731 _In_ HANDLE hProcess,
1732 _In_opt_ LPVOID lpAddress,
1733 _In_ SIZE_T dwSize,
1734 _In_ DWORD flAllocationType,
1735 _In_ DWORD flProtect) noexcept
1736 {
1737 handle_type h = VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect);
1738 if (h != invalid) {
1739 attach(hProcess, h);
1740 return true;
1741 } else
1742 return false;
1743 }
1744
1745 protected:
1751 void free_internal() noexcept override
1752 {
1753 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
1754 }
1755
1756 protected:
1757 HANDLE m_proc;
1758 };
1759
1766 class reg_key : public handle<HKEY, NULL>
1767 {
1768 WINSTD_HANDLE_IMPL(reg_key, HKEY, NULL)
1769
1770 public:
1776 virtual ~reg_key()
1777 {
1778 if (m_h != invalid)
1779 free_internal();
1780 }
1781
1791 bool delete_subkey(_In_z_ LPCTSTR szSubkey)
1792 {
1793 LSTATUS s;
1794
1795 s = RegDeleteKey(m_h, szSubkey);
1796 if (s == ERROR_SUCCESS || s == ERROR_FILE_NOT_FOUND)
1797 return true;
1798
1799 {
1800 reg_key k;
1801 handle_type h;
1802 s = RegOpenKeyEx(m_h, szSubkey, 0, KEY_ENUMERATE_SUB_KEYS, &h);
1803 if (s == ERROR_SUCCESS)
1804 k.attach(h);
1805 else {
1806 SetLastError(s);
1807 return false;
1808 }
1809 for (;;) {
1810 TCHAR szName[MAX_PATH];
1811 DWORD dwSize = _countof(szName);
1812 s = RegEnumKeyEx(k, 0, szName, &dwSize, NULL, NULL, NULL, NULL);
1813 if (s == ERROR_SUCCESS)
1814 k.delete_subkey(szName);
1815 else if (s == ERROR_NO_MORE_ITEMS)
1816 break;
1817 else {
1818 SetLastError(s);
1819 return false;
1820 }
1821 }
1822 }
1823
1824 s = RegDeleteKey(m_h, szSubkey);
1825 if (s == ERROR_SUCCESS)
1826 return true;
1827 else {
1828 SetLastError(s);
1829 return false;
1830 }
1831 }
1832
1833 protected:
1839 void free_internal() noexcept override
1840 {
1841 RegCloseKey(m_h);
1842 }
1843 };
1844
1848 class security_id : public handle<PSID, NULL>
1849 {
1850 WINSTD_HANDLE_IMPL(security_id, PSID, NULL)
1851
1852 public:
1859 {
1860 if (m_h != invalid)
1861 free_internal();
1862 }
1863
1864 protected:
1870 void free_internal() noexcept override
1871 {
1872 FreeSid(m_h);
1873 }
1874 };
1875
1879 class process_information : public PROCESS_INFORMATION
1880 {
1883
1884 public:
1889 {
1890 hProcess = INVALID_HANDLE_VALUE;
1891 hThread = INVALID_HANDLE_VALUE;
1892 dwProcessId = 0;
1893 dwThreadId = 0;
1894 }
1895
1900 {
1901 #pragma warning(push)
1902 #pragma warning(disable: 6001) // Using uninitialized memory '*this'. << ???
1903
1904 if (hProcess != INVALID_HANDLE_VALUE)
1905 CloseHandle(hProcess);
1906
1907 if (hThread != INVALID_HANDLE_VALUE)
1908 CloseHandle(hThread);
1909
1910 #pragma warning(pop)
1911 }
1912 };
1913
1919 class event_log : public handle<HANDLE, NULL>
1920 {
1921 WINSTD_HANDLE_IMPL(event_log, HANDLE, NULL)
1922
1923 public:
1929 virtual ~event_log()
1930 {
1931 if (m_h != invalid)
1932 free_internal();
1933 }
1934
1935 protected:
1941 void free_internal() noexcept override
1942 {
1943 DeregisterEventSource(m_h);
1944 }
1945 };
1946
1950 class sc_handle : public handle<SC_HANDLE, NULL>
1951 {
1952 WINSTD_HANDLE_IMPL(sc_handle, SC_HANDLE, NULL)
1953
1954 public:
1960 virtual ~sc_handle()
1961 {
1962 if (m_h != invalid)
1963 free_internal();
1964 }
1965
1966 protected:
1972 void free_internal() noexcept override
1973 {
1974 CloseServiceHandle(m_h);
1975 }
1976 };
1977
1979}
1980
1983
1984#pragma warning(push)
1985#pragma warning(disable: 4505) // Don't warn on unused code
1986
1988static LSTATUS RegCreateKeyExA(
1989 _In_ HKEY hKey,
1990 _In_ LPCSTR lpSubKey,
1991 _Reserved_ DWORD Reserved,
1992 _In_opt_ LPSTR lpClass,
1993 _In_ DWORD dwOptions,
1994 _In_ REGSAM samDesired,
1995 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1996 _Inout_ winstd::reg_key &result,
1997 _Out_opt_ LPDWORD lpdwDisposition)
1998{
1999 HKEY h;
2000 LSTATUS s = RegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2001 if (s == ERROR_SUCCESS)
2002 result.attach(h);
2003 return s;
2004}
2005
2011static LSTATUS RegCreateKeyExW(
2012 _In_ HKEY hKey,
2013 _In_ LPCWSTR lpSubKey,
2014 _Reserved_ DWORD Reserved,
2015 _In_opt_ LPWSTR lpClass,
2016 _In_ DWORD dwOptions,
2017 _In_ REGSAM samDesired,
2018 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2019 _Inout_ winstd::reg_key &result,
2020 _Out_opt_ LPDWORD lpdwDisposition)
2021{
2022 HKEY h;
2023 LSTATUS s = RegCreateKeyExW(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2024 if (s == ERROR_SUCCESS)
2025 result.attach(h);
2026 return s;
2027}
2028
2030static LSTATUS RegOpenKeyExA(
2031 _In_ HKEY hKey,
2032 _In_opt_ LPCSTR lpSubKey,
2033 _In_opt_ DWORD ulOptions,
2034 _In_ REGSAM samDesired,
2035 _Inout_ winstd::reg_key &result)
2036{
2037 HKEY h;
2038 LSTATUS s = RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, &h);
2039 if (s == ERROR_SUCCESS)
2040 result.attach(h);
2041 return s;
2042}
2043
2049static LSTATUS RegOpenKeyExW(
2050 _In_ HKEY hKey,
2051 _In_opt_ LPCWSTR lpSubKey,
2052 _In_opt_ DWORD ulOptions,
2053 _In_ REGSAM samDesired,
2054 _Inout_ winstd::reg_key &result)
2055{
2056 HKEY h;
2057 LSTATUS s = RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, &h);
2058 if (s == ERROR_SUCCESS)
2059 result.attach(h);
2060 return s;
2061}
2062
2068static BOOL OpenProcessToken(_In_ HANDLE ProcessHandle, _In_ DWORD DesiredAccess, _Inout_ winstd::win_handle<NULL> &TokenHandle)
2069{
2070 HANDLE h;
2071 if (OpenProcessToken(ProcessHandle, DesiredAccess, &h)) {
2072 TokenHandle.attach(h);
2073 return TRUE;
2074 }
2075 return FALSE;
2076}
2077
2083static 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)
2084{
2085 HANDLE h;
2086 if (DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, &h)) {
2087 NewToken.attach(h);
2088 return TRUE;
2089 }
2090 return FALSE;
2091}
2092
2098static 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)
2099{
2100 PSID h;
2101 if (AllocateAndInitializeSid(pIdentifierAuthority, nSubAuthorityCount, nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3, nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, &h)) {
2102 Sid.attach(h);
2103 return TRUE;
2104 }
2105 return FALSE;
2106}
2107
2109static 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)
2110{
2111 PACL h;
2112 DWORD dwResult = SetEntriesInAclA(cCountOfExplicitEntries, pListOfExplicitEntries, OldAcl, &h);
2113 if (dwResult == ERROR_SUCCESS)
2114 Acl.reset(h);
2115 return ERROR_SUCCESS;
2116}
2117
2123static 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)
2124{
2125 PACL h;
2126 DWORD dwResult = SetEntriesInAclW(cCountOfExplicitEntries, pListOfExplicitEntries, OldAcl, &h);
2127 if (dwResult == ERROR_SUCCESS)
2128 Acl.reset(h);
2129 return ERROR_SUCCESS;
2130}
2131
2137template<class _Traits, class _Ax>
2138_Success_(return != 0) BOOL GetThreadPreferredUILanguages(_In_ DWORD dwFlags, _Out_ PULONG pulNumLanguages, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
2139{
2140 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
2141 ULONG ulSize = _countof(szStackBuffer);
2142
2143 // Try with stack buffer first.
2144 if (GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, szStackBuffer, &ulSize)) {
2145 // Copy from stack.
2146 sValue.assign(szStackBuffer, ulSize - 1);
2147 return TRUE;
2148 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
2149 // Query required size.
2150 ulSize = 0;
2151 GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, NULL, &ulSize);
2152 // Allocate on heap and retry.
2153 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[ulSize]);
2154 if (GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, szBuffer.get(), &ulSize)) {
2155 sValue.assign(szBuffer.get(), ulSize - 1);
2156 return TRUE;
2157 }
2158 }
2159 return FALSE;
2160}
2161
2162#pragma warning(pop)
2163
Activates given activation context in constructor and deactivates it in destructor.
Definition Win.h:1433
actctx_activator(HANDLE hActCtx) noexcept
Construct the activator and activates the given activation context.
Definition Win.h:1445
virtual ~actctx_activator()
Deactivates activation context and destructs the activator.
Definition Win.h:1456
ULONG_PTR m_cookie
Cookie for context deactivation.
Definition Win.h:1463
Base template class to support string formatting using printf() style templates.
Definition Common.h:1611
Clipboard management.
Definition Win.h:1581
virtual ~clipboard_opener()
Closes the clipboard.
Definition Win.h:1599
clipboard_opener(HWND hWndNewOwner=NULL)
Opens the clipboard for examination and prevents other applications from modifying the clipboard cont...
Definition Win.h:1588
Console control handler stack management.
Definition Win.h:1609
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:1621
virtual ~console_ctrl_handler()
Pops console control handler from the console control handler stack.
Definition Win.h:1631
PHANDLER_ROUTINE m_handler
Pointer to console control handler.
Definition Win.h:1639
BOOL m_cookie
Did pushing the console control handler succeed?
Definition Win.h:1638
Critical section wrapper.
Definition Win.h:1162
critical_section() noexcept
Construct the object and initializes a critical section object.
Definition Win.h:1172
CRITICAL_SECTION m_data
Critical section struct.
Definition Win.h:1198
virtual ~critical_section()
Releases all resources used by an unowned critical section object.
Definition Win.h:1182
Event log handle wrapper.
Definition Win.h:1920
void free_internal() noexcept override
Closes an event log handle.
Definition Win.h:1941
virtual ~event_log()
Closes an event log handle.
Definition Win.h:1929
Find-file handle wrapper.
Definition Win.h:1207
virtual ~find_file()
Closes a file search handle.
Definition Win.h:1216
void free_internal() noexcept override
Closes a file search handle.
Definition Win.h:1228
Base abstract template class to support generic object handle keeping.
Definition Common.h:1020
LPVOID handle_type
Datatype of the object handle this template class handles.
Definition Common.h:1025
handle_type m_h
Object handle.
Definition Common.h:1274
void attach(handle_type h) noexcept
Sets a new object handle for the class.
Definition Common.h:1237
HeapAlloc allocator.
Definition Win.h:1318
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:1327
_Ty value_type
A type that is managed by the allocator.
Definition Win.h:1320
heap_allocator(const heap_allocator< _Other > &other)
Constructs allocator from another type.
Definition Win.h:1355
HANDLE m_heap
Heap handle.
Definition Win.h:1426
pointer allocate(size_type count)
Allocates a new memory block.
Definition Win.h:1366
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:1328
heap_allocator(HANDLE heap)
Constructs allocator.
Definition Win.h:1345
_Ty & reference
A type that provides a reference to the type of object managed by the allocator.
Definition Win.h:1323
void construct(pointer ptr, _Ty &&val)
Calls moving constructor for the element.
Definition Win.h:1402
void deallocate(pointer ptr, size_type size)
Frees memory block.
Definition Win.h:1378
size_type max_size() const
Returns maximum memory block size.
Definition Win.h:1420
void construct(pointer ptr, const _Ty &val)
Calls copying constructor for the element.
Definition Win.h:1391
const _Ty & const_reference
A type that provides a constant reference to type of object managed by the allocator.
Definition Win.h:1325
const _Ty * const_pointer
A type that provides a constant pointer to the type of object managed by the allocator.
Definition Win.h:1324
_Ty * pointer
A type that provides a pointer to the type of object managed by the allocator.
Definition Win.h:1322
void destroy(pointer ptr)
Calls destructor for the element.
Definition Win.h:1412
Heap handle wrapper.
Definition Win.h:1240
bool enumerate() noexcept
Enumerates allocated heap blocks using OutputDebugString()
Definition Win.h:1262
void free_internal() noexcept override
Destroys the heap.
Definition Win.h:1306
virtual ~heap()
Destroys the heap.
Definition Win.h:1249
Base class for thread impersonation of another security context.
Definition Win.h:1470
virtual ~impersonator()
Reverts to current user and destructs the impersonator.
Definition Win.h:1482
impersonator() noexcept
Construct the impersonator.
Definition Win.h:1475
BOOL m_cookie
Did impersonation succeed?
Definition Win.h:1494
Module handle wrapper.
Definition Win.h:1065
void free_internal() noexcept override
Frees the module.
Definition Win.h:1086
virtual ~library()
Frees the module.
Definition Win.h:1074
PROCESS_INFORMATION struct wrapper.
Definition Win.h:1880
~process_information()
Closes process and thread handles.
Definition Win.h:1899
process_information() noexcept
Constructs blank PROCESS_INFORMATION.
Definition Win.h:1888
Registry key wrapper class.
Definition Win.h:1767
void free_internal() noexcept override
Closes a handle to the registry key.
Definition Win.h:1839
bool delete_subkey(LPCTSTR szSubkey)
Deletes the specified registry subkey.
Definition Win.h:1791
virtual ~reg_key()
Closes a handle to the registry key.
Definition Win.h:1776
SC_HANDLE wrapper class.
Definition Win.h:1951
void free_internal() noexcept override
Closes an open object handle.
Definition Win.h:1972
virtual ~sc_handle()
Closes an open object handle.
Definition Win.h:1960
SID wrapper class.
Definition Win.h:1849
void free_internal() noexcept override
Closes a handle to the SID.
Definition Win.h:1870
virtual ~security_id()
Closes a handle to the SID.
Definition Win.h:1858
Lets the calling thread impersonate the security context of the SYSTEM user.
Definition Win.h:1523
system_impersonator() noexcept
Construct the impersonator and impersonates the SYSTEM user.
Definition Win.h:1531
Lets the calling thread impersonate the security context of a logged-on user.
Definition Win.h:1501
user_impersonator(HANDLE hToken) noexcept
Construct the impersonator and impersonates the given user.
Definition Win.h:1513
Memory in virtual address space of a process handle wrapper.
Definition Win.h:1646
vmemory & operator=(vmemory &&other) noexcept
Move assignment.
Definition Win.h:1696
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:1730
void free_internal() noexcept override
Frees the memory.
Definition Win.h:1751
void attach(HANDLE proc, handle_type h) noexcept
Sets a new memory handle for the class.
Definition Win.h:1713
virtual ~vmemory()
Frees the memory.
Definition Win.h:1685
vmemory(handle_type h, HANDLE proc) noexcept
Initializes a new class instance with an already available object handle.
Definition Win.h:1663
vmemory() noexcept
Initializes a new class instance with the memory handle set to INVAL.
Definition Win.h:1653
vmemory(vmemory &&h) noexcept
Move constructor.
Definition Win.h:1674
HANDLE m_proc
Handle of memory's process.
Definition Win.h:1757
Windows HANDLE wrapper class.
Definition Win.h:1032
void free_internal() noexcept override
Closes an open object handle.
Definition Win.h:1053
virtual ~win_handle()
Closes an open object handle.
Definition Win.h:1041
Windows runtime error.
Definition Common.h:1528
#define WINSTD_NONCOPYABLE(C)
Declares a class as non-copyable.
Definition Common.h:67
#define WINSTD_STACK_BUFFER_BYTES
Size of the stack buffer in bytes used for initial system function call.
Definition Common.h:94
#define WINSTD_NONMOVABLE(C)
Declares a class as non-movable.
Definition Common.h:75
static int vsprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format, va_list arg)
Formats string using printf().
Definition Common.h:288
static int sprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format,...)
Formats string using printf().
Definition Common.h:321
#define WINSTD_HANDLE_IMPL(C, T, INVAL)
Implements default constructors and operators to prevent their auto-generation by compiler.
Definition Common.h:164
static const HANDLE invalid
Invalid handle value.
Definition Common.h:1030
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:641
static DWORD ExpandEnvironmentStringsW(LPCWSTR lpSrc, std::basic_string< wchar_t, _Traits, _Ax > &sValue)
Expands environment-variable strings, replaces them with the values defined for the current user,...
Definition Win.h:210
static BOOL StringToGuidA(LPCSTR lpszGuid, LPGUID lpGuid, LPCSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition Win.h:273
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:82
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:2011
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:723
win_handle< INVALID_HANDLE_VALUE > file
File handle wrapper.
Definition Win.h:1126
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:144
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:1988
static LSTATUS RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition Win.h:2030
static LSTATUS RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition Win.h:2049
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:234
static BOOL StringToGuidW(LPCWSTR lpszGuid, LPGUID lpGuid, LPCWSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition Win.h:346
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:611
static BOOL OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, winstd::win_handle< NULL > &TokenHandle)
Opens the access token associated with a process.
Definition Win.h:2068
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:2123
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:841
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:57
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:880
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:2098
win_handle< INVALID_HANDLE_VALUE > process_snapshot
Process snapshot handle wrapper.
Definition Win.h:1111
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:26
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:825
static BOOL CreateWellKnownSid(WELL_KNOWN_SID_TYPE WellKnownSidType, PSID DomainSid, std::unique_ptr< SID > &Sid)
Creates a SID for predefined aliases.
Definition Win.h:918
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:741
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:942
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:2083
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:2109
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:572
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:164
win_handle< NULL > event
Event handle wrapper.
Definition Win.h:1156
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:597
static VOID OutputDebugStr(LPCSTR lpOutputString,...) noexcept
Formats and sends a string to the debugger for display.
Definition Win.h:782
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:966
win_handle< NULL > mutex
Mutex handle wrapper.
Definition Win.h:1118
static DWORD ExpandEnvironmentStringsA(LPCSTR lpSrc, std::basic_string< char, _Traits, _Ax > &sValue)
Expands environment-variable strings, replaces them with the values defined for the current user,...
Definition Win.h:180
win_handle< NULL > file_mapping
File mapping.
Definition Win.h:1133
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:995
win_handle< NULL > process
Process handle wrapper.
Definition Win.h:1097
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:545
BOOL GetThreadPreferredUILanguages(DWORD dwFlags, PULONG pulNumLanguages, std::basic_string< wchar_t, _Traits, _Ax > &sValue)
Retrieves the thread preferred UI languages for the current thread.
Definition Win.h:2138
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:434
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:115
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:805
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:253
static VOID OutputDebugStrV(LPCSTR lpOutputString, va_list arg) noexcept
Formats and sends a string to the debugger for display.
Definition Win.h:758
win_handle< NULL > thread
Thread handle wrapper.
Definition Win.h:1104
Deleter for unique_ptr using LocalFree.
Definition Common.h:731
Deleter for unique_ptr using UnmapViewOfFile.
Definition Win.h:1139
void operator()(void *_Ptr) const
Delete a pointer.
Definition Win.h:1143
A structure that enables an allocator for objects of one type to allocate storage for objects of anot...
Definition Win.h:1335
heap_allocator< _Other > other
Other allocator type.
Definition Win.h:1336