Discontinue forward declarations

They are pain to maintain. We'll use them only if really needed (cyclic
dependencies).

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2022-02-04 11:33:08 +01:00
parent e513782854
commit 921aa9f4e9
15 changed files with 1776 additions and 2543 deletions

View File

@ -4,36 +4,15 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
/// #pragma once
/// \defgroup WinStdCOM COM object management
/// Provides helper templates for Windows COM object manipulation
///
#include "Common.h" #include "Common.h"
#include <unknwn.h>
#include <string> #include <string>
namespace winstd namespace winstd
{ {
class com_runtime_error; /// \addtogroup WinStdExceptions
struct CoTaskMemFree_delete;
template <class T> class com_obj;
class bstr;
class variant;
class com_initializer;
}
#pragma once
#include <unknwn.h>
namespace winstd
{
///
/// \defgroup WinStdExceptions Exceptions
/// Additional exceptions
///
/// @{ /// @{
/// ///
@ -54,7 +33,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception /// Constructs an exception
/// ///
@ -67,7 +45,11 @@ namespace winstd
}; };
/// @} /// @}
/// \addtogroup WinStdCOM
///
/// \defgroup WinStdCOM COM object management
/// Provides helper templates for Windows COM object manipulation
///
/// @{ /// @{
/// ///
@ -111,7 +93,6 @@ namespace winstd
CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (LPVOID*)&m_h); CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (LPVOID*)&m_h);
} }
/// ///
/// Queries the object for another interface and creates new class with it /// Queries the object for another interface and creates new class with it
/// ///
@ -124,7 +105,6 @@ namespace winstd
other->QueryInterface(__uuidof(T), (void**)&m_h); other->QueryInterface(__uuidof(T), (void**)&m_h);
} }
/// ///
/// Queries the object for another interface and creates new class with it /// Queries the object for another interface and creates new class with it
/// ///
@ -136,7 +116,6 @@ namespace winstd
other->QueryInterface(__uuidof(T), (void**)&m_h); other->QueryInterface(__uuidof(T), (void**)&m_h);
} }
/// ///
/// Releases object /// Releases object
/// ///
@ -146,7 +125,6 @@ namespace winstd
free_internal(); free_internal();
} }
/// ///
/// Creates a new object /// Creates a new object
/// ///
@ -161,7 +139,6 @@ namespace winstd
return hr; return hr;
} }
/// ///
/// Queries the object for another interface /// Queries the object for another interface
/// ///
@ -175,7 +152,6 @@ namespace winstd
return m_h->QueryInterface(__uuidof(_Other), (void**)h); return m_h->QueryInterface(__uuidof(_Other), (void**)h);
} }
/// ///
/// Queries the object for another interface /// Queries the object for another interface
/// ///
@ -203,7 +179,6 @@ namespace winstd
m_h->Release(); m_h->Release();
} }
/// ///
/// Duplicates the object by incrementing the reference counter /// Duplicates the object by incrementing the reference counter
/// ///
@ -220,7 +195,6 @@ namespace winstd
} }
}; };
/// ///
/// BSTR string wrapper /// BSTR string wrapper
/// ///
@ -301,7 +275,6 @@ namespace winstd
} }
}; };
/// ///
/// VARIANT struct wrapper /// VARIANT struct wrapper
/// ///
@ -680,7 +653,6 @@ namespace winstd
return *this; return *this;
} }
/// ///
/// Copy from long long value /// Copy from long long value
/// ///
@ -1057,7 +1029,6 @@ namespace winstd
}; };
#pragma warning(pop) #pragma warning(pop)
/// ///
/// Context scope automatic COM (un)initialization /// Context scope automatic COM (un)initialization
/// ///
@ -1077,7 +1048,6 @@ namespace winstd
m_result = CoInitialize(pvReserved); m_result = CoInitialize(pvReserved);
} }
/// ///
/// Initializes the COM library for use by the calling thread, sets the thread's concurrency model, and creates a new apartment for the thread if one is required. /// Initializes the COM library for use by the calling thread, sets the thread's concurrency model, and creates a new apartment for the thread if one is required.
/// ///
@ -1088,7 +1058,6 @@ namespace winstd
m_result = CoInitializeEx(pvReserved, dwCoInit); m_result = CoInitializeEx(pvReserved, dwCoInit);
} }
/// ///
/// Uninitializes COM. /// Uninitializes COM.
/// ///
@ -1100,7 +1069,6 @@ namespace winstd
CoUninitialize(); CoUninitialize();
} }
/// ///
/// Return result of `CoInitialize()` call. /// Return result of `CoInitialize()` call.
/// ///

View File

