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
1138 template <class _Ty> struct UnmapViewOfFile_delete
1139 {
1141
1146
1151
1155 void operator()(_Ty* _Ptr) const
1156 {
1157 if (!UnmapViewOfFile(_Ptr))
1158 throw win_runtime_error("UnmapViewOfFile failed");
1159 }
1160 };
1161
1165 template <class _Ty> struct UnmapViewOfFile_delete<_Ty[]>
1166 {
1168
1173
1177 void operator()(_Ty* _Ptr) const
1178 {
1179 if (!UnmapViewOfFile(_Ptr))
1180 throw win_runtime_error("UnmapViewOfFile failed");
1181 }
1182
1186 template<class _Other>
1187 void operator()(_Other*) const
1188 {
1189 if (!UnmapViewOfFile(_Ptr))
1190 throw win_runtime_error("UnmapViewOfFile failed");
1191 }
1192 };
1193
1201
1206 {
1209
1210 public:
1217 {
1218 InitializeCriticalSection(&m_data);
1219 }
1220
1227 {
1228 DeleteCriticalSection(&m_data);
1229 }
1230
1236 operator LPCRITICAL_SECTION() noexcept
1237 {
1238 return &m_data;
1239 }
1240
1241 protected:
1242 CRITICAL_SECTION m_data;
1243 };
1244
1250 class find_file : public handle<HANDLE, INVALID_HANDLE_VALUE>
1251 {
1252 WINSTD_HANDLE_IMPL(find_file, HANDLE, INVALID_HANDLE_VALUE)
1253
1254 public:
1260 virtual ~find_file()
1261 {
1262 if (m_h != invalid)
1263 free_internal();
1264 }
1265
1266 protected:
1272 void free_internal() noexcept override
1273 {
1274 FindClose(m_h);
1275 }
1276 };
1277
1283 class heap : public handle<HANDLE, NULL>
1284 {
1285 WINSTD_HANDLE_IMPL(heap, HANDLE, NULL)
1286
1287 public:
1293 virtual ~heap()
1294 {
1295 if (m_h != invalid)
1296 free_internal();
1297 }
1298
1306 bool enumerate() noexcept
1307 {
1308 assert(m_h != invalid);
1309
1310 bool found = false;
1311
1312 // Lock the heap for exclusive access.
1313 HeapLock(m_h);
1314
1315 PROCESS_HEAP_ENTRY e;
1316 e.lpData = NULL;
1317 while (HeapWalk(m_h, &e) != FALSE) {
1318 if ((e.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
1320 _T("Allocated block%s%s\n")
1321 _T(" Data portion begins at: %#p\n Size: %d bytes\n")
1322 _T(" Overhead: %d bytes\n Region index: %d\n"),
1323 (e.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0 ? tstring_printf(_T(", movable with HANDLE %#p"), e.Block.hMem).c_str() : _T(""),
1324 (e.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0 ? _T(", DDESHARE") : _T(""),
1325 e.lpData,
1326 e.cbData,
1327 e.cbOverhead,
1328 e.iRegionIndex);
1329
1330 found = true;
1331 }
1332 }
1333
1334 const DWORD dwResult = GetLastError();
1335 if (dwResult != ERROR_NO_MORE_ITEMS)
1336 OutputDebugStr(_T("HeapWalk failed (error %u).\n"), dwResult);
1337
1338 // Unlock the heap.
1339 HeapUnlock(m_h);
1340
1341 return found;
1342 }
1343
1344 protected:
1350 void free_internal() noexcept override
1351 {
1352 enumerate();
1353 HeapDestroy(m_h);
1354 }
1355 };
1356
1360 template <class _Ty>
1362 {
1363 public:
1364 typedef typename _Ty value_type;
1365
1366 typedef _Ty *pointer;
1367 typedef _Ty& reference;
1368 typedef const _Ty *const_pointer;
1369 typedef const _Ty& const_reference;
1370
1371 typedef SIZE_T size_type;
1372 typedef ptrdiff_t difference_type;
1373
1377 template <class _Other>
1378 struct rebind
1379 {
1381 };
1382
1383 public:
1390 {
1391 }
1392
1398 template <class _Other>
1400 {
1401 }
1402
1411 {
1412 assert(m_heap);
1413 return (pointer)HeapAlloc(m_heap, 0, count * sizeof(_Ty));
1414 }
1415
1422 void deallocate(_In_ pointer ptr, _In_ size_type size)
1423 {
1424 UNREFERENCED_PARAMETER(size);
1425 assert(m_heap);
1426 HeapFree(m_heap, 0, ptr);
1427 }
1428
1435 void construct(_Inout_ pointer ptr, _In_ const _Ty& val)
1436 {
1437 ::new ((void*)ptr) _Ty(val);
1438 }
1439
1446 void construct(_Inout_ pointer ptr, _Inout_ _Ty&& val)
1447 {
1448 ::new ((void*)ptr) _Ty(std::forward<_Ty>(val));
1449 }
1450
1456 void destroy(_Inout_ pointer ptr)
1457 {
1458 ptr->_Ty::~_Ty();
1459 }
1460
1465 {
1466 return (SIZE_T)-1;
1467 }
1468
1469 public:
1470 HANDLE m_heap;
1471 };
1472
1477 {
1480
1481 public:
1489 actctx_activator(_In_ HANDLE hActCtx) noexcept
1490 {
1491 if (!ActivateActCtx(hActCtx, &m_cookie))
1492 m_cookie = 0;
1493 }
1494
1501 {
1502 if (m_cookie)
1503 DeactivateActCtx(0, m_cookie);
1504 }
1505
1506 protected:
1507 ULONG_PTR m_cookie;
1508 };
1509
1514 {
1515 public:
1519 impersonator() noexcept : m_cookie(FALSE) {}
1520
1527 {
1528 if (m_cookie)
1529 RevertToSelf();
1530 }
1531
1535 operator bool () const { return m_cookie; }
1536
1537 protected:
1539 };
1540
1545 {
1548
1549 public:
1557 user_impersonator(_In_opt_ HANDLE hToken) noexcept
1558 {
1559 m_cookie = hToken && ImpersonateLoggedOnUser(hToken);
1560 }
1561 };
1562
1567 {
1570
1571 public:
1576 {
1577 TOKEN_PRIVILEGES privileges = { 1, {{{ 0, 0 }, SE_PRIVILEGE_ENABLED }} };
1578 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid) ||
1579 !ImpersonateSelf(SecurityImpersonation))
1580 return;
1581
1582 {
1583 HANDLE h;
1584 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &h))
1585 goto revert;
1586 win_handle<INVALID_HANDLE_VALUE> thread_token(h);
1587 if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL))
1588 goto revert;
1589 process_snapshot process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1590 if (!process_snapshot)
1591 goto revert;
1592 PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32) };
1593 if (!Process32First(process_snapshot, &entry))
1594 goto revert;
1595 while (_tcsicmp(entry.szExeFile, TEXT("winlogon.exe")) != 0)
1596 if (!Process32Next(process_snapshot, &entry))
1597 goto revert;
1598 process winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
1599 if (!winlogon_process)
1600 goto revert;
1601 if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &h))
1602 goto revert;
1603 win_handle<INVALID_HANDLE_VALUE> winlogon_token(h);
1604 if (!DuplicateToken(winlogon_token, SecurityImpersonation, &h))
1605 goto revert;
1606 win_handle<INVALID_HANDLE_VALUE> duplicated_token(h);
1607 if (!SetThreadToken(NULL, duplicated_token))
1608 goto revert;
1609 }
1610
1611 m_cookie = TRUE;
1612 return;
1613
1614 revert:
1615 DWORD dwResult = GetLastError();
1616 RevertToSelf();
1617 SetLastError(dwResult);
1618 }
1619 };
1620
1625 {
1626 public:
1632 clipboard_opener(_In_opt_ HWND hWndNewOwner = NULL)
1633 {
1634 if (!OpenClipboard(hWndNewOwner))
1635 throw win_runtime_error("OpenClipboard failed");
1636 }
1637
1644 {
1645 CloseClipboard();
1646 }
1647 };
1648
1653 {
1656
1657 public:
1665 console_ctrl_handler(_In_opt_ PHANDLER_ROUTINE HandlerRoutine) noexcept : m_handler(HandlerRoutine)
1666 {
1667 m_cookie = SetConsoleCtrlHandler(m_handler, TRUE);
1668 }
1669
1676 {
1677 if (m_cookie)
1678 SetConsoleCtrlHandler(m_handler, FALSE);
1679 }
1680
1681 protected:
1683 PHANDLER_ROUTINE m_handler;
1684 };
1685
1689 class vmemory : public handle<LPVOID, NULL>
1690 {
1692
1693 public:
1697 vmemory() noexcept : m_proc(NULL)
1698 {
1699 }
1700
1707 vmemory(_In_ handle_type h, _In_ HANDLE proc) noexcept :
1708 m_proc(proc),
1710 {
1711 }
1712
1718 vmemory(_Inout_ vmemory &&h) noexcept :
1719 m_proc(std::move(h.m_proc)),
1720 handle<LPVOID, NULL>(std::move(h))
1721 {
1722 }
1723
1729 virtual ~vmemory()
1730 {
1731 if (m_h != invalid)
1732 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
1733 }
1734
1740 vmemory& operator=(_Inout_ vmemory &&other) noexcept
1741 {
1742 if (this != std::addressof(other)) {
1743 (handle<handle_type, NULL>&&)*this = std::move(other);
1744 m_proc = std::move(other.m_proc);
1745 }
1746 return *this;
1747 }
1748
1757 void attach(_In_ HANDLE proc, _In_opt_ handle_type h) noexcept
1758 {
1759 m_proc = proc;
1760 if (m_h != invalid)
1761 free_internal();
1762 m_h = h;
1763 }
1764
1774 bool alloc(
1775 _In_ HANDLE hProcess,
1776 _In_opt_ LPVOID lpAddress,
1777 _In_ SIZE_T dwSize,
1778 _In_ DWORD flAllocationType,
1779 _In_ DWORD flProtect) noexcept
1780 {
1781 handle_type h = VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect);
1782 if (h != invalid) {
1783 attach(hProcess, h);
1784 return true;
1785 } else
1786 return false;
1787 }
1788
1789 protected:
1795 void free_internal() noexcept override
1796 {
1797 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
1798 }
1799
1800 protected:
1801 HANDLE m_proc;
1802 };
1803
1810 class reg_key : public handle<HKEY, NULL>
1811 {
1812 WINSTD_HANDLE_IMPL(reg_key, HKEY, NULL)
1813
1814 public:
1820 virtual ~reg_key()
1821 {
1822 if (m_h != invalid)
1823 free_internal();
1824 }
1825
1835 bool delete_subkey(_In_z_ LPCTSTR szSubkey)
1836 {
1837 LSTATUS s;
1838
1839 s = RegDeleteKey(m_h, szSubkey);
1840 if (s == ERROR_SUCCESS || s == ERROR_FILE_NOT_FOUND)
1841 return true;
1842
1843 {
1844 reg_key k;
1845 handle_type h;
1846 s = RegOpenKeyEx(m_h, szSubkey, 0, KEY_ENUMERATE_SUB_KEYS, &h);
1847 if (s == ERROR_SUCCESS)
1848 k.attach(h);
1849 else {
1850 SetLastError(s);
1851 return false;
1852 }
1853 for (;;) {
1854 TCHAR szName[MAX_PATH];
1855 DWORD dwSize = _countof(szName);
1856 s = RegEnumKeyEx(k, 0, szName, &dwSize, NULL, NULL, NULL, NULL);
1857 if (s == ERROR_SUCCESS)
1858 k.delete_subkey(szName);
1859 else if (s == ERROR_NO_MORE_ITEMS)
1860 break;
1861 else {
1862 SetLastError(s);
1863 return false;
1864 }
1865 }
1866 }
1867
1868 s = RegDeleteKey(m_h, szSubkey);
1869 if (s == ERROR_SUCCESS)
1870 return true;
1871 else {
1872 SetLastError(s);
1873 return false;
1874 }
1875 }
1876
1877 protected:
1883 void free_internal() noexcept override
1884 {
1885 RegCloseKey(m_h);
1886 }
1887 };
1888
1892 class security_id : public handle<PSID, NULL>
1893 {
1894 WINSTD_HANDLE_IMPL(security_id, PSID, NULL)
1895
1896 public:
1903 {
1904 if (m_h != invalid)
1905 free_internal();
1906 }
1907
1908 protected:
1914 void free_internal() noexcept override
1915 {
1916 FreeSid(m_h);
1917 }
1918 };
1919
1923 class process_information : public PROCESS_INFORMATION
1924 {
1927
1928 public:
1933 {
1934 hProcess = INVALID_HANDLE_VALUE;
1935 hThread = INVALID_HANDLE_VALUE;
1936 dwProcessId = 0;
1937 dwThreadId = 0;
1938 }
1939
1944 {
1945 #pragma warning(push)
1946 #pragma warning(disable: 6001) // Using uninitialized memory '*this'. << ???
1947
1948 if (hProcess != INVALID_HANDLE_VALUE)
1949 CloseHandle(hProcess);
1950
1951 if (hThread != INVALID_HANDLE_VALUE)
1952 CloseHandle(hThread);
1953
1954 #pragma warning(pop)
1955 }
1956 };
1957
1963 class event_log : public handle<HANDLE, NULL>
1964 {
1965 WINSTD_HANDLE_IMPL(event_log, HANDLE, NULL)
1966
1967 public:
1973 virtual ~event_log()
1974 {
1975 if (m_h != invalid)
1976 free_internal();
1977 }
1978
1979 protected:
1985 void free_internal() noexcept override
1986 {
1987 DeregisterEventSource(m_h);
1988 }
1989 };
1990
1994 class sc_handle : public handle<SC_HANDLE, NULL>
1995 {
1996 WINSTD_HANDLE_IMPL(sc_handle, SC_HANDLE, NULL)
1997
1998 public:
2004 virtual ~sc_handle()
2005 {
2006 if (m_h != invalid)
2007 free_internal();
2008 }
2009
2010 protected:
2016 void free_internal() noexcept override
2017 {
2018 CloseServiceHandle(m_h);
2019 }
2020 };
2021
2023}
2024
2027
2028#pragma warning(push)
2029#pragma warning(disable: 4505) // Don't warn on unused code
2030
2032static LSTATUS RegCreateKeyExA(
2033 _In_ HKEY hKey,
2034 _In_ LPCSTR lpSubKey,
2035 _Reserved_ DWORD Reserved,
2036 _In_opt_ LPSTR lpClass,
2037 _In_ DWORD dwOptions,
2038 _In_ REGSAM samDesired,
2039 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2040 _Inout_ winstd::reg_key &result,
2041 _Out_opt_ LPDWORD lpdwDisposition)
2042{
2043 HKEY h;
2044 LSTATUS s = RegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2045 if (s == ERROR_SUCCESS)
2046 result.attach(h);
2047 return s;
2048}
2049
2055static LSTATUS RegCreateKeyExW(
2056 _In_ HKEY hKey,
2057 _In_ LPCWSTR lpSubKey,
2058 _Reserved_ DWORD Reserved,
2059 _In_opt_ LPWSTR lpClass,
2060 _In_ DWORD dwOptions,
2061 _In_ REGSAM samDesired,
2062 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2063 _Inout_ winstd::reg_key &result,
2064 _Out_opt_ LPDWORD lpdwDisposition)
2065{
2066 HKEY h;
2067 LSTATUS s = RegCreateKeyExW(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2068 if (s == ERROR_SUCCESS)
2069 result.attach(h);
2070 return s;
2071}
2072
2074static LSTATUS RegOpenKeyExA(
2075 _In_ HKEY hKey,
2076 _In_opt_ LPCSTR lpSubKey,
2077 _In_opt_ DWORD ulOptions,
2078 _In_ REGSAM samDesired,
2079 _Inout_ winstd::reg_key &result)
2080{
2081 HKEY h;
2082 LSTATUS s = RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, &h);
2083 if (s == ERROR_SUCCESS)
2084 result.attach(h);
2085 return s;
2086}
2087
2093static LSTATUS RegOpenKeyExW(
2094 _In_ HKEY hKey,
2095 _In_opt_ LPCWSTR lpSubKey,
2096 _In_opt_ DWORD ulOptions,
2097 _In_ REGSAM samDesired,
2098 _Inout_ winstd::reg_key &result)
2099{
2100 HKEY h;
2101 LSTATUS s = RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, &h);
2102 if (s == ERROR_SUCCESS)
2103 result.attach(h);
2104 return s;
2105}
2106
2112static BOOL OpenProcessToken(_In_ HANDLE ProcessHandle, _In_ DWORD DesiredAccess, _Inout_ winstd::win_handle<NULL> &TokenHandle)
2113{
2114 HANDLE h;
2115 if (OpenProcessToken(ProcessHandle, DesiredAccess, &h)) {
2116 TokenHandle.attach(h);
2117 return TRUE;
2118 }
2119 return FALSE;
2120}
2121
2127static 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)
2128{
2129 HANDLE h;
2130 if (DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, &h)) {
2131 NewToken.attach(h);
2132 return TRUE;
2133 }
2134 return FALSE;
2135}
2136
2142static 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)
2143{
2144 PSID h;
2145 if (AllocateAndInitializeSid(pIdentifierAuthority, nSubAuthorityCount, nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3, nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, &h)) {
2146 Sid.attach(h);
2147 return TRUE;
2148 }
2149 return FALSE;
2150}
2151
2153static 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)
2154{
2155 PACL h;
2156 DWORD dwResult = SetEntriesInAclA(cCountOfExplicitEntries, pListOfExplicitEntries, OldAcl, &h);
2157 if (dwResult == ERROR_SUCCESS)
2158 Acl.reset(h);
2159 return ERROR_SUCCESS;
2160}
2161
2167static 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)
2168{
2169 PACL h;
2170 DWORD dwResult = SetEntriesInAclW(cCountOfExplicitEntries, pListOfExplicitEntries, OldAcl, &h);
2171 if (dwResult == ERROR_SUCCESS)
2172 Acl.reset(h);
2173 return ERROR_SUCCESS;
2174}
2175
2181template<class _Traits, class _Ax>
2182_Success_(return != 0) BOOL GetThreadPreferredUILanguages(_In_ DWORD dwFlags, _Out_ PULONG pulNumLanguages, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
2183{
2184 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
2185 ULONG ulSize = _countof(szStackBuffer);
2186
2187 // Try with stack buffer first.
2188 if (GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, szStackBuffer, &ulSize)) {
2189 // Copy from stack.
2190 sValue.assign(szStackBuffer, ulSize - 1);
2191 return TRUE;
2192 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
2193 // Query required size.
2194 ulSize = 0;
2195 GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, NULL, &ulSize);
2196 // Allocate on heap and retry.
2197 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[ulSize]);
2198 if (GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, szBuffer.get(), &ulSize)) {
2199 sValue.assign(szBuffer.get(), ulSize - 1);
2200 return TRUE;
2201 }
2202 }
2203 return FALSE;
2204}
2205
2206#pragma warning(pop)
2207
Activates given activation context in constructor and deactivates it in destructor.
Definition Win.h:1477
actctx_activator(HANDLE hActCtx) noexcept
Construct the activator and activates the given activation context.
Definition Win.h:1489
virtual ~actctx_activator()
Deactivates activation context and destructs the activator.
Definition Win.h:1500
ULONG_PTR m_cookie
Cookie for context deactivation.
Definition Win.h:1507
Base template class to support string formatting using printf() style templates.
Definition Common.h:1611
Clipboard management.
Definition Win.h:1625
virtual ~clipboard_opener()
Closes the clipboard.
Definition Win.h:1643
clipboard_opener(HWND hWndNewOwner=NULL)
Opens the clipboard for examination and prevents other applications from modifying the clipboard cont...
Definition Win.h:1632
Console control handler stack management.
Definition Win.h:1653
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:1665
virtual ~console_ctrl_handler()
Pops console control handler from the console control handler stack.
Definition Win.h:1675
PHANDLER_ROUTINE m_handler
Pointer to console control handler.
Definition Win.h:1683
BOOL m_cookie
Did pushing the console control handler succeed?
Definition Win.h:1682
Critical section wrapper.
Definition Win.h:1206
critical_section() noexcept
Construct the object and initializes a critical section object.
Definition Win.h:1216
CRITICAL_SECTION m_data
Critical section struct.
Definition Win.h:1242
virtual ~critical_section()
Releases all resources used by an unowned critical section object.
Definition Win.h:1226
Event log handle wrapper.
Definition Win.h:1964
void free_internal() noexcept override
Closes an event log handle.
Definition Win.h:1985
virtual ~event_log()
Closes an event log handle.
Definition Win.h:1973
Find-file handle wrapper.
Definition Win.h:1251
virtual ~find_file()
Closes a file search handle.
Definition Win.h:1260
void free_internal() noexcept override
Closes a file search handle.
Definition Win.h:1272
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:1362
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:1371
_Ty value_type
A type that is managed by the allocator.
Definition Win.h:1364
heap_allocator(const heap_allocator< _Other > &other)
Constructs allocator from another type.
Definition Win.h:1399
HANDLE m_heap
Heap handle.
Definition Win.h:1470
pointer allocate(size_type count)
Allocates a new memory block.
Definition Win.h:1410
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:1372
heap_allocator(HANDLE heap)
Constructs allocator.
Definition Win.h:1389
_Ty & reference
A type that provides a reference to the type of object managed by the allocator.
Definition Win.h:1367
void construct(pointer ptr, _Ty &&val)
Calls moving constructor for the element.
Definition Win.h:1446
void deallocate(pointer ptr, size_type size)
Frees memory block.
Definition Win.h:1422
size_type max_size() const
Returns maximum memory block size.
Definition Win.h:1464
void construct(pointer ptr, const _Ty &val)
Calls copying constructor for the element.
Definition Win.h:1435
const _Ty & const_reference
A type that provides a constant reference to type of object managed by the allocator.
Definition Win.h:1369
const _Ty * const_pointer
A type that provides a constant pointer to the type of object managed by the allocator.
Definition Win.h:1368
_Ty * pointer
A type that provides a pointer to the type of object managed by the allocator.
Definition Win.h:1366
void destroy(pointer ptr)
Calls destructor for the element.
Definition Win.h:1456
Heap handle wrapper.
Definition Win.h:1284
bool enumerate() noexcept
Enumerates allocated heap blocks using OutputDebugString()
Definition Win.h:1306
void free_internal() noexcept override
Destroys the heap.
Definition Win.h:1350
virtual ~heap()
Destroys the heap.
Definition Win.h:1293
Base class for thread impersonation of another security context.
Definition Win.h:1514
virtual ~impersonator()
Reverts to current user and destructs the impersonator.
Definition Win.h:1526
impersonator() noexcept
Construct the impersonator.
Definition Win.h:1519
BOOL m_cookie
Did impersonation succeed?
Definition Win.h:1538
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:1924
~process_information()
Closes process and thread handles.
Definition Win.h:1943
process_information() noexcept
Constructs blank PROCESS_INFORMATION.
Definition Win.h:1932
Registry key wrapper class.
Definition Win.h:1811
void free_internal() noexcept override
Closes a handle to the registry key.
Definition Win.h:1883
bool delete_subkey(LPCTSTR szSubkey)
Deletes the specified registry subkey.
Definition Win.h:1835
virtual ~reg_key()
Closes a handle to the registry key.
Definition Win.h:1820
SC_HANDLE wrapper class.
Definition Win.h:1995
void free_internal() noexcept override
Closes an open object handle.
Definition Win.h:2016
virtual ~sc_handle()
Closes an open object handle.
Definition Win.h:2004
SID wrapper class.
Definition Win.h:1893
void free_internal() noexcept override
Closes a handle to the SID.
Definition Win.h:1914
virtual ~security_id()
Closes a handle to the SID.
Definition Win.h:1902
Lets the calling thread impersonate the security context of the SYSTEM user.
Definition Win.h:1567
system_impersonator() noexcept
Construct the impersonator and impersonates the SYSTEM user.
Definition Win.h:1575
Lets the calling thread impersonate the security context of a logged-on user.
Definition Win.h:1545
user_impersonator(HANDLE hToken) noexcept
Construct the impersonator and impersonates the given user.
Definition Win.h:1557
Memory in virtual address space of a process handle wrapper.
Definition Win.h:1690
vmemory & operator=(vmemory &&other) noexcept
Move assignment.
Definition Win.h:1740
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:1774
void free_internal() noexcept override
Frees the memory.
Definition Win.h:1795
void attach(HANDLE proc, handle_type h) noexcept
Sets a new memory handle for the class.
Definition Win.h:1757
virtual ~vmemory()
Frees the memory.
Definition Win.h:1729
vmemory(handle_type h, HANDLE proc) noexcept
Initializes a new class instance with an already available object handle.
Definition Win.h:1707
vmemory() noexcept
Initializes a new class instance with the memory handle set to INVAL.
Definition Win.h:1697
vmemory(vmemory &&h) noexcept
Move constructor.
Definition Win.h:1718
HANDLE m_proc
Handle of memory's process.
Definition Win.h:1801
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:2055
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:2032
static LSTATUS RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition Win.h:2074
static LSTATUS RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition Win.h:2093
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:2112
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:2167
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:2142
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:2127
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:2153
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:1200
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:2182
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
UnmapViewOfFile_delete()
Default construct.
Definition Win.h:1172
void operator()(_Other *) const
Delete a pointer of another type.
Definition Win.h:1187
void operator()(_Ty *_Ptr) const
Delete a pointer.
Definition Win.h:1177
UnmapViewOfFile_delete< _Ty > _Myt
This type.
Definition Win.h:1167
Deleter for unique_ptr using UnmapViewOfFile.
Definition Win.h:1139
UnmapViewOfFile_delete(const UnmapViewOfFile_delete< _Ty2 > &)
Construct from another UnmapViewOfFile_delete.
Definition Win.h:1150
void operator()(_Ty *_Ptr) const
Delete a pointer.
Definition Win.h:1155
UnmapViewOfFile_delete< _Ty > _Myt
This type.
Definition Win.h:1140
UnmapViewOfFile_delete()
Default construct.
Definition Win.h:1145
A structure that enables an allocator for objects of one type to allocate storage for objects of anot...
Definition Win.h:1379
heap_allocator< _Other > other
Other allocator type.
Definition Win.h:1380