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) noexcept
181{
182 assert(0); // TODO: Test this code.
183
184 for (DWORD dwSizeOut = (DWORD)strlen(lpSrc) + 0x100;;) {
185 DWORD dwSizeIn = dwSizeOut;
186 std::unique_ptr<char[]> szBuffer(new char[(size_t)dwSizeIn + 2]); // Note: ANSI version requires one extra char.
187 dwSizeOut = ::ExpandEnvironmentStringsA(lpSrc, szBuffer.get(), dwSizeIn);
188 if (dwSizeOut == 0) {
189 // Error or zero-length input.
190 break;
191 } else if (dwSizeOut <= dwSizeIn) {
192 // The buffer was sufficient.
193 sValue.assign(szBuffer.get(), dwSizeOut - 1);
194 return dwSizeOut;
195 }
196 }
197
198 sValue.clear();
199 return 0;
200}
201
207template<class _Traits, class _Ax>
208static _Success_(return != 0) DWORD ExpandEnvironmentStringsW(_In_z_ LPCWSTR lpSrc, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
209{
210 for (DWORD dwSizeOut = (DWORD)wcslen(lpSrc) + 0x100;;) {
211 DWORD dwSizeIn = dwSizeOut;
212 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[(size_t)dwSizeIn + 1]);
213 dwSizeOut = ::ExpandEnvironmentStringsW(lpSrc, szBuffer.get(), dwSizeIn);
214 if (dwSizeOut == 0) {
215 // Error or zero-length input.
216 break;
217 } else if (dwSizeOut <= dwSizeIn) {
218 // The buffer was sufficient.
219 sValue.assign(szBuffer.get(), dwSizeOut - 1);
220 return dwSizeOut;
221 }
222 }
223
224 sValue.clear();
225 return 0;
226}
227
229template<class _Traits, class _Ax>
230static VOID GuidToStringA(_In_ LPCGUID lpGuid, _Out_ std::basic_string<char, _Traits, _Ax> &str) noexcept
231{
232 assert(0); // TODO: Test this code.
233
234 sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
235 lpGuid->Data1,
236 lpGuid->Data2,
237 lpGuid->Data3,
238 lpGuid->Data4[0], lpGuid->Data4[1],
239 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
240}
241
248template<class _Traits, class _Ax>
249static VOID GuidToStringW(_In_ LPCGUID lpGuid, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &str) noexcept
250{
251 assert(0); // TODO: Test this code.
252
253 sprintf(str, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
254 lpGuid->Data1,
255 lpGuid->Data2,
256 lpGuid->Data3,
257 lpGuid->Data4[0], lpGuid->Data4[1],
258 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
259}
260
262#ifdef _UNICODE
263#define GuidToString GuidToStringW
264#else
265#define GuidToString GuidToStringA
266#endif
267
269static _Success_(return) BOOL StringToGuidA(_In_z_ LPCSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCSTR *lpszGuidEnd = NULL) noexcept
270{
271 GUID g;
272 LPSTR lpszEnd;
273 unsigned long ulTmp;
274 unsigned long long ullTmp;
275
276 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
277 lpszGuid++;
278
279 g.Data1 = strtoul(lpszGuid, &lpszEnd, 16);
280 if (errno == ERANGE) return FALSE;
281 lpszGuid = lpszEnd;
282
283 if (*lpszGuid != '-') return FALSE;
284 lpszGuid++;
285
286 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
287 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
288 g.Data2 = static_cast<unsigned short>(ulTmp);
289 lpszGuid = lpszEnd;
290
291 if (*lpszGuid != '-') return FALSE;
292 lpszGuid++;
293
294 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
295 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
296 g.Data3 = static_cast<unsigned short>(ulTmp);
297 lpszGuid = lpszEnd;
298
299 if (*lpszGuid != '-') return FALSE;
300 lpszGuid++;
301
302 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
303 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
304 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
305 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
306 lpszGuid = lpszEnd;
307
308 if (*lpszGuid != '-') return FALSE;
309 lpszGuid++;
310
311 ullTmp = _strtoui64(lpszGuid, &lpszEnd, 16);
312 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
313 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
314 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
315 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
316 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
317 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
318 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
319 lpszGuid = lpszEnd;
320
321 if (*lpszGuid != '}') return FALSE;
322 lpszGuid++;
323
324 if (lpszGuidEnd)
325 *lpszGuidEnd = lpszGuid;
326
327 *lpGuid = g;
328 return TRUE;
329}
330
342static _Success_(return) BOOL StringToGuidW(_In_z_ LPCWSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCWSTR *lpszGuidEnd = NULL) noexcept
343{
344 GUID g;
345 LPWSTR lpszEnd;
346 unsigned long ulTmp;
347 unsigned long long ullTmp;
348
349 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
350 lpszGuid++;
351
352 g.Data1 = wcstoul(lpszGuid, &lpszEnd, 16);
353 if (errno == ERANGE) return FALSE;
354 lpszGuid = lpszEnd;
355
356 if (*lpszGuid != '-') return FALSE;
357 lpszGuid++;
358
359 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
360 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
361 g.Data2 = static_cast<unsigned short>(ulTmp);
362 lpszGuid = lpszEnd;
363
364 if (*lpszGuid != '-') return FALSE;
365 lpszGuid++;
366
367 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
368 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
369 g.Data3 = static_cast<unsigned short>(ulTmp);
370 lpszGuid = lpszEnd;
371
372 if (*lpszGuid != '-') return FALSE;
373 lpszGuid++;
374
375 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
376 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
377 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
378 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
379 lpszGuid = lpszEnd;
380
381 if (*lpszGuid != '-') return FALSE;
382 lpszGuid++;
383
384 ullTmp = _wcstoui64(lpszGuid, &lpszEnd, 16);
385 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
386 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
387 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
388 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
389 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
390 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
391 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
392 lpszGuid = lpszEnd;
393
394 if (*lpszGuid != '}') return FALSE;
395 lpszGuid++;
396
397 if (lpszGuidEnd)
398 *lpszGuidEnd = lpszGuid;
399
400 *lpGuid = g;
401 return TRUE;
402}
403
405#ifdef _UNICODE
406#define StringToGuid StringToGuidW
407#else
408#define StringToGuid StringToGuidA
409#endif
410
429template<class _Traits, class _Ax>
430static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCSTR pszName, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
431{
432 LSTATUS lResult;
433 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
434 DWORD dwSize = sizeof(aStackBuffer), dwType;
435
436 // Try with stack buffer first.
437 lResult = ::RegQueryValueExA(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
438 if (lResult == ERROR_SUCCESS) {
439 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
440 // The value is REG_SZ or REG_MULTI_SZ.
441 dwSize /= sizeof(CHAR);
442 sValue.assign(reinterpret_cast<LPCSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
443 } else if (dwType == REG_EXPAND_SZ) {
444 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
445 if (::ExpandEnvironmentStringsA(reinterpret_cast<LPCSTR>(aStackBuffer), sValue) == 0)
446 lResult = ::GetLastError();
447 } else {
448 // The value is not a string type.
449 lResult = ERROR_INVALID_DATA;
450 }
451 } else if (lResult == ERROR_MORE_DATA) {
452 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
453 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
454 std::unique_ptr<CHAR[]> szBuffer(new CHAR[dwSize / sizeof(CHAR)]);
455 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
456 dwSize /= sizeof(CHAR);
457 sValue.assign(szBuffer.get(), dwSize && szBuffer[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
458 }
459 } else if (dwType == REG_EXPAND_SZ) {
460 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
461 std::unique_ptr<CHAR[]> szBuffer(new CHAR[dwSize / sizeof(CHAR)]);
462 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
463 if (::ExpandEnvironmentStringsA(szBuffer.get(), sValue) == 0)
464 lResult = ::GetLastError();
465 }
466 } else {
467 // The value is not a string type.
468 lResult = ERROR_INVALID_DATA;
469 }
470 }
471
472 return lResult;
473}
474
493template<class _Traits, class _Ax>
494static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCWSTR pszName, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
495{
496 LSTATUS lResult;
497 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
498 DWORD dwSize = sizeof(aStackBuffer), dwType;
499
500 // Try with stack buffer first.
501 lResult = ::RegQueryValueExW(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
502 if (lResult == ERROR_SUCCESS) {
503 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
504 // The value is REG_SZ or REG_MULTI_SZ.
505 dwSize /= sizeof(WCHAR);
506 sValue.assign(reinterpret_cast<LPCWSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCWSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
507 } else if (dwType == REG_EXPAND_SZ) {
508 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
509 if (::ExpandEnvironmentStringsW(reinterpret_cast<LPCWSTR>(aStackBuffer), sValue) == 0)
510 lResult = ::GetLastError();
511 } else {
512 // The value is not a string type.
513 lResult = ERROR_INVALID_DATA;
514 }
515 } else if (lResult == ERROR_MORE_DATA) {
516 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
517 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
518 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[dwSize / sizeof(WCHAR)]);
519 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
520 dwSize /= sizeof(WCHAR);
521 sValue.assign(szBuffer.get(), dwSize && szBuffer[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
522 }
523 } else if (dwType == REG_EXPAND_SZ) {
524 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
525 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[dwSize / sizeof(WCHAR)]);
526 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
527 if (::ExpandEnvironmentStringsW(szBuffer.get(), sValue) == 0)
528 lResult = ::GetLastError();
529 }
530 } else {
531 // The value is not a string type.
532 lResult = ERROR_INVALID_DATA;
533 }
534 }
535
536 return lResult;
537}
538
540template<class _Ty, class _Ax>
541static LSTATUS RegQueryValueExA(_In_ HKEY hKey, _In_opt_z_ LPCSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
542{
543 LSTATUS lResult;
544 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
545 DWORD dwSize = sizeof(aStackBuffer);
546
547 // Try with stack buffer first.
548 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
549 if (lResult == ERROR_SUCCESS) {
550 // Copy from stack buffer.
551 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
552 memcpy(aData.data(), aStackBuffer, dwSize);
553 } else if (lResult == ERROR_MORE_DATA) {
554 // Allocate buffer on heap and retry.
555 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
556 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, NULL, reinterpret_cast<LPBYTE>(aData.data()), &dwSize);
557 }
558
559 return lResult;
560}
561
567template<class _Ty, class _Ax>
568static LSTATUS RegQueryValueExW(_In_ HKEY hKey, _In_opt_z_ LPCWSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
569{
570 LSTATUS lResult;
571 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
572 DWORD dwSize = sizeof(aStackBuffer);
573
574 // Try with stack buffer first.
575 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
576 if (lResult == ERROR_SUCCESS) {
577 // Copy from stack buffer.
578 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
579 memcpy(aData.data(), aStackBuffer, dwSize);
580 } else if (lResult == ERROR_MORE_DATA) {
581 // Allocate buffer on heap and retry.
582 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
583 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, NULL, reinterpret_cast<LPBYTE>(aData.data()), &dwSize);
584 }
585
586 return lResult;
587}
588
589#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
590
592template<class _Traits, class _Ax>
593static 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
594{
595 // According to "Remarks" section in MSDN documentation of RegLoadMUIString(),
596 // this function is defined but not implemented as ANSI variation.
597 assert(0);
598 return ERROR_CALL_NOT_IMPLEMENTED;
599}
600
606template<class _Traits, class _Ax>
607static 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
608{
609 LSTATUS lResult;
610 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
611 DWORD dwSize;
612
613 Flags &= ~REG_MUI_STRING_TRUNCATE;
614
615 // Try with stack buffer first.
616 lResult = RegLoadMUIStringW(hKey, pszValue, szStackBuffer, sizeof(szStackBuffer), &dwSize, Flags, pszDirectory);
617 if (lResult == ERROR_SUCCESS) {
618 // Copy from stack buffer.
619 sOut.assign(szStackBuffer, wcsnlen(szStackBuffer, dwSize/sizeof(wchar_t)));
620 } else if (lResult == ERROR_MORE_DATA) {
621 // Allocate buffer on heap and retry.
622 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[(dwSize + sizeof(wchar_t) - 1)/sizeof(wchar_t)]);
623 sOut.assign(szBuffer.get(), (lResult = RegLoadMUIStringW(hKey, pszValue, szBuffer.get(), dwSize, &dwSize, Flags, pszDirectory)) == ERROR_SUCCESS ? wcsnlen(szBuffer.get(), dwSize/sizeof(wchar_t)) : 0);
624 }
625
626 return lResult;
627}
628
629#endif
630
636template<class _Traits, class _Ax>
637static _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
638{
639 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
640
641 // Try to convert to stack buffer first.
642 int cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szStackBuffer, _countof(szStackBuffer));
643 if (cch > 0) {
644 // Copy from stack.
645 sDstString.assign(szStackBuffer, cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
646 } else {
647 switch (::GetLastError()) {
648 case ERROR_INSUFFICIENT_BUFFER:
649 for (int i = 10; i--;) {
650 // Allocate buffer. Then convert again.
651 cch = -cch;
652 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
653 cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szBuffer.get(), cch);
654 if (cch > 0) {
655 sDstString.assign(szBuffer.get(), cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
656 break;
657 }
658 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
659 sDstString.clear();
660 break;
661 }
662 }
663 break;
664
665 case ERROR_SUCCESS:
666 sDstString.clear();
667 break;
668 }
669 }
670
671 return cch;
672}
673
679template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
680static _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
681{
682 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
683
684 // Try to convert to stack buffer first.
685 int cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szStackBuffer, _countof(szStackBuffer));
686 if (cch > 0) {
687 // Copy from stack.
688 sDstString.assign(szStackBuffer, cch);
689 } else {
690 switch (::GetLastError()) {
691 case ERROR_INSUFFICIENT_BUFFER:
692 for (int i = 10; i--;) {
693 // Allocate buffer. Then convert again.
694 cch = -cch;
695 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[cch]);
696 cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szBuffer.get(), cch);
697 if (cch > 0) {
698 sDstString.assign(szBuffer.get(), cch);
699 break;
700 }
701 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
702 sDstString.clear();
703 break;
704 }
705 }
706 break;
707
708 case ERROR_SUCCESS:
709 sDstString.clear();
710 break;
711 }
712 }
713
714 return cch;
715}
716
718template<class _Traits, class _Ax>
719static _Success_(return != 0) int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<char, _Traits, _Ax> &sBuffer) noexcept
720{
721 // Get read-only pointer to string resource.
722 LPCSTR pszStr;
723 int i = LoadStringA(hInstance, uID, reinterpret_cast<LPSTR>(&pszStr), 0);
724 if (i) {
725 sBuffer.assign(pszStr, i);
726 return i;
727 } else
728 return 0;
729}
730
736template<class _Traits, class _Ax>
737static _Success_(return != 0) int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sBuffer) noexcept
738{
739 // Get read-only pointer to string resource.
740 LPCWSTR pszStr;
741 int i = LoadStringW(hInstance, uID, reinterpret_cast<LPWSTR>(&pszStr), 0);
742 if (i) {
743 sBuffer.assign(pszStr, i);
744 return i;
745 } else
746 return 0;
747}
748
754static VOID OutputDebugStrV(_In_z_ LPCSTR lpOutputString, _In_ va_list arg) noexcept
755{
756 std::string str;
757 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
758 OutputDebugStringA(str.c_str());
759}
760
766static VOID OutputDebugStrV(_In_z_ LPCWSTR lpOutputString, _In_ va_list arg) noexcept
767{
768 std::wstring str;
769 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
770 OutputDebugStringW(str.c_str());
771}
772
778static VOID OutputDebugStr(_In_z_ LPCSTR lpOutputString, ...) noexcept
779{
780 va_list arg;
781 va_start(arg, lpOutputString);
782 OutputDebugStrV(lpOutputString, arg);
783 va_end(arg);
784}
785
791static VOID OutputDebugStr(_In_z_ LPCWSTR lpOutputString, ...) noexcept
792{
793 va_list arg;
794 va_start(arg, lpOutputString);
795 OutputDebugStrV(lpOutputString, arg);
796 va_end(arg);
797}
798
800template<class _Traits, class _Ax>
801static _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
802{
803 int iResult = GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
804 if (iResult) {
805 // Allocate buffer on heap and retry.
806 std::unique_ptr<char[]> szBuffer(new char[iResult]);
807 iResult = GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, szBuffer.get(), iResult);
808 sDate.assign(szBuffer.get(), iResult ? iResult - 1 : 0);
809 return iResult;
810 }
811
812 return iResult;
813}
814
820template<class _Traits, class _Ax>
821static _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
822{
823 int iResult = GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
824 if (iResult) {
825 // Allocate buffer on heap and retry.
826 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[iResult]);
827 iResult = GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, szBuffer.get(), iResult);
828 sDate.assign(szBuffer.get(), iResult ? iResult - 1 : 0);
829 return iResult;
830 }
831
832 return iResult;
833}
834
836template<class _Traits, class _Ax>
837static _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
838{
839 assert(0); // TODO: Test this code.
840
841 DWORD dwNameLen = 0, dwRefDomainLen = 0;
842
843 if (LookupAccountSidA(lpSystemName, lpSid,
844 NULL, &dwNameLen ,
845 NULL, &dwRefDomainLen,
846 peUse))
847 {
848 // Name and domain is blank.
849 if (sName ) sName ->clear();
850 if (sReferencedDomainName) sReferencedDomainName->clear();
851 return TRUE;
852 } else if (GetLastError() == ERROR_MORE_DATA) {
853 // Allocate on heap and retry.
854 std::unique_ptr<char[]> bufName (new char[dwNameLen ]);
855 std::unique_ptr<char[]> bufRefDomain(new char[dwRefDomainLen]);
856 if (LookupAccountSidA(lpSystemName, lpSid,
857 bufName .get(), &dwNameLen ,
858 bufRefDomain.get(), &dwRefDomainLen,
859 peUse))
860 {
861 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
862 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
863 return TRUE;
864 }
865 }
866
867 return FALSE;
868}
869
875template<class _Traits, class _Ax>
876static _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
877{
878 assert(0); // TODO: Test this code.
879
880 DWORD dwNameLen = 0, dwRefDomainLen = 0;
881
882 if (LookupAccountSidW(lpSystemName, lpSid,
883 NULL, &dwNameLen ,
884 NULL, &dwRefDomainLen,
885 peUse))
886 {
887 // Name and domain is blank.
888 if (sName ) sName ->clear();
889 if (sReferencedDomainName) sReferencedDomainName->clear();
890 return TRUE;
891 } else if (GetLastError() == ERROR_MORE_DATA) {
892 // Allocate on heap and retry.
893 std::unique_ptr<wchar_t[]> bufName (new wchar_t[dwNameLen ]);
894 std::unique_ptr<wchar_t[]> bufRefDomain(new wchar_t[dwRefDomainLen]);
895 if (LookupAccountSidW(lpSystemName, lpSid,
896 bufName .get(), &dwNameLen ,
897 bufRefDomain.get(), &dwRefDomainLen,
898 peUse))
899 {
900 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
901 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
902 return TRUE;
903 }
904 }
905
906 return FALSE;
907}
908
914static _Success_(return != FALSE) BOOL CreateWellKnownSid(_In_ WELL_KNOWN_SID_TYPE WellKnownSidType, _In_opt_ PSID DomainSid, _Inout_ std::unique_ptr<SID> &Sid)
915{
916 BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES];
917 DWORD dwSize = sizeof(szStackBuffer);
918
919 if (CreateWellKnownSid(WellKnownSidType, DomainSid, szStackBuffer, &dwSize)) {
920 // The stack buffer was big enough to retrieve complete data. Alloc and copy.
921 Sid.reset((SID*)new BYTE[dwSize]);
922 memcpy(Sid.get(), szStackBuffer, dwSize);
923 return TRUE;
924 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
925 // The stack buffer was too small to retrieve complete data. Alloc and retry.
926 Sid.reset((SID*)new BYTE[dwSize]);
927 return CreateWellKnownSid(WellKnownSidType, DomainSid, Sid.get(), &dwSize);
928 } else
929 return FALSE;
930}
931
937template<class _Ty>
938static _Success_(return != 0) BOOL GetTokenInformation(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_ std::unique_ptr<_Ty> &TokenInformation) noexcept
939{
940 BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES];
941 DWORD dwSize;
942
943 if (GetTokenInformation(TokenHandle, TokenInformationClass, szStackBuffer, sizeof(szStackBuffer), &dwSize)) {
944 // The stack buffer was big enough to retrieve complete data. Alloc and copy.
945 TokenInformation.reset((_Ty*)(new BYTE[dwSize]));
946 memcpy(TokenInformation.get(), szStackBuffer, dwSize);
947 return TRUE;
948 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
949 // The stack buffer was too small to retrieve complete data. Alloc and retry.
950 TokenInformation.reset((_Ty*)(new BYTE[dwSize]));
951 return GetTokenInformation(TokenHandle, TokenInformationClass, TokenInformation.get(), dwSize, &dwSize);
952 } else
953 return FALSE;
954}
955
961template<class _Traits, class _Ax>
962static _Success_(return != 0) BOOL QueryFullProcessImageNameA(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<char, _Traits, _Ax>& sExeName)
963{
964 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(char)];
965 DWORD dwSize = _countof(szStackBuffer);
966
967 // Try with stack buffer first.
968 if (::QueryFullProcessImageNameA(hProcess, dwFlags, szStackBuffer, &dwSize)) {
969 // Copy from stack.
970 sExeName.assign(szStackBuffer, dwSize);
971 return TRUE;
972 }
973 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(char); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
974 // Allocate on heap and retry.
975 std::unique_ptr<char[]> szBuffer(new char[dwCapacity]);
976 dwSize = dwCapacity;
977 if (::QueryFullProcessImageNameA(hProcess, dwFlags, szBuffer.get(), &dwSize)) {
978 sExeName.assign(szBuffer.get(), dwSize);
979 return TRUE;
980 }
981 }
982 return FALSE;
983}
984
990template<class _Traits, class _Ax>
991static _Success_(return != 0) BOOL QueryFullProcessImageNameW(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<wchar_t, _Traits, _Ax>& sExeName)
992{
993 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t)];
994 DWORD dwSize = _countof(szStackBuffer);
995
996 // Try with stack buffer first.
997 if (::QueryFullProcessImageNameW(hProcess, dwFlags, szStackBuffer, &dwSize)) {
998 // Copy from stack.
999 sExeName.assign(szStackBuffer, dwSize);
1000 return TRUE;
1001 }
1002 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
1003 // Allocate on heap and retry.
1004 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwCapacity]);
1005 dwSize = dwCapacity;
1006 if (::QueryFullProcessImageNameW(hProcess, dwFlags, szBuffer.get(), &dwSize)) {
1007 sExeName.assign(szBuffer.get(), dwSize);
1008 return TRUE;
1009 }
1010 }
1011 return FALSE;
1012}
1013
1015
1016#pragma warning(pop)
1017
1018namespace winstd
1019{
1022
1026 template<HANDLE INVALID>
1027 class win_handle : public handle<HANDLE, INVALID>
1028 {
1030
1031 public:
1037 virtual ~win_handle()
1038 {
1039 if (m_h != invalid)
1040 free_internal();
1041 }
1042
1043 protected:
1049 void free_internal() noexcept override
1050 {
1051 CloseHandle(m_h);
1052 }
1053 };
1054
1060 class library : public handle<HMODULE, NULL>
1061 {
1063
1064 public:
1070 virtual ~library()
1071 {
1072 if (m_h != invalid)
1073 free_internal();
1074 }
1075
1076 protected:
1082 void free_internal() noexcept override
1083 {
1084 FreeLibrary(m_h);
1085 }
1086 };
1087
1094
1101
1108
1115
1123
1130
1134 template <class _Ty> struct UnmapViewOfFile_delete
1135 {
1137
1142
1147
1151 void operator()(_Ty* _Ptr) const
1152 {
1153 if (!UnmapViewOfFile(_Ptr))
1154 throw win_runtime_error("UnmapViewOfFile failed");
1155 }
1156 };
1157
1161 template <class _Ty> struct UnmapViewOfFile_delete<_Ty[]>
1162 {
1164
1169
1173 void operator()(_Ty* _Ptr) const
1174 {
1175 if (!UnmapViewOfFile(_Ptr))
1176 throw win_runtime_error("UnmapViewOfFile failed");
1177 }
1178
1182 template<class _Other>
1183 void operator()(_Other*) const
1184 {
1185 if (!UnmapViewOfFile(_Ptr))
1186 throw win_runtime_error("UnmapViewOfFile failed");
1187 }
1188 };
1189
1197
1202 {
1205
1206 public:
1213 {
1214 InitializeCriticalSection(&m_data);
1215 }
1216
1223 {
1224 DeleteCriticalSection(&m_data);
1225 }
1226
1232 operator LPCRITICAL_SECTION() noexcept
1233 {
1234 return &m_data;
1235 }
1236
1237 protected:
1238 CRITICAL_SECTION m_data;
1239 };
1240
1246 class find_file : public handle<HANDLE, INVALID_HANDLE_VALUE>
1247 {
1248 WINSTD_HANDLE_IMPL(find_file, INVALID_HANDLE_VALUE)
1249
1250 public:
1256 virtual ~find_file()
1257 {
1258 if (m_h != invalid)
1259 free_internal();
1260 }
1261
1262 protected:
1268 void free_internal() noexcept override
1269 {
1270 FindClose(m_h);
1271 }
1272 };
1273
1279 class heap : public handle<HANDLE, NULL>
1280 {
1282
1283 public:
1289 virtual ~heap()
1290 {
1291 if (m_h != invalid)
1292 free_internal();
1293 }
1294
1302 bool enumerate() noexcept
1303 {
1304 assert(m_h != invalid);
1305
1306 bool found = false;
1307
1308 // Lock the heap for exclusive access.
1309 HeapLock(m_h);
1310
1311 PROCESS_HEAP_ENTRY e;
1312 e.lpData = NULL;
1313 while (HeapWalk(m_h, &e) != FALSE) {
1314 if ((e.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
1316 _T("Allocated block%s%s\n")
1317 _T(" Data portion begins at: %#p\n Size: %d bytes\n")
1318 _T(" Overhead: %d bytes\n Region index: %d\n"),
1319 (e.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0 ? tstring_printf(_T(", movable with HANDLE %#p"), e.Block.hMem).c_str() : _T(""),
1320 (e.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0 ? _T(", DDESHARE") : _T(""),
1321 e.lpData,
1322 e.cbData,
1323 e.cbOverhead,
1324 e.iRegionIndex);
1325
1326 found = true;
1327 }
1328 }
1329
1330 const DWORD dwResult = GetLastError();
1331 if (dwResult != ERROR_NO_MORE_ITEMS)
1332 OutputDebugStr(_T("HeapWalk failed (error %u).\n"), dwResult);
1333
1334 // Unlock the heap.
1335 HeapUnlock(m_h);
1336
1337 return found;
1338 }
1339
1340 protected:
1346 void free_internal() noexcept override
1347 {
1348 enumerate();
1349 HeapDestroy(m_h);
1350 }
1351 };
1352
1356 template <class _Ty>
1358 {
1359 public:
1360 typedef typename _Ty value_type;
1361
1362 typedef _Ty *pointer;
1363 typedef _Ty& reference;
1364 typedef const _Ty *const_pointer;
1365 typedef const _Ty& const_reference;
1366
1367 typedef SIZE_T size_type;
1368 typedef ptrdiff_t difference_type;
1369
1373 template <class _Other>
1374 struct rebind
1375 {
1377 };
1378
1379 public:
1386 {
1387 }
1388
1394 template <class _Other>
1396 {
1397 }
1398
1407 {
1408 assert(m_heap);
1409 return (pointer)HeapAlloc(m_heap, 0, count * sizeof(_Ty));
1410 }
1411
1418 void deallocate(_In_ pointer ptr, _In_ size_type size)
1419 {
1420 UNREFERENCED_PARAMETER(size);
1421 assert(m_heap);
1422 HeapFree(m_heap, 0, ptr);
1423 }
1424
1431 void construct(_Inout_ pointer ptr, _In_ const _Ty& val)
1432 {
1433 ::new ((void*)ptr) _Ty(val);
1434 }
1435
1442 void construct(_Inout_ pointer ptr, _Inout_ _Ty&& val)
1443 {
1444 ::new ((void*)ptr) _Ty(std::forward<_Ty>(val));
1445 }
1446
1452 void destroy(_Inout_ pointer ptr)
1453 {
1454 ptr->_Ty::~_Ty();
1455 }
1456
1461 {
1462 return (SIZE_T)-1;
1463 }
1464
1465 public:
1466 HANDLE m_heap;
1467 };
1468
1473 {
1476
1477 public:
1485 actctx_activator(_In_ HANDLE hActCtx) noexcept
1486 {
1487 if (!ActivateActCtx(hActCtx, &m_cookie))
1488 m_cookie = 0;
1489 }
1490
1497 {
1498 if (m_cookie)
1499 DeactivateActCtx(0, m_cookie);
1500 }
1501
1502 protected:
1503 ULONG_PTR m_cookie;
1504 };
1505
1510 {
1511 public:
1515 impersonator() noexcept : m_cookie(FALSE) {}
1516
1523 {
1524 if (m_cookie)
1525 RevertToSelf();
1526 }
1527
1531 operator bool () const { return m_cookie; }
1532
1533 protected:
1535 };
1536
1541 {
1544
1545 public:
1553 user_impersonator(_In_opt_ HANDLE hToken) noexcept
1554 {
1555 m_cookie = hToken && ImpersonateLoggedOnUser(hToken);
1556 }
1557 };
1558
1563 {
1566
1567 public:
1572 {
1573 TOKEN_PRIVILEGES privileges = { 1, {{{ 0, 0 }, SE_PRIVILEGE_ENABLED }} };
1574 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid) ||
1575 !ImpersonateSelf(SecurityImpersonation))
1576 return;
1577
1578 {
1579 HANDLE h;
1580 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &h))
1581 goto revert;
1582 win_handle<INVALID_HANDLE_VALUE> thread_token(h);
1583 if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL))
1584 goto revert;
1585 process_snapshot process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1586 if (!process_snapshot)
1587 goto revert;
1588 PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32) };
1589 if (!Process32First(process_snapshot, &entry))
1590 goto revert;
1591 while (_tcsicmp(entry.szExeFile, TEXT("winlogon.exe")) != 0)
1592 if (!Process32Next(process_snapshot, &entry))
1593 goto revert;
1594 process winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
1595 if (!winlogon_process)
1596 goto revert;
1597 if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &h))
1598 goto revert;
1599 win_handle<INVALID_HANDLE_VALUE> winlogon_token(h);
1600 if (!DuplicateToken(winlogon_token, SecurityImpersonation, &h))
1601 goto revert;
1602 win_handle<INVALID_HANDLE_VALUE> duplicated_token(h);
1603 if (!SetThreadToken(NULL, duplicated_token))
1604 goto revert;
1605 }
1606
1607 m_cookie = TRUE;
1608 return;
1609
1610 revert:
1611 DWORD dwResult = GetLastError();
1612 RevertToSelf();
1613 SetLastError(dwResult);
1614 }
1615 };
1616
1621 {
1622 public:
1628 clipboard_opener(_In_opt_ HWND hWndNewOwner = NULL)
1629 {
1630 if (!OpenClipboard(hWndNewOwner))
1631 throw win_runtime_error("OpenClipboard failed");
1632 }
1633
1640 {
1641 CloseClipboard();
1642 }
1643 };
1644
1649 {
1652
1653 public:
1661 console_ctrl_handler(_In_opt_ PHANDLER_ROUTINE HandlerRoutine) noexcept : m_handler(HandlerRoutine)
1662 {
1663 m_cookie = SetConsoleCtrlHandler(m_handler, TRUE);
1664 }
1665
1672 {
1673 if (m_cookie)
1674 SetConsoleCtrlHandler(m_handler, FALSE);
1675 }
1676
1677 protected:
1679 PHANDLER_ROUTINE m_handler;
1680 };
1681
1685 class vmemory : public handle<LPVOID, NULL>
1686 {
1688
1689 public:
1693 vmemory() noexcept : m_proc(NULL)
1694 {
1695 }
1696
1703 vmemory(_In_ handle_type h, _In_ HANDLE proc) noexcept :
1704 m_proc(proc),
1706 {
1707 }
1708
1714 vmemory(_Inout_ vmemory &&h) noexcept :
1715 m_proc(std::move(h.m_proc)),
1716 handle<LPVOID, NULL>(std::move(h))
1717 {
1718 }
1719
1725 virtual ~vmemory()
1726 {
1727 if (m_h != invalid)
1728 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
1729 }
1730
1736 vmemory& operator=(_Inout_ vmemory &&other) noexcept
1737 {
1738 if (this != std::addressof(other)) {
1739 (handle<handle_type, NULL>&&)*this = std::move(other);
1740 m_proc = std::move(other.m_proc);
1741 }
1742 return *this;
1743 }
1744
1753 void attach(_In_ HANDLE proc, _In_opt_ handle_type h) noexcept
1754 {
1755 m_proc = proc;
1756 if (m_h != invalid)
1757 free_internal();
1758 m_h = h;
1759 }
1760
1770 bool alloc(
1771 _In_ HANDLE hProcess,
1772 _In_opt_ LPVOID lpAddress,
1773 _In_ SIZE_T dwSize,
1774 _In_ DWORD flAllocationType,
1775 _In_ DWORD flProtect) noexcept
1776 {
1777 handle_type h = VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect);
1778 if (h != invalid) {
1779 attach(hProcess, h);
1780 return true;
1781 } else
1782 return false;
1783 }
1784
1785 protected:
1791 void free_internal() noexcept override
1792 {
1793 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
1794 }
1795
1796 protected:
1797 HANDLE m_proc;
1798 };
1799
1806 class reg_key : public handle<HKEY, NULL>
1807 {
1809
1810 public:
1816 virtual ~reg_key()
1817 {
1818 if (m_h != invalid)
1819 free_internal();
1820 }
1821
1831 bool delete_subkey(_In_z_ LPCTSTR szSubkey)
1832 {
1833 LSTATUS s;
1834
1835 s = RegDeleteKey(m_h, szSubkey);
1836 if (s == ERROR_SUCCESS || s == ERROR_FILE_NOT_FOUND)
1837 return true;
1838
1839 {
1840 reg_key k;
1841 handle_type h;
1842 s = RegOpenKeyEx(m_h, szSubkey, 0, KEY_ENUMERATE_SUB_KEYS, &h);
1843 if (s == ERROR_SUCCESS)
1844 k.attach(h);
1845 else {
1846 SetLastError(s);
1847 return false;
1848 }
1849 for (;;) {
1850 TCHAR szName[MAX_PATH];
1851 DWORD dwSize = _countof(szName);
1852 s = RegEnumKeyEx(k, 0, szName, &dwSize, NULL, NULL, NULL, NULL);
1853 if (s == ERROR_SUCCESS)
1854 k.delete_subkey(szName);
1855 else if (s == ERROR_NO_MORE_ITEMS)
1856 break;
1857 else {
1858 SetLastError(s);
1859 return false;
1860 }
1861 }
1862 }
1863
1864 s = RegDeleteKey(m_h, szSubkey);
1865 if (s == ERROR_SUCCESS)
1866 return true;
1867 else {
1868 SetLastError(s);
1869 return false;
1870 }
1871 }
1872
1873 protected:
1879 void free_internal() noexcept override
1880 {
1881 RegCloseKey(m_h);
1882 }
1883 };
1884
1888 class security_id : public handle<PSID, NULL>
1889 {
1891
1892 public:
1899 {
1900 if (m_h != invalid)
1901 free_internal();
1902 }
1903
1904 protected:
1910 void free_internal() noexcept override
1911 {
1912 FreeSid(m_h);
1913 }
1914 };
1915
1919 class process_information : public PROCESS_INFORMATION
1920 {
1923
1924 public:
1929 {
1930 hProcess = INVALID_HANDLE_VALUE;
1931 hThread = INVALID_HANDLE_VALUE;
1932 dwProcessId = 0;
1933 dwThreadId = 0;
1934 }
1935
1940 {
1941 #pragma warning(push)
1942 #pragma warning(disable: 6001) // Using uninitialized memory '*this'. << ???
1943
1944 if (hProcess != INVALID_HANDLE_VALUE)
1945 CloseHandle(hProcess);
1946
1947 if (hThread != INVALID_HANDLE_VALUE)
1948 CloseHandle(hThread);
1949
1950 #pragma warning(pop)
1951 }
1952 };
1953
1959 class event_log : public handle<HANDLE, NULL>
1960 {
1962
1963 public:
1969 virtual ~event_log()
1970 {
1971 if (m_h != invalid)
1972 free_internal();
1973 }
1974
1975 protected:
1981 void free_internal() noexcept override
1982 {
1983 DeregisterEventSource(m_h);
1984 }
1985 };
1986
1990 class sc_handle : public handle<SC_HANDLE, NULL>
1991 {
1993
1994 public:
2000 virtual ~sc_handle()
2001 {
2002 if (m_h != invalid)
2003 free_internal();
2004 }
2005
2006 protected:
2012 void free_internal() noexcept override
2013 {
2014 CloseServiceHandle(m_h);
2015 }
2016 };
2017
2019}
2020
2023
2024#pragma warning(push)
2025#pragma warning(disable: 4505) // Don't warn on unused code
2026
2028static LSTATUS RegCreateKeyExA(
2029 _In_ HKEY hKey,
2030 _In_ LPCSTR lpSubKey,
2031 _Reserved_ DWORD Reserved,
2032 _In_opt_ LPSTR lpClass,
2033 _In_ DWORD dwOptions,
2034 _In_ REGSAM samDesired,
2035 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2036 _Inout_ winstd::reg_key &result,
2037 _Out_opt_ LPDWORD lpdwDisposition)
2038{
2039 HKEY h;
2040 LSTATUS s = RegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2041 if (s == ERROR_SUCCESS)
2042 result.attach(h);
2043 return s;
2044}
2045
2051static LSTATUS RegCreateKeyExW(
2052 _In_ HKEY hKey,
2053 _In_ LPCWSTR lpSubKey,
2054 _Reserved_ DWORD Reserved,
2055 _In_opt_ LPWSTR lpClass,
2056 _In_ DWORD dwOptions,
2057 _In_ REGSAM samDesired,
2058 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2059 _Inout_ winstd::reg_key &result,
2060 _Out_opt_ LPDWORD lpdwDisposition)
2061{
2062 HKEY h;
2063 LSTATUS s = RegCreateKeyExW(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2064 if (s == ERROR_SUCCESS)
2065 result.attach(h);
2066 return s;
2067}
2068
2070static LSTATUS RegOpenKeyExA(
2071 _In_ HKEY hKey,
2072 _In_opt_ LPCSTR lpSubKey,
2073 _In_opt_ DWORD ulOptions,
2074 _In_ REGSAM samDesired,
2075 _Inout_ winstd::reg_key &result)
2076{
2077 HKEY h;
2078 LSTATUS s = RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, &h);
2079 if (s == ERROR_SUCCESS)
2080 result.attach(h);
2081 return s;
2082}
2083
2089static LSTATUS RegOpenKeyExW(
2090 _In_ HKEY hKey,
2091 _In_opt_ LPCWSTR lpSubKey,
2092 _In_opt_ DWORD ulOptions,
2093 _In_ REGSAM samDesired,
2094 _Inout_ winstd::reg_key &result)
2095{
2096 HKEY h;
2097 LSTATUS s = RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, &h);
2098 if (s == ERROR_SUCCESS)
2099 result.attach(h);
2100 return s;
2101}
2102
2108static BOOL OpenProcessToken(_In_ HANDLE ProcessHandle, _In_ DWORD DesiredAccess, _Inout_ winstd::win_handle<NULL> &TokenHandle)
2109{
2110 HANDLE h;
2111 if (OpenProcessToken(ProcessHandle, DesiredAccess, &h)) {
2112 TokenHandle.attach(h);
2113 return TRUE;
2114 }
2115 return FALSE;
2116}
2117
2123static 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)
2124{
2125 HANDLE h;
2126 if (DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, &h)) {
2127 NewToken.attach(h);
2128 return TRUE;
2129 }
2130 return FALSE;
2131}
2132
2138static 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)
2139{
2140 PSID h;
2141 if (AllocateAndInitializeSid(pIdentifierAuthority, nSubAuthorityCount, nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3, nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, &h)) {
2142 Sid.attach(h);
2143 return TRUE;
2144 }
2145 return FALSE;
2146}
2147
2149static 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)
2150{
2151 PACL h;
2152 DWORD dwResult = SetEntriesInAclA(cCountOfExplicitEntries, pListOfExplicitEntries, OldAcl, &h);
2153 if (dwResult == ERROR_SUCCESS)
2154 Acl.reset(h);
2155 return ERROR_SUCCESS;
2156}
2157
2163static 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)
2164{
2165 PACL h;
2166 DWORD dwResult = SetEntriesInAclW(cCountOfExplicitEntries, pListOfExplicitEntries, OldAcl, &h);
2167 if (dwResult == ERROR_SUCCESS)
2168 Acl.reset(h);
2169 return ERROR_SUCCESS;
2170}
2171
2177template<class _Traits, class _Ax>
2178_Success_(return != 0) BOOL GetThreadPreferredUILanguages(_In_ DWORD dwFlags, _Out_ PULONG pulNumLanguages, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
2179{
2180 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
2181 ULONG ulSize = _countof(szStackBuffer);
2182
2183 // Try with stack buffer first.
2184 if (GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, szStackBuffer, &ulSize)) {
2185 // Copy from stack.
2186 sValue.assign(szStackBuffer, ulSize - 1);
2187 return TRUE;
2188 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
2189 // Query required size.
2190 ulSize = 0;
2191 GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, NULL, &ulSize);
2192 // Allocate on heap and retry.
2193 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[ulSize]);
2194 if (GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, szBuffer.get(), &ulSize)) {
2195 sValue.assign(szBuffer.get(), ulSize - 1);
2196 return TRUE;
2197 }
2198 }
2199 return FALSE;
2200}
2201
2202#pragma warning(pop)
2203
Activates given activation context in constructor and deactivates it in destructor.
Definition Win.h:1473
actctx_activator(HANDLE hActCtx) noexcept
Construct the activator and activates the given activation context.
Definition Win.h:1485
virtual ~actctx_activator()
Deactivates activation context and destructs the activator.
Definition Win.h:1496
ULONG_PTR m_cookie
Cookie for context deactivation.
Definition Win.h:1503
Base template class to support string formatting using printf() style templates.
Definition Common.h:1504
Clipboard management.
Definition Win.h:1621
virtual ~clipboard_opener()
Closes the clipboard.
Definition Win.h:1639
clipboard_opener(HWND hWndNewOwner=NULL)
Opens the clipboard for examination and prevents other applications from modifying the clipboard cont...
Definition Win.h:1628
Console control handler stack management.
Definition Win.h:1649
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:1661
virtual ~console_ctrl_handler()
Pops console control handler from the console control handler stack.
Definition Win.h:1671
PHANDLER_ROUTINE m_handler
Pointer to console control handler.
Definition Win.h:1679
BOOL m_cookie
Did pushing the console control handler succeed?
Definition Win.h:1678
Critical section wrapper.
Definition Win.h:1202
critical_section() noexcept
Construct the object and initializes a critical section object.
Definition Win.h:1212
CRITICAL_SECTION m_data
Critical section struct.
Definition Win.h:1238
virtual ~critical_section()
Releases all resources used by an unowned critical section object.
Definition Win.h:1222
Event log handle wrapper.
Definition Win.h:1960
void free_internal() noexcept override
Closes an event log handle.
Definition Win.h:1981
virtual ~event_log()
Closes an event log handle.
Definition Win.h:1969
Find-file handle wrapper.
Definition Win.h:1247
virtual ~find_file()
Closes a file search handle.
Definition Win.h:1256
void free_internal() noexcept override
Closes a file search handle.
Definition Win.h:1268
Base abstract template class to support generic object handle keeping.
Definition Common.h:983
LPVOID handle_type
Datatype of the object handle this template class handles.
Definition Common.h:988
handle_type m_h
Object handle.
Definition Common.h:1237
void attach(handle_type h) noexcept
Sets a new object handle for the class.
Definition Common.h:1200
HeapAlloc allocator.
Definition Win.h:1358
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:1367
_Ty value_type
A type that is managed by the allocator.
Definition Win.h:1360
heap_allocator(const heap_allocator< _Other > &other)
Constructs allocator from another type.
Definition Win.h:1395
HANDLE m_heap
Heap handle.
Definition Win.h:1466
pointer allocate(size_type count)
Allocates a new memory block.
Definition Win.h:1406
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:1368
heap_allocator(HANDLE heap)
Constructs allocator.
Definition Win.h:1385
_Ty & reference
A type that provides a reference to the type of object managed by the allocator.
Definition Win.h:1363
void construct(pointer ptr, _Ty &&val)
Calls moving constructor for the element.
Definition Win.h:1442
void deallocate(pointer ptr, size_type size)
Frees memory block.
Definition Win.h:1418
size_type max_size() const
Returns maximum memory block size.
Definition Win.h:1460
void construct(pointer ptr, const _Ty &val)
Calls copying constructor for the element.
Definition Win.h:1431
const _Ty & const_reference
A type that provides a constant reference to type of object managed by the allocator.
Definition Win.h:1365
const _Ty * const_pointer
A type that provides a constant pointer to the type of object managed by the allocator.
Definition Win.h:1364
_Ty * pointer
A type that provides a pointer to the type of object managed by the allocator.
Definition Win.h:1362
void destroy(pointer ptr)
Calls destructor for the element.
Definition Win.h:1452
Heap handle wrapper.
Definition Win.h:1280
bool enumerate() noexcept
Enumerates allocated heap blocks using OutputDebugString()
Definition Win.h:1302
void free_internal() noexcept override
Destroys the heap.
Definition Win.h:1346
virtual ~heap()
Destroys the heap.
Definition Win.h:1289
Base class for thread impersonation of another security context.
Definition Win.h:1510
virtual ~impersonator()
Reverts to current user and destructs the impersonator.
Definition Win.h:1522
impersonator() noexcept
Construct the impersonator.
Definition Win.h:1515
BOOL m_cookie
Did impersonation succeed?
Definition Win.h:1534
Module handle wrapper.
Definition Win.h:1061
void free_internal() noexcept override
Frees the module.
Definition Win.h:1082
virtual ~library()
Frees the module.
Definition Win.h:1070
PROCESS_INFORMATION struct wrapper.
Definition Win.h:1920
~process_information()
Closes process and thread handles.
Definition Win.h:1939
process_information() noexcept
Constructs blank PROCESS_INFORMATION.
Definition Win.h:1928
Registry key wrapper class.
Definition Win.h:1807
void free_internal() noexcept override
Closes a handle to the registry key.
Definition Win.h:1879
bool delete_subkey(LPCTSTR szSubkey)
Deletes the specified registry subkey.
Definition Win.h:1831
virtual ~reg_key()
Closes a handle to the registry key.
Definition Win.h:1816
SC_HANDLE wrapper class.
Definition Win.h:1991
void free_internal() noexcept override
Closes an open object handle.
Definition Win.h:2012
virtual ~sc_handle()
Closes an open object handle.
Definition Win.h:2000
SID wrapper class.
Definition Win.h:1889
void free_internal() noexcept override
Closes a handle to the SID.
Definition Win.h:1910
virtual ~security_id()
Closes a handle to the SID.
Definition Win.h:1898
Lets the calling thread impersonate the security context of the SYSTEM user.
Definition Win.h:1563
system_impersonator() noexcept
Construct the impersonator and impersonates the SYSTEM user.
Definition Win.h:1571
Lets the calling thread impersonate the security context of a logged-on user.
Definition Win.h:1541
user_impersonator(HANDLE hToken) noexcept
Construct the impersonator and impersonates the given user.
Definition Win.h:1553
Memory in virtual address space of a process handle wrapper.
Definition Win.h:1686
vmemory & operator=(vmemory &&other) noexcept
Move assignment.
Definition Win.h:1736
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:1770
void free_internal() noexcept override
Frees the memory.
Definition Win.h:1791
void attach(HANDLE proc, handle_type h) noexcept
Sets a new memory handle for the class.
Definition Win.h:1753
virtual ~vmemory()
Frees the memory.
Definition Win.h:1725
vmemory(handle_type h, HANDLE proc) noexcept
Initializes a new class instance with an already available object handle.
Definition Win.h:1703
vmemory() noexcept
Initializes a new class instance with the memory handle set to INVAL.
Definition Win.h:1693
vmemory(vmemory &&h) noexcept
Move constructor.
Definition Win.h:1714
HANDLE m_proc
Handle of memory's process.
Definition Win.h:1797
Windows HANDLE wrapper class.
Definition Win.h:1028
void free_internal() noexcept override
Closes an open object handle.
Definition Win.h:1049
virtual ~win_handle()
Closes an open object handle.
Definition Win.h:1037
Windows runtime error.
Definition Common.h:1422
#define WINSTD_NONCOPYABLE(C)
Declares a class as non-copyable.
Definition Common.h:66
#define WINSTD_STACK_BUFFER_BYTES
Size of the stack buffer in bytes used for initial system function call.
Definition Common.h:93
#define WINSTD_NONMOVABLE(C)
Declares a class as non-movable.
Definition Common.h:74
static int vsprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format, va_list arg)
Formats string using printf().
Definition Common.h:251
static int sprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format,...)
Formats string using printf().
Definition Common.h:284
#define WINSTD_HANDLE_IMPL(C, INVAL)
Implements default constructors and operators to prevent their auto-generation by compiler.
Definition Common.h:163
static const HANDLE invalid
Invalid handle value.
Definition Common.h:993
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:637
static DWORD ExpandEnvironmentStringsA(LPCSTR lpSrc, std::basic_string< char, _Traits, _Ax > &sValue) noexcept
Expands environment-variable strings, replaces them with the values defined for the current user,...
Definition Win.h:180
static BOOL StringToGuidA(LPCSTR lpszGuid, LPGUID lpGuid, LPCSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition Win.h:269
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:2051
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:719
win_handle< INVALID_HANDLE_VALUE > file
File handle wrapper.
Definition Win.h:1122
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:2028
static LSTATUS RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition Win.h:2070
static LSTATUS RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition Win.h:2089
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:230
static BOOL StringToGuidW(LPCWSTR lpszGuid, LPGUID lpGuid, LPCWSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition Win.h:342
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:607
static BOOL OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, winstd::win_handle< NULL > &TokenHandle)
Opens the access token associated with a process.
Definition Win.h:2108
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:2163
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:837
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:876
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:2138
win_handle< INVALID_HANDLE_VALUE > process_snapshot
Process snapshot handle wrapper.
Definition Win.h:1107
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:821
static BOOL CreateWellKnownSid(WELL_KNOWN_SID_TYPE WellKnownSidType, PSID DomainSid, std::unique_ptr< SID > &Sid)
Creates a SID for predefined aliases.
Definition Win.h:914
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:737
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:938
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:2123
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:2149
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:568
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:1196
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:593
static VOID OutputDebugStr(LPCSTR lpOutputString,...) noexcept
Formats and sends a string to the debugger for display.
Definition Win.h:778
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:962
win_handle< NULL > mutex
Mutex handle wrapper.
Definition Win.h:1114
win_handle< NULL > file_mapping
File mapping.
Definition Win.h:1129
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:991
win_handle< NULL > process
Process handle wrapper.
Definition Win.h:1093
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:541
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:2178
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:430
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:801
static DWORD ExpandEnvironmentStringsW(LPCWSTR lpSrc, std::basic_string< wchar_t, _Traits, _Ax > &sValue) noexcept
Expands environment-variable strings, replaces them with the values defined for the current user,...
Definition Win.h:208
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:249
static VOID OutputDebugStrV(LPCSTR lpOutputString, va_list arg) noexcept
Formats and sends a string to the debugger for display.
Definition Win.h:754
win_handle< NULL > thread
Thread handle wrapper.
Definition Win.h:1100
Deleter for unique_ptr using LocalFree.
Definition Common.h:694
UnmapViewOfFile_delete()
Default construct.
Definition Win.h:1168
void operator()(_Other *) const
Delete a pointer of another type.
Definition Win.h:1183
void operator()(_Ty *_Ptr) const
Delete a pointer.
Definition Win.h:1173
UnmapViewOfFile_delete< _Ty > _Myt
This type.
Definition Win.h:1163
Deleter for unique_ptr using UnmapViewOfFile.
Definition Win.h:1135
UnmapViewOfFile_delete(const UnmapViewOfFile_delete< _Ty2 > &)
Construct from another UnmapViewOfFile_delete.
Definition Win.h:1146
void operator()(_Ty *_Ptr) const
Delete a pointer.
Definition Win.h:1151
UnmapViewOfFile_delete< _Ty > _Myt
This type.
Definition Win.h:1136
UnmapViewOfFile_delete()
Default construct.
Definition Win.h:1141
A structure that enables an allocator for objects of one type to allocate storage for objects of anot...
Definition Win.h:1375
heap_allocator< _Other > other
Other allocator type.
Definition Win.h:1376