@ -4,41 +4,23 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
/// #pragma once
/// \defgroup WinStdGeneral General
/// General API
///
/// \defgroup WinStdSysHandles System Handles
/// Simplifies work with object handles of various type
///
/// \defgroup WinStdExceptions Exceptions
/// Additional exceptions
///
/// \defgroup WinStdStrFormat String Formatting
/// Formatted string generation
///
/// \par Example
/// \code
/// // Please note the PCSTR typecasting invokes an operator to return
/// // pointer to formatted buffer rather than class reference itself.
/// cout << (PCSTR)(winstd::string_printf("%i is less than %i.\n", 1, 5));
/// \endcode
///
/// \defgroup WinStdMemSanitize Auto-sanitize Memory Management
/// Sanitizes memory before dismissed
///
#define _WINSOCKAPI_ // Prevent inclusion of winsock.h in windows.h. #define _WINSOCKAPI_ // Prevent inclusion of winsock.h in windows.h.
#include <Windows.h> #include <Windows.h>
#include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include <tchar.h>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <vector>
/// \addtogroup WinStdGeneral ///
/// \defgroup WinStdGeneral General
/// General API
///
/// @{ /// @{
/// ///
@ -81,10 +63,35 @@ private: \
C (_Inout_ C &&h) noexcept; \ C (_Inout_ C &&h) noexcept; \
C& operator=(_Inout_ C &&h) noexcept; C& operator=(_Inout_ C &&h) noexcept;
#ifndef WINSTD_STACK_BUFFER_BYTES
///
/// Size of the stack buffer in bytes used for initial system function call
///
/// Some system functions with variable length output data fail for
/// insufficient buffer sizes, and return an exact buffer length required.
/// The function helpers use a fixed size stack buffer first. If the stack
/// buffer really prooved sufficient, the helper allocates the exact length
/// output on heap and copies the data without calling the system function
/// again. Otherwise it allocates the exact length output on heap and retries.
///
/// \note
/// Decrease this value in case of stack overflow.
///
#define WINSTD_STACK_BUFFER_BYTES 1024
#endif
/// @} /// @}
/// \defgroup WinStdStrFormat String Formatting
/// \addtogroup WinStdStrFormat /// Formatted string generation
///
/// \par Example
/// \code
/// // Please note the PCSTR typecasting invokes an operator to return
/// // pointer to formatted buffer rather than class reference itself.
/// cout << (PCSTR)(winstd::string_printf("%i is less than %i.\n", 1, 5));
/// \endcode
///
/// @{ /// @{
/// ///
@ -119,8 +126,10 @@ private: \
/// @} /// @}
///
/// \addtogroup WinStdSysHandles /// \defgroup WinStdSysHandles System Handles
/// Simplifies work with object handles of various type
///
/// @{ /// @{
/// ///
@ -151,166 +160,21 @@ private:
/// @} /// @}
#ifndef _FormatMessage_format_string_ #ifndef _FormatMessage_format_string_
#define _FormatMessage_format_string_ _In_z_ #define _FormatMessage_format_string_ _In_z_
#endif #endif
#ifndef _LPCBYTE_DEFINED #ifndef _LPCBYTE_DEFINED
#define _LPCBYTE_DEFINED #define _LPCBYTE_DEFINED
typedef const BYTE *LPCBYTE; typedef const BYTE *LPCBYTE;
#endif #endif
#pragma warning(push)
namespace winstd // Do not use _vsnprintf_s/_vsnwprintf_s(), since it terminates string by force even when we explicitly want to write unterminated string.
{ // Threfore turn off compiler warning instead. ;)
/// \addtogroup WinStdStrFormat #pragma warning(disable: 4995)
/// @{ #pragma warning(disable: 4996)
#pragma warning(disable: 4505) // Don't warn on unused code
///
/// Multi-byte / Wide-character string (according to _UNICODE)
///
#ifdef _UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif
/// @}
template <class _Ty> struct LocalFree_delete;
template <class _Ty> struct LocalFree_delete<_Ty[]>;
template<class _Ty, class _Dx = std::default_delete<_Ty>> class ref_unique_ptr;
template<class _Ty, class _Dx> class ref_unique_ptr<_Ty[], _Dx>;
template <class T, T INVAL> class handle;
template <class T, T INVAL> class dplhandle;
template <class T> class vector_queue;
template <typename _Tn> class num_runtime_error;
class win_runtime_error;
/// \addtogroup WinStdGeneral
/// @{
///
/// Helper function template for returning pointers to std::unique_ptr
///
/// \param[inout] owner Original owner of the pointer
///
/// \returns A helper wrapper class to handle returning a reference to the pointer
///
template<class _Ty, class _Dx> ref_unique_ptr<_Ty, _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty, _Dx> &owner) noexcept;
///
/// Helper function template for returning pointers to std::unique_ptr
/// (specialization for arrays)
///
/// \param[inout] owner Original owner of the pointer
///
/// \returns A helper wrapper class to handle returning a reference to the pointer
///
template<class _Ty, class _Dx> ref_unique_ptr<_Ty[], _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty[], _Dx> &owner) noexcept;
/// @}
/// \addtogroup WinStdStrFormat
/// @{
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem> > class basic_string_printf;
///
/// Single-byte character implementation of a class to support string formatting using `printf()` style templates
///
typedef basic_string_printf<char, std::char_traits<char>, std::allocator<char> > string_printf;
///
/// Wide character implementation of a class to support string formatting using `printf()` style templates
///
typedef basic_string_printf<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > wstring_printf;
///
/// Multi-byte / Wide-character formatted string (according to _UNICODE)
///
#ifdef _UNICODE
typedef wstring_printf tstring_printf;
#else
typedef string_printf tstring_printf;
#endif
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem> > class basic_string_msg;
///
/// Single-byte character implementation of a class to support string formatting using `FormatMessage()` style templates
///
typedef basic_string_msg<char, std::char_traits<char>, std::allocator<char> > string_msg;
///
/// Wide character implementation of a class to support string formatting using `FormatMessage()` style templates
///
typedef basic_string_msg<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > wstring_msg;
///
/// Multi-byte / Wide-character formatted string (according to _UNICODE)
///
#ifdef _UNICODE
typedef wstring_msg tstring_msg;
#else
typedef string_msg tstring_msg;
#endif
template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem> > class basic_string_guid;
class string_guid;
class wstring_guid;
///
/// Multi-byte / Wide-character string GUID (according to _UNICODE)
///
#ifdef _UNICODE
typedef wstring_guid tstring_guid;
#else
typedef string_guid tstring_guid;
#endif
/// @}
/// \addtogroup WinStdMemSanitize
/// @{
template<class _Ty> class sanitizing_allocator;
template<size_t N> class sanitizing_blob;
///
/// A sanitizing variant of std::string
///
/// \note
/// `sanitizing_string` introduces a performance penalty. However, it provides an additional level of security.
/// Use for security sensitive data memory storage only.
///
typedef std::basic_string<char, std::char_traits<char>, sanitizing_allocator<char> > sanitizing_string;
///
/// A sanitizing variant of std::wstring
///
/// \note
/// `sanitizing_wstring` introduces a performance penalty. However, it provides an additional level of security.
/// Use for security sensitive data memory storage only.
///
typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, sanitizing_allocator<wchar_t> > sanitizing_wstring;
///
/// Multi-byte / Wide-character sanitizing string (according to _UNICODE)
///
#ifdef _UNICODE
typedef sanitizing_wstring sanitizing_tstring;
#else
typedef sanitizing_string sanitizing_tstring;
#endif
/// @}
}
/// \addtogroup WinStdStrFormat /// \addtogroup WinStdStrFormat
/// @{ /// @{
@ -326,7 +190,10 @@ namespace winstd
/// \returns Number of characters in result. /// \returns Number of characters in result.
/// ///
#if _MSC_VER <= 1600 #if _MSC_VER <= 1600
static int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const char *format, _In_ va_list arg); static int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const char *format, _In_ va_list arg)
{
return _vsnprintf(str, capacity, format, arg);
}
#endif #endif
/// ///
@ -339,7 +206,10 @@ static int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_
/// ///
/// \returns Number of characters in result. /// \returns Number of characters in result.
/// ///
static int vsnprintf(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const wchar_t *format, _In_ va_list arg) noexcept; static int vsnprintf(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const wchar_t *format, _In_ va_list arg) noexcept
{
return _vsnwprintf(str, capacity, format, arg);
}
/// ///
/// Formats string using `printf()`. /// Formats string using `printf()`.
@ -351,7 +221,29 @@ static int vsnprintf(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _
/// \returns Number of characters in result. /// \returns Number of characters in result.
/// ///
template<class _Elem, class _Traits, class _Ax> template<class _Elem, class _Traits, class _Ax>
static int vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, _In_ va_list arg); static int vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, _In_ va_list arg)
{
_Elem buf[WINSTD_STACK_BUFFER_BYTES/sizeof(_Elem)];
// Try with stack buffer first.
int count = vsnprintf(buf, _countof(buf) - 1, format, arg);
if (count >= 0) {
// Copy from stack.
str.assign(buf, count);
} else {
for (size_t capacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(_Elem);; capacity *= 2) {
// Allocate on heap and retry.
auto buf_dyn = std::make_unique<_Elem[]>(capacity);
count = vsnprintf(buf_dyn.get(), capacity - 1, format, arg);
if (count >= 0) {
str.assign(buf_dyn.get(), count);
break;
}
}
}
return count;
}
/// ///
/// Formats string using `printf()`. /// Formats string using `printf()`.
@ -362,7 +254,14 @@ static int vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_
/// \returns Number of characters in result. /// \returns Number of characters in result.
/// ///
template<class _Elem, class _Traits, class _Ax> template<class _Elem, class _Traits, class _Ax>
static int sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, ...); static int sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, ...)
{
va_list arg;
va_start(arg, format);
const int res = vsprintf(str, format, arg);
va_end(arg);
return res;
}
/// ///
/// Formats a message string. /// Formats a message string.
@ -370,7 +269,14 @@ static int sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _
/// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx) /// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Inout_ std::basic_string<char, _Traits, _Ax> &str, _In_opt_ va_list *Arguments); static DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Inout_ std::basic_string<char, _Traits, _Ax> &str, _In_opt_ va_list *Arguments)
{
std::unique_ptr<CHAR[], winstd::LocalFree_delete<CHAR[]> > lpBuffer;
DWORD dwResult = FormatMessageA(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER, lpSource, dwMessageId, dwLanguageId, reinterpret_cast<LPSTR>((LPSTR*)get_ptr(lpBuffer)), 0, Arguments);
if (dwResult)
str.assign(lpBuffer.get(), dwResult);
return dwResult;
}
/// ///
/// Formats a message string. /// Formats a message string.
@ -378,47 +284,33 @@ static DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ D
/// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx) /// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &str, _In_opt_ va_list *Arguments); static DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &str, _In_opt_ va_list *Arguments)
{
/// @} std::unique_ptr<WCHAR[], winstd::LocalFree_delete<WCHAR[]> > lpBuffer;
DWORD dwResult = FormatMessageW(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER, lpSource, dwMessageId, dwLanguageId, reinterpret_cast<LPWSTR>((LPWSTR*)get_ptr(lpBuffer)), 0, Arguments);
#pragma once if (dwResult)
str.assign(lpBuffer.get(), dwResult);
#include <assert.h> return dwResult;
#include <tchar.h> }
#include <memory>
#include <vector>
/// \addtogroup WinStdGeneral
/// @{
#ifndef WINSTD_STACK_BUFFER_BYTES
///
/// Size of the stack buffer in bytes used for initial system function call
///
/// Some system functions with variable length output data fail for
/// insufficient buffer sizes, and return an exact buffer length required.
/// The function helpers use a fixed size stack buffer first. If the stack
/// buffer really prooved sufficient, the helper allocates the exact length
/// output on heap and copies the data without calling the system function
/// again. Otherwise it allocates the exact length output on heap and retries.
///
/// \note
/// Decrease this value in case of stack overflow.
///
#define WINSTD_STACK_BUFFER_BYTES 1024
#endif
/// @} /// @}
#pragma warning(pop)
namespace winstd namespace winstd
{ {
/// \addtogroup WinStdGeneral /// \addtogroup WinStdGeneral
/// @{ /// @{
///
/// Multi-byte / Wide-character string (according to _UNICODE)
///
#ifdef _UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif
/// ///
/// Deleter for unique_ptr using LocalFree /// Deleter for unique_ptr using LocalFree
/// ///
@ -448,7 +340,6 @@ namespace winstd
} }
}; };
/// ///
/// Deleter for unique_ptr to array of unknown size using LocalFree /// Deleter for unique_ptr to array of unknown size using LocalFree
/// ///
@ -482,7 +373,6 @@ namespace winstd
} }
}; };
/// ///
/// Helper class for returning pointers to std::unique_ptr /// Helper class for returning pointers to std::unique_ptr
/// ///
@ -546,6 +436,32 @@ namespace winstd
_Ty *m_ptr; ///< Pointer _Ty *m_ptr; ///< Pointer
}; };
///
/// Helper function template for returning pointers to std::unique_ptr
///
/// \param[inout] owner Original owner of the pointer
///
/// \returns A helper wrapper class to handle returning a reference to the pointer
///
template<class _Ty, class _Dx>
ref_unique_ptr<_Ty, _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty, _Dx> &owner) noexcept
{
return ref_unique_ptr<_Ty, _Dx>(owner);
}
///
/// Helper function template for returning pointers to std::unique_ptr
/// (specialization for arrays)
///
/// \param[inout] owner Original owner of the pointer
///
/// \returns A helper wrapper class to handle returning a reference to the pointer
///
template<class _Ty, class _Dx>
ref_unique_ptr<_Ty[], _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty[], _Dx> &owner) noexcept
{
return ref_unique_ptr<_Ty[], _Dx>(owner);
}
/// ///
/// Helper class for returning pointers to std::unique_ptr /// Helper class for returning pointers to std::unique_ptr
@ -649,21 +565,8 @@ namespace winstd
}; };
#pragma warning(pop) #pragma warning(pop)
template<class _Ty, class _Dx>
ref_unique_ptr<_Ty, _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty, _Dx> &owner) noexcept
{
return ref_unique_ptr<_Ty, _Dx>(owner);
}
template<class _Ty, class _Dx>
ref_unique_ptr<_Ty[], _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty[], _Dx> &owner) noexcept
{
return ref_unique_ptr<_Ty[], _Dx>(owner);
}
/// @} /// @}
/// \addtogroup WinStdSysHandles /// \addtogroup WinStdSysHandles
/// @{ /// @{
@ -930,11 +833,9 @@ namespace winstd
handle_type m_h; ///< Object handle handle_type m_h; ///< Object handle
}; };
template <class T, const T INVAL> template <class T, const T INVAL>
const T handle<T, INVAL>::invalid = INVAL; const T handle<T, INVAL>::invalid = INVAL;
/// ///
/// Base abstract template class to support object handle keeping for objects that support handle duplication /// Base abstract template class to support object handle keeping for objects that support handle duplication
/// ///
@ -1475,7 +1376,10 @@ namespace winstd
/// @} /// @}
/// \addtogroup WinStdExceptions ///
/// \defgroup WinStdExceptions Exceptions
/// Additional exceptions
///
/// @{ /// @{
/// ///
@ -1500,7 +1404,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception /// Constructs an exception
/// ///
@ -1513,7 +1416,6 @@ namespace winstd
{ {
} }
/// ///
/// Returns the Windows error number /// Returns the Windows error number
/// ///
@ -1526,7 +1428,6 @@ namespace winstd
error_type m_num; ///< Numeric error code error_type m_num; ///< Numeric error code
}; };
/// ///
/// Windows runtime error /// Windows runtime error
/// ///
@ -1543,7 +1444,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception /// Constructs an exception
/// ///
@ -1554,7 +1454,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception using `GetLastError()` /// Constructs an exception using `GetLastError()`
/// ///
@ -1564,7 +1463,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception using `GetLastError()` /// Constructs an exception using `GetLastError()`
/// ///
@ -1574,7 +1472,6 @@ namespace winstd
{ {
} }
/// ///
/// Returns a user-readable Windows error message /// Returns a user-readable Windows error message
/// ///
@ -1663,6 +1560,24 @@ namespace winstd
/// }@ /// }@
}; };
///
/// Single-byte character implementation of a class to support string formatting using `printf()` style templates
///
typedef basic_string_printf<char, std::char_traits<char>, std::allocator<char> > string_printf;
///
/// Wide character implementation of a class to support string formatting using `printf()` style templates
///
typedef basic_string_printf<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > wstring_printf;
///
/// Multi-byte / Wide-character formatted string (according to _UNICODE)
///
#ifdef _UNICODE
typedef wstring_printf tstring_printf;
#else
typedef string_printf tstring_printf;
#endif
/// ///
/// Base template class to support string formatting using `FormatMessage()` style templates /// Base template class to support string formatting using `FormatMessage()` style templates
@ -1729,7 +1644,6 @@ namespace winstd
/// @} /// @}
/// ///
/// Initializes a new string and formats its contents using `FormatMessage()` style. /// Initializes a new string and formats its contents using `FormatMessage()` style.
/// ///
@ -1740,7 +1654,6 @@ namespace winstd
FormatMessage(dwFlags & ~FORMAT_MESSAGE_ARGUMENT_ARRAY, lpSource, dwMessageId, dwLanguageId, *this, Arguments); FormatMessage(dwFlags & ~FORMAT_MESSAGE_ARGUMENT_ARRAY, lpSource, dwMessageId, dwLanguageId, *this, Arguments);
} }
/// ///
/// Initializes a new string and formats its contents using `FormatMessage()` style. /// Initializes a new string and formats its contents using `FormatMessage()` style.
/// ///
@ -1751,7 +1664,6 @@ namespace winstd
FormatMessage(dwFlags | FORMAT_MESSAGE_ARGUMENT_ARRAY, lpSource, dwMessageId, dwLanguageId, *this, (va_list*)Arguments); FormatMessage(dwFlags | FORMAT_MESSAGE_ARGUMENT_ARRAY, lpSource, dwMessageId, dwLanguageId, *this, (va_list*)Arguments);
} }
/// ///
/// Initializes a new string and formats its contents using `FormatMessage()` style. /// Initializes a new string and formats its contents using `FormatMessage()` style.
/// ///
@ -1762,7 +1674,6 @@ namespace winstd
FormatMessage(dwFlags & ~FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING, pszFormat, 0, 0, *this, Arguments); FormatMessage(dwFlags & ~FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING, pszFormat, 0, 0, *this, Arguments);
} }
/// ///
/// Initializes a new string and formats its contents using `FormatMessage()` style. /// Initializes a new string and formats its contents using `FormatMessage()` style.
/// ///
@ -1774,6 +1685,24 @@ namespace winstd
} }
}; };
///
/// Single-byte character implementation of a class to support string formatting using `FormatMessage()` style templates
///
typedef basic_string_msg<char, std::char_traits<char>, std::allocator<char> > string_msg;
///
/// Wide character implementation of a class to support string formatting using `FormatMessage()` style templates
///
typedef basic_string_msg<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > wstring_msg;
///
/// Multi-byte / Wide-character formatted string (according to _UNICODE)
///
#ifdef _UNICODE
typedef wstring_msg tstring_msg;
#else
typedef string_msg tstring_msg;
#endif
/// ///
/// Base template class to support converting GUID to string /// Base template class to support converting GUID to string
@ -1804,7 +1733,6 @@ namespace winstd
/// @} /// @}
}; };
/// ///
/// Single-byte character implementation of a class to support converting GUID to string /// Single-byte character implementation of a class to support converting GUID to string
/// ///
@ -1827,7 +1755,6 @@ namespace winstd
/// @} /// @}
}; };
/// ///
/// Wide character implementation of a class to support converting GUID to string /// Wide character implementation of a class to support converting GUID to string
/// ///
@ -1850,9 +1777,21 @@ namespace winstd
/// @} /// @}
}; };
///
/// Multi-byte / Wide-character string GUID (according to _UNICODE)
///
#ifdef _UNICODE
typedef wstring_guid tstring_guid;
#else
typedef string_guid tstring_guid;
#endif
/// @} /// @}
/// \addtogroup WinStdMemSanitize ///
/// \defgroup WinStdMemSanitize Auto-sanitize Memory Management
/// Sanitizes memory before dismissed
///
/// @{ /// @{
// winstd::sanitizing_allocator::destroy() member generates _Ptr parameter not used warning for primitive datatypes _Ty. // winstd::sanitizing_allocator::destroy() member generates _Ptr parameter not used warning for primitive datatypes _Ty.
@ -1881,7 +1820,6 @@ namespace winstd
typedef sanitizing_allocator<_Other> other; ///< Other type typedef sanitizing_allocator<_Other> other; ///< Other type
}; };
/// ///
/// Construct default allocator /// Construct default allocator
/// ///
@ -1889,7 +1827,6 @@ namespace winstd
{ {
} }
/// ///
/// Construct by copying /// Construct by copying
/// ///
@ -1897,7 +1834,6 @@ namespace winstd
{ {
} }
/// ///
/// Construct from a related allocator /// Construct from a related allocator
/// ///
@ -1906,7 +1842,6 @@ namespace winstd
{ {
} }
/// ///
/// Deallocate object at _Ptr sanitizing its content first /// Deallocate object at _Ptr sanitizing its content first
/// ///
@ -1920,6 +1855,33 @@ namespace winstd
#pragma warning(pop) #pragma warning(pop)
///
/// A sanitizing variant of std::string
///
/// \note
/// `sanitizing_string` introduces a performance penalty. However, it provides an additional level of security.
/// Use for security sensitive data memory storage only.
///
typedef std::basic_string<char, std::char_traits<char>, sanitizing_allocator<char> > sanitizing_string;
///
/// A sanitizing variant of std::wstring
///
/// \note
/// `sanitizing_wstring` introduces a performance penalty. However, it provides an additional level of security.
/// Use for security sensitive data memory storage only.
///
typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, sanitizing_allocator<wchar_t> > sanitizing_wstring;
///
/// Multi-byte / Wide-character sanitizing string (according to _UNICODE)
///
#ifdef _UNICODE
typedef sanitizing_wstring sanitizing_tstring;
#else
typedef sanitizing_string sanitizing_tstring;
#endif
/// ///
/// Sanitizing BLOB /// Sanitizing BLOB
/// ///
@ -1949,87 +1911,3 @@ namespace winstd
/// @} /// @}
} }
#pragma warning(push)
// Do not use _vsnprintf_s/_vsnwprintf_s(), since it terminates string by force even when we explicitly want to write unterminated string.
// Threfore turn off compiler warning instead. ;)
#pragma warning(disable: 4995)
#pragma warning(disable: 4996)
#pragma warning(disable: 4505) // Don't warn on unused code
#if _MSC_VER <= 1600
static int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const char *format, _In_ va_list arg)
{
return _vsnprintf(str, capacity, format, arg);
}
#endif
static int vsnprintf(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const wchar_t *format, _In_ va_list arg) noexcept
{
return _vsnwprintf(str, capacity, format, arg);
}
template<class _Elem, class _Traits, class _Ax>
static int vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, _In_ va_list arg)
{
_Elem buf[WINSTD_STACK_BUFFER_BYTES/sizeof(_Elem)];
// Try with stack buffer first.
int count = vsnprintf(buf, _countof(buf) - 1, format, arg);
if (count >= 0) {
// Copy from stack.
str.assign(buf, count);
} else {
for (size_t capacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(_Elem);; capacity *= 2) {
// Allocate on heap and retry.
auto buf_dyn = std::make_unique<_Elem[]>(capacity);
count = vsnprintf(buf_dyn.get(), capacity - 1, format, arg);
if (count >= 0) {
str.assign(buf_dyn.get(), count);
break;
}
}
}
return count;
}
template<class _Elem, class _Traits, class _Ax>
static int sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, ...)
{
va_list arg;
va_start(arg, format);
const int res = vsprintf(str, format, arg);
va_end(arg);
return res;
}
template<class _Traits, class _Ax>
static DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Inout_ std::basic_string<char, _Traits, _Ax> &str, _In_opt_ va_list *Arguments)
{
std::unique_ptr<CHAR[], winstd::LocalFree_delete<CHAR[]> > lpBuffer;
DWORD dwResult = FormatMessageA(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER, lpSource, dwMessageId, dwLanguageId, reinterpret_cast<LPSTR>((LPSTR*)get_ptr(lpBuffer)), 0, Arguments);
if (dwResult)
str.assign(lpBuffer.get(), dwResult);
return dwResult;
}
template<class _Traits, class _Ax>
static DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &str, _In_opt_ va_list *Arguments)
{
std::unique_ptr<WCHAR[], winstd::LocalFree_delete<WCHAR[]> > lpBuffer;
DWORD dwResult = FormatMessageW(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER, lpSource, dwMessageId, dwLanguageId, reinterpret_cast<LPWSTR>((LPWSTR*)get_ptr(lpBuffer)), 0, Arguments);
if (dwResult)
str.assign(lpBuffer.get(), dwResult);
return dwResult;
}
#pragma warning(pop)

View File

