WinStd
Windows Win32 API using Standard C++
Loading...
Searching...
No Matches
Win.h
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 1991-2024 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 sValue.resize(dwCapacity - 1);
42 dwResult = ::GetModuleFileNameA(hModule, &sValue[0], dwCapacity);
43 if (dwResult < dwCapacity) {
44 sValue.resize(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 sValue.resize(dwCapacity - 1);
71 dwResult = ::GetModuleFileNameW(hModule, &sValue[0], dwCapacity);
72 if (dwResult < dwCapacity) {
73 sValue.resize(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 // Allocate buffer on heap and read the string data into it.
92 sValue.resize(iResult++);
93 return ::GetWindowTextA(hWnd, &sValue[0], iResult);
94 }
95
96 sValue.clear();
97 return 0;
98}
99
105template<class _Traits, class _Ax>
106static _Success_(return != 0) int GetWindowTextW(_In_ HWND hWnd, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
107{
108 assert(0); // TODO: Test this code.
109
110 int iResult;
111
112 // Query the final string length first.
113 iResult = ::GetWindowTextLengthW(hWnd);
114 if (iResult > 0) {
115 // Allocate buffer on heap and read the string data into it.
116 sValue.resize(iResult++);
117 return ::GetWindowTextW(hWnd, &sValue[0], iResult);
118 }
119
120 sValue.clear();
121 return 0;
122}
123
125template<class _Ty, class _Ax>
126static _Success_(return != 0) BOOL GetFileVersionInfoA(_In_z_ LPCSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<_Ty, _Ax> &aValue) noexcept
127{
128 assert(0); // TODO: Test this code.
129
130 // Get version info size.
131 DWORD dwVerInfoSize = ::GetFileVersionInfoSizeA(lptstrFilename, &dwHandle);
132 if (dwVerInfoSize != 0) {
133 // Read version info.
134 aValue.resize((dwVerInfoSize + sizeof(_Ty) - 1) / sizeof(_Ty));
135 return ::GetFileVersionInfoA(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
136 } else
137 return FALSE;
138}
139
145template<class _Ty, class _Ax>
146static _Success_(return != 0) BOOL GetFileVersionInfoW(_In_z_ LPCWSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<_Ty, _Ax> &aValue) noexcept
147{
148 assert(0); // TODO: Test this code.
149
150 // Get version info size.
151 DWORD dwVerInfoSize = ::GetFileVersionInfoSizeW(lptstrFilename, &dwHandle);
152 if (dwVerInfoSize != 0) {
153 // Read version info.
154 aValue.resize((dwVerInfoSize + sizeof(_Ty) - 1) / sizeof(_Ty));
155 return ::GetFileVersionInfoW(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
156 } else
157 return FALSE;
158}
159
161template<class _Traits, class _Ax>
162static _Success_(return != 0) DWORD ExpandEnvironmentStringsA(_In_z_ LPCSTR lpSrc, _Out_ std::basic_string<char, _Traits, _Ax> &sValue)
163{
164 assert(0); // TODO: Test this code.
165
166 for (SIZE_T sSizeOut = SIZETAdd(strlen(lpSrc), 0x100);;) {
167 if (sSizeOut > DWORD_MAX)
168 throw std::invalid_argument("String too big");
169 DWORD dwSizeIn = static_cast<DWORD>(sSizeOut);
170 sValue.resize((size_t)dwSizeIn + 1); // Note: ANSI version requires one extra char.
171 sSizeOut = ::ExpandEnvironmentStringsA(lpSrc, &sValue[0], dwSizeIn);
172 if (sSizeOut == 0) {
173 // Error or zero-length input.
174 break;
175 } else if (sSizeOut <= dwSizeIn) {
176 // The buffer was sufficient.
177 sValue.resize(sSizeOut - 1);
178 return static_cast<DWORD>(sSizeOut);
179 }
180 }
181
182 sValue.clear();
183 return 0;
184}
185
191template<class _Traits, class _Ax>
192static _Success_(return != 0) DWORD ExpandEnvironmentStringsW(_In_z_ LPCWSTR lpSrc, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
193{
194 for (SIZE_T sSizeOut = SIZETAdd(wcslen(lpSrc), 0x100);;) {
195 if (sSizeOut > DWORD_MAX)
196 throw std::invalid_argument("String too big");
197 DWORD dwSizeIn = static_cast<DWORD>(sSizeOut);
198 sValue.resize(dwSizeIn);
199 sSizeOut = ::ExpandEnvironmentStringsW(lpSrc, &sValue[0], dwSizeIn);
200 if (sSizeOut == 0) {
201 // Error or zero-length input.
202 break;
203 } else if (sSizeOut <= dwSizeIn) {
204 // The buffer was sufficient.
205 sValue.resize(sSizeOut - 1);
206 return static_cast<DWORD>(sSizeOut);
207 }
208 }
209
210 sValue.clear();
211 return 0;
212}
213
215template<class _Traits, class _Ax>
216static VOID GuidToStringA(_In_ LPCGUID lpGuid, _Out_ std::basic_string<char, _Traits, _Ax> &str) noexcept
217{
218 assert(0); // TODO: Test this code.
219
220 sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
221 lpGuid->Data1,
222 lpGuid->Data2,
223 lpGuid->Data3,
224 lpGuid->Data4[0], lpGuid->Data4[1],
225 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
226}
227
234template<class _Traits, class _Ax>
235static VOID GuidToStringW(_In_ LPCGUID lpGuid, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &str) noexcept
236{
237 assert(0); // TODO: Test this code.
238
239 sprintf(str, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
240 lpGuid->Data1,
241 lpGuid->Data2,
242 lpGuid->Data3,
243 lpGuid->Data4[0], lpGuid->Data4[1],
244 lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
245}
246
248#ifdef _UNICODE
249#define GuidToString GuidToStringW
250#else
251#define GuidToString GuidToStringA
252#endif
253
255static _Success_(return) BOOL StringToGuidA(_In_z_ LPCSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCSTR *lpszGuidEnd = NULL) noexcept
256{
257 GUID g;
258 LPSTR lpszEnd;
259 unsigned long ulTmp;
260 unsigned long long ullTmp;
261
262 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
263 lpszGuid++;
264
265 g.Data1 = strtoul(lpszGuid, &lpszEnd, 16);
266 if (errno == ERANGE) return FALSE;
267 lpszGuid = lpszEnd;
268
269 if (*lpszGuid != '-') return FALSE;
270 lpszGuid++;
271
272 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
273 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
274 g.Data2 = static_cast<unsigned short>(ulTmp);
275 lpszGuid = lpszEnd;
276
277 if (*lpszGuid != '-') return FALSE;
278 lpszGuid++;
279
280 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
281 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
282 g.Data3 = static_cast<unsigned short>(ulTmp);
283 lpszGuid = lpszEnd;
284
285 if (*lpszGuid != '-') return FALSE;
286 lpszGuid++;
287
288 ulTmp = strtoul(lpszGuid, &lpszEnd, 16);
289 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
290 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
291 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
292 lpszGuid = lpszEnd;
293
294 if (*lpszGuid != '-') return FALSE;
295 lpszGuid++;
296
297 ullTmp = _strtoui64(lpszGuid, &lpszEnd, 16);
298 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
299 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
300 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
301 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
302 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
303 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
304 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
305 lpszGuid = lpszEnd;
306
307 if (*lpszGuid != '}') return FALSE;
308 lpszGuid++;
309
310 if (lpszGuidEnd)
311 *lpszGuidEnd = lpszGuid;
312
313 *lpGuid = g;
314 return TRUE;
315}
316
328static _Success_(return) BOOL StringToGuidW(_In_z_ LPCWSTR lpszGuid, _Out_ LPGUID lpGuid, _Out_opt_ LPCWSTR *lpszGuidEnd = NULL) noexcept
329{
330 GUID g;
331 LPWSTR lpszEnd;
332 unsigned long ulTmp;
333 unsigned long long ullTmp;
334
335 if (!lpszGuid || !lpGuid || *lpszGuid != '{') return FALSE;
336 lpszGuid++;
337
338 g.Data1 = wcstoul(lpszGuid, &lpszEnd, 16);
339 if (errno == ERANGE) return FALSE;
340 lpszGuid = lpszEnd;
341
342 if (*lpszGuid != '-') return FALSE;
343 lpszGuid++;
344
345 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
346 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
347 g.Data2 = static_cast<unsigned short>(ulTmp);
348 lpszGuid = lpszEnd;
349
350 if (*lpszGuid != '-') return FALSE;
351 lpszGuid++;
352
353 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
354 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
355 g.Data3 = static_cast<unsigned short>(ulTmp);
356 lpszGuid = lpszEnd;
357
358 if (*lpszGuid != '-') return FALSE;
359 lpszGuid++;
360
361 ulTmp = wcstoul(lpszGuid, &lpszEnd, 16);
362 if (errno == ERANGE || ulTmp > 0xFFFF) return FALSE;
363 g.Data4[0] = static_cast<unsigned char>((ulTmp >> 8) & 0xff);
364 g.Data4[1] = static_cast<unsigned char>( ulTmp & 0xff);
365 lpszGuid = lpszEnd;
366
367 if (*lpszGuid != '-') return FALSE;
368 lpszGuid++;
369
370 ullTmp = _wcstoui64(lpszGuid, &lpszEnd, 16);
371 if (errno == ERANGE || ullTmp > 0xFFFFFFFFFFFF) return FALSE;
372 g.Data4[2] = static_cast<unsigned char>((ullTmp >> 40) & 0xff);
373 g.Data4[3] = static_cast<unsigned char>((ullTmp >> 32) & 0xff);
374 g.Data4[4] = static_cast<unsigned char>((ullTmp >> 24) & 0xff);
375 g.Data4[5] = static_cast<unsigned char>((ullTmp >> 16) & 0xff);
376 g.Data4[6] = static_cast<unsigned char>((ullTmp >> 8) & 0xff);
377 g.Data4[7] = static_cast<unsigned char>( ullTmp & 0xff);
378 lpszGuid = lpszEnd;
379
380 if (*lpszGuid != '}') return FALSE;
381 lpszGuid++;
382
383 if (lpszGuidEnd)
384 *lpszGuidEnd = lpszGuid;
385
386 *lpGuid = g;
387 return TRUE;
388}
389
391#ifdef _UNICODE
392#define StringToGuid StringToGuidW
393#else
394#define StringToGuid StringToGuidA
395#endif
396
415template<class _Traits, class _Ax>
416static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCSTR pszName, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) noexcept
417{
418 LSTATUS lResult;
419 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
420 DWORD dwSize = sizeof(aStackBuffer), dwType;
421
422 // Try with stack buffer first.
423 lResult = ::RegQueryValueExA(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
424 if (lResult == ERROR_SUCCESS) {
425 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
426 // The value is REG_SZ or REG_MULTI_SZ.
427 dwSize /= sizeof(CHAR);
428 sValue.assign(reinterpret_cast<LPCSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
429 } else if (dwType == REG_EXPAND_SZ) {
430 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
431 if (::ExpandEnvironmentStringsA(reinterpret_cast<LPCSTR>(aStackBuffer), sValue) == 0)
432 lResult = ::GetLastError();
433 } else {
434 // The value is not a string type.
435 lResult = ERROR_INVALID_DATA;
436 }
437 } else if (lResult == ERROR_MORE_DATA) {
438 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
439 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
440 sValue.resize(dwSize / sizeof(CHAR));
441 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(&sValue[0]), &dwSize)) == ERROR_SUCCESS) {
442 dwSize /= sizeof(CHAR);
443 sValue.resize(dwSize && sValue[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
444 }
445 } else if (dwType == REG_EXPAND_SZ) {
446 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
447 std::unique_ptr<CHAR[]> szBuffer(new CHAR[dwSize / sizeof(CHAR) + 1]);
448 if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
449 dwSize /= sizeof(CHAR);
450 szBuffer[dwSize] = 0;
451 if (::ExpandEnvironmentStringsA(szBuffer.get(), sValue) == 0)
452 lResult = ::GetLastError();
453 }
454 } else {
455 // The value is not a string type.
456 lResult = ERROR_INVALID_DATA;
457 }
458 }
459
460 return lResult;
461}
462
481template<class _Traits, class _Ax>
482static LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCWSTR pszName, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) noexcept
483{
484 LSTATUS lResult;
485 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
486 DWORD dwSize = sizeof(aStackBuffer), dwType;
487
488 // Try with stack buffer first.
489 lResult = ::RegQueryValueExW(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
490 if (lResult == ERROR_SUCCESS) {
491 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
492 // The value is REG_SZ or REG_MULTI_SZ.
493 dwSize /= sizeof(WCHAR);
494 sValue.assign(reinterpret_cast<LPCWSTR>(aStackBuffer), dwSize && reinterpret_cast<LPCWSTR>(aStackBuffer)[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
495 } else if (dwType == REG_EXPAND_SZ) {
496 // The value is REG_EXPAND_SZ. Expand it from stack buffer.
497 if (::ExpandEnvironmentStringsW(reinterpret_cast<LPCWSTR>(aStackBuffer), sValue) == 0)
498 lResult = ::GetLastError();
499 } else {
500 // The value is not a string type.
501 lResult = ERROR_INVALID_DATA;
502 }
503 } else if (lResult == ERROR_MORE_DATA) {
504 if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
505 // The value is REG_SZ or REG_MULTI_SZ. Read it now.
506 sValue.resize(dwSize / sizeof(WCHAR));
507 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(&sValue[0]), &dwSize)) == ERROR_SUCCESS) {
508 dwSize /= sizeof(WCHAR);
509 sValue.resize(dwSize && sValue[dwSize - 1] == 0 ? dwSize - 1 : dwSize);
510 }
511 } else if (dwType == REG_EXPAND_SZ) {
512 // The value is REG_EXPAND_SZ. Read it and expand environment variables.
513 std::unique_ptr<WCHAR[]> szBuffer(new WCHAR[dwSize / sizeof(WCHAR) + 1]);
514 if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, reinterpret_cast<LPBYTE>(szBuffer.get()), &dwSize)) == ERROR_SUCCESS) {
515 dwSize /= sizeof(WCHAR);
516 szBuffer[dwSize] = 0;
517 if (::ExpandEnvironmentStringsW(szBuffer.get(), sValue) == 0)
518 lResult = ::GetLastError();
519 }
520 } else {
521 // The value is not a string type.
522 lResult = ERROR_INVALID_DATA;
523 }
524 }
525
526 return lResult;
527}
528
530template<class _Ty, class _Ax>
531static LSTATUS RegQueryValueExA(_In_ HKEY hKey, _In_opt_z_ LPCSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
532{
533 LSTATUS lResult;
534 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
535 DWORD dwSize = sizeof(aStackBuffer);
536
537 // Try with stack buffer first.
538 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
539 if (lResult == ERROR_SUCCESS) {
540 // Copy from stack buffer.
541 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
542 memcpy(aData.data(), aStackBuffer, dwSize);
543 } else if (lResult == ERROR_MORE_DATA) {
544 // Allocate buffer on heap and retry.
545 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
546 lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, NULL, reinterpret_cast<LPBYTE>(aData.data()), &dwSize);
547 }
548
549 return lResult;
550}
551
557template<class _Ty, class _Ax>
558static LSTATUS RegQueryValueExW(_In_ HKEY hKey, _In_opt_z_ LPCWSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<_Ty, _Ax> &aData) noexcept
559{
560 LSTATUS lResult;
561 BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
562 DWORD dwSize = sizeof(aStackBuffer);
563
564 // Try with stack buffer first.
565 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, aStackBuffer, &dwSize);
566 if (lResult == ERROR_SUCCESS) {
567 // Copy from stack buffer.
568 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
569 memcpy(aData.data(), aStackBuffer, dwSize);
570 } else if (lResult == ERROR_MORE_DATA) {
571 // Allocate buffer on heap and retry.
572 aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
573 lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, NULL, reinterpret_cast<LPBYTE>(aData.data()), &dwSize);
574 }
575
576 return lResult;
577}
578
579#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
580
582template<class _Traits, class _Ax>
583static 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
584{
585 // According to "Remarks" section in MSDN documentation of RegLoadMUIString(),
586 // this function is defined but not implemented as ANSI variation.
587 assert(0);
588 return ERROR_CALL_NOT_IMPLEMENTED;
589}
590
596template<class _Traits, class _Ax>
597static 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
598{
599 LSTATUS lResult;
600 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
601 DWORD dwSize;
602
603 Flags &= ~REG_MUI_STRING_TRUNCATE;
604
605 // Try with stack buffer first.
606 lResult = RegLoadMUIStringW(hKey, pszValue, szStackBuffer, sizeof(szStackBuffer), &dwSize, Flags, pszDirectory);
607 if (lResult == ERROR_SUCCESS) {
608 // Copy from stack buffer.
609 sOut.assign(szStackBuffer, wcsnlen(szStackBuffer, dwSize/sizeof(wchar_t)));
610 } else if (lResult == ERROR_MORE_DATA) {
611 // Allocate buffer on heap and retry.
612 sOut.resize((dwSize + sizeof(wchar_t) - 1)/sizeof(wchar_t) - 1);
613 sOut.resize((lResult = RegLoadMUIStringW(hKey, pszValue, &sOut[0], dwSize, &dwSize, Flags, pszDirectory)) == ERROR_SUCCESS ? wcsnlen(&sOut[0], dwSize/sizeof(wchar_t)) : 0);
614 }
615
616 return lResult;
617}
618
619#endif
620
626template<class _Traits, class _Ax>
627static _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
628{
629 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
630
631 // Try to convert to stack buffer first.
632 int cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, szStackBuffer, _countof(szStackBuffer));
633 if (cch > 0) {
634 // Copy from stack.
635 sDstString.assign(szStackBuffer, cwSrcLength != -1 ? wcsnlen(szStackBuffer, cch) : (size_t)cch - 1);
636 } else {
637 switch (::GetLastError()) {
638 case ERROR_INSUFFICIENT_BUFFER:
639 for (int i = 10; i--;) {
640 // Allocate buffer. Then convert again.
641 cch = -cch;
642 sDstString.resize((size_t)cch - 1);
643 cch = ::NormalizeString(NormForm, lpSrcString, cwSrcLength, &sDstString[0], cch);
644 if (cch > 0) {
645 sDstString.resize(cwSrcLength != -1 ? wcsnlen(&sDstString[0], cch) : (size_t)cch - 1);
646 break;
647 }
648 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
649 sDstString.clear();
650 break;
651 }
652 }
653 break;
654
655 case ERROR_SUCCESS:
656 sDstString.clear();
657 break;
658 }
659 }
660
661 return cch;
662}
663
669template<class _Traits1, class _Ax1, class _Traits2, class _Ax2>
670static _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
671{
672 WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
673
674 // Try to convert to stack buffer first.
675 int cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), szStackBuffer, _countof(szStackBuffer));
676 if (cch > 0) {
677 // Copy from stack.
678 sDstString.assign(szStackBuffer, cch);
679 } else {
680 switch (::GetLastError()) {
681 case ERROR_INSUFFICIENT_BUFFER:
682 for (int i = 10; i--;) {
683 // Allocate buffer. Then convert again.
684 cch = -cch;
685 sDstString.resize(cch);
686 cch = ::NormalizeString(NormForm, sSrcString.c_str(), (int)sSrcString.length(), &sDstString[0], cch);
687 if (cch > 0)
688 break;
689 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
690 sDstString.clear();
691 break;
692 }
693 }
694 break;
695
696 case ERROR_SUCCESS:
697 sDstString.clear();
698 break;
699 }
700 }
701
702 return cch;
703}
704
706template<class _Traits, class _Ax>
707static _Success_(return != 0) int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<char, _Traits, _Ax> &sBuffer) noexcept
708{
709 // Get read-only pointer to string resource.
710 LPCSTR pszStr;
711 int i = LoadStringA(hInstance, uID, reinterpret_cast<LPSTR>(&pszStr), 0);
712 if (i) {
713 sBuffer.assign(pszStr, i);
714 return i;
715 } else
716 return 0;
717}
718
724template<class _Traits, class _Ax>
725static _Success_(return != 0) int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sBuffer) noexcept
726{
727 // Get read-only pointer to string resource.
728 LPCWSTR pszStr;
729 int i = LoadStringW(hInstance, uID, reinterpret_cast<LPWSTR>(&pszStr), 0);
730 if (i) {
731 sBuffer.assign(pszStr, i);
732 return i;
733 } else
734 return 0;
735}
736
742static VOID OutputDebugStrV(_In_z_ LPCSTR lpOutputString, _In_ va_list arg) noexcept
743{
744 std::string str;
745 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
746 OutputDebugStringA(str.c_str());
747}
748
754static VOID OutputDebugStrV(_In_z_ LPCWSTR lpOutputString, _In_ va_list arg) noexcept
755{
756 std::wstring str;
757 try { vsprintf(str, lpOutputString, arg); } catch (...) { return; }
758 OutputDebugStringW(str.c_str());
759}
760
766static VOID OutputDebugStr(_In_z_ LPCSTR lpOutputString, ...) noexcept
767{
768 va_list arg;
769 va_start(arg, lpOutputString);
770 OutputDebugStrV(lpOutputString, arg);
771 va_end(arg);
772}
773
779static VOID OutputDebugStr(_In_z_ LPCWSTR lpOutputString, ...) noexcept
780{
781 va_list arg;
782 va_start(arg, lpOutputString);
783 OutputDebugStrV(lpOutputString, arg);
784 va_end(arg);
785}
786
788template<class _Traits, class _Ax>
789static _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
790{
791 int iResult = GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
792 if (iResult) {
793 // Allocate buffer on heap and retry.
794 sDate.resize(iResult - 1);
795 return GetDateFormatA(Locale, dwFlags, lpDate, lpFormat, &sDate[0], iResult);
796 }
797
798 return iResult;
799}
800
806template<class _Traits, class _Ax>
807static _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
808{
809 int iResult = GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, NULL, 0);
810 if (iResult) {
811 // Allocate buffer on heap and retry.
812 sDate.resize(iResult - 1);
813 return GetDateFormatW(Locale, dwFlags, lpDate, lpFormat, &sDate[0], iResult);
814 }
815
816 return iResult;
817}
818
820template<class _Traits, class _Ax>
821static _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
822{
823 assert(0); // TODO: Test this code.
824
825 DWORD dwNameLen = 0, dwRefDomainLen = 0;
826
827 if (LookupAccountSidA(lpSystemName, lpSid,
828 NULL, &dwNameLen ,
829 NULL, &dwRefDomainLen,
830 peUse))
831 {
832 // Name and domain is blank.
833 if (sName ) sName ->clear();
834 if (sReferencedDomainName) sReferencedDomainName->clear();
835 return TRUE;
836 } else if (GetLastError() == ERROR_MORE_DATA) {
837 // Allocate on heap and retry.
838 std::unique_ptr<char[]> bufName (new char[dwNameLen ]);
839 std::unique_ptr<char[]> bufRefDomain(new char[dwRefDomainLen]);
840 if (LookupAccountSidA(lpSystemName, lpSid,
841 bufName .get(), &dwNameLen ,
842 bufRefDomain.get(), &dwRefDomainLen,
843 peUse))
844 {
845 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
846 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
847 return TRUE;
848 }
849 }
850
851 return FALSE;
852}
853
859template<class _Traits, class _Ax>
860static _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
861{
862 assert(0); // TODO: Test this code.
863
864 DWORD dwNameLen = 0, dwRefDomainLen = 0;
865
866 if (LookupAccountSidW(lpSystemName, lpSid,
867 NULL, &dwNameLen ,
868 NULL, &dwRefDomainLen,
869 peUse))
870 {
871 // Name and domain is blank.
872 if (sName ) sName ->clear();
873 if (sReferencedDomainName) sReferencedDomainName->clear();
874 return TRUE;
875 } else if (GetLastError() == ERROR_MORE_DATA) {
876 // Allocate on heap and retry.
877 std::unique_ptr<wchar_t[]> bufName (new wchar_t[dwNameLen ]);
878 std::unique_ptr<wchar_t[]> bufRefDomain(new wchar_t[dwRefDomainLen]);
879 if (LookupAccountSidW(lpSystemName, lpSid,
880 bufName .get(), &dwNameLen ,
881 bufRefDomain.get(), &dwRefDomainLen,
882 peUse))
883 {
884 if (sName ) sName ->assign(bufName .get(), dwNameLen - 1);
885 if (sReferencedDomainName) sReferencedDomainName->assign(bufRefDomain.get(), dwRefDomainLen - 1);
886 return TRUE;
887 }
888 }
889
890 return FALSE;
891}
892
898static _Success_(return != FALSE) BOOL CreateWellKnownSid(_In_ WELL_KNOWN_SID_TYPE WellKnownSidType, _In_opt_ PSID DomainSid, _Inout_ std::unique_ptr<SID> &Sid)
899{
900 BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES];
901 DWORD dwSize = sizeof(szStackBuffer);
902
903 if (CreateWellKnownSid(WellKnownSidType, DomainSid, szStackBuffer, &dwSize)) {
904 // The stack buffer was big enough to retrieve complete data. Alloc and copy.
905 Sid.reset((SID*)new BYTE[dwSize]);
906 memcpy(Sid.get(), szStackBuffer, dwSize);
907 return TRUE;
908 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
909 // The stack buffer was too small to retrieve complete data. Alloc and retry.
910 Sid.reset((SID*)new BYTE[dwSize]);
911 return CreateWellKnownSid(WellKnownSidType, DomainSid, Sid.get(), &dwSize);
912 } else
913 return FALSE;
914}
915
921template<class _Ty>
922static _Success_(return != 0) BOOL GetTokenInformation(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_ std::unique_ptr<_Ty> &TokenInformation) noexcept
923{
924 BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES];
925 DWORD dwSize;
926
927 if (GetTokenInformation(TokenHandle, TokenInformationClass, szStackBuffer, sizeof(szStackBuffer), &dwSize)) {
928 // The stack buffer was big enough to retrieve complete data. Alloc and copy.
929 TokenInformation.reset((_Ty*)(new BYTE[dwSize]));
930 memcpy(TokenInformation.get(), szStackBuffer, dwSize);
931 return TRUE;
932 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
933 // The stack buffer was too small to retrieve complete data. Alloc and retry.
934 TokenInformation.reset((_Ty*)(new BYTE[dwSize]));
935 return GetTokenInformation(TokenHandle, TokenInformationClass, TokenInformation.get(), dwSize, &dwSize);
936 } else
937 return FALSE;
938}
939
945template<class _Traits, class _Ax>
946static _Success_(return != 0) BOOL QueryFullProcessImageNameA(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<char, _Traits, _Ax>& sExeName)
947{
948 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(char)];
949 DWORD dwSize = _countof(szStackBuffer);
950
951 // Try with stack buffer first.
952 if (::QueryFullProcessImageNameA(hProcess, dwFlags, szStackBuffer, &dwSize)) {
953 // Copy from stack.
954 sExeName.assign(szStackBuffer, dwSize);
955 return TRUE;
956 }
957 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(char); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
958 // Allocate on heap and retry.
959 sExeName.resize(dwCapacity - 1);
960 dwSize = dwCapacity;
961 if (::QueryFullProcessImageNameA(hProcess, dwFlags, &sExeName[0], &dwSize)) {
962 sExeName.resize(dwSize);
963 return TRUE;
964 }
965 }
966 return FALSE;
967}
968
974template<class _Traits, class _Ax>
975static _Success_(return != 0) BOOL QueryFullProcessImageNameW(_In_ HANDLE hProcess, _In_ DWORD dwFlags, _Inout_ std::basic_string<wchar_t, _Traits, _Ax>& sExeName)
976{
977 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t)];
978 DWORD dwSize = _countof(szStackBuffer);
979
980 // Try with stack buffer first.
981 if (::QueryFullProcessImageNameW(hProcess, dwFlags, szStackBuffer, &dwSize)) {
982 // Copy from stack.
983 sExeName.assign(szStackBuffer, dwSize);
984 return TRUE;
985 }
986 for (DWORD dwCapacity = 2 * WINSTD_STACK_BUFFER_BYTES / sizeof(wchar_t); GetLastError() == ERROR_INSUFFICIENT_BUFFER; dwCapacity *= 2) {
987 // Allocate on heap and retry.
988 sExeName.resize(dwCapacity - 1);
989 dwSize = dwCapacity;
990 if (::QueryFullProcessImageNameW(hProcess, dwFlags, &sExeName[0], &dwSize)) {
991 sExeName.resize(dwSize);
992 return TRUE;
993 }
994 }
995 return FALSE;
996}
997
999
1000#pragma warning(pop)
1001
1002namespace winstd
1003{
1006
1010 template<HANDLE INVALID>
1011 class win_handle : public handle<HANDLE, INVALID>
1012 {
1013 WINSTD_HANDLE_IMPL(win_handle, HANDLE, INVALID)
1014
1015 public:
1021 virtual ~win_handle()
1022 {
1023 if (m_h != invalid)
1024 free_internal();
1025 }
1026
1027 protected:
1033 void free_internal() noexcept override
1034 {
1035 CloseHandle(m_h);
1036 }
1037 };
1038
1044 class library : public handle<HMODULE, NULL>
1045 {
1046 WINSTD_HANDLE_IMPL(library, HMODULE, NULL)
1047
1048 public:
1054 virtual ~library()
1055 {
1056 if (m_h != invalid)
1057 free_internal();
1058 }
1059
1060 protected:
1066 void free_internal() noexcept override
1067 {
1068 FreeLibrary(m_h);
1069 }
1070 };
1071
1078
1085
1092
1099
1104 {
1107
1108 public:
1117 mutex_locker(_In_ HANDLE hMutex, _In_ DWORD dwMilliseconds = INFINITE) : m_h(hMutex)
1118 {
1119 switch (WaitForSingleObject(m_h, dwMilliseconds)) {
1120 case WAIT_OBJECT_0:
1121 case WAIT_ABANDONED:
1122 return;
1123 case WAIT_TIMEOUT:
1124 throw std::runtime_error("timeout");
1125 case WAIT_FAILED:
1126 throw win_runtime_error("WaitForSingleObject failed");
1127 }
1128 }
1129
1136 {
1137 ReleaseMutex(m_h);
1138 }
1139
1140 protected:
1141 HANDLE m_h;
1142 };
1143
1151
1158
1163 {
1167 void operator()(void* _Ptr) const
1168 {
1169 if (!UnmapViewOfFile(_Ptr))
1170 throw win_runtime_error("UnmapViewOfFile failed");
1171 }
1172 };
1173
1181
1186 {
1189
1190 public:
1197 {
1198 InitializeCriticalSection(&m_data);
1199 }
1200
1207 {
1208 DeleteCriticalSection(&m_data);
1209 }
1210
1216 operator LPCRITICAL_SECTION() noexcept
1217 {
1218 return &m_data;
1219 }
1220
1221 protected:
1222 CRITICAL_SECTION m_data;
1223 };
1224
1230 class find_file : public handle<HANDLE, INVALID_HANDLE_VALUE>
1231 {
1232 WINSTD_HANDLE_IMPL(find_file, HANDLE, INVALID_HANDLE_VALUE)
1233
1234 public:
1240 virtual ~find_file()
1241 {
1242 if (m_h != invalid)
1243 free_internal();
1244 }
1245
1246 protected:
1252 void free_internal() noexcept override
1253 {
1254 FindClose(m_h);
1255 }
1256 };
1257
1263 class heap : public handle<HANDLE, NULL>
1264 {
1265 WINSTD_HANDLE_IMPL(heap, HANDLE, NULL)
1266
1267 public:
1273 virtual ~heap()
1274 {
1275 if (m_h != invalid)
1276 free_internal();
1277 }
1278
1286 bool enumerate() noexcept
1287 {
1288 assert(m_h != invalid);
1289
1290 bool found = false;
1291
1292 // Lock the heap for exclusive access.
1293 HeapLock(m_h);
1294
1295 PROCESS_HEAP_ENTRY e;
1296 e.lpData = NULL;
1297 while (HeapWalk(m_h, &e) != FALSE) {
1298 if ((e.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
1300 _T("Allocated block%s%s\n")
1301 _T(" Data portion begins at: %#p\n Size: %d bytes\n")
1302 _T(" Overhead: %d bytes\n Region index: %d\n"),
1303 (e.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0 ? tstring_printf(_T(", movable with HANDLE %#p"), e.Block.hMem).c_str() : _T(""),
1304 (e.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0 ? _T(", DDESHARE") : _T(""),
1305 e.lpData,
1306 e.cbData,
1307 e.cbOverhead,
1308 e.iRegionIndex);
1309
1310 found = true;
1311 }
1312 }
1313
1314 const DWORD dwResult = GetLastError();
1315 if (dwResult != ERROR_NO_MORE_ITEMS)
1316 OutputDebugStr(_T("HeapWalk failed (error %u).\n"), dwResult);
1317
1318 // Unlock the heap.
1319 HeapUnlock(m_h);
1320
1321 return found;
1322 }
1323
1324 protected:
1330 void free_internal() noexcept override
1331 {
1332 enumerate();
1333 HeapDestroy(m_h);
1334 }
1335 };
1336
1340 template <class _Ty>
1342 {
1343 public:
1344 typedef typename _Ty value_type;
1345
1346 typedef _Ty *pointer;
1347 typedef _Ty& reference;
1348 typedef const _Ty *const_pointer;
1349 typedef const _Ty& const_reference;
1350
1351 typedef SIZE_T size_type;
1352 typedef ptrdiff_t difference_type;
1353
1357 template <class _Other>
1358 struct rebind
1359 {
1361 };
1362
1363 public:
1370 {}
1371
1377 template <class _Other>
1379 {}
1380
1389 {
1390 assert(m_heap);
1391 return (pointer)HeapAlloc(m_heap, 0, count * sizeof(_Ty));
1392 }
1393
1400 void deallocate(_In_ pointer ptr, _In_ size_type size)
1401 {
1402 UNREFERENCED_PARAMETER(size);
1403 assert(m_heap);
1404 HeapFree(m_heap, 0, ptr);
1405 }
1406
1413 void construct(_Inout_ pointer ptr, _In_ const _Ty& val)
1414 {
1415 ::new ((void*)ptr) _Ty(val);
1416 }
1417
1424 void construct(_Inout_ pointer ptr, _Inout_ _Ty&& val)
1425 {
1426 ::new ((void*)ptr) _Ty(std::forward<_Ty>(val));
1427 }
1428
1434 void destroy(_Inout_ pointer ptr)
1435 {
1436 ptr->_Ty::~_Ty();
1437 }
1438
1443 {
1444 return (SIZE_T)-1;
1445 }
1446
1447 public:
1448 HANDLE m_heap;
1449 };
1450
1455 {
1458
1459 public:
1467 actctx_activator(_In_ HANDLE hActCtx) noexcept
1468 {
1469 if (!ActivateActCtx(hActCtx, &m_cookie))
1470 m_cookie = 0;
1471 }
1472
1479 {
1480 if (m_cookie)
1481 DeactivateActCtx(0, m_cookie);
1482 }
1483
1484 protected:
1485 ULONG_PTR m_cookie;
1486 };
1487
1492 {
1493 public:
1497 impersonator() noexcept : m_cookie(FALSE) {}
1498
1505 {
1506 if (m_cookie)
1507 RevertToSelf();
1508 }
1509
1513 operator bool () const { return m_cookie; }
1514
1515 protected:
1517 };
1518
1523 {
1526
1527 public:
1535 user_impersonator(_In_opt_ HANDLE hToken) noexcept
1536 {
1537 m_cookie = hToken && ImpersonateLoggedOnUser(hToken);
1538 }
1539 };
1540
1545 {
1548
1549 public:
1554 {
1555 TOKEN_PRIVILEGES privileges = { 1, {{{ 0, 0 }, SE_PRIVILEGE_ENABLED }} };
1556 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid) ||
1557 !ImpersonateSelf(SecurityImpersonation))
1558 return;
1559
1560 {
1561 HANDLE h;
1562 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &h))
1563 goto revert;
1564 win_handle<INVALID_HANDLE_VALUE> thread_token(h);
1565 if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL))
1566 goto revert;
1567 process_snapshot process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1568 if (!process_snapshot)
1569 goto revert;
1570 PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32) };
1571 if (!Process32First(process_snapshot, &entry))
1572 goto revert;
1573 while (_tcsicmp(entry.szExeFile, TEXT("winlogon.exe")) != 0)
1574 if (!Process32Next(process_snapshot, &entry))
1575 goto revert;
1576 process winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
1577 if (!winlogon_process)
1578 goto revert;
1579 if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &h))
1580 goto revert;
1581 win_handle<INVALID_HANDLE_VALUE> winlogon_token(h);
1582 if (!DuplicateToken(winlogon_token, SecurityImpersonation, &h))
1583 goto revert;
1584 win_handle<INVALID_HANDLE_VALUE> duplicated_token(h);
1585 if (!SetThreadToken(NULL, duplicated_token))
1586 goto revert;
1587 }
1588
1589 m_cookie = TRUE;
1590 return;
1591
1592 revert:
1593 last_error_saver last_error_save;
1594 RevertToSelf();
1595 }
1596 };
1597
1602 {
1603 public:
1609 clipboard_opener(_In_opt_ HWND hWndNewOwner = NULL)
1610 {
1611 if (!OpenClipboard(hWndNewOwner))
1612 throw win_runtime_error("OpenClipboard failed");
1613 }
1614
1621 {
1622 CloseClipboard();
1623 }
1624 };
1625
1630 {
1633
1634 public:
1642 console_ctrl_handler(_In_opt_ PHANDLER_ROUTINE HandlerRoutine) noexcept : m_handler(HandlerRoutine)
1643 {
1644 m_cookie = SetConsoleCtrlHandler(m_handler, TRUE);
1645 }
1646
1653 {
1654 if (m_cookie)
1655 SetConsoleCtrlHandler(m_handler, FALSE);
1656 }
1657
1658 protected:
1660 PHANDLER_ROUTINE m_handler;
1661 };
1662
1666 class vmemory : public handle<LPVOID, NULL>
1667 {
1669
1670 public:
1674 vmemory() noexcept : m_proc(NULL)
1675 {}
1676
1683 vmemory(_In_ handle_type h, _In_ HANDLE proc) noexcept :
1684 m_proc(proc),
1686 {}
1687
1693 vmemory(_Inout_ vmemory &&h) noexcept :
1694 m_proc(std::move(h.m_proc)),
1695 handle<LPVOID, NULL>(std::move(h))
1696 {}
1697
1703 virtual ~vmemory()
1704 {
1705 if (m_h != invalid)
1706 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
1707 }
1708
1714 vmemory& operator=(_Inout_ vmemory &&other) noexcept
1715 {
1716 if (this != std::addressof(other)) {
1717 (handle<handle_type, NULL>&&)*this = std::move(other);
1718 m_proc = std::move(other.m_proc);
1719 }
1720 return *this;
1721 }
1722
1731 void attach(_In_ HANDLE proc, _In_opt_ handle_type h) noexcept
1732 {
1733 m_proc = proc;
1734 if (m_h != invalid)
1735 free_internal();
1736 m_h = h;
1737 }
1738
1748 bool alloc(
1749 _In_ HANDLE hProcess,
1750 _In_opt_ LPVOID lpAddress,
1751 _In_ SIZE_T dwSize,
1752 _In_ DWORD flAllocationType,
1753 _In_ DWORD flProtect) noexcept
1754 {
1755 handle_type h = VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect);
1756 if (h != invalid) {
1757 attach(hProcess, h);
1758 return true;
1759 } else
1760 return false;
1761 }
1762
1763 protected:
1769 void free_internal() noexcept override
1770 {
1771 VirtualFreeEx(m_proc, m_h, 0, MEM_RELEASE);
1772 }
1773
1774 protected:
1775 HANDLE m_proc;
1776 };
1777
1784 class reg_key : public handle<HKEY, NULL>
1785 {
1786 WINSTD_HANDLE_IMPL(reg_key, HKEY, NULL)
1787
1788 public:
1794 virtual ~reg_key()
1795 {
1796 if (m_h != invalid)
1797 free_internal();
1798 }
1799
1809 bool delete_subkey(_In_z_ LPCTSTR szSubkey)
1810 {
1811 LSTATUS s;
1812
1813 s = RegDeleteKey(m_h, szSubkey);
1814 if (s == ERROR_SUCCESS || s == ERROR_FILE_NOT_FOUND)
1815 return true;
1816
1817 {
1818 reg_key k;
1819 handle_type h;
1820 s = RegOpenKeyEx(m_h, szSubkey, 0, KEY_ENUMERATE_SUB_KEYS, &h);
1821 if (s == ERROR_SUCCESS)
1822 k.attach(h);
1823 else {
1824 SetLastError(s);
1825 return false;
1826 }
1827 for (;;) {
1828 TCHAR szName[MAX_PATH];
1829 DWORD dwSize = _countof(szName);
1830 s = RegEnumKeyEx(k, 0, szName, &dwSize, NULL, NULL, NULL, NULL);
1831 if (s == ERROR_SUCCESS)
1832 k.delete_subkey(szName);
1833 else if (s == ERROR_NO_MORE_ITEMS)
1834 break;
1835 else {
1836 SetLastError(s);
1837 return false;
1838 }
1839 }
1840 }
1841
1842 s = RegDeleteKey(m_h, szSubkey);
1843 if (s == ERROR_SUCCESS)
1844 return true;
1845 else {
1846 SetLastError(s);
1847 return false;
1848 }
1849 }
1850
1851 protected:
1857 void free_internal() noexcept override
1858 {
1859 RegCloseKey(m_h);
1860 }
1861 };
1862
1866 class security_id : public handle<PSID, NULL>
1867 {
1868 WINSTD_HANDLE_IMPL(security_id, PSID, NULL)
1869
1870 public:
1877 {
1878 if (m_h != invalid)
1879 free_internal();
1880 }
1881
1882 protected:
1888 void free_internal() noexcept override
1889 {
1890 FreeSid(m_h);
1891 }
1892 };
1893
1897 class process_information : public PROCESS_INFORMATION
1898 {
1901
1902 public:
1907 {
1908 hProcess = INVALID_HANDLE_VALUE;
1909 hThread = INVALID_HANDLE_VALUE;
1910 dwProcessId = 0;
1911 dwThreadId = 0;
1912 }
1913
1918 {
1919 #pragma warning(push)
1920 #pragma warning(disable: 6001) // Using uninitialized memory '*this'. << ???
1921
1922 if (hProcess != INVALID_HANDLE_VALUE)
1923 CloseHandle(hProcess);
1924
1925 if (hThread != INVALID_HANDLE_VALUE)
1926 CloseHandle(hThread);
1927
1928 #pragma warning(pop)
1929 }
1930 };
1931
1937 class event_log : public handle<HANDLE, NULL>
1938 {
1939 WINSTD_HANDLE_IMPL(event_log, HANDLE, NULL)
1940
1941 public:
1947 virtual ~event_log()
1948 {
1949 if (m_h != invalid)
1950 free_internal();
1951 }
1952
1953 protected:
1959 void free_internal() noexcept override
1960 {
1961 DeregisterEventSource(m_h);
1962 }
1963 };
1964
1968 class sc_handle : public handle<SC_HANDLE, NULL>
1969 {
1970 WINSTD_HANDLE_IMPL(sc_handle, SC_HANDLE, NULL)
1971
1972 public:
1978 virtual ~sc_handle()
1979 {
1980 if (m_h != invalid)
1981 free_internal();
1982 }
1983
1984 protected:
1990 void free_internal() noexcept override
1991 {
1992 CloseServiceHandle(m_h);
1993 }
1994 };
1995
1997}
1998
2001
2002#pragma warning(push)
2003#pragma warning(disable: 4505) // Don't warn on unused code
2004
2006static LSTATUS RegCreateKeyExA(
2007 _In_ HKEY hKey,
2008 _In_ LPCSTR lpSubKey,
2009 _Reserved_ DWORD Reserved,
2010 _In_opt_ LPSTR lpClass,
2011 _In_ DWORD dwOptions,
2012 _In_ REGSAM samDesired,
2013 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2014 _Inout_ winstd::reg_key &result,
2015 _Out_opt_ LPDWORD lpdwDisposition)
2016{
2017 HKEY h;
2018 LSTATUS s = RegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2019 if (s == ERROR_SUCCESS)
2020 result.attach(h);
2021 return s;
2022}
2023
2029static LSTATUS RegCreateKeyExW(
2030 _In_ HKEY hKey,
2031 _In_ LPCWSTR lpSubKey,
2032 _Reserved_ DWORD Reserved,
2033 _In_opt_ LPWSTR lpClass,
2034 _In_ DWORD dwOptions,
2035 _In_ REGSAM samDesired,
2036 _In_opt_ CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
2037 _Inout_ winstd::reg_key &result,
2038 _Out_opt_ LPDWORD lpdwDisposition)
2039{
2040 HKEY h;
2041 LSTATUS s = RegCreateKeyExW(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, &h, lpdwDisposition);
2042 if (s == ERROR_SUCCESS)
2043 result.attach(h);
2044 return s;
2045}
2046
2048static LSTATUS RegOpenKeyExA(
2049 _In_ HKEY hKey,
2050 _In_opt_ LPCSTR lpSubKey,
2051 _In_opt_ DWORD ulOptions,
2052 _In_ REGSAM samDesired,
2053 _Inout_ winstd::reg_key &result)
2054{
2055 HKEY h;
2056 LSTATUS s = RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, &h);
2057 if (s == ERROR_SUCCESS)
2058 result.attach(h);
2059 return s;
2060}
2061
2067static LSTATUS RegOpenKeyExW(
2068 _In_ HKEY hKey,
2069 _In_opt_ LPCWSTR lpSubKey,
2070 _In_opt_ DWORD ulOptions,
2071 _In_ REGSAM samDesired,
2072 _Inout_ winstd::reg_key &result)
2073{
2074 HKEY h;
2075 LSTATUS s = RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, &h);
2076 if (s == ERROR_SUCCESS)
2077 result.attach(h);
2078 return s;
2079}
2080
2086static BOOL OpenProcessToken(_In_ HANDLE ProcessHandle, _In_ DWORD DesiredAccess, _Inout_ winstd::win_handle<NULL> &TokenHandle)
2087{
2088 HANDLE h;
2089 if (OpenProcessToken(ProcessHandle, DesiredAccess, &h)) {
2090 TokenHandle.attach(h);
2091 return TRUE;
2092 }
2093 return FALSE;
2094}
2095
2101static 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)
2102{
2103 HANDLE h;
2104 if (DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, &h)) {
2105 NewToken.attach(h);
2106 return TRUE;
2107 }
2108 return FALSE;
2109}
2110
2116static 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)
2117{
2118 PSID h;
2119 if (AllocateAndInitializeSid(pIdentifierAuthority, nSubAuthorityCount, nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3, nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, &h)) {
2120 Sid.attach(h);
2121 return TRUE;
2122 }
2123 return FALSE;
2124}
2125
2127static 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)
2128{
2129 PACL h;
2130 DWORD dwResult = SetEntriesInAclA(cCountOfExplicitEntries, pListOfExplicitEntries, OldAcl, &h);
2131 if (dwResult == ERROR_SUCCESS)
2132 Acl.reset(h);
2133 return ERROR_SUCCESS;
2134}
2135
2141static 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)
2142{
2143 PACL h;
2144 DWORD dwResult = SetEntriesInAclW(cCountOfExplicitEntries, pListOfExplicitEntries, OldAcl, &h);
2145 if (dwResult == ERROR_SUCCESS)
2146 Acl.reset(h);
2147 return ERROR_SUCCESS;
2148}
2149
2155template<class _Traits, class _Ax>
2156_Success_(return != 0) BOOL GetThreadPreferredUILanguages(_In_ DWORD dwFlags, _Out_ PULONG pulNumLanguages, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
2157{
2158 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
2159 ULONG ulSize = _countof(szStackBuffer);
2160
2161 // Try with stack buffer first.
2162 if (GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, szStackBuffer, &ulSize)) {
2163 // Copy from stack.
2164 sValue.assign(szStackBuffer, ulSize - 1);
2165 return TRUE;
2166 } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
2167 // Query required size.
2168 ulSize = 0;
2169 GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, NULL, &ulSize);
2170 // Allocate on heap and retry.
2171 sValue.resize(ulSize - 1);
2172 if (GetThreadPreferredUILanguages(dwFlags, pulNumLanguages, &sValue[0], &ulSize))
2173 return TRUE;
2174 }
2175 return FALSE;
2176}
2177
2178#pragma warning(pop)
2179
Activates given activation context in constructor and deactivates it in destructor.
Definition Win.h:1455
actctx_activator(HANDLE hActCtx) noexcept
Construct the activator and activates the given activation context.
Definition Win.h:1467
virtual ~actctx_activator()
Deactivates activation context and destructs the activator.
Definition Win.h:1478
ULONG_PTR m_cookie
Cookie for context deactivation.
Definition Win.h:1485
Base template class to support string formatting using printf() style templates.
Definition Common.h:1485
Clipboard management.
Definition Win.h:1602
virtual ~clipboard_opener()
Closes the clipboard.
Definition Win.h:1620
clipboard_opener(HWND hWndNewOwner=NULL)
Opens the clipboard for examination and prevents other applications from modifying the clipboard cont...
Definition Win.h:1609
Console control handler stack management.
Definition Win.h:1630
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:1642
virtual ~console_ctrl_handler()
Pops console control handler from the console control handler stack.
Definition Win.h:1652
PHANDLER_ROUTINE m_handler
Pointer to console control handler.
Definition Win.h:1660
BOOL m_cookie
Did pushing the console control handler succeed?
Definition Win.h:1659
Critical section wrapper.
Definition Win.h:1186
critical_section() noexcept
Construct the object and initializes a critical section object.
Definition Win.h:1196
CRITICAL_SECTION m_data
Critical section struct.
Definition Win.h:1222
virtual ~critical_section()
Releases all resources used by an unowned critical section object.
Definition Win.h:1206
Event log handle wrapper.
Definition Win.h:1938
void free_internal() noexcept override
Closes an event log handle.
Definition Win.h:1959
virtual ~event_log()
Closes an event log handle.
Definition Win.h:1947
Find-file handle wrapper.
Definition Win.h:1231
virtual ~find_file()
Closes a file search handle.
Definition Win.h:1240
void free_internal() noexcept override
Closes a file search handle.
Definition Win.h:1252
Base abstract template class to support generic object handle keeping.
Definition Common.h:874
handle_type m_h
Definition Common.h:1126
void attach(handle_type h) noexcept
Sets a new object handle for the class.
Definition Common.h:1089
LPVOID handle_type
Definition Common.h:879
HeapAlloc allocator.
Definition Win.h:1342
_Ty value_type
A type that is managed by the allocator.
Definition Win.h:1344
heap_allocator(const heap_allocator< _Other > &other)
Constructs allocator from another type.
Definition Win.h:1378
_Ty * pointer
A type that provides a pointer to the type of object managed by the allocator.
Definition Win.h:1346
const _Ty * const_pointer
A type that provides a constant pointer to the type of object managed by the allocator.
Definition Win.h:1348
HANDLE m_heap
Heap handle.
Definition Win.h:1448
pointer allocate(size_type count)
Allocates a new memory block.
Definition Win.h:1388
_Ty & reference
A type that provides a reference to the type of object managed by the allocator.
Definition Win.h:1347
heap_allocator(HANDLE heap)
Constructs allocator.
Definition Win.h:1369
void construct(pointer ptr, _Ty &&val)
Calls moving constructor for the element.
Definition Win.h:1424
void deallocate(pointer ptr, size_type size)
Frees memory block.
Definition Win.h:1400
size_type max_size() const
Returns maximum memory block size.
Definition Win.h:1442
void construct(pointer ptr, const _Ty &val)
Calls copying constructor for the element.
Definition Win.h:1413
const _Ty & const_reference
A type that provides a constant reference to type of object managed by the allocator.
Definition Win.h:1349
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:1351
void destroy(pointer ptr)
Calls destructor for the element.
Definition Win.h:1434
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:1352
Heap handle wrapper.
Definition Win.h:1264
bool enumerate() noexcept
Enumerates allocated heap blocks using OutputDebugString()
Definition Win.h:1286
void free_internal() noexcept override
Destroys the heap.
Definition Win.h:1330
virtual ~heap()
Destroys the heap.
Definition Win.h:1273
Base class for thread impersonation of another security context.
Definition Win.h:1492
virtual ~impersonator()
Reverts to current user and destructs the impersonator.
Definition Win.h:1504
impersonator() noexcept
Construct the impersonator.
Definition Win.h:1497
BOOL m_cookie
Did impersonation succeed?
Definition Win.h:1516
Saves GetLastError and restores SetLastError when going out of scope.
Definition Common.h:1374
Module handle wrapper.
Definition Win.h:1045
void free_internal() noexcept override
Frees the module.
Definition Win.h:1066
virtual ~library()
Frees the module.
Definition Win.h:1054
Locks given mutex in constructor and releases it in destructor.
Definition Win.h:1104
virtual ~mutex_locker()
Releases ownership of the mutex object.
Definition Win.h:1135
mutex_locker(HANDLE hMutex, DWORD dwMilliseconds=INFINITE)
Waits until the specified mutex is in the signaled state or the time-out interval elapses.
Definition Win.h:1117
PROCESS_INFORMATION struct wrapper.
Definition Win.h:1898
~process_information()
Closes process and thread handles.
Definition Win.h:1917
process_information() noexcept
Constructs blank PROCESS_INFORMATION.
Definition Win.h:1906
Registry key wrapper class.
Definition Win.h:1785
void free_internal() noexcept override
Closes a handle to the registry key.
Definition Win.h:1857
bool delete_subkey(LPCTSTR szSubkey)
Deletes the specified registry subkey.
Definition Win.h:1809
virtual ~reg_key()
Closes a handle to the registry key.
Definition Win.h:1794
SC_HANDLE wrapper class.
Definition Win.h:1969
void free_internal() noexcept override
Closes an open object handle.
Definition Win.h:1990
virtual ~sc_handle()
Closes an open object handle.
Definition Win.h:1978
SID wrapper class.
Definition Win.h:1867
void free_internal() noexcept override
Closes a handle to the SID.
Definition Win.h:1888
virtual ~security_id()
Closes a handle to the SID.
Definition Win.h:1876
Lets the calling thread impersonate the security context of the SYSTEM user.
Definition Win.h:1545
system_impersonator() noexcept
Construct the impersonator and impersonates the SYSTEM user.
Definition Win.h:1553
Lets the calling thread impersonate the security context of a logged-on user.
Definition Win.h:1523
user_impersonator(HANDLE hToken) noexcept
Construct the impersonator and impersonates the given user.
Definition Win.h:1535
Memory in virtual address space of a process handle wrapper.
Definition Win.h:1667
vmemory & operator=(vmemory &&other) noexcept
Move assignment.
Definition Win.h:1714
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:1748
void free_internal() noexcept override
Frees the memory.
Definition Win.h:1769
void attach(HANDLE proc, handle_type h) noexcept
Sets a new memory handle for the class.
Definition Win.h:1731
virtual ~vmemory()
Frees the memory.
Definition Win.h:1703
vmemory(handle_type h, HANDLE proc) noexcept
Initializes a new class instance with an already available object handle.
Definition Win.h:1683
vmemory() noexcept
Initializes a new class instance with the memory handle set to INVAL.
Definition Win.h:1674
vmemory(vmemory &&h) noexcept
Move constructor.
Definition Win.h:1693
HANDLE m_proc
Handle of memory's process.
Definition Win.h:1775
Windows HANDLE wrapper class.
Definition Win.h:1012
void free_internal() noexcept override
Closes an open object handle.
Definition Win.h:1033
virtual ~win_handle()
Closes an open object handle.
Definition Win.h:1021
Windows runtime error.
Definition Common.h:1403
#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 sprintf(std::basic_string< _Elem, _Traits, _Ax > &str, const _Elem *format,...)
Formats string using printf().
Definition Common.h:333
static int vsprintf(std::basic_string< char, _Traits, _Ax > &str, const char *format, va_list arg)
Formats string using printf().
Definition Common.h:256
#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
Definition Common.h:884
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:627
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:192
static BOOL StringToGuidA(LPCSTR lpszGuid, LPGUID lpGuid, LPCSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition Win.h:255
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:2029
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:707
win_handle< INVALID_HANDLE_VALUE > file
File handle wrapper.
Definition Win.h:1150
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:126
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:2006
static LSTATUS RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition Win.h:2048
static LSTATUS RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, winstd::reg_key &result)
Opens the specified registry key.
Definition Win.h:2067
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:216
static BOOL StringToGuidW(LPCWSTR lpszGuid, LPGUID lpGuid, LPCWSTR *lpszGuidEnd=NULL) noexcept
Parses string with GUID and stores it to GUID.
Definition Win.h:328
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:597
static BOOL OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, winstd::win_handle< NULL > &TokenHandle)
Opens the access token associated with a process.
Definition Win.h:2086
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:2141
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:821
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:860
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:2116
win_handle< INVALID_HANDLE_VALUE > process_snapshot
Process snapshot handle wrapper.
Definition Win.h:1091
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:807
static BOOL CreateWellKnownSid(WELL_KNOWN_SID_TYPE WellKnownSidType, PSID DomainSid, std::unique_ptr< SID > &Sid)
Creates a SID for predefined aliases.
Definition Win.h:898
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:725
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:922
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:2101
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:2127
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:558
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:146
win_handle< NULL > event
Event handle wrapper.
Definition Win.h:1180
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:583
static VOID OutputDebugStr(LPCSTR lpOutputString,...) noexcept
Formats and sends a string to the debugger for display.
Definition Win.h:766
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:946
win_handle< NULL > mutex
Mutex handle wrapper.
Definition Win.h:1098
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:162
win_handle< NULL > file_mapping
File mapping.
Definition Win.h:1157
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:975
win_handle< NULL > process
Process handle wrapper.
Definition Win.h:1077
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:531
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:2156
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:416
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:106
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:789
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:235
static VOID OutputDebugStrV(LPCSTR lpOutputString, va_list arg) noexcept
Formats and sends a string to the debugger for display.
Definition Win.h:742
win_handle< NULL > thread
Thread handle wrapper.
Definition Win.h:1084
Deleter for unique_ptr using LocalFree.
Definition Common.h:739
Deleter for unique_ptr using UnmapViewOfFile.
Definition Win.h:1163
void operator()(void *_Ptr) const
Delete a pointer.
Definition Win.h:1167
A structure that enables an allocator for objects of one type to allocate storage for objects of anot...
Definition Win.h:1359
heap_allocator< _Other > other
Other allocator type.
Definition Win.h:1360