@ -4,37 +4,41 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
/// #pragma once
/// \defgroup WinStdCryptoAPI Cryptography API
/// Integrates WinStd classes with Microsoft Cryptography API
///
#include "Common.h" #include "Common.h"
#include <wincred.h> #include <wincred.h>
#include <memory> #include <memory>
namespace winstd ///
{ /// \defgroup WinStdCredAPI Credentials API
template <class _Ty> struct CredFree_delete; /// Integrates WinStd classes with Microsoft Credentials API
template <class _Ty> struct CredFree_delete<_Ty[]>; ///
}
/// \addtogroup WinStdCryptoAPI
/// @{ /// @{
///
/// Enumerates the credentials from the user's credential set. The credential set used is the one associated with the logon session of the current token. The token must not have the user's SID disabled.
///
/// \sa [CredEnumerate function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374794.aspx)
///
static BOOL CredEnumerate(_In_z_ LPCTSTR Filter, _Reserved_ DWORD Flags, _Out_ DWORD *Count, _Inout_ std::unique_ptr<PCREDENTIAL[], winstd::CredFree_delete<PCREDENTIAL[]> > &cCredentials) noexcept;
/// @copydoc CredProtectW() /// @copydoc CredProtectW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOL CredProtectA(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCSTR pszCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<char, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType); static BOOL CredProtectA(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCSTR pszCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<char, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType)
{
char buf[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
DWORD dwSize = _countof(buf);
// Try with the stack buffer first.
if (CredProtectA(fAsSelf, const_cast<LPSTR>(pszCredentials), cchCredentials, buf, &dwSize, ProtectionType)) {
// Copy from stack.
sProtectedCredentials.assign(buf, dwSize - 1);
return TRUE;
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate on heap and retry.
std::unique_ptr<char[]> buf(new char[dwSize]);
if (CredProtectA(fAsSelf, const_cast<LPSTR>(pszCredentials), cchCredentials, buf.get(), &dwSize, ProtectionType)) {
sProtectedCredentials.assign(buf.get(), dwSize - 1);
return TRUE;
}
}
return FALSE;
}
/// ///
/// Encrypts the specified credentials so that only the current security context can decrypt them. /// Encrypts the specified credentials so that only the current security context can decrypt them.
@ -42,11 +46,51 @@ static BOOL CredProtectA(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCSTR ps
/// \sa [CredProtect function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374803.aspx) /// \sa [CredProtect function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374803.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOL CredProtectW(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCWSTR pszCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType); static BOOL CredProtectW(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCWSTR pszCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType)
{
wchar_t buf[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
DWORD dwSize = _countof(buf);
// Try with the stack buffer first.
if (CredProtectW(fAsSelf, const_cast<LPWSTR>(pszCredentials), cchCredentials, buf, &dwSize, ProtectionType)) {
// Copy from stack.
sProtectedCredentials.assign(buf, dwSize - 1);
return TRUE;
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate on heap and retry.
std::unique_ptr<wchar_t[]> buf(new wchar_t[dwSize]);
if (CredProtectW(fAsSelf, const_cast<LPWSTR>(pszCredentials), cchCredentials, buf.get(), &dwSize, ProtectionType)) {
sProtectedCredentials.assign(buf.get(), dwSize - 1);
return TRUE;
}
}
return FALSE;
}
/// @copydoc CredUnprotectW() /// @copydoc CredUnprotectW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOL CredUnprotectA(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<char, _Traits, _Ax> &sCredentials); static BOOL CredUnprotectA(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<char, _Traits, _Ax> &sCredentials)
{
char buf[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
DWORD dwSize = _countof(buf);
// Try with the stack buffer first.
if (CredUnprotectA(fAsSelf, const_cast<LPSTR>(pszProtectedCredentials), cchCredentials, buf, &dwSize)) {
// Copy from stack.
sCredentials.assign(buf, dwSize);
return TRUE;
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate on heap and retry.
std::unique_ptr<char[]> buf(new char[dwSize]);
if (CredUnprotectA(fAsSelf, const_cast<LPSTR>(pszProtectedCredentials), cchCredentials, buf.get(), &dwSize)) {
sCredentials.assign(buf.get(), dwSize);
return TRUE;
}
}
return FALSE;
}
/// ///
/// Decrypts credentials that were previously encrypted by using the CredProtect function. /// Decrypts credentials that were previously encrypted by using the CredProtect function.
@ -54,16 +98,33 @@ static BOOL CredUnprotectA(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCSTR
/// \sa [CredUnprotect function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375186.aspx) /// \sa [CredUnprotect function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa375186.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOL CredUnprotectW(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCWSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sCredentials); static BOOL CredUnprotectW(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCWSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sCredentials)
{
wchar_t buf[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
DWORD dwSize = _countof(buf);
// Try with the stack buffer first.
if (CredUnprotectW(fAsSelf, const_cast<LPWSTR>(pszProtectedCredentials), cchCredentials, buf, &dwSize)) {
// Copy from stack.
sCredentials.assign(buf, dwSize);
return TRUE;
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate on heap and retry.
std::unique_ptr<wchar_t[]> buf(new wchar_t[dwSize]);
if (CredUnprotectW(fAsSelf, const_cast<LPWSTR>(pszProtectedCredentials), cchCredentials, buf.get(), &dwSize)) {
sCredentials.assign(buf.get(), dwSize);
return TRUE;
}
}
return FALSE;
}
/// @} /// @}
#pragma once
namespace winstd namespace winstd
{ {
/// \addtogroup WinStdCryptoAPI /// \addtogroup WinStdCredAPI
/// @{ /// @{
/// ///
@ -94,7 +155,6 @@ namespace winstd
} }
}; };
/// ///
/// Deleter for unique_ptr to array of unknown size using CredFree /// Deleter for unique_ptr to array of unknown size using CredFree
/// ///
@ -132,11 +192,15 @@ namespace winstd
/// @} /// @}
} }
/// \addtogroup WinStdCredAPI
/// @{
#pragma warning(push) ///
#pragma warning(disable: 4505) // Don't warn on unused code /// Enumerates the credentials from the user's credential set. The credential set used is the one associated with the logon session of the current token. The token must not have the user's SID disabled.
///
/// \sa [CredEnumerate function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa374794.aspx)
///
#pragma warning(suppress: 4505) // Don't warn on unused code
static BOOL CredEnumerate(_In_z_ LPCTSTR Filter, _Reserved_ DWORD Flags, _Out_ DWORD *Count, _Inout_ std::unique_ptr<PCREDENTIAL[], winstd::CredFree_delete<PCREDENTIAL[]> > &cCredentials) noexcept static BOOL CredEnumerate(_In_z_ LPCTSTR Filter, _Reserved_ DWORD Flags, _Out_ DWORD *Count, _Inout_ std::unique_ptr<PCREDENTIAL[], winstd::CredFree_delete<PCREDENTIAL[]> > &cCredentials) noexcept
{ {
PCREDENTIAL *pCredentials; PCREDENTIAL *pCredentials;
@ -148,100 +212,4 @@ static BOOL CredEnumerate(_In_z_ LPCTSTR Filter, _Reserved_ DWORD Flags, _Out_ D
return FALSE; return FALSE;
} }
/// @}
template<class _Traits, class _Ax>
static BOOL CredProtectA(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCSTR pszCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<char, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType)
{
char buf[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
DWORD dwSize = _countof(buf);
// Try with the stack buffer first.
if (CredProtectA(fAsSelf, const_cast<LPSTR>(pszCredentials), cchCredentials, buf, &dwSize, ProtectionType)) {
// Copy from stack.
sProtectedCredentials.assign(buf, dwSize - 1);
return TRUE;
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate on heap and retry.
std::unique_ptr<char[]> buf(new char[dwSize]);
if (CredProtectA(fAsSelf, const_cast<LPSTR>(pszCredentials), cchCredentials, buf.get(), &dwSize, ProtectionType)) {
sProtectedCredentials.assign(buf.get(), dwSize - 1);
return TRUE;
}
}
return FALSE;
}
template<class _Traits, class _Ax>
static BOOL CredProtectW(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCWSTR pszCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sProtectedCredentials, _Out_ CRED_PROTECTION_TYPE *ProtectionType)
{
wchar_t buf[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
DWORD dwSize = _countof(buf);
// Try with the stack buffer first.
if (CredProtectW(fAsSelf, const_cast<LPWSTR>(pszCredentials), cchCredentials, buf, &dwSize, ProtectionType)) {
// Copy from stack.
sProtectedCredentials.assign(buf, dwSize - 1);
return TRUE;
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate on heap and retry.
std::unique_ptr<wchar_t[]> buf(new wchar_t[dwSize]);
if (CredProtectW(fAsSelf, const_cast<LPWSTR>(pszCredentials), cchCredentials, buf.get(), &dwSize, ProtectionType)) {
sProtectedCredentials.assign(buf.get(), dwSize - 1);
return TRUE;
}
}
return FALSE;
}
template<class _Traits, class _Ax>
static BOOL CredUnprotectA(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<char, _Traits, _Ax> &sCredentials)
{
char buf[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
DWORD dwSize = _countof(buf);
// Try with the stack buffer first.
if (CredUnprotectA(fAsSelf, const_cast<LPSTR>(pszProtectedCredentials), cchCredentials, buf, &dwSize)) {
// Copy from stack.
sCredentials.assign(buf, dwSize);
return TRUE;
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate on heap and retry.
std::unique_ptr<char[]> buf(new char[dwSize]);
if (CredUnprotectA(fAsSelf, const_cast<LPSTR>(pszProtectedCredentials), cchCredentials, buf.get(), &dwSize)) {
sCredentials.assign(buf.get(), dwSize);
return TRUE;
}
}
return FALSE;
}
template<class _Traits, class _Ax>
static BOOL CredUnprotectW(_In_ BOOL fAsSelf, _In_count_(cchCredentials) LPCWSTR pszProtectedCredentials, _In_ DWORD cchCredentials, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sCredentials)
{
wchar_t buf[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
DWORD dwSize = _countof(buf);
// Try with the stack buffer first.
if (CredUnprotectW(fAsSelf, const_cast<LPWSTR>(pszProtectedCredentials), cchCredentials, buf, &dwSize)) {
// Copy from stack.
sCredentials.assign(buf, dwSize);
return TRUE;
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate on heap and retry.
std::unique_ptr<wchar_t[]> buf(new wchar_t[dwSize]);
if (CredUnprotectW(fAsSelf, const_cast<LPWSTR>(pszProtectedCredentials), cchCredentials, buf.get(), &dwSize)) {
sCredentials.assign(buf.get(), dwSize);
return TRUE;
}
}
return FALSE;
}
#pragma warning(pop)

View File

@ -4,35 +4,34 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
#pragma once
#include "Common.h"
#include <assert.h>
#include <WinCrypt.h>
#include <algorithm>
#include <string>
#include <vector>
/// ///
/// \defgroup WinStdCryptoAPI Cryptography API /// \defgroup WinStdCryptoAPI Cryptography API
/// Integrates WinStd classes with Microsoft Cryptography API /// Integrates WinStd classes with Microsoft Cryptography API
/// ///
#include "Common.h"
#include <WinCrypt.h>
#include <string>
#include <vector>
namespace winstd
{
class cert_context;
class cert_chain_context;
class cert_store;
class crypt_prov;
class crypt_hash;
class crypt_key;
class data_blob;
}
/// \addtogroup WinStdCryptoAPI
/// @{ /// @{
/// @copydoc CertGetNameStringW() /// @copydoc CertGetNameStringW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static DWORD CertGetNameStringA(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwType, _In_ DWORD dwFlags, _In_opt_ void *pvTypePara, _Out_ std::basic_string<char, _Traits, _Ax> &sNameString); static DWORD CertGetNameStringA(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwType, _In_ DWORD dwFlags, _In_opt_ void *pvTypePara, _Out_ std::basic_string<char, _Traits, _Ax> &sNameString)
{
// Query the final string length first.
DWORD dwSize = ::CertGetNameStringA(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
// Allocate buffer on heap to format the string data into and read it.
std::unique_ptr<char[]> szBuffer(new char[dwSize]);
dwSize = ::CertGetNameStringA(pCertContext, dwType, dwFlags, pvTypePara, szBuffer.get(), dwSize);
sNameString.assign(szBuffer.get(), dwSize - 1);
return dwSize;
}
/// ///
/// Obtains the subject or issuer name from a certificate [CERT_CONTEXT](https://msdn.microsoft.com/en-us/library/windows/desktop/aa377189.aspx) structure and stores it in a std::wstring string. /// Obtains the subject or issuer name from a certificate [CERT_CONTEXT](https://msdn.microsoft.com/en-us/library/windows/desktop/aa377189.aspx) structure and stores it in a std::wstring string.
@ -40,7 +39,17 @@ static DWORD CertGetNameStringA(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwT
/// \sa [CertGetNameString function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx) /// \sa [CertGetNameString function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static DWORD CertGetNameStringW(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwType, _In_ DWORD dwFlags, _In_opt_ void *pvTypePara, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sNameString); static DWORD CertGetNameStringW(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwType, _In_ DWORD dwFlags, _In_opt_ void *pvTypePara, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sNameString)
{
// Query the final string length first.
DWORD dwSize = ::CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
// Allocate buffer on heap to format the string data into and read it.
std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwSize]);
dwSize = ::CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, szBuffer.get(), dwSize);
sNameString.assign(szBuffer.get(), dwSize - 1);
return dwSize;
}
/// ///
/// Retrieves the information contained in an extended property of a certificate context. /// Retrieves the information contained in an extended property of a certificate context.
@ -48,7 +57,24 @@ static DWORD CertGetNameStringW(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwT
/// \sa [CertGetCertificateContextProperty function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376079.aspx) /// \sa [CertGetCertificateContextProperty function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376079.aspx)
/// ///
template<class _Ty, class _Ax> template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL WINAPI CertGetCertificateContextProperty(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwPropId, _Out_ std::vector<_Ty, _Ax> &aData); static _Success_(return != 0) BOOL WINAPI CertGetCertificateContextProperty(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwPropId, _Out_ std::vector<_Ty, _Ax> &aData)
{
BYTE buf[WINSTD_STACK_BUFFER_BYTES];
DWORD dwSize = WINSTD_STACK_BUFFER_BYTES;
// Try with the stack buffer first.
if (CertGetCertificateContextProperty(pCertContext, dwPropId, buf, &dwSize)) {
// Copy from stack.
aData.assign((const _Ty*)buf, (const _Ty*)buf + (dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
} else if (GetLastError() == ERROR_MORE_DATA) {
aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
if (CertGetCertificateContextProperty(pCertContext, dwPropId, (BYTE*)aData.data(), &dwSize))
return TRUE;
}
return FALSE;
}
/// ///
/// Retrieves data that governs the operations of a hash object. The actual hash value can be retrieved by using this function. /// Retrieves data that governs the operations of a hash object. The actual hash value can be retrieved by using this function.
@ -56,7 +82,36 @@ static _Success_(return != 0) BOOL WINAPI CertGetCertificateContextProperty(_In_
/// \sa [CryptGetHashParam function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379947.aspx) /// \sa [CryptGetHashParam function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379947.aspx)
/// ///
template<class _Ty, class _Ax> template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptGetHashParam(_In_ HCRYPTHASH hHash, _In_ DWORD dwParam, _Out_ std::vector<_Ty, _Ax> &aData, _In_ DWORD dwFlags); static _Success_(return != 0) BOOL CryptGetHashParam(_In_ HCRYPTHASH hHash, _In_ DWORD dwParam, _Out_ std::vector<_Ty, _Ax> &aData, _In_ DWORD dwFlags)
{
BYTE buf[WINSTD_STACK_BUFFER_BYTES];
DWORD dwSize = WINSTD_STACK_BUFFER_BYTES;
// Try with the stack buffer first.
if (CryptGetHashParam(hHash, dwParam, buf, &dwSize, dwFlags)) {
// Copy from stack.
aData.assign((const _Ty*)buf, (const _Ty*)buf + (dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
} else if (GetLastError() == ERROR_MORE_DATA) {
aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
if (CryptGetHashParam(hHash, dwParam, (BYTE*)aData.data(), &dwSize, dwFlags))
return TRUE;
}
return FALSE;
}
///
/// Retrieves data that governs the operations of a hash object. The actual hash value can be retrieved by using this function.
///
/// \sa [CryptGetHashParam function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379947.aspx)
///
template<class T>
static _Success_(return != 0) BOOL CryptGetHashParam(_In_ HCRYPTHASH hHash, _In_ DWORD dwParam, _Out_ T &data, _In_ DWORD dwFlags)
{
DWORD dwSize = sizeof(T);
return CryptGetHashParam(hHash, dwParam, (BYTE*)&data, &dwSize, dwFlags);
}
/// ///
/// Retrieves data that governs the operations of a key. /// Retrieves data that governs the operations of a key.
@ -64,7 +119,24 @@ static _Success_(return != 0) BOOL CryptGetHashParam(_In_ HCRYPTHASH hHash, _In_
/// \sa [CryptGetKeyParam function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379949.aspx) /// \sa [CryptGetKeyParam function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379949.aspx)
/// ///
template<class _Ty, class _Ax> template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptGetKeyParam(_In_ HCRYPTKEY hKey, _In_ DWORD dwParam, _Out_ std::vector<_Ty, _Ax> &aData, _In_ DWORD dwFlags); static _Success_(return != 0) BOOL CryptGetKeyParam(_In_ HCRYPTKEY hKey, _In_ DWORD dwParam, _Out_ std::vector<_Ty, _Ax> &aData, _In_ DWORD dwFlags)
{
BYTE buf[WINSTD_STACK_BUFFER_BYTES];
DWORD dwSize = WINSTD_STACK_BUFFER_BYTES;
// Try with the stack buffer first.
if (CryptGetKeyParam(hKey, dwParam, buf, &dwSize, dwFlags)) {
// Copy from stack.
aData.assign((const _Ty*)buf, (const _Ty*)buf + (dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
} else if (GetLastError() == ERROR_MORE_DATA) {
aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
if (CryptGetKeyParam(hKey, dwParam, (BYTE*)aData.data(), &dwSize, dwFlags))
return TRUE;
}
return FALSE;
}
/// ///
/// Retrieves data that governs the operations of a key. /// Retrieves data that governs the operations of a key.
@ -72,7 +144,11 @@ static _Success_(return != 0) BOOL CryptGetKeyParam(_In_ HCRYPTKEY hKey, _In_ DW
/// \sa [CryptGetKeyParam function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379949.aspx) /// \sa [CryptGetKeyParam function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379949.aspx)
/// ///
template<class T> template<class T>
static _Success_(return != 0) BOOL CryptGetKeyParam(_In_ HCRYPTKEY hKey, _In_ DWORD dwParam, _Out_ T &data, _In_ DWORD dwFlags); static BOOL CryptGetKeyParam(_In_ HCRYPTKEY hKey, _In_ DWORD dwParam, _Out_ T &data, _In_ DWORD dwFlags)
{
DWORD dwSize = sizeof(T);
return CryptGetKeyParam(hKey, dwParam, (BYTE*)&data, &dwSize, dwFlags);
}
/// ///
/// Exports a cryptographic key or a key pair from a cryptographic service provider (CSP) in a secure manner. /// Exports a cryptographic key or a key pair from a cryptographic service provider (CSP) in a secure manner.
@ -80,7 +156,18 @@ static _Success_(return != 0) BOOL CryptGetKeyParam(_In_ HCRYPTKEY hKey, _In_ DW
/// \sa [CryptExportKey function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379931.aspx) /// \sa [CryptExportKey function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379931.aspx)
/// ///
template<class _Ty, class _Ax> template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptExportKey(_In_ HCRYPTKEY hKey, _In_ HCRYPTKEY hExpKey, _In_ DWORD dwBlobType, _In_ DWORD dwFlags, _Out_ std::vector<_Ty, _Ax> &aData); static _Success_(return != 0) BOOL CryptExportKey(_In_ HCRYPTKEY hKey, _In_ HCRYPTKEY hExpKey, _In_ DWORD dwBlobType, _In_ DWORD dwFlags, _Out_ std::vector<_Ty, _Ax> &aData)
{
DWORD dwKeyBLOBSize = 0;
if (CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, NULL, &dwKeyBLOBSize)) {
aData.resize((dwKeyBLOBSize + sizeof(_Ty) - 1) / sizeof(_Ty));
if (CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, aData.data(), &dwKeyBLOBSize))
return TRUE;
}
return FALSE;
}
/// ///
/// Encrypts data. /// Encrypts data.
@ -88,7 +175,49 @@ static _Success_(return != 0) BOOL CryptExportKey(_In_ HCRYPTKEY hKey, _In_ HCRY
/// \sa [CryptEncrypt function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379924.aspx) /// \sa [CryptEncrypt function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379924.aspx)
/// ///
template<class _Ty, class _Ax> template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptEncrypt(_In_ HCRYPTKEY hKey, _In_opt_ HCRYPTHASH hHash, _In_ BOOL Final, _In_ DWORD dwFlags, _Inout_ std::vector<_Ty, _Ax> &aData); static _Success_(return != 0) BOOL CryptEncrypt(_In_ HCRYPTKEY hKey, _In_opt_ HCRYPTHASH hHash, _In_ BOOL Final, _In_ DWORD dwFlags, _Inout_ std::vector<_Ty, _Ax> &aData)
{
DWORD
dwDataLen = (DWORD)(aData.size() * sizeof(_Ty)),
dwBufLen = (DWORD)(aData.capacity() * sizeof(_Ty)),
dwEncLen = dwDataLen,
dwResult;
if (dwBufLen) {
aData.resize(dwBufLen);
if (CryptEncrypt(hKey, hHash, Final, dwFlags, (BYTE*)aData.data(), &dwEncLen, dwBufLen)) {
// Encryption succeeded.
assert(dwEncLen <= dwBufLen);
if (dwEncLen < dwBufLen)
aData.resize((dwEncLen + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
} else
dwResult = GetLastError();
} else if (CryptEncrypt(hKey, NULL, Final, dwFlags, NULL, &dwEncLen, 0)) {
// CryptEncrypt() always succeeds for output data size queries.
// dwEncLen contains required output data size. Continue as if the buffer was to small. Actually, the output buffer _was_ too small!
dwResult = ERROR_MORE_DATA;
} else
dwResult = GetLastError();
if (dwResult == ERROR_MORE_DATA) {
// Encrypted data will be longer. Reserve more space and retry.
aData.resize(((dwBufLen = dwEncLen) + sizeof(_Ty) - 1) / sizeof(_Ty));
dwEncLen = dwDataLen;
if (CryptEncrypt(hKey, hHash, Final, dwFlags, (BYTE*)aData.data(), &dwEncLen, dwBufLen)) {
// Encryption succeeded.
assert(dwEncLen <= dwBufLen);
if (dwEncLen < dwBufLen)
aData.resize((dwEncLen + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
}
} else {
// Resize back to data length.
aData.resize((dwDataLen + sizeof(_Ty) - 1) / sizeof(_Ty));
}
return FALSE;
}
/// ///
/// Decrypts data previously encrypted by using the CryptEncrypt function. /// Decrypts data previously encrypted by using the CryptEncrypt function.
@ -96,17 +225,21 @@ static _Success_(return != 0) BOOL CryptEncrypt(_In_ HCRYPTKEY hKey, _In_opt_ HC
/// \sa [CryptDecrypt function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379913.aspx) /// \sa [CryptDecrypt function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379913.aspx)
/// ///
template<class _Ty, class _Ax> template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptDecrypt(_In_ HCRYPTKEY hKey, _In_opt_ HCRYPTHASH hHash, _In_ BOOL Final, _In_ DWORD dwFlags, _Inout_ std::vector<_Ty, _Ax> &aData); static _Success_(return != 0) BOOL CryptDecrypt(_In_ HCRYPTKEY hKey, _In_opt_ HCRYPTHASH hHash, _In_ BOOL Final, _In_ DWORD dwFlags, _Inout_ std::vector<_Ty, _Ax> &aData)
{
DWORD dwDataLen = (DWORD)(aData.size() * sizeof(_Ty));
if (CryptDecrypt(hKey, hHash, Final, dwFlags, (BYTE*)aData.data(), &dwDataLen)) {
// Decryption succeeded.
aData.resize((dwDataLen + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
}
return FALSE;
}
/// @} /// @}
#pragma once
#include <assert.h>
#include <algorithm>
namespace winstd namespace winstd
{ {
/// \addtogroup WinStdCryptoAPI /// \addtogroup WinStdCryptoAPI
@ -261,7 +394,6 @@ namespace winstd
} }
}; };
/// ///
/// PCCERT_CHAIN_CONTEXT wrapper class /// PCCERT_CHAIN_CONTEXT wrapper class
/// ///
@ -326,7 +458,6 @@ namespace winstd
} }
}; };
/// ///
/// HCERTSTORE wrapper class /// HCERTSTORE wrapper class
/// ///
@ -396,7 +527,6 @@ namespace winstd
} }
}; };
/// ///
/// HCRYPTPROV wrapper class /// HCRYPTPROV wrapper class
/// ///
@ -447,7 +577,6 @@ namespace winstd
} }
}; };
/// ///
/// HCRYPTHASH wrapper class /// HCRYPTHASH wrapper class
/// ///
@ -513,7 +642,6 @@ namespace winstd
} }
}; };
/// ///
/// HCRYPTKEY wrapper class /// HCRYPTKEY wrapper class
/// ///
@ -815,186 +943,3 @@ namespace winstd
/// @} /// @}
} }
template<class _Traits, class _Ax>
static DWORD CertGetNameStringA(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwType, _In_ DWORD dwFlags, _In_opt_ void *pvTypePara, _Out_ std::basic_string<char, _Traits, _Ax> &sNameString)
{
// Query the final string length first.
DWORD dwSize = ::CertGetNameStringA(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
// Allocate buffer on heap to format the string data into and read it.
std::unique_ptr<char[]> szBuffer(new char[dwSize]);
dwSize = ::CertGetNameStringA(pCertContext, dwType, dwFlags, pvTypePara, szBuffer.get(), dwSize);
sNameString.assign(szBuffer.get(), dwSize - 1);
return dwSize;
}
template<class _Traits, class _Ax>
static DWORD CertGetNameStringW(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwType, _In_ DWORD dwFlags, _In_opt_ void *pvTypePara, _Out_ std::basic_string<wchar_t, _Traits, _Ax> &sNameString)
{
// Query the final string length first.
DWORD dwSize = ::CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
// Allocate buffer on heap to format the string data into and read it.
std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwSize]);
dwSize = ::CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, szBuffer.get(), dwSize);
sNameString.assign(szBuffer.get(), dwSize - 1);
return dwSize;
}
template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL WINAPI CertGetCertificateContextProperty(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwPropId, _Out_ std::vector<_Ty, _Ax> &aData)
{
BYTE buf[WINSTD_STACK_BUFFER_BYTES];
DWORD dwSize = WINSTD_STACK_BUFFER_BYTES;
// Try with the stack buffer first.
if (CertGetCertificateContextProperty(pCertContext, dwPropId, buf, &dwSize)) {
// Copy from stack.
aData.assign((const _Ty*)buf, (const _Ty*)buf + (dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
} else if (GetLastError() == ERROR_MORE_DATA) {
aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
if (CertGetCertificateContextProperty(pCertContext, dwPropId, (BYTE*)aData.data(), &dwSize))
return TRUE;
}
return FALSE;
}
template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptGetHashParam(_In_ HCRYPTHASH hHash, _In_ DWORD dwParam, _Out_ std::vector<_Ty, _Ax> &aData, _In_ DWORD dwFlags)
{
BYTE buf[WINSTD_STACK_BUFFER_BYTES];
DWORD dwSize = WINSTD_STACK_BUFFER_BYTES;
// Try with the stack buffer first.
if (CryptGetHashParam(hHash, dwParam, buf, &dwSize, dwFlags)) {
// Copy from stack.
aData.assign((const _Ty*)buf, (const _Ty*)buf + (dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
} else if (GetLastError() == ERROR_MORE_DATA) {
aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
if (CryptGetHashParam(hHash, dwParam, (BYTE*)aData.data(), &dwSize, dwFlags))
return TRUE;
}
return FALSE;
}
template<class T>
static BOOL CryptGetHashParam(_In_ HCRYPTHASH hHash, _In_ DWORD dwParam, _Out_ T &data, _In_ DWORD dwFlags)
{
DWORD dwSize = sizeof(T);
return CryptGetHashParam(hHash, dwParam, (BYTE*)&data, &dwSize, dwFlags);
}
template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptGetKeyParam(_In_ HCRYPTKEY hKey, _In_ DWORD dwParam, _Out_ std::vector<_Ty, _Ax> &aData, _In_ DWORD dwFlags)
{
BYTE buf[WINSTD_STACK_BUFFER_BYTES];
DWORD dwSize = WINSTD_STACK_BUFFER_BYTES;
// Try with the stack buffer first.
if (CryptGetKeyParam(hKey, dwParam, buf, &dwSize, dwFlags)) {
// Copy from stack.
aData.assign((const _Ty*)buf, (const _Ty*)buf + (dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
} else if (GetLastError() == ERROR_MORE_DATA) {
aData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
if (CryptGetKeyParam(hKey, dwParam, (BYTE*)aData.data(), &dwSize, dwFlags))
return TRUE;
}
return FALSE;
}
template<class T>
static BOOL CryptGetKeyParam(_In_ HCRYPTKEY hKey, _In_ DWORD dwParam, _Out_ T &data, _In_ DWORD dwFlags)
{
DWORD dwSize = sizeof(T);
return CryptGetKeyParam(hKey, dwParam, (BYTE*)&data, &dwSize, dwFlags);
}
template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptExportKey(_In_ HCRYPTKEY hKey, _In_ HCRYPTKEY hExpKey, _In_ DWORD dwBlobType, _In_ DWORD dwFlags, _Out_ std::vector<_Ty, _Ax> &aData)
{
DWORD dwKeyBLOBSize = 0;
if (CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, NULL, &dwKeyBLOBSize)) {
aData.resize((dwKeyBLOBSize + sizeof(_Ty) - 1) / sizeof(_Ty));
if (CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, aData.data(), &dwKeyBLOBSize))
return TRUE;
}
return FALSE;
}
template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptEncrypt(_In_ HCRYPTKEY hKey, _In_opt_ HCRYPTHASH hHash, _In_ BOOL Final, _In_ DWORD dwFlags, _Inout_ std::vector<_Ty, _Ax> &aData)
{
DWORD
dwDataLen = (DWORD)(aData.size() * sizeof(_Ty)),
dwBufLen = (DWORD)(aData.capacity() * sizeof(_Ty)),
dwEncLen = dwDataLen,
dwResult;
if (dwBufLen) {
aData.resize(dwBufLen);
if (CryptEncrypt(hKey, hHash, Final, dwFlags, (BYTE*)aData.data(), &dwEncLen, dwBufLen)) {
// Encryption succeeded.
assert(dwEncLen <= dwBufLen);
if (dwEncLen < dwBufLen)
aData.resize((dwEncLen + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
} else
dwResult = GetLastError();
} else if (CryptEncrypt(hKey, NULL, Final, dwFlags, NULL, &dwEncLen, 0)) {
// CryptEncrypt() always succeeds for output data size queries.
// dwEncLen contains required output data size. Continue as if the buffer was to small. Actually, the output buffer _was_ too small!
dwResult = ERROR_MORE_DATA;
} else
dwResult = GetLastError();
if (dwResult == ERROR_MORE_DATA) {
// Encrypted data will be longer. Reserve more space and retry.
aData.resize(((dwBufLen = dwEncLen) + sizeof(_Ty) - 1) / sizeof(_Ty));
dwEncLen = dwDataLen;
if (CryptEncrypt(hKey, hHash, Final, dwFlags, (BYTE*)aData.data(), &dwEncLen, dwBufLen)) {
// Encryption succeeded.
assert(dwEncLen <= dwBufLen);
if (dwEncLen < dwBufLen)
aData.resize((dwEncLen + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
}
} else {
// Resize back to data length.
aData.resize((dwDataLen + sizeof(_Ty) - 1) / sizeof(_Ty));
}
return FALSE;
}
template<class _Ty, class _Ax>
static _Success_(return != 0) BOOL CryptDecrypt(_In_ HCRYPTKEY hKey, _In_opt_ HCRYPTHASH hHash, _In_ BOOL Final, _In_ DWORD dwFlags, _Inout_ std::vector<_Ty, _Ax> &aData)
{
DWORD dwDataLen = (DWORD)(aData.size() * sizeof(_Ty));
if (CryptDecrypt(hKey, hHash, Final, dwFlags, (BYTE*)aData.data(), &dwDataLen)) {
// Decryption succeeded.
aData.resize((dwDataLen + sizeof(_Ty) - 1) / sizeof(_Ty));
return TRUE;
}
return FALSE;
}

View File

@ -4,59 +4,27 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
#pragma once
#include "Common.h"
#include <eaphostpeerconfigapis.h>
#include <eaptypes.h>
#include <EapHostPeerTypes.h>
#include <eapmethodtypes.h>
#include <eappapis.h>
#include <WinSock2.h>
#include <memory>
#pragma warning(push)
#pragma warning(disable: 26812) // Windows EAP API is using unscoped enums
#pragma warning(push)
#pragma warning(disable: 4505) // Don't warn on unused code
/// ///
/// \defgroup WinStdEAPAPI Extensible Authentication Protocol API /// \defgroup WinStdEAPAPI Extensible Authentication Protocol API
/// Integrates WinStd classes with Microsoft EAP API /// Integrates WinStd classes with Microsoft EAP API
/// ///
#include "Common.h"
#include <eaphostpeerconfigapis.h>
#include <eaptypes.h>
#include <memory>
namespace winstd
{
enum class eap_type_t : unsigned char;
struct EapHostPeerFreeMemory_delete;
struct EapHostPeerFreeRuntimeMemory_delete;
struct EapHostPeerFreeErrorMemory_delete;
struct EapHostPeerFreeEapError_delete;
class eap_attr;
class eap_method_prop;
class eap_packet;
class eap_method_info_array;
class eap_runtime_error;
/// \addtogroup WinStdEAPAPI
/// @{
///
/// EapHost BLOB wrapper class
///
typedef std::unique_ptr<BYTE[], EapHostPeerFreeMemory_delete> eap_blob;
///
/// EapHost BLOB wrapper class
///
typedef std::unique_ptr<BYTE[], EapHostPeerFreeRuntimeMemory_delete> eap_blob_runtime;
///
/// EAP_ERROR wrapper class
///
typedef std::unique_ptr<EAP_ERROR, EapHostPeerFreeErrorMemory_delete> eap_error;
///
/// EAP_ERROR wrapper class
///
typedef std::unique_ptr<EAP_ERROR, EapHostPeerFreeEapError_delete> eap_error_runtime;
/// @}
}
/// \addtogroup WinStdEAPAPI
/// @{ /// @{
/// ///
@ -69,7 +37,14 @@ namespace winstd
/// - Non zero when \p a is equal to \p b; /// - Non zero when \p a is equal to \p b;
/// - Zero otherwise. /// - Zero otherwise.
/// ///
static bool operator==(_In_ const EAP_METHOD_TYPE &a, _In_ const EAP_METHOD_TYPE &b) noexcept; static bool operator==(_In_ const EAP_METHOD_TYPE &a, _In_ const EAP_METHOD_TYPE &b) noexcept
{
return
a.eapType.type == b.eapType.type &&
a.eapType.dwVendorId == b.eapType.dwVendorId &&
a.eapType.dwVendorType == b.eapType.dwVendorType &&
a.dwAuthorId == a.dwAuthorId;
}
/// ///
/// Are EAP method types non-equal? /// Are EAP method types non-equal?
@ -81,19 +56,14 @@ static bool operator==(_In_ const EAP_METHOD_TYPE &a, _In_ const EAP_METHOD_TYPE
/// - Non zero when \p a is not equal to \p b; /// - Non zero when \p a is not equal to \p b;
/// - Zero otherwise. /// - Zero otherwise.
/// ///
static bool operator!=(_In_ const EAP_METHOD_TYPE &a, _In_ const EAP_METHOD_TYPE &b) noexcept; static bool operator!=(_In_ const EAP_METHOD_TYPE &a, _In_ const EAP_METHOD_TYPE &b) noexcept
{
return !operator==(a, b);
}
/// @} /// @}
#pragma once #pragma warning(pop)
#include <EapHostPeerTypes.h>
#include <eapmethodtypes.h>
#include <eappapis.h>
#include <WinSock2.h>
#pragma warning(push)
#pragma warning(disable: 26812) // Windows EAP API is using unscoped enums
namespace winstd namespace winstd
{ {
@ -131,7 +101,6 @@ namespace winstd
noneap_end = 254, ///< End of non-EAP methods (non-inclusive) noneap_end = 254, ///< End of non-EAP methods (non-inclusive)
}; };
/// ///
/// Deleter for unique_ptr using EapHostPeerFreeMemory /// Deleter for unique_ptr using EapHostPeerFreeMemory
/// ///
@ -154,6 +123,10 @@ namespace winstd
} }
}; };
///
/// EapHost BLOB wrapper class
///
typedef std::unique_ptr<BYTE[], EapHostPeerFreeMemory_delete> eap_blob;
/// ///
/// Deleter for unique_ptr using EapHostPeerFreeRuntimeMemory /// Deleter for unique_ptr using EapHostPeerFreeRuntimeMemory
@ -175,6 +148,10 @@ namespace winstd
} }
}; };
///
/// EapHost BLOB wrapper class
///
typedef std::unique_ptr<BYTE[], EapHostPeerFreeRuntimeMemory_delete> eap_blob_runtime;
/// ///
/// Deleter for unique_ptr to EAP_ERROR using EapHostPeerFreeErrorMemory /// Deleter for unique_ptr to EAP_ERROR using EapHostPeerFreeErrorMemory
@ -197,6 +174,10 @@ namespace winstd
} }
}; };
///
/// EAP_ERROR wrapper class
///
typedef std::unique_ptr<EAP_ERROR, EapHostPeerFreeErrorMemory_delete> eap_error;
/// ///
/// Deleter for unique_ptr to EAP_ERROR using EapHostPeerFreeEapError /// Deleter for unique_ptr to EAP_ERROR using EapHostPeerFreeEapError
@ -219,6 +200,10 @@ namespace winstd
} }
}; };
///
/// EAP_ERROR wrapper class
///
typedef std::unique_ptr<EAP_ERROR, EapHostPeerFreeEapError_delete> eap_error_runtime;
/// ///
/// EAP_ATTRIBUTE wrapper class /// EAP_ATTRIBUTE wrapper class
@ -371,7 +356,6 @@ namespace winstd
/// ///
static const EAP_ATTRIBUTE blank_eap_attr = {}; static const EAP_ATTRIBUTE blank_eap_attr = {};
/// ///
/// EAP_METHOD_PROPERTY wrapper class /// EAP_METHOD_PROPERTY wrapper class
/// ///
@ -392,7 +376,6 @@ namespace winstd
eapMethodPropertyValue.empvBool.value = value; eapMethodPropertyValue.empvBool.value = value;
} }
/// ///
/// Constructs a DWORD method property /// Constructs a DWORD method property
/// ///
@ -407,7 +390,6 @@ namespace winstd
eapMethodPropertyValue.empvDword.value = value; eapMethodPropertyValue.empvDword.value = value;
} }
/// ///
/// Constructs a Unicode string method property /// Constructs a Unicode string method property
/// ///
@ -423,7 +405,6 @@ namespace winstd
} }
}; };
/// ///
/// EapPacket wrapper class /// EapPacket wrapper class
/// ///
@ -441,7 +422,6 @@ namespace winstd
free_internal(); free_internal();
} }
/// ///
/// Create new EAP packet /// Create new EAP packet
/// ///
@ -473,7 +453,6 @@ namespace winstd
} }
} }
/// ///
/// Returns total EAP packet size in bytes. /// Returns total EAP packet size in bytes.
/// ///
@ -482,7 +461,6 @@ namespace winstd
return m_h != NULL ? ntohs(*(WORD*)m_h->Length) : 0; return m_h != NULL ? ntohs(*(WORD*)m_h->Length) : 0;
} }
protected: protected:
/// ///
/// Destroys the EAP packet. /// Destroys the EAP packet.
@ -508,7 +486,6 @@ namespace winstd
} }
}; };
/// ///
/// EAP_METHOD_INFO_ARRAY wrapper class /// EAP_METHOD_INFO_ARRAY wrapper class
/// ///
@ -591,10 +568,7 @@ namespace winstd
/// @} /// @}
/// /// \addtogroup WinStdExceptions
/// \defgroup WinStdExceptions Exceptions
/// Additional exceptions
///
/// @{ /// @{
/// ///
@ -623,7 +597,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception /// Constructs an exception
/// ///
@ -642,7 +615,6 @@ namespace winstd
{ {
} }
/// ///
/// Returns EAP method type /// Returns EAP method type
/// ///
@ -651,7 +623,6 @@ namespace winstd
return m_type; return m_type;
} }
/// ///
/// Returns the reason code for error /// Returns the reason code for error
/// ///
@ -660,7 +631,6 @@ namespace winstd
return m_reason; return m_reason;
} }
/// ///
/// Returns root cause ID /// Returns root cause ID
/// ///
@ -669,7 +639,6 @@ namespace winstd
return m_root_cause_id; return m_root_cause_id;
} }
/// ///
/// Returns root cause ID /// Returns root cause ID
/// ///
@ -678,7 +647,6 @@ namespace winstd
return m_root_cause_desc.c_str(); return m_root_cause_desc.c_str();
} }
/// ///
/// Returns repair ID /// Returns repair ID
/// ///
@ -687,7 +655,6 @@ namespace winstd
return m_repair_id; return m_repair_id;
} }
/// ///
/// Returns root cause ID /// Returns root cause ID
/// ///
@ -696,7 +663,6 @@ namespace winstd
return m_repair_desc.c_str(); return m_repair_desc.c_str();
} }
/// ///
/// Returns help_link ID /// Returns help_link ID
/// ///
@ -722,24 +688,4 @@ namespace winstd
/// @} /// @}
} }
#pragma warning(push)
#pragma warning(disable: 4505) // Don't warn on unused code
static bool operator==(_In_ const EAP_METHOD_TYPE &a, _In_ const EAP_METHOD_TYPE &b) noexcept
{
return
a.eapType.type == b.eapType.type &&
a.eapType.dwVendorId == b.eapType.dwVendorId &&
a.eapType.dwVendorType == b.eapType.dwVendorType &&
a.dwAuthorId == a.dwAuthorId;
}
static bool operator!=(_In_ const EAP_METHOD_TYPE &a, _In_ const EAP_METHOD_TYPE &b) noexcept
{
return !operator==(a, b);
}
#pragma warning(pop)
#pragma warning(pop) #pragma warning(pop)

View File

@ -4,64 +4,108 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
/// #pragma once
/// \defgroup WinStdETWAPI Event Tracing for Windows API
/// Integrates WinStd classes with Event Tracing for Windows API
///
#include "Common.h" #include "Common.h"
#include <assert.h> #include <assert.h>
#include <evntprov.h> #include <evntprov.h>
#include <evntcons.h> #include <evntcons.h>
#include <stdarg.h> #include <stdarg.h>
#include <tdh.h> #include <tdh.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
namespace winstd #pragma warning(push)
{ #pragma warning(disable: 4505) // Don't warn on unused code
class event_data;
class event_rec;
class event_provider;
class event_session;
class event_trace;
class event_trace_enabler;
class event_fn_auto;
template<class T> class event_fn_auto_ret;
}
/// \addtogroup WinStdCryptoAPI ///
/// \defgroup WinStdETWAPI Event Tracing for Windows API
/// Integrates WinStd classes with Event Tracing for Windows API
///
/// @{ /// @{
///
/// Retrieves metadata about an event.
///
/// \sa [TdhGetEventInformation function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa964840.aspx)
///
static _Success_(return == ERROR_SUCCESS) ULONG TdhGetEventInformation(_In_ PEVENT_RECORD pEvent, _In_ ULONG TdhContextCount, _In_reads_opt_(TdhContextCount) PTDH_CONTEXT pTdhContext, _Out_ std::unique_ptr<TRACE_EVENT_INFO> &info);
///
/// Retrieves information about the event map contained in the event.
///
/// \sa [TdhGetEventMapInformation function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa964841.aspx)
///
static _Success_(return == ERROR_SUCCESS) ULONG TdhGetEventMapInformation(_In_ PEVENT_RECORD pEvent, _In_ LPWSTR pMapName, _Inout_ std::unique_ptr<EVENT_MAP_INFO> &info);
/// ///
/// Retrieves a property value from the event data. /// Retrieves a property value from the event data.
/// ///
/// \sa [TdhGetProperty function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa964843.aspx) /// \sa [TdhGetProperty function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa964843.aspx)
/// ///
template<class _Ty, class _Ax> template<class _Ty, class _Ax>
static _Success_(return == ERROR_SUCCESS) ULONG TdhGetProperty(_In_ PEVENT_RECORD pEvent, _In_ ULONG TdhContextCount, _In_reads_opt_(TdhContextCount) PTDH_CONTEXT pTdhContext, _In_ ULONG PropertyDataCount, _In_reads_(PropertyDataCount) PPROPERTY_DATA_DESCRIPTOR pPropertyData, _Inout_ std::vector<_Ty, _Ax> &aData); static _Success_(return == ERROR_SUCCESS) ULONG TdhGetProperty(_In_ PEVENT_RECORD pEvent, _In_ ULONG TdhContextCount, _In_reads_opt_(TdhContextCount) PTDH_CONTEXT pTdhContext, _In_ ULONG PropertyDataCount, _In_reads_(PropertyDataCount) PPROPERTY_DATA_DESCRIPTOR pPropertyData, _Inout_ std::vector<_Ty, _Ax> &aData)
{
ULONG ulSize, ulResult;
// Query property size.
ulResult = TdhGetPropertySize(pEvent, TdhContextCount, pTdhContext, PropertyDataCount, pPropertyData, &ulSize);
if (ulResult == ERROR_SUCCESS) {
if (ulSize) {
// Query property value.
aData.resize((ulSize + sizeof(_Ty) - 1) / sizeof(_Ty));
ulResult = TdhGetProperty(pEvent, TdhContextCount, pTdhContext, PropertyDataCount, pPropertyData, ulSize, reinterpret_cast<LPBYTE>(aData.data()));
} else {
// Property value size is zero.
aData.clear();
}
}
return ulResult;
}
///
/// Retrieves metadata about an event.
///
/// \sa [TdhGetEventInformation function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa964840.aspx)
///
static _Success_(return == ERROR_SUCCESS) ULONG TdhGetEventInformation(_In_ PEVENT_RECORD pEvent, _In_ ULONG TdhContextCount, _In_reads_opt_(TdhContextCount) PTDH_CONTEXT pTdhContext, _Out_ std::unique_ptr<TRACE_EVENT_INFO> &info)
{
BYTE szBuffer[WINSTD_STACK_BUFFER_BYTES];
ULONG ulSize = sizeof(szBuffer), ulResult;
// Try with stack buffer first.
ulResult = TdhGetEventInformation(pEvent, TdhContextCount, pTdhContext, (PTRACE_EVENT_INFO)szBuffer, &ulSize);
if (ulResult == ERROR_SUCCESS) {
// Copy from stack.
info.reset(reinterpret_cast<PTRACE_EVENT_INFO>(new char[ulSize]));
memcpy(info.get(), szBuffer, ulSize);
return ERROR_SUCCESS;
} else if (ulResult == ERROR_INSUFFICIENT_BUFFER) {
// Create buffer on heap and retry.
info.reset(reinterpret_cast<PTRACE_EVENT_INFO>(new char[ulSize]));
return TdhGetEventInformation(pEvent, TdhContextCount, pTdhContext, info.get(), &ulSize);
}
return ulResult;
}
///
/// Retrieves information about the event map contained in the event.
///
/// \sa [TdhGetEventMapInformation function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa964841.aspx)
///
static _Success_(return == ERROR_SUCCESS) ULONG TdhGetEventMapInformation(_In_ PEVENT_RECORD pEvent, _In_ LPWSTR pMapName, _Inout_ std::unique_ptr<EVENT_MAP_INFO> &info)
{
BYTE szBuffer[WINSTD_STACK_BUFFER_BYTES];
ULONG ulSize = sizeof(szBuffer), ulResult;
// Try with stack buffer first.
ulResult = TdhGetEventMapInformation(pEvent, pMapName, (PEVENT_MAP_INFO)szBuffer, &ulSize);
if (ulResult == ERROR_SUCCESS) {
// Copy from stack.
info.reset(reinterpret_cast<PEVENT_MAP_INFO>(new char[ulSize]));
memcpy(info.get(), szBuffer, ulSize);
return ERROR_SUCCESS;
} else if (ulResult == ERROR_INSUFFICIENT_BUFFER) {
// Create buffer on heap and retry.
info.reset(reinterpret_cast<PEVENT_MAP_INFO>(new char[ulSize]));
return TdhGetEventMapInformation(pEvent, pMapName, info.get(), &ulSize);
}
return ulResult;
}
/// @} /// @}
#pragma once #pragma warning(pop)
namespace winstd namespace winstd
{ {
@ -84,7 +128,6 @@ namespace winstd
Reserved = (ULONG)-1; // Used for varadic argument terminator. Reserved = (ULONG)-1; // Used for varadic argument terminator.
} }
/// ///
/// Construct class pointing to an `char`. /// Construct class pointing to an `char`.
/// ///
@ -98,7 +141,6 @@ namespace winstd
EventDataDescCreate(this, &data, (ULONG)(sizeof(data))); EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
} }
/// ///
/// Construct class pointing to an `unsigned char`. /// Construct class pointing to an `unsigned char`.
/// ///
@ -112,7 +154,6 @@ namespace winstd
EventDataDescCreate(this, &data, (ULONG)(sizeof(data))); EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
} }
/// ///
/// Construct class pointing to an `int`. /// Construct class pointing to an `int`.
/// ///
@ -126,7 +167,6 @@ namespace winstd
EventDataDescCreate(this, &data, (ULONG)(sizeof(data))); EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
} }
/// ///
/// Construct class pointing to an `unsigned int`. /// Construct class pointing to an `unsigned int`.
/// ///
@ -140,7 +180,6 @@ namespace winstd
EventDataDescCreate(this, &data, (ULONG)(sizeof(data))); EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
} }
/// ///
/// Construct class pointing to a `long`. /// Construct class pointing to a `long`.
/// ///
@ -154,7 +193,6 @@ namespace winstd
EventDataDescCreate(this, &data, (ULONG)(sizeof(data))); EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
} }
/// ///
/// Construct class pointing to an `unsigned long`. /// Construct class pointing to an `unsigned long`.
/// ///
@ -168,7 +206,6 @@ namespace winstd
EventDataDescCreate(this, &data, (ULONG)(sizeof(data))); EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
} }
/// ///
/// Construct class pointing to a `GUID`. /// Construct class pointing to a `GUID`.
/// ///
@ -182,7 +219,6 @@ namespace winstd
EventDataDescCreate(this, &data, (ULONG)(sizeof(data))); EventDataDescCreate(this, &data, (ULONG)(sizeof(data)));
} }
/// ///
/// Construct class pointing to a string. /// Construct class pointing to a string.
/// ///
@ -202,7 +238,6 @@ namespace winstd
} }
} }
/// ///
/// Construct class pointing to a wide string. /// Construct class pointing to a wide string.
/// ///
@ -222,7 +257,6 @@ namespace winstd
} }
} }
/// ///
/// Template to construct pointing to a `std::basic_string<>`. /// Template to construct pointing to a `std::basic_string<>`.
/// ///
@ -237,7 +271,6 @@ namespace winstd
EventDataDescCreate(this, data.c_str(), (ULONG)((data.length() + 1) * sizeof(_Elem))); EventDataDescCreate(this, data.c_str(), (ULONG)((data.length() + 1) * sizeof(_Elem)));
} }
/// ///
/// Construct class pointing to binary data. /// Construct class pointing to binary data.
/// ///
@ -258,7 +291,6 @@ namespace winstd
/// ///
static const event_data blank_event_data; static const event_data blank_event_data;
/// ///
/// EVENT_RECORD wrapper /// EVENT_RECORD wrapper
/// ///
@ -273,7 +305,6 @@ namespace winstd
memset((EVENT_RECORD*)this, 0, sizeof(EVENT_RECORD)); memset((EVENT_RECORD*)this, 0, sizeof(EVENT_RECORD));
} }
/// ///
/// Copies an existing event record. /// Copies an existing event record.
/// ///
@ -285,7 +316,6 @@ namespace winstd
set_user_data_internal(other.UserDataLength, other.UserData); set_user_data_internal(other.UserDataLength, other.UserData);
} }
/// ///
/// Copies an existing event record. /// Copies an existing event record.
/// ///
@ -297,7 +327,6 @@ namespace winstd
set_user_data_internal(other.UserDataLength, other.UserData); set_user_data_internal(other.UserDataLength, other.UserData);
} }
/// ///
/// Moves the event record. /// Moves the event record.
/// ///
@ -308,7 +337,6 @@ namespace winstd
memset((EVENT_RECORD*)&other, 0, sizeof(EVENT_RECORD)); memset((EVENT_RECORD*)&other, 0, sizeof(EVENT_RECORD));
} }
/// ///
/// Destroys event record data and frees the allocated memory. /// Destroys event record data and frees the allocated memory.
/// ///
@ -321,7 +349,6 @@ namespace winstd
delete reinterpret_cast<unsigned char*>(UserData); delete reinterpret_cast<unsigned char*>(UserData);
} }
/// ///
/// Copies an existing event record. /// Copies an existing event record.
/// ///
@ -338,7 +365,6 @@ namespace winstd
return *this; return *this;
} }
/// ///
/// Copies an existing event record. /// Copies an existing event record.
/// ///
@ -355,7 +381,6 @@ namespace winstd
return *this; return *this;
} }
/// ///
/// Moves the event record. /// Moves the event record.
/// ///
@ -371,7 +396,6 @@ namespace winstd
return *this; return *this;
} }
/// ///
/// Sets event record extended data. /// Sets event record extended data.
/// ///
@ -386,7 +410,6 @@ namespace winstd
set_extended_data_internal(count, data); set_extended_data_internal(count, data);
} }
/// ///
/// Sets event record user data. /// Sets event record user data.
/// ///
@ -463,7 +486,6 @@ namespace winstd
} }
}; };
/// ///
/// ETW event provider /// ETW event provider
/// ///
@ -483,7 +505,6 @@ namespace winstd
free_internal(); free_internal();
} }
/// ///
/// Registers the event provider. /// Registers the event provider.
/// ///
@ -502,7 +523,6 @@ namespace winstd
return ulRes; return ulRes;
} }
/// ///
/// Writes an event with no parameters. /// Writes an event with no parameters.
/// ///
@ -518,7 +538,6 @@ namespace winstd
return EventWrite(m_h, EventDescriptor, 0, NULL); return EventWrite(m_h, EventDescriptor, 0, NULL);
} }
/// ///
/// Writes an event with parameters stored in array. /// Writes an event with parameters stored in array.
/// ///
@ -534,7 +553,6 @@ namespace winstd
return EventWrite(m_h, EventDescriptor, UserDataCount, UserData); return EventWrite(m_h, EventDescriptor, UserDataCount, UserData);
} }
/// ///
/// Writes an event with one or more parameter. /// Writes an event with one or more parameter.
/// ///
@ -589,7 +607,6 @@ namespace winstd
#pragma warning(pop) #pragma warning(pop)
} }
/// ///
/// Writes an event with variable number of parameters. /// Writes an event with variable number of parameters.
/// ///
@ -634,7 +651,6 @@ namespace winstd
#pragma warning(pop) #pragma warning(pop)
} }
/// ///
/// Writes a string event. /// Writes a string event.
/// ///
@ -671,7 +687,6 @@ namespace winstd
EventUnregister(m_h); EventUnregister(m_h);
} }
/// ///
/// Receive enable or disable notification requests /// Receive enable or disable notification requests
/// ///
@ -687,7 +702,6 @@ namespace winstd
UNREFERENCED_PARAMETER(FilterData); UNREFERENCED_PARAMETER(FilterData);
} }
/// ///
/// Receive enable or disable notification requests /// Receive enable or disable notification requests
/// ///
@ -702,7 +716,6 @@ namespace winstd
} }
}; };
/// ///
/// ETW session /// ETW session
/// ///
@ -718,7 +731,6 @@ namespace winstd
{ {
} }
/// ///
/// Initializes a new session with an already available object handle. /// Initializes a new session with an already available object handle.
/// ///
@ -732,7 +744,6 @@ namespace winstd
memcpy(m_prop.get(), prop, prop->Wnode.BufferSize); memcpy(m_prop.get(), prop, prop->Wnode.BufferSize);
} }
/// ///
/// Move constructor /// Move constructor
/// ///
@ -744,7 +755,6 @@ namespace winstd
{ {
} }
/// ///
/// Closes the session. /// Closes the session.
/// ///
@ -756,7 +766,6 @@ namespace winstd
free_internal(); free_internal();
} }
/// ///
/// Move assignment /// Move assignment
/// ///
@ -771,7 +780,6 @@ namespace winstd
return *this; return *this;
} }
/// ///
/// Auto-typecasting operator /// Auto-typecasting operator
/// ///
@ -782,7 +790,6 @@ namespace winstd
return m_prop.get(); return m_prop.get();
} }
/// ///
/// Auto-typecasting operator /// Auto-typecasting operator
/// ///
@ -794,7 +801,6 @@ namespace winstd
return reinterpret_cast<LPCTSTR>(reinterpret_cast<const char*>(prop) + prop->LoggerNameOffset); return reinterpret_cast<LPCTSTR>(reinterpret_cast<const char*>(prop) + prop->LoggerNameOffset);
} }
/// ///
/// Sets a new session handle for the class /// Sets a new session handle for the class
/// ///
@ -809,7 +815,6 @@ namespace winstd
m_prop.reset(prop); m_prop.reset(prop);
} }
/// ///
/// Registers and starts an event tracing session. /// Registers and starts an event tracing session.
/// ///
@ -830,7 +835,6 @@ namespace winstd
return ulRes; return ulRes;
} }
/// ///
/// Enables the specified event trace provider. /// Enables the specified event trace provider.
/// ///
@ -855,7 +859,6 @@ namespace winstd
EnableFilterDesc); EnableFilterDesc);
} }
/// ///
/// Disables the specified event trace provider. /// Disables the specified event trace provider.
/// ///
@ -880,7 +883,6 @@ namespace winstd
EnableFilterDesc); EnableFilterDesc);
} }
protected: protected:
/// ///
/// Releases the session. /// Releases the session.
@ -896,7 +898,6 @@ namespace winstd
std::unique_ptr<EVENT_TRACE_PROPERTIES> m_prop; ///< Session properties std::unique_ptr<EVENT_TRACE_PROPERTIES> m_prop; ///< Session properties
}; };
/// ///
/// ETW trace /// ETW trace
/// ///
@ -916,7 +917,6 @@ namespace winstd
free_internal(); free_internal();
} }
/// ///
/// Opens a real-time trace session or log file for consuming. /// Opens a real-time trace session or log file for consuming.
/// ///
@ -948,7 +948,6 @@ namespace winstd
} }
}; };
/// ///
/// Helper class to enable event provider in constructor and disables it in destructor /// Helper class to enable event provider in constructor and disables it in destructor
/// ///
@ -990,7 +989,6 @@ namespace winstd
m_enable_filter_desc); m_enable_filter_desc);
} }
/// ///
/// Enables event trace /// Enables event trace
/// ///
@ -1025,7 +1023,6 @@ namespace winstd
m_enable_filter_desc); m_enable_filter_desc);
} }
/// ///
/// Return result of `EnableTraceEx()` call. /// Return result of `EnableTraceEx()` call.
/// ///
@ -1036,7 +1033,6 @@ namespace winstd
return m_status; return m_status;
} }
/// ///
/// Disables event trace. /// Disables event trace.
/// ///
@ -1069,7 +1065,6 @@ namespace winstd
PEVENT_FILTER_DESCRIPTOR m_enable_filter_desc; ///< Event filter descriptor PEVENT_FILTER_DESCRIPTOR m_enable_filter_desc; ///< Event filter descriptor
}; };
/// ///
/// Helper class to write an event on entry/exit of scope. /// Helper class to write an event on entry/exit of scope.
/// ///
@ -1089,7 +1084,6 @@ namespace winstd
m_ep.write(event_cons, 1, &m_fn_name); m_ep.write(event_cons, 1, &m_fn_name);
} }
/// ///
/// Copies the object /// Copies the object
/// ///
@ -1100,7 +1094,6 @@ namespace winstd
{ {
} }
/// ///
/// Moves the object /// Moves the object
/// ///
@ -1112,7 +1105,6 @@ namespace winstd
other.m_event_dest = NULL; other.m_event_dest = NULL;
} }
/// ///
/// Writes the `event_dest` event /// Writes the `event_dest` event
/// ///
@ -1122,7 +1114,6 @@ namespace winstd
m_ep.write(m_event_dest, 1, &m_fn_name); m_ep.write(m_event_dest, 1, &m_fn_name);
} }
/// ///
/// Copies the object /// Copies the object
/// ///
@ -1137,7 +1128,6 @@ namespace winstd
return *this; return *this;
} }
/// ///
/// Moves the object /// Moves the object
/// ///
@ -1153,14 +1143,12 @@ namespace winstd
return *this; return *this;
} }
protected: protected:
event_provider &m_ep; ///< Reference to event provider in use event_provider &m_ep; ///< Reference to event provider in use
const EVENT_DESCRIPTOR *m_event_dest; ///< Event descriptor at destruction const EVENT_DESCRIPTOR *m_event_dest; ///< Event descriptor at destruction
EVENT_DATA_DESCRIPTOR m_fn_name; ///< Function name EVENT_DATA_DESCRIPTOR m_fn_name; ///< Function name
}; };
/// ///
/// Helper template to write an event on entry/exit of scope with one parameter (typically result). /// Helper template to write an event on entry/exit of scope with one parameter (typically result).
/// ///
@ -1182,7 +1170,6 @@ namespace winstd
m_ep.write(event_cons, 1, m_desc); m_ep.write(event_cons, 1, m_desc);
} }
/// ///
/// Copies the object /// Copies the object
/// ///
@ -1194,7 +1181,6 @@ namespace winstd
m_desc[0] = other.m_desc[0]; m_desc[0] = other.m_desc[0];
} }
/// ///
/// Moves the object /// Moves the object
/// ///
@ -1207,7 +1193,6 @@ namespace winstd
other.m_event_dest = NULL; other.m_event_dest = NULL;
} }
/// ///
/// Writes the `event_dest` event /// Writes the `event_dest` event
/// ///
@ -1219,7 +1204,6 @@ namespace winstd
} }
} }
/// ///
/// Copies the object /// Copies the object
/// ///
@ -1235,7 +1219,6 @@ namespace winstd
return *this; return *this;
} }
/// ///
/// Moves the object /// Moves the object
/// ///
@ -1252,7 +1235,6 @@ namespace winstd
return *this; return *this;
} }
protected: protected:
event_provider &m_ep; ///< Reference to event provider in use event_provider &m_ep; ///< Reference to event provider in use
const EVENT_DESCRIPTOR *m_event_dest; ///< Event descriptor at destruction const EVENT_DESCRIPTOR *m_event_dest; ///< Event descriptor at destruction
@ -1262,74 +1244,3 @@ namespace winstd
/// @} /// @}
} }
#pragma warning(push)
#pragma warning(disable: 4505) // Don't warn on unused code
static _Success_(return == ERROR_SUCCESS) ULONG TdhGetEventInformation(_In_ PEVENT_RECORD pEvent, _In_ ULONG TdhContextCount, _In_reads_opt_(TdhContextCount) PTDH_CONTEXT pTdhContext, _Out_ std::unique_ptr<TRACE_EVENT_INFO> &info)
{
BYTE szBuffer[WINSTD_STACK_BUFFER_BYTES];
ULONG ulSize = sizeof(szBuffer), ulResult;
// Try with stack buffer first.
ulResult = TdhGetEventInformation(pEvent, TdhContextCount, pTdhContext, (PTRACE_EVENT_INFO)szBuffer, &ulSize);
if (ulResult == ERROR_SUCCESS) {
// Copy from stack.
info.reset(reinterpret_cast<PTRACE_EVENT_INFO>(new char[ulSize]));
memcpy(info.get(), szBuffer, ulSize);
return ERROR_SUCCESS;
} else if (ulResult == ERROR_INSUFFICIENT_BUFFER) {
// Create buffer on heap and retry.
info.reset(reinterpret_cast<PTRACE_EVENT_INFO>(new char[ulSize]));
return TdhGetEventInformation(pEvent, TdhContextCount, pTdhContext, info.get(), &ulSize);
}
return ulResult;
}
static _Success_(return == ERROR_SUCCESS) ULONG TdhGetEventMapInformation(_In_ PEVENT_RECORD pEvent, _In_ LPWSTR pMapName, _Inout_ std::unique_ptr<EVENT_MAP_INFO> &info)
{
BYTE szBuffer[WINSTD_STACK_BUFFER_BYTES];
ULONG ulSize = sizeof(szBuffer), ulResult;
// Try with stack buffer first.
ulResult = TdhGetEventMapInformation(pEvent, pMapName, (PEVENT_MAP_INFO)szBuffer, &ulSize);
if (ulResult == ERROR_SUCCESS) {
// Copy from stack.
info.reset(reinterpret_cast<PEVENT_MAP_INFO>(new char[ulSize]));
memcpy(info.get(), szBuffer, ulSize);
return ERROR_SUCCESS;
} else if (ulResult == ERROR_INSUFFICIENT_BUFFER) {
// Create buffer on heap and retry.
info.reset(reinterpret_cast<PEVENT_MAP_INFO>(new char[ulSize]));
return TdhGetEventMapInformation(pEvent, pMapName, info.get(), &ulSize);
}
return ulResult;
}
template<class _Ty, class _Ax>
static _Success_(return == ERROR_SUCCESS) ULONG TdhGetProperty(_In_ PEVENT_RECORD pEvent, _In_ ULONG TdhContextCount, _In_reads_opt_(TdhContextCount) PTDH_CONTEXT pTdhContext, _In_ ULONG PropertyDataCount, _In_reads_(PropertyDataCount) PPROPERTY_DATA_DESCRIPTOR pPropertyData, _Inout_ std::vector<_Ty, _Ax> &aData)
{
ULONG ulSize, ulResult;
// Query property size.
ulResult = TdhGetPropertySize(pEvent, TdhContextCount, pTdhContext, PropertyDataCount, pPropertyData, &ulSize);
if (ulResult == ERROR_SUCCESS) {
if (ulSize) {
// Query property value.
aData.resize((ulSize + sizeof(_Ty) - 1) / sizeof(_Ty));
ulResult = TdhGetProperty(pEvent, TdhContextCount, pTdhContext, PropertyDataCount, pPropertyData, ulSize, reinterpret_cast<LPBYTE>(aData.data()));
} else {
// Property value size is zero.
aData.clear();
}
}
return ulResult;
}
#pragma warning(pop)

View File

@ -3,28 +3,16 @@
Copyright © 1991-2022 Amebis Copyright © 1991-2022 Amebis
*/ */
/// #pragma once
/// \defgroup WinStdGdiAPI GDI API
/// Integrates WinStd classes with Microsoft Windows GDI
///
#include "Common.h" #include "Common.h"
namespace winstd namespace winstd
{ {
template<class T> class gdi_handle; ///
class dc; /// \defgroup WinStdGdiAPI GDI API
class window_dc; /// Integrates WinStd classes with Microsoft Windows GDI
class dc_selector; ///
}
#pragma once
namespace winstd
{
/// \addtogroup WinStdGdiAPI
/// @{ /// @{
/// ///
@ -59,7 +47,6 @@ namespace winstd
} }
}; };
/// ///
/// Device context wrapper class /// Device context wrapper class
/// ///
@ -91,7 +78,6 @@ namespace winstd
} }
}; };
/// ///
/// Device context wrapper class /// Device context wrapper class
/// ///
@ -148,7 +134,6 @@ namespace winstd
HWND m_hwnd; ///< Window handle HWND m_hwnd; ///< Window handle
}; };
/// ///
/// Context scope DC object restorer /// Context scope DC object restorer
/// ///
@ -169,7 +154,6 @@ namespace winstd
{ {
} }
/// ///
/// Restores original object. /// Restores original object.
/// ///
@ -181,7 +165,6 @@ namespace winstd
SelectObject(m_hdc, m_orig); SelectObject(m_hdc, m_orig);
} }
/// ///
/// Return result of `SelectObject()` call. /// Return result of `SelectObject()` call.
/// ///

View File

@ -4,94 +4,21 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
#pragma once
#include "Common.h"
#include <MsiQuery.h>
#include <string>
#include <vector>
/// ///
/// \defgroup WinStdMSIAPI Microsoft Installer API /// \defgroup WinStdMSIAPI Microsoft Installer API
/// Integrates WinStd classes with Microsoft Installer API /// Integrates WinStd classes with Microsoft Installer API
/// ///
#include "Common.h"
#include <MsiQuery.h>
#include <string>
#include <vector>
/// \addtogroup WinStdMSIAPI /// \addtogroup WinStdMSIAPI
/// @{ /// @{
/// @copydoc MsiGetPropertyW() /// @copydoc MsiGetPropertyW()
template<class _Traits, class _Ax>
static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue);
///
/// Gets the value for an installer property and stores it in a std::wstring string.
///
/// \sa [MsiGetProperty function](https://msdn.microsoft.com/en-us/library/aa370134.aspx)
///
template<class _Traits, class _Ax>
static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue);
/// @copydoc MsiRecordGetStringW()
template<class _Traits, class _Ax>
static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue);
///
/// Returns the string value of a record field and stores it in a std::wstring string.
///
/// \sa [MsiRecordGetString function](https://msdn.microsoft.com/en-us/library/aa370368.aspx)
///
template<class _Traits, class _Ax>
static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue);
/// @copydoc MsiFormatRecordW()
template<class _Traits, class _Ax>
static UINT MsiFormatRecordA(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue);
///
/// Formats record field data and properties using a format string and stores it in a std::wstring string.
///
/// \sa [MsiFormatRecord function](https://msdn.microsoft.com/en-us/library/aa370109.aspx)
///
template<class _Traits, class _Ax>
static UINT MsiFormatRecordW(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue);
///
/// Reads bytes from a record stream field into a std::vector buffer.
///
/// \sa [MsiRecordReadStream function](https://msdn.microsoft.com/en-us/library/aa370370.aspx)
///
template<class _Ty, class _Ax>
static UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::vector<_Ty, _Ax> &binData);
/// @copydoc MsiGetTargetPathW()
template<class _Traits, class _Ax>
static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue);
///
/// Returns the full target path for a folder in the Directory table and stores it in a std::wstring string.
///
/// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
///
template<class _Traits, class _Ax>
static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue);
/// @copydoc MsiGetComponentPathW()
template<class _Traits, class _Ax>
static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue);
///
/// Returns the full path to an installed component. If the key path for the component is a registry key then the registry key is returned.
///
/// \sa [MsiGetComponentPath function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa370112.aspx)
///
template<class _Traits, class _Ax>
static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue);
/// @}
#pragma once
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue) static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
@ -119,7 +46,11 @@ static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inou
} }
} }
///
/// Gets the value for an installer property and stores it in a std::wstring string.
///
/// \sa [MsiGetProperty function](https://msdn.microsoft.com/en-us/library/aa370134.aspx)
///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{ {
@ -145,7 +76,7 @@ static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Ino
} }
} }
/// @copydoc MsiRecordGetStringW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue) static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
@ -173,7 +104,11 @@ static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField
} }
} }
///
/// Returns the string value of a record field and stores it in a std::wstring string.
///
/// \sa [MsiRecordGetString function](https://msdn.microsoft.com/en-us/library/aa370368.aspx)
///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{ {
@ -199,7 +134,7 @@ static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField
} }
} }
/// @copydoc MsiFormatRecordW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiFormatRecordA(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue) static UINT MsiFormatRecordA(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
@ -227,7 +162,11 @@ static UINT MsiFormatRecordA(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _I
} }
} }
///
/// Formats record field data and properties using a format string and stores it in a std::wstring string.
///
/// \sa [MsiFormatRecord function](https://msdn.microsoft.com/en-us/library/aa370109.aspx)
///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiFormatRecordW(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) static UINT MsiFormatRecordW(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{ {
@ -253,7 +192,11 @@ static UINT MsiFormatRecordW(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _I
} }
} }
///
/// Reads bytes from a record stream field into a std::vector buffer.
///
/// \sa [MsiRecordReadStream function](https://msdn.microsoft.com/en-us/library/aa370370.aspx)
///
template<class _Ty, class _Ax> template<class _Ty, class _Ax>
static UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::vector<_Ty, _Ax> &binData) static UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::vector<_Ty, _Ax> &binData)
{ {
@ -273,7 +216,7 @@ static UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField
} }
} }
/// @copydoc MsiGetTargetPathW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Out_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
@ -301,7 +244,11 @@ static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _
} }
} }
///
/// Returns the full target path for a folder in the Directory table and stores it in a std::wstring string.
///
/// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{ {
@ -327,7 +274,7 @@ static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder,
} }
} }
/// @copydoc MsiGetComponentPathW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue) static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
@ -353,7 +300,11 @@ static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR
} }
} }
///
/// Returns the full path to an installed component. If the key path for the component is a registry key then the registry key is returned.
///
/// \sa [MsiGetComponentPath function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa370112.aspx)
///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{ {
@ -378,3 +329,5 @@ static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWST
return state; return state;
} }
} }
/// @}

View File

@ -4,33 +4,47 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
#pragma once
#include "Common.h"
#include <Security.h>
#include <string>
/// ///
/// \defgroup WinStdSecurityAPI Security API /// \defgroup WinStdSecurityAPI Security API
/// Integrates WinStd classes with Microsoft Security API /// Integrates WinStd classes with Microsoft Security API
/// ///
/// @{
#include "Common.h"
#include <Security.h>
#include <string>
namespace winstd
{
class sec_credentials;
class sec_context;
class sec_buffer_desc;
class sec_runtime_error;
}
#if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL) #if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL)
/// \addtogroup WinStdSecurityAPI
/// @{
/// @copydoc GetUserNameExW() /// @copydoc GetUserNameExW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOLEAN GetUserNameExA(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<char, _Traits, _Ax> &sName); static BOOLEAN GetUserNameExA(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<char, _Traits, _Ax> &sName)
{
assert(0); // TODO: Test this code.
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
ULONG ulSize = _countof(szStackBuffer);
// Try with stack buffer first.
if (::GetUserNameExA(NameFormat, szStackBuffer, &ulSize)) {
// Copy from stack.
sName.assign(szStackBuffer, ulSize);
return TRUE;
} else {
if (::GetLastError() == ERROR_MORE_DATA) {
// Allocate buffer on heap and retry.
std::unique_ptr<char[]> szBuffer(new char[ulSize]);
if (::GetUserNameExA(NameFormat, szBuffer.get(), &ulSize)) {
sName.assign(szBuffer.get(), ulSize);
return TRUE;
}
}
}
return FALSE;
}
/// ///
/// Retrieves the name of the user or other security principal associated with the calling thread and stores it in a std::wstring string. /// Retrieves the name of the user or other security principal associated with the calling thread and stores it in a std::wstring string.
@ -38,15 +52,36 @@ static BOOLEAN GetUserNameExA(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std:
/// \sa [GetUserNameEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx) /// \sa [GetUserNameEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOLEAN GetUserNameExW(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sName); static BOOLEAN GetUserNameExW(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sName)
{
assert(0); // TODO: Test this code.
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
ULONG ulSize = _countof(szStackBuffer);
// Try with stack buffer first.
if (::GetUserNameExW(NameFormat, szStackBuffer, &ulSize)) {
// Copy from stack.
sName.assign(szStackBuffer, ulSize);
return TRUE;
} else {
if (::GetLastError() == ERROR_MORE_DATA) {
// Allocate buffer on heap and retry.
std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[ulSize]);
if (::GetUserNameExW(NameFormat, szBuffer.get(), &ulSize)) {
sName.assign(szBuffer.get(), ulSize);
return TRUE;
}
}
}
return FALSE;
}
#endif #endif
/// @} /// @}
#pragma once
namespace winstd namespace winstd
{ {
/// \addtogroup WinStdSecurityAPI /// \addtogroup WinStdSecurityAPI
@ -161,7 +196,6 @@ namespace winstd
TimeStamp m_expires; ///< Credentials expiration time TimeStamp m_expires; ///< Credentials expiration time
}; };
/// ///
/// PCtxtHandle wrapper class /// PCtxtHandle wrapper class
/// ///
@ -285,7 +319,6 @@ namespace winstd
TimeStamp m_expires; ///< Context expiration time TimeStamp m_expires; ///< Context expiration time
}; };
/// ///
/// SecBufferDesc wrapper class /// SecBufferDesc wrapper class
/// ///
@ -318,10 +351,7 @@ namespace winstd
/// @} /// @}
/// /// \addtogroup WinStdExceptions
/// \defgroup WinStdExceptions Exceptions
/// Additional exceptions
///
/// @{ /// @{
/// ///
@ -342,7 +372,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception /// Constructs an exception
/// ///
@ -353,7 +382,6 @@ namespace winstd
{ {
} }
/// ///
/// Copies an exception /// Copies an exception
/// ///
@ -366,63 +394,3 @@ namespace winstd
/// @} /// @}
} }
#if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL)
template<class _Traits, class _Ax>
static BOOLEAN GetUserNameExA(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<char, _Traits, _Ax> &sName)
{
assert(0); // TODO: Test this code.
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
ULONG ulSize = _countof(szStackBuffer);
// Try with stack buffer first.
if (::GetUserNameExA(NameFormat, szStackBuffer, &ulSize)) {
// Copy from stack.
sName.assign(szStackBuffer, ulSize);
return TRUE;
} else {
if (::GetLastError() == ERROR_MORE_DATA) {
// Allocate buffer on heap and retry.
std::unique_ptr<char[]> szBuffer(new char[ulSize]);
if (::GetUserNameExA(NameFormat, szBuffer.get(), &ulSize)) {
sName.assign(szBuffer.get(), ulSize);
return TRUE;
}
}
}
return FALSE;
}
template<class _Traits, class _Ax>
static BOOLEAN GetUserNameExW(_In_ EXTENDED_NAME_FORMAT NameFormat, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sName)
{
assert(0); // TODO: Test this code.
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
ULONG ulSize = _countof(szStackBuffer);
// Try with stack buffer first.
if (::GetUserNameExW(NameFormat, szStackBuffer, &ulSize)) {
// Copy from stack.
sName.assign(szStackBuffer, ulSize);
return TRUE;
} else {
if (::GetLastError() == ERROR_MORE_DATA) {
// Allocate buffer on heap and retry.
std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[ulSize]);
if (::GetUserNameExW(NameFormat, szBuffer.get(), &ulSize)) {
sName.assign(szBuffer.get(), ulSize);
return TRUE;
}
}
}
return FALSE;
}
#endif

View File

@ -4,28 +4,17 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
///
/// \defgroup SetupAPI Setup API
/// Integrates WinStd classes with Microsoft Setup API
///
#include "Common.h"
namespace winstd
{
class setup_device_info_list;
class setup_driver_info_list_builder;
}
#pragma once #pragma once
#include "Common.h"
#include <SetupAPI.h> #include <SetupAPI.h>
namespace winstd namespace winstd
{ {
/// \addtogroup SetupAPI ///
/// \defgroup SetupAPI Setup API
/// Integrates WinStd classes with Microsoft Setup API
///
/// @{ /// @{
/// ///
@ -108,7 +97,6 @@ namespace winstd
} }
}; };
/// ///
/// Builds a list of drivers in constructor and deletes it in destructor /// Builds a list of drivers in constructor and deletes it in destructor
/// ///
@ -145,7 +133,6 @@ namespace winstd
SetupDiDestroyDriverInfoList(m_DeviceInfoSet, m_DeviceInfoData, m_DriverType); SetupDiDestroyDriverInfoList(m_DeviceInfoSet, m_DeviceInfoData, m_DriverType);
} }
/// ///
/// Return result of `SetupDiBuildDriverInfoList()` call. /// Return result of `SetupDiBuildDriverInfoList()` call.
/// ///

View File

@ -4,36 +4,19 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
#pragma once
#include "Common.h"
#include <Shlwapi.h>
#include <string>
/// ///
/// \defgroup WinStdShellWAPI Shell API /// \defgroup WinStdShellWAPI Shell API
/// Integrates WinStd classes with Microsoft Shell API /// Integrates WinStd classes with Microsoft Shell API
/// ///
#include "Common.h"
#include <Shlwapi.h>
#include <string>
/// \addtogroup WinStdShellWAPI
/// @{ /// @{
/// @copydoc PathCanonicalizeW() /// @copydoc PathCanonicalizeW()
template<class _Traits, class _Ax>
static BOOL PathCanonicalizeA(_Inout_ std::basic_string<char, _Traits, _Ax> &sValue, _In_ LPCSTR pszPath);
///
/// Simplifies a path by removing navigation elements such as "." and ".." to produce a direct, well-formed path, and stores it in a std::wstring string.
///
/// \sa [PathCanonicalize function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773569.aspx)
///
template<class _Traits, class _Ax>
static BOOL PathCanonicalizeW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, _In_ LPCWSTR pszPath);
/// @}
#pragma once
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOL PathCanonicalizeA(_Inout_ std::basic_string<char, _Traits, _Ax> &sValue, _In_ LPCSTR pszPath) static BOOL PathCanonicalizeA(_Inout_ std::basic_string<char, _Traits, _Ax> &sValue, _In_ LPCSTR pszPath)
{ {
@ -46,7 +29,11 @@ static BOOL PathCanonicalizeA(_Inout_ std::basic_string<char, _Traits, _Ax> &sVa
return bResult; return bResult;
} }
///
/// Simplifies a path by removing navigation elements such as "." and ".." to produce a direct, well-formed path, and stores it in a std::wstring string.
///
/// \sa [PathCanonicalize function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773569.aspx)
///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOL PathCanonicalizeW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, _In_ LPCWSTR pszPath) static BOOL PathCanonicalizeW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, _In_ LPCWSTR pszPath)
{ {
@ -57,3 +44,5 @@ static BOOL PathCanonicalizeW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax> &
sValue.assign(szBuffer, bResult ? MAX_PATH : 0); sValue.assign(szBuffer, bResult ? MAX_PATH : 0);
return bResult; return bResult;
} }
/// @}

View File

@ -4,28 +4,20 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
/// #pragma once
/// \defgroup WinStdWLANAPI WLAN API
/// Integrates WinStd classes with Microsoft WLAN API
///
#include "Common.h" #include "Common.h"
#include <wlanapi.h> #include <wlanapi.h>
#include <string> #include <string>
// Must not statically link to Wlanapi.dll as it is not available on Windows // Must not statically link to Wlanapi.dll as it is not available on Windows
// without a WLAN interface. // without a WLAN interface.
extern DWORD (WINAPI *pfnWlanReasonCodeToString)(__in DWORD dwReasonCode, __in DWORD dwBufferSize, __in_ecount(dwBufferSize) PWCHAR pStringBuffer, __reserved PVOID pReserved); extern DWORD (WINAPI *pfnWlanReasonCodeToString)(__in DWORD dwReasonCode, __in DWORD dwBufferSize, __in_ecount(dwBufferSize) PWCHAR pStringBuffer, __reserved PVOID pReserved);
namespace winstd { ///
template <class _Ty> struct WlanFreeMemory_delete; /// \defgroup WinStdWLANAPI WLAN API
template <class _Ty> struct WlanFreeMemory_delete<_Ty[]>; /// Integrates WinStd classes with Microsoft WLAN API
class wlan_handle; ///
}
/// \addtogroup WinStdWLANAPI
/// @{ /// @{
/// ///
@ -38,13 +30,36 @@ namespace winstd {
/// function must be loaded dynamically. /// function must be loaded dynamically.
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, __reserved PVOID pReserved); static DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, __reserved PVOID pReserved)
{
DWORD dwSize = 0;
if (!::pfnWlanReasonCodeToString)
return ERROR_CALL_NOT_IMPLEMENTED;
for (;;) {
// Increment size and allocate buffer.
dwSize += 1024;
std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwSize]);
// Try!
DWORD dwResult = ::pfnWlanReasonCodeToString(dwReasonCode, dwSize, szBuffer.get(), pReserved);
if (dwResult == ERROR_SUCCESS) {
DWORD dwLength = (DWORD)wcsnlen(szBuffer.get(), dwSize);
if (dwLength < dwSize - 1) {
// Buffer was long enough.
sValue.assign(szBuffer.get(), dwLength);
return ERROR_SUCCESS;
}
} else {
// Return error code.
return dwResult;
}
}
}
/// @} /// @}
#pragma once
namespace winstd namespace winstd
{ {
/// \addtogroup WinStdWLANAPI /// \addtogroup WinStdWLANAPI
@ -76,7 +91,6 @@ namespace winstd
} }
}; };
/// ///
/// Deleter for unique_ptr to array of unknown size using WlanFreeMemory /// Deleter for unique_ptr to array of unknown size using WlanFreeMemory
/// ///
@ -107,7 +121,6 @@ namespace winstd
} }
}; };
/// ///
/// WLAN handle wrapper /// WLAN handle wrapper
/// ///
@ -163,33 +176,3 @@ namespace winstd
/// @} /// @}
} }
template<class _Traits, class _Ax>
static DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, __reserved PVOID pReserved)
{
DWORD dwSize = 0;
if (!::pfnWlanReasonCodeToString)
return ERROR_CALL_NOT_IMPLEMENTED;
for (;;) {
// Increment size and allocate buffer.
dwSize += 1024;
std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[dwSize]);
// Try!
DWORD dwResult = ::pfnWlanReasonCodeToString(dwReasonCode, dwSize, szBuffer.get(), pReserved);
if (dwResult == ERROR_SUCCESS) {
DWORD dwLength = (DWORD)wcsnlen(szBuffer.get(), dwSize);
if (dwLength < dwSize - 1) {
// Buffer was long enough.
sValue.assign(szBuffer.get(), dwLength);
return ERROR_SUCCESS;
}
} else {
// Return error code.
return dwResult;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -4,31 +4,19 @@
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
///
/// \defgroup WinSock2API WinSock2 API
/// Integrates WinStd classes with Microsoft WinSock2 API
///
#include "Common.h"
namespace winstd
{
class ws2_runtime_error;
#if (NTDDI_VERSION >= NTDDI_WINXPSP2) || (_WIN32_WINNT >= 0x0502)
class addrinfo;
#endif
}
#pragma once #pragma once
#include "Common.h"
#include <WinSock2.h> #include <WinSock2.h>
#include <ws2def.h> #include <ws2def.h>
#include <WS2tcpip.h> #include <WS2tcpip.h>
namespace winstd namespace winstd
{ {
/// \addtogroup WinStdExceptions ///
/// \defgroup WinSock2API WinSock2 API
/// Integrates WinStd classes with Microsoft WinSock2 API
///
/// @{ /// @{
/// ///
@ -47,7 +35,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception /// Constructs an exception
/// ///
@ -58,7 +45,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception using `WSAGetLastError()` /// Constructs an exception using `WSAGetLastError()`
/// ///
@ -68,7 +54,6 @@ namespace winstd
{ {
} }
/// ///
/// Constructs an exception using `WSAGetLastError()` /// Constructs an exception using `WSAGetLastError()`
/// ///
@ -78,7 +63,6 @@ namespace winstd
{ {
} }
/// ///
/// Returns a user-readable Windows error message /// Returns a user-readable Windows error message
/// ///
@ -98,7 +82,6 @@ namespace winstd
/// @} /// @}
/// \addtogroup WinSock2API /// \addtogroup WinSock2API
/// @{ /// @{
@ -141,7 +124,6 @@ namespace winstd
free_internal(); free_internal();
} }
protected: protected:
/// ///
/// Frees address information /// Frees address information

View File

@ -6,26 +6,15 @@
#pragma once #pragma once
///
/// \defgroup WinTrustAPI WinTrust API
/// Integrates WinStd classes with Microsoft WinTrust API
///
#include "Common.h" #include "Common.h"
#include <WinTrust.h> #include <WinTrust.h>
namespace winstd namespace winstd
{ {
class wintrust; ///
} /// \defgroup WinTrustAPI WinTrust API
/// Integrates WinStd classes with Microsoft WinTrust API
#pragma once ///
namespace winstd
{
/// \addtogroup WinTrustAPI
/// @{ /// @{
/// ///