diff --git a/include/WinStd/Base64.h b/include/WinStd/Base64.h
index 1c90a379..596578e3 100644
--- a/include/WinStd/Base64.h
+++ b/include/WinStd/Base64.h
@@ -1,280 +1,287 @@
-/*
- Copyright 1991-2018 Amebis
- Copyright 2016 GÉANT
-
- This file is part of WinStd.
-
- Setup is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Setup is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Setup. If not, see .
-*/
-
-///
-/// \defgroup WinStdBase64 Base64 conversion
-/// Provides Base64 conversion for WinStd classes
-///
-
-#include "Common.h"
-
-#include
-#include
-
-namespace winstd
-{
- class WINSTD_API base64_enc;
- class WINSTD_API base64_dec;
-}
-
-#pragma once
-
-
-namespace winstd
-{
- /// \addtogroup WinStdBase64
- /// @{
-
- ///
- /// Base64 encoding session
- ///
- class WINSTD_API base64_enc
- {
- public:
- ///
- /// Constructs blank encoding session
- ///
- inline base64_enc() : num(0)
- {
- }
-
-
- ///
- /// Encodes one block of information, and _appends_ it to the output
- ///
- /// \param[out] out Output
- /// \param[in ] data Data to encode
- /// \param[in ] size Length of `data` in bytes
- /// \param[in ] is_last Is this the last block of data?
- ///
- template
- inline void encode(_Out_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_bytecount_(size) const void *data, _In_ size_t size, _In_opt_ bool is_last = true)
- {
- assert(data || !size);
-
- // Preallocate output
- out.reserve(out.size() + enc_size(size));
-
- // Convert data character by character.
- for (size_t i = 0;; i++) {
- if (num >= 3) {
- encode(out);
- num = 0;
- }
-
- if (i >= size)
- break;
-
- buf[num++] = reinterpret_cast(data)[i];
- }
-
- // If this is the last block, flush the buffer.
- if (is_last && num) {
- encode(out, num);
- num = 0;
- }
- }
-
-
- ///
- /// Resets encoding session
- ///
- inline void clear()
- {
- num = 0;
- }
-
-
- ///
- /// Returns maximum encoded size
- ///
- /// \param size Number of bytes to encode
- ///
- /// \returns Maximum number of bytes for the encoded data of `size` length
- ///
- inline size_t enc_size(size_t size) const
- {
- return ((num + size + 2)/3)*4;
- }
-
-
- protected:
- ///
- /// Encodes one complete internal buffer of data
- ///
- template
- inline void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out)
- {
- out += lookup[ buf[0] >> 2 ];
- out += lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
- out += lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
- out += lookup[ buf[2] & 0x3f];
- }
-
-
- ///
- /// Encodes partial internal buffer of data
- ///
- template
- inline void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_ size_t size)
- {
- if (size > 0) {
- out += lookup[buf[0] >> 2];
- if (size > 1) {
- out += lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
- if (size > 2) {
- out += lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
- out += lookup[buf[2] & 0x3f];
- } else {
- out += lookup[(buf[1] << 2) & 0x3f];
- out += '=';
- }
- } else {
- out += lookup[(buf[0] << 4) & 0x3f];
- out += '=';
- out += '=';
- }
- } else {
- out += '=';
- out += '=';
- out += '=';
- out += '=';
- }
- }
-
-
- protected:
- unsigned char buf[3]; ///< Internal buffer
- size_t num; ///< Number of bytes used in `buf`
-
- /// \cond internal
- static const char lookup[64];
- /// \endcond
- };
-
-
- ///
- /// Base64 decoding session
- ///
- class WINSTD_API base64_dec
- {
- public:
- ///
- /// Constructs blank decoding session
- ///
- inline base64_dec() : num(0)
- {
- }
-
-
- ///
- /// Decodes one block of information, and _appends_ it to the output
- ///
- /// \param[out] out Output
- /// \param[in ] is_last Was this the last block of data?
- /// \param[in ] data Data to decode
- /// \param[in ] size Length of `data` in bytes
- ///
- template
- inline void decode(_Out_ std::vector<_Ty, _Ax> &out, _Out_ bool &is_last, _In_z_count_(size) const _Tchr *data, _In_ size_t size)
- {
- is_last = false;
-
- // Trim data size to first terminator.
- for (size_t k = 0; k < size; k++)
- if (!data[k]) { size = k; break; }
-
- // Preallocate output
- out.reserve(out.size() + dec_size(size));
-
- for (size_t i = 0;; i++) {
- if (num >= 4) {
- // Buffer full; decode it.
- size_t nibbles = decode(out);
- num = 0;
- if (nibbles < 3) {
- is_last = true;
- break;
- }
- }
-
- if (i >= size)
- break;
-
- int x = data[i];
- if ((buf[num] = x < _countof(lookup) ? lookup[x] : 255) != 255)
- num++;
- }
- }
-
-
- ///
- /// Resets decoding session
- ///
- inline void clear()
- {
- num = 0;
- }
-
-
- ///
- /// Returns maximum decoded size
- ///
- /// \param size Number of bytes to decode
- ///
- /// \returns Maximum number of bytes for the decoded data of `size` length
- ///
- inline size_t dec_size(size_t size) const
- {
- return ((num + size + 3)/4)*3;
- }
-
-
- protected:
- ///
- /// Decodes one complete internal buffer of data
- ///
- template
- inline size_t decode(_Inout_ std::vector<_Ty, _Ax> &out)
- {
- out.push_back((_Ty)(((buf[0] << 2) | (buf[1] >> 4)) & 0xff));
- if (buf[2] < 64) {
- out.push_back((_Ty)(((buf[1] << 4) | (buf[2] >> 2)) & 0xff));
- if (buf[3] < 64) {
- out.push_back((_Ty)(((buf[2] << 6) | buf[3]) & 0xff));
- return 3;
- } else
- return 2;
- } else
- return 1;
- }
-
-
- protected:
- unsigned char buf[4]; ///< Internal buffer
- size_t num; ///< Number of bytes used in `buf`
-
- /// \cond internal
- static const unsigned char lookup[256];
- /// \endcond
- };
-
- /// @}
-}
+/*
+ Copyright 1991-2018 Amebis
+ Copyright 2016 GÉANT
+
+ This file is part of WinStd.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+///
+/// \defgroup WinStdBase64 Base64 conversion
+/// Provides Base64 conversion for WinStd classes
+///
+
+#include "Common.h"
+
+#include
+#include
+
+namespace winstd
+{
+ class WINSTD_API base64_enc;
+ class WINSTD_API base64_dec;
+}
+
+#pragma once
+
+
+namespace winstd
+{
+ /// \addtogroup WinStdBase64
+ /// @{
+
+ ///
+ /// Base64 encoding session
+ ///
+ class WINSTD_API base64_enc
+ {
+ public:
+ ///
+ /// Constructs blank encoding session
+ ///
+ inline base64_enc() : num(0)
+ {
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = 0;
+ }
+
+
+ ///
+ /// Encodes one block of information, and _appends_ it to the output
+ ///
+ /// \param[out] out Output
+ /// \param[in ] data Data to encode
+ /// \param[in ] size Length of `data` in bytes
+ /// \param[in ] is_last Is this the last block of data?
+ ///
+ template
+ inline void encode(_Out_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_bytecount_(size) const void *data, _In_ size_t size, _In_opt_ bool is_last = true)
+ {
+ assert(data || !size);
+
+ // Preallocate output
+ out.reserve(out.size() + enc_size(size));
+
+ // Convert data character by character.
+ for (size_t i = 0;; i++) {
+ if (num >= 3) {
+ encode(out);
+ num = 0;
+ }
+
+ if (i >= size)
+ break;
+
+ buf[num++] = reinterpret_cast(data)[i];
+ }
+
+ // If this is the last block, flush the buffer.
+ if (is_last && num) {
+ encode(out, num);
+ num = 0;
+ }
+ }
+
+
+ ///
+ /// Resets encoding session
+ ///
+ inline void clear()
+ {
+ num = 0;
+ }
+
+
+ ///
+ /// Returns maximum encoded size
+ ///
+ /// \param size Number of bytes to encode
+ ///
+ /// \returns Maximum number of bytes for the encoded data of `size` length
+ ///
+ inline size_t enc_size(size_t size) const
+ {
+ return ((num + size + 2)/3)*4;
+ }
+
+
+ protected:
+ ///
+ /// Encodes one complete internal buffer of data
+ ///
+ template
+ inline void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out)
+ {
+ out += lookup[ buf[0] >> 2 ];
+ out += lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
+ out += lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
+ out += lookup[ buf[2] & 0x3f];
+ }
+
+
+ ///
+ /// Encodes partial internal buffer of data
+ ///
+ template
+ inline void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_ size_t size)
+ {
+ if (size > 0) {
+ out += lookup[buf[0] >> 2];
+ if (size > 1) {
+ out += lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
+ if (size > 2) {
+ out += lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
+ out += lookup[buf[2] & 0x3f];
+ } else {
+ out += lookup[(buf[1] << 2) & 0x3f];
+ out += '=';
+ }
+ } else {
+ out += lookup[(buf[0] << 4) & 0x3f];
+ out += '=';
+ out += '=';
+ }
+ } else {
+ out += '=';
+ out += '=';
+ out += '=';
+ out += '=';
+ }
+ }
+
+
+ protected:
+ unsigned char buf[3]; ///< Internal buffer
+ size_t num; ///< Number of bytes used in `buf`
+
+ /// \cond internal
+ static const char lookup[64];
+ /// \endcond
+ };
+
+
+ ///
+ /// Base64 decoding session
+ ///
+ class WINSTD_API base64_dec
+ {
+ public:
+ ///
+ /// Constructs blank decoding session
+ ///
+ inline base64_dec() : num(0)
+ {
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+ }
+
+
+ ///
+ /// Decodes one block of information, and _appends_ it to the output
+ ///
+ /// \param[out] out Output
+ /// \param[in ] is_last Was this the last block of data?
+ /// \param[in ] data Data to decode
+ /// \param[in ] size Length of `data` in bytes
+ ///
+ template
+ inline void decode(_Out_ std::vector<_Ty, _Ax> &out, _Out_ bool &is_last, _In_z_count_(size) const _Tchr *data, _In_ size_t size)
+ {
+ is_last = false;
+
+ // Trim data size to first terminator.
+ for (size_t k = 0; k < size; k++)
+ if (!data[k]) { size = k; break; }
+
+ // Preallocate output
+ out.reserve(out.size() + dec_size(size));
+
+ for (size_t i = 0;; i++) {
+ if (num >= 4) {
+ // Buffer full; decode it.
+ size_t nibbles = decode(out);
+ num = 0;
+ if (nibbles < 3) {
+ is_last = true;
+ break;
+ }
+ }
+
+ if (i >= size)
+ break;
+
+ int x = data[i];
+ if ((buf[num] = x < _countof(lookup) ? lookup[x] : 255) != 255)
+ num++;
+ }
+ }
+
+
+ ///
+ /// Resets decoding session
+ ///
+ inline void clear()
+ {
+ num = 0;
+ }
+
+
+ ///
+ /// Returns maximum decoded size
+ ///
+ /// \param size Number of bytes to decode
+ ///
+ /// \returns Maximum number of bytes for the decoded data of `size` length
+ ///
+ inline size_t dec_size(size_t size) const
+ {
+ return ((num + size + 3)/4)*3;
+ }
+
+
+ protected:
+ ///
+ /// Decodes one complete internal buffer of data
+ ///
+ template
+ inline size_t decode(_Inout_ std::vector<_Ty, _Ax> &out)
+ {
+ out.push_back((_Ty)(((buf[0] << 2) | (buf[1] >> 4)) & 0xff));
+ if (buf[2] < 64) {
+ out.push_back((_Ty)(((buf[1] << 4) | (buf[2] >> 2)) & 0xff));
+ if (buf[3] < 64) {
+ out.push_back((_Ty)(((buf[2] << 6) | buf[3]) & 0xff));
+ return 3;
+ } else
+ return 2;
+ } else
+ return 1;
+ }
+
+
+ protected:
+ unsigned char buf[4]; ///< Internal buffer
+ size_t num; ///< Number of bytes used in `buf`
+
+ /// \cond internal
+ static const unsigned char lookup[256];
+ /// \endcond
+ };
+
+ /// @}
+}
diff --git a/include/WinStd/COM.h b/include/WinStd/COM.h
index ef48db1f..c6b632c4 100644
--- a/include/WinStd/COM.h
+++ b/include/WinStd/COM.h
@@ -1,1091 +1,1096 @@
-/*
- Copyright 1991-2018 Amebis
- Copyright 2016 GÉANT
-
- This file is part of WinStd.
-
- Setup is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Setup is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Setup. If not, see .
-*/
-
-///
-/// \defgroup WinStdCOM COM object management
-/// Provides helper templates for Windows COM object manipulation
-///
-
-#include "Common.h"
-
-#include
-
-namespace winstd
-{
- template class com_obj;
- class WINSTD_API bstr;
- class WINSTD_API variant;
- class WINSTD_API com_initializer;
- class WINSTD_API com_runtime_error;
-}
-
-#pragma once
-
-
-namespace winstd
-{
- /// \addtogroup WinStdCOM
- /// @{
-
- ///
- /// COM object wrapper template
- ///
- template
- class com_obj : public dplhandle
- {
- DPLHANDLE_IMPL(com_obj)
-
- public:
- ///
- /// Constructs a new object and creates a new class with it
- ///
- /// \sa [CoCreateInstance function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686615.aspx)
- ///
- inline com_obj(_In_ REFCLSID rclsid, _In_opt_ LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
- {
- CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (LPVOID*)&m_h);
- }
-
-
- ///
- /// Queries the object for another interface and creates new class with it
- ///
- /// \sa [IUnknown::QueryInterface method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521.aspx)
- ///
- template
- inline com_obj(_Out_ _Other **other)
- {
- assert(other);
- other->QueryInterface(__uuidof(T), (void**)&m_h);
- }
-
-
- ///
- /// Queries the object for another interface and creates new class with it
- ///
- /// \sa [IUnknown::QueryInterface method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521.aspx)
- ///
- template
- inline com_obj(_Out_ com_obj<_Other> &other)
- {
- assert(other);
- other->QueryInterface(__uuidof(T), (void**)&m_h);
- }
-
-
- ///
- /// Releases object
- ///
- virtual ~com_obj()
- {
- if (m_h)
- m_h->Release();
- }
-
-
- ///
- /// Creates a new object
- ///
- /// \sa [CoCreateInstance function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686615.aspx)
- ///
- inline HRESULT create(_In_ REFCLSID rclsid, _In_opt_ LPUNKNOWN pUnkOuter = NULL, _In_ DWORD dwClsContext = CLSCTX_ALL)
- {
- handle_type h;
- HRESULT hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&h);
- if (SUCCEEDED(hr))
- attach(h);
- return hr;
- }
-
-
- ///
- /// Queries the object for another interface
- ///
- /// \sa [IUnknown::QueryInterface method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521.aspx)
- ///
- template
- HRESULT query_interface(_Out_ _Other **h) const
- {
- assert(h);
- assert(m_h);
- return m_h->QueryInterface(__uuidof(_Other), (void**)h);
- }
-
-
- ///
- /// Queries the object for another interface
- ///
- /// \sa [IUnknown::QueryInterface method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521.aspx)
- ///
- template
- HRESULT query_interface(_Out_ com_obj<_Other> &h) const
- {
- assert(m_h);
- _Other *_h;
- HRESULT hr = m_h->QueryInterface(__uuidof(_Other), (void**)&_h);
- if (SUCCEEDED(hr))
- h.attach(_h);
- return hr;
- }
-
- protected:
- ///
- /// Releases the object by decrementing reference counter
- ///
- /// \sa [IUnknown::Release method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682317.aspx)
- ///
- virtual void free_internal()
- {
- m_h->Release();
- }
-
-
- ///
- /// Duplicates the object by incrementing the reference counter
- ///
- /// \sa [IUnknown::AddRef method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms691379.aspx)
- ///
- /// \param[in] h Object handle of existing object
- ///
- /// \return Duplicated object handle
- ///
- virtual handle_type duplicate_internal(_In_ handle_type h) const
- {
- h->AddRef();
- return h;
- }
- };
-
-
- ///
- /// BSTR string wrapper
- ///
- class WINSTD_API bstr : public dplhandle
- {
- DPLHANDLE_IMPL(bstr)
-
- public:
- ///
- /// Constructs BSTR from OLE string
- ///
- inline bstr(_In_ LPCOLESTR src)
- {
- m_h = SysAllocString(src);
- }
-
- ///
- /// Constructs BSTR from OLE string with length
- ///
- inline bstr(_In_ LPCOLESTR src, _In_ UINT len)
- {
- m_h = SysAllocStringLen(src, len);
- }
-
- ///
- /// Constructs BSTR from std::basic_string
- ///
- template
- inline bstr(_In_ const std::basic_string &src)
- {
- m_h = SysAllocStringLen(src.c_str(), (UINT)src.length());
- }
-
- ///
- /// Destroys the string
- ///
- /// \sa [SysFreeString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221481.aspx)
- ///
- virtual ~bstr();
-
- ///
- /// Returns the length of the string
- ///
- /// \sa [SysStringLen function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221240.aspx)
- ///
- inline UINT length() const
- {
- return SysStringLen(m_h);
- }
-
- protected:
- ///
- /// Destroys the string
- ///
- /// \sa [SysFreeString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221481.aspx)
- ///
- virtual void free_internal();
-
- ///
- /// Duplicates the string
- ///
- /// \param[in] h Existing string
- ///
- /// \return Duplicated string
- ///
- /// \sa [SysAllocString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221458.aspx)
- ///
- virtual handle_type duplicate_internal(_In_ handle_type h) const;
- };
-
-
- ///
- /// VARIANT struct wrapper
- ///
- class WINSTD_API variant : public VARIANT
- {
- public:
- ///
- /// Constructs blank VARIANT
- ///
- inline variant()
- {
- VariantInit(this);
- }
-
- ///
- /// Constructs VARIANT from another
- ///
- inline variant(_In_ const VARIANT& varSrc)
- {
- vt = VT_EMPTY;
- VariantCopy(this, &varSrc);
- }
-
- ///
- /// Moves VARIANT from another
- ///
- inline variant(_Inout_ VARIANT&& varSrc)
- {
- memcpy(this, &varSrc, sizeof(VARIANT));
- varSrc.vt = VT_EMPTY;
- }
-
- ///
- /// Constructs VARIANT from bool
- ///
- inline variant(_In_ bool bSrc)
- {
- vt = VT_BOOL;
- boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
- }
-
- ///
- /// Constructs VARIANT from character
- ///
- inline variant(_In_ char cSrc)
- {
- vt = VT_I1;
- cVal = cSrc;
- }
-
- ///
- /// Constructs VARIANT from byte
- ///
- inline variant(_In_ unsigned char nSrc)
- {
- vt = VT_UI1;
- bVal = nSrc;
- }
-
- ///
- /// Constructs VARIANT from short
- ///
- inline variant(_In_ short nSrc)
- {
- vt = VT_I2;
- iVal = nSrc;
- }
-
- ///
- /// Constructs VARIANT from unsigned short
- ///
- inline variant(_In_ unsigned short nSrc)
- {
- vt = VT_UI2;
- uiVal = nSrc;
- }
-
- ///
- /// Constructs VARIANT from integer
- ///
- inline variant(_In_ int nSrc, _In_ VARTYPE vtSrc = VT_I4)
- {
- assert(vtSrc == VT_I4 || vtSrc == VT_INT);
- vt = vtSrc;
- intVal = nSrc;
- }
-
- ///
- /// Constructs VARIANT from unsigned integer
- ///
- inline variant(_In_ unsigned int nSrc, _In_ VARTYPE vtSrc = VT_UI4)
- {
- assert(vtSrc == VT_UI4 || vtSrc == VT_UINT);
- vt = vtSrc;
- uintVal= nSrc;
- }
-
- ///
- /// Constructs VARIANT from long
- ///
- inline variant(_In_ long nSrc, _In_ VARTYPE vtSrc = VT_I4)
- {
- assert(vtSrc == VT_I4 || vtSrc == VT_ERROR);
- vt = vtSrc;
- lVal = nSrc;
- }
-
- ///
- /// Constructs VARIANT from unsigned long
- ///
- inline variant(_In_ unsigned long nSrc)
- {
- vt = VT_UI4;
- ulVal = nSrc;
- }
-
- ///
- /// Constructs VARIANT from float
- ///
- inline variant(_In_ float fltSrc)
- {
- vt = VT_R4;
- fltVal = fltSrc;
- }
-
- ///
- /// Constructs VARIANT from double or variant date
- ///
- inline variant(_In_ double dblSrc, _In_ VARTYPE vtSrc = VT_R8)
- {
- assert(vtSrc == VT_R8 || vtSrc == VT_DATE);
- vt = vtSrc;
- dblVal = dblSrc;
- }
-
- ///
- /// Constructs VARIANT from 64-bit integer
- ///
- inline variant(_In_ long long nSrc)
- {
- vt = VT_I8;
- llVal = nSrc;
- }
-
- ///
- /// Constructs VARIANT from unsigned integer
- ///
- inline variant(_In_ unsigned long long nSrc)
- {
- vt = VT_UI8;
- ullVal = nSrc;
- }
-
- ///
- /// Constructs VARIANT from CY (64-bit integer)
- ///
- inline variant(_In_ CY cySrc)
- {
- vt = VT_CY;
- cyVal.Hi = cySrc.Hi;
- cyVal.Lo = cySrc.Lo;
- }
-
- ///
- /// Constructs VARIANT from OLE string
- ///
- inline variant(_In_z_ LPCOLESTR lpszSrc)
- {
- vt = VT_EMPTY;
- *this = lpszSrc;
- }
-
- ///
- /// Constructs VARIANT from BSTR
- ///
- inline variant(_In_z_ BSTR bstr)
- {
- vt = VT_EMPTY;
- *this = bstr;
- }
-
- ///
- /// Constructs VARIANT from IDispatch
- ///
- inline variant(_In_opt_ IDispatch* pSrc)
- {
- vt = VT_DISPATCH;
- pdispVal = pSrc;
-
- if (pdispVal != NULL)
- pdispVal->AddRef();
- }
-
- ///
- /// Constructs VARIANT from IUnknown
- ///
- inline variant(_In_opt_ IUnknown* pSrc)
- {
- vt = VT_UNKNOWN;
- punkVal = pSrc;
-
- if (punkVal != NULL)
- punkVal->AddRef();
- }
-
- ///
- /// Constructs VARIANT from SAFEARRAY
- ///
- inline variant(_In_ const SAFEARRAY *pSrc)
- {
- assert(pSrc != NULL);
-
- LPSAFEARRAY pCopy;
- HRESULT hRes = SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy);
- if (SUCCEEDED(hRes)) {
- SafeArrayGetVartype((LPSAFEARRAY)pSrc, &vt);
- vt |= VT_ARRAY;
- parray = pCopy;
- } else
- assert(0);
- }
-
- ///
- /// Destroys VARIANT
- ///
- virtual ~variant();
-
- ///
- /// Copy from another VARIANT
- ///
- inline variant& operator=(_In_ const VARIANT& varSrc)
- {
- if (this != &varSrc)
- VariantCopy(this, &varSrc);
- return *this;
- }
-
- ///
- /// Moves from another VARIANT
- ///
- inline variant& operator=(_Inout_ VARIANT&& varSrc)
- {
- if (this != &varSrc) {
- VariantClear(this);
- memcpy(this, &varSrc, sizeof(VARIANT));
- varSrc.vt = VT_EMPTY;
- }
- return *this;
- }
-
- ///
- /// Copy from bool value
- ///
- inline variant& operator=(_In_ bool bSrc)
- {
- if (vt != VT_BOOL) {
- VariantClear(this);
- vt = VT_BOOL;
- }
- boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
- return *this;
- }
-
- ///
- /// Copy from char value
- ///
- inline variant& operator=(_In_ char cSrc)
- {
- if (vt != VT_I1) {
- VariantClear(this);
- vt = VT_I1;
- }
- cVal = cSrc;
- return *this;
- }
-
- ///
- /// Copy from unsigned char value
- ///
- inline variant& operator=(_In_ unsigned char nSrc)
- {
- if (vt != VT_UI1) {
- VariantClear(this);
- vt = VT_UI1;
- }
- bVal = nSrc;
- return *this;
- }
-
- ///
- /// Copy from short value
- ///
- inline variant& operator=(_In_ short nSrc)
- {
- if (vt != VT_I2) {
- VariantClear(this);
- vt = VT_I2;
- }
- iVal = nSrc;
- return *this;
- }
-
- ///
- /// Copy from unsigned short value
- ///
- inline variant& operator=(_In_ unsigned short nSrc)
- {
- if (vt != VT_UI2) {
- VariantClear(this);
- vt = VT_UI2;
- }
- uiVal = nSrc;
- return *this;
- }
-
- ///
- /// Copy from int value
- ///
- inline variant& operator=(_In_ int nSrc)
- {
- if (vt != VT_I4) {
- VariantClear(this);
- vt = VT_I4;
- }
- intVal = nSrc;
- return *this;
- }
-
- ///
- /// Copy from unsigned int value
- ///
- inline variant& operator=(_In_ unsigned int nSrc)
- {
- if (vt != VT_UI4) {
- VariantClear(this);
- vt = VT_UI4;
- }
- uintVal= nSrc;
- return *this;
- }
-
- ///
- /// Copy from long value
- ///
- inline variant& operator=(_In_ long nSrc)
- {
- if (vt != VT_I4) {
- VariantClear(this);
- vt = VT_I4;
- }
- lVal = nSrc;
- return *this;
- }
-
- ///
- /// Copy from unsigned long value
- ///
- inline variant& operator=(_In_ unsigned long nSrc)
- {
- if (vt != VT_UI4) {
- VariantClear(this);
- vt = VT_UI4;
- }
- ulVal = nSrc;
- return *this;
- }
-
-
- ///
- /// Copy from long long value
- ///
- inline variant& operator=(_In_ long long nSrc)
- {
- if (vt != VT_I8) {
- VariantClear(this);
- vt = VT_I8;
- }
- llVal = nSrc;
- return *this;
- }
-
- ///
- /// Copy from unsigned long long value
- ///
- inline variant& operator=(_In_ unsigned long long nSrc)
- {
- if (vt != VT_UI8) {
- VariantClear(this);
- vt = VT_UI8;
- }
- ullVal = nSrc;
-
- return *this;
- }
-
- ///
- /// Copy from float value
- ///
- inline variant& operator=(_In_ float fltSrc)
- {
- if (vt != VT_R4) {
- VariantClear(this);
- vt = VT_R4;
- }
- fltVal = fltSrc;
- return *this;
- }
-
- ///
- /// Copy from double value
- ///
- inline variant& operator=(_In_ double dblSrc)
- {
- if (vt != VT_R8) {
- VariantClear(this);
- vt = VT_R8;
- }
- dblVal = dblSrc;
- return *this;
- }
-
- ///
- /// Copy from CY value
- ///
- inline variant& operator=(_In_ CY cySrc)
- {
- if (vt != VT_CY) {
- VariantClear(this);
- vt = VT_CY;
- }
- cyVal.Hi = cySrc.Hi;
- cyVal.Lo = cySrc.Lo;
- return *this;
- }
-
- ///
- /// Copy from OLE string value
- ///
- inline variant& operator=(_In_z_ LPCOLESTR lpszSrc)
- {
- VariantClear(this);
- vt = VT_BSTR;
- bstrVal = SysAllocString(lpszSrc);
- return *this;
- }
-
- ///
- /// Copy from IDispatch
- ///
- inline variant& operator=(_Inout_opt_ IDispatch* pSrc)
- {
- VariantClear(this);
- vt = VT_DISPATCH;
- pdispVal = pSrc;
- if (pdispVal != NULL)
- pdispVal->AddRef();
- return *this;
- }
-
- ///
- /// Copy from IUnknown
- ///
- inline variant& operator=(_Inout_opt_ IUnknown* pSrc)
- {
- VariantClear(this);
- vt = VT_UNKNOWN;
- punkVal = pSrc;
- if (punkVal != NULL)
- punkVal->AddRef();
- return *this;
- }
-
- ///
- /// Copy from unsigned char reference
- ///
- inline variant& operator=(_In_ unsigned char* pbSrc)
- {
- if (vt != (VT_UI1|VT_BYREF)) {
- VariantClear(this);
- vt = VT_UI1|VT_BYREF;
- }
- pbVal = pbSrc;
- return *this;
- }
-
- ///
- /// Copy from short reference
- ///
- inline variant& operator=(_In_ short* pnSrc)
- {
- if (vt != (VT_I2|VT_BYREF)) {
- VariantClear(this);
- vt = VT_I2|VT_BYREF;
- }
- piVal = pnSrc;
- return *this;
- }
-
- ///
- /// Copy from unsigned short reference
- ///
- inline variant& operator=(_In_ unsigned short* pnSrc)
- {
- if (vt != (VT_UI2|VT_BYREF)) {
- VariantClear(this);
- vt = VT_UI2|VT_BYREF;
- }
- puiVal = pnSrc;
- return *this;
- }
-
- ///
- /// Copy from int reference
- ///
- inline variant& operator=(_In_ int* pnSrc)
- {
- if (vt != (VT_I4|VT_BYREF)) {
- VariantClear(this);
- vt = VT_I4|VT_BYREF;
- }
- pintVal = pnSrc;
- return *this;
- }
-
- ///
- /// Copy from unsigned int reference
- ///
- inline variant& operator=(_In_ unsigned int* pnSrc)
- {
- if (vt != (VT_UI4|VT_BYREF)) {
- VariantClear(this);
- vt = VT_UI4|VT_BYREF;
- }
- puintVal = pnSrc;
- return *this;
- }
-
- ///
- /// Copy from long reference
- ///
- inline variant& operator=(_In_ long* pnSrc)
- {
- if (vt != (VT_I4|VT_BYREF)) {
- VariantClear(this);
- vt = VT_I4|VT_BYREF;
- }
- plVal = pnSrc;
- return *this;
- }
-
- ///
- /// Copy from unsigned long reference
- ///
- inline variant& operator=(_In_ unsigned long* pnSrc)
- {
- if (vt != (VT_UI4|VT_BYREF)) {
- VariantClear(this);
- vt = VT_UI4|VT_BYREF;
- }
- pulVal = pnSrc;
- return *this;
- }
-
- ///
- /// Copy from long long reference
- ///
- inline variant& operator=(_In_ long long* pnSrc)
- {
- if (vt != (VT_I8|VT_BYREF)) {
- VariantClear(this);
- vt = VT_I8|VT_BYREF;
- }
- pllVal = pnSrc;
- return *this;
- }
-
- ///
- /// Copy from unsigned long long reference
- ///
- inline variant& operator=(_In_ unsigned long long* pnSrc)
- {
- if (vt != (VT_UI8|VT_BYREF)) {
- VariantClear(this);
- vt = VT_UI8|VT_BYREF;
- }
- pullVal = pnSrc;
- return *this;
- }
-
- ///
- /// Copy from float reference
- ///
- inline variant& operator=(_In_ float* pfSrc)
- {
- if (vt != (VT_R4|VT_BYREF)) {
- VariantClear(this);
- vt = VT_R4|VT_BYREF;
- }
- pfltVal = pfSrc;
- return *this;
- }
-
- ///
- /// Copy from double reference
- ///
- inline variant& operator=(_In_ double* pfSrc)
- {
- if (vt != (VT_R8|VT_BYREF)) {
- VariantClear(this);
- vt = VT_R8|VT_BYREF;
- }
- pdblVal = pfSrc;
- return *this;
- }
-
- ///
- /// Copy from SAFEARRAY
- ///
- inline variant& operator=(_In_ const SAFEARRAY *pSrc)
- {
- assert(pSrc != NULL);
- VariantClear(this);
-
- LPSAFEARRAY pCopy;
- HRESULT hr = SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy);
- if (SUCCEEDED(hr)) {
- SafeArrayGetVartype((LPSAFEARRAY)pSrc, &vt);
- vt |= VT_ARRAY;
- parray = pCopy;
- } else
- assert(0);
-
- return *this;
- }
-
- public:
- ///
- /// Is variant equal to?
- ///
- /// \param[in] varSrc Variant to compare against
- /// \return
- /// - Non zero when variant is equal to \p varSrc;
- /// - Zero otherwise.
- ///
- inline bool operator==(_In_ const VARIANT& varSrc) const
- {
- if (vt == VT_NULL && varSrc.vt == VT_NULL) return true;
- if (vt != varSrc.vt) return false;
- return compare(static_cast(*this), varSrc, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_EQ);
- }
-
- ///
- /// Is variant not equal to?
- ///
- /// \param[in] varSrc Variant to compare against
- /// \return
- /// - Non zero when variant is not equal to \p varSrc;
- /// - Zero otherwise.
- ///
- inline bool operator!=(_In_ const VARIANT& varSrc) const
- {
- return !operator==(varSrc);
- }
-
- ///
- /// Is variant less than?
- ///
- /// \param[in] varSrc Variant to compare against
- /// \return
- /// - Non zero when variant is less than \p varSrc;
- /// - Zero otherwise.
- ///
- inline bool operator<(_In_ const VARIANT& varSrc) const
- {
- if (vt == VT_NULL && varSrc.vt == VT_NULL) return false;
- return compare(static_cast(*this), varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_LT);
- }
-
- ///
- /// Is variant greater than?
- ///
- /// \param[in] varSrc Variant to compare against
- /// \return
- /// - Non zero when variant is greater than \p varSrc;
- /// - Zero otherwise.
- ///
- inline bool operator>(_In_ const VARIANT& varSrc) const
- {
- if (vt == VT_NULL && varSrc.vt == VT_NULL) return false;
- return compare(static_cast(*this), varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_GT);
- }
-
- ///
- /// Is variant less than or equal to?
- ///
- /// \param[in] varSrc Variant to compare against
- /// \return
- /// - Non zero when variant is less than or equal to \p varSrc;
- /// - Zero otherwise.
- ///
- inline bool operator<=(_In_ const VARIANT& varSrc) const
- {
- return !operator>(varSrc);
- }
-
- ///
- /// Is variant greater than or equal to?
- ///
- /// \param[in] varSrc Variant to compare against
- /// \return
- /// - Non zero when variant is greater than or equal to \p varSrc;
- /// - Zero otherwise.
- ///
- inline bool operator>=(_In_ const VARIANT& varSrc) const
- {
- return !operator<(varSrc);
- }
-
- ///
- /// Converts a variant from one type to another.
- ///
- /// \sa [VariantChangeType function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221258.aspx)
- ///
- inline HRESULT change_type(_In_ VARTYPE _vt, _In_opt_ USHORT wFlags = 0)
- {
- return VariantChangeType(this, this, wFlags, _vt);
- }
-
- private:
- /// \cond internal
- inline HRESULT compare(_In_ const VARIANT &varLeft, _In_ const VARIANT &varRight, _In_ LCID lcid, _In_ ULONG dwFlags) const
- {
- switch(vt) {
- case VT_I1: return varLeft.cVal == varRight.cVal ? VARCMP_EQ : varLeft.cVal > varRight.cVal ? VARCMP_GT : VARCMP_LT;
- case VT_UI2: return varLeft.uiVal == varRight.uiVal ? VARCMP_EQ : varLeft.uiVal > varRight.uiVal ? VARCMP_GT : VARCMP_LT;
- case VT_UI4: return varLeft.uintVal == varRight.uintVal ? VARCMP_EQ : varLeft.uintVal > varRight.uintVal ? VARCMP_GT : VARCMP_LT;
- case VT_UI8: return varLeft.ullVal == varRight.ullVal ? VARCMP_EQ : varLeft.ullVal > varRight.ullVal ? VARCMP_GT : VARCMP_LT;
- default: return VarCmp(const_cast(&varLeft), const_cast(&varRight), lcid, dwFlags);
- }
- }
- /// \endcond
- };
-
-
- ///
- /// Context scope automatic COM (un)initialization
- ///
- class WINSTD_API com_initializer
- {
- public:
- ///
- /// Initializes the COM library on the current thread and identifies the concurrency model as single-thread apartment (STA).
- ///
- /// \sa [CoInitialize function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms678543.aspx)
- ///
- inline com_initializer(_In_opt_ LPVOID 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.
- ///
- /// \sa [CoInitializeEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms695279.aspx)
- ///
- inline com_initializer(_In_opt_ LPVOID pvReserved, _In_ DWORD dwCoInit)
- {
- m_result = CoInitializeEx(pvReserved, dwCoInit);
- }
-
-
- ///
- /// Uninitializes COM.
- ///
- /// \sa [CoUninitialize function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms688715.aspx)
- ///
- virtual ~com_initializer();
-
-
- ///
- /// Return result of `CoInitialize()` call.
- ///
- /// \sa [CoInitialize function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms678543.aspx)
- ///
- inline HRESULT status() const
- {
- return m_result;
- }
-
- protected:
- HRESULT m_result; ///< Result of CoInitialize call
- };
-
- /// @}
-
- ///
- /// \defgroup WinStdExceptions Exceptions
- /// Additional exceptions
- ///
- /// @{
-
- ///
- /// COM runtime error
- ///
- /// \note Must be defined as derived class from num_runtime_error<> to allow correct type info for dynamic typecasting and prevent folding with other derivates of num_runtime_error<>.
- ///
- class WINSTD_API com_runtime_error : public num_runtime_error
- {
- public:
- ///
- /// Constructs an exception
- ///
- /// \param[in] num COM error code
- /// \param[in] msg Error message
- ///
- inline com_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error(num, msg.c_str())
- {
- }
-
-
- ///
- /// Constructs an exception
- ///
- /// \param[in] num COM error code
- /// \param[in] msg Error message
- ///
- inline com_runtime_error(_In_ error_type num, _In_z_ const char *msg) : num_runtime_error(num, msg)
- {
- }
-
-
- ///
- /// Copies an exception
- ///
- /// \param[in] other Exception to copy from
- ///
- inline com_runtime_error(const com_runtime_error &other) : num_runtime_error(other)
- {
- }
- };
-
- /// @}
-}
+/*
+ Copyright 1991-2018 Amebis
+ Copyright 2016 GÉANT
+
+ This file is part of WinStd.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+///
+/// \defgroup WinStdCOM COM object management
+/// Provides helper templates for Windows COM object manipulation
+///
+
+#include "Common.h"
+
+#include
+
+namespace winstd
+{
+ class WINSTD_API com_runtime_error;
+ template class com_obj;
+ class WINSTD_API bstr;
+ class WINSTD_API variant;
+ class WINSTD_API com_initializer;
+}
+
+#pragma once
+
+
+namespace winstd
+{
+
+ ///
+ /// \defgroup WinStdExceptions Exceptions
+ /// Additional exceptions
+ ///
+ /// @{
+
+ ///
+ /// COM runtime error
+ ///
+ /// \note Must be defined as derived class from num_runtime_error<> to allow correct type info for dynamic typecasting and prevent folding with other derivates of num_runtime_error<>.
+ ///
+ class WINSTD_API com_runtime_error : public num_runtime_error
+ {
+ public:
+ ///
+ /// Constructs an exception
+ ///
+ /// \param[in] num COM error code
+ /// \param[in] msg Error message
+ ///
+ inline com_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error(num, msg.c_str())
+ {
+ }
+
+
+ ///
+ /// Constructs an exception
+ ///
+ /// \param[in] num COM error code
+ /// \param[in] msg Error message
+ ///
+ inline com_runtime_error(_In_ error_type num, _In_z_ const char *msg) : num_runtime_error(num, msg)
+ {
+ }
+
+
+ ///
+ /// Copies an exception
+ ///
+ /// \param[in] other Exception to copy from
+ ///
+ inline com_runtime_error(const com_runtime_error &other) : num_runtime_error(other)
+ {
+ }
+ };
+
+ /// @}
+ /// \addtogroup WinStdCOM
+ /// @{
+
+ ///
+ /// COM object wrapper template
+ ///
+ template
+ class com_obj : public dplhandle
+ {
+ DPLHANDLE_IMPL(com_obj)
+
+ public:
+ ///
+ /// Constructs a new object and creates a new class with it
+ ///
+ /// \sa [CoCreateInstance function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686615.aspx)
+ ///
+ inline com_obj(_In_ REFCLSID rclsid, _In_opt_ LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
+ {
+ CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (LPVOID*)&m_h);
+ }
+
+
+ ///
+ /// Queries the object for another interface and creates new class with it
+ ///
+ /// \sa [IUnknown::QueryInterface method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521.aspx)
+ ///
+ template
+ inline com_obj(_Out_ _Other **other)
+ {
+ assert(other);
+ other->QueryInterface(__uuidof(T), (void**)&m_h);
+ }
+
+
+ ///
+ /// Queries the object for another interface and creates new class with it
+ ///
+ /// \sa [IUnknown::QueryInterface method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521.aspx)
+ ///
+ template
+ inline com_obj(_Out_ com_obj<_Other> &other)
+ {
+ assert(other);
+ other->QueryInterface(__uuidof(T), (void**)&m_h);
+ }
+
+
+ ///
+ /// Releases object
+ ///
+ virtual ~com_obj()
+ {
+ if (m_h)
+ m_h->Release();
+ }
+
+
+ ///
+ /// Creates a new object
+ ///
+ /// \sa [CoCreateInstance function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686615.aspx)
+ ///
+ inline HRESULT create(_In_ REFCLSID rclsid, _In_opt_ LPUNKNOWN pUnkOuter = NULL, _In_ DWORD dwClsContext = CLSCTX_ALL)
+ {
+ handle_type h;
+ HRESULT hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&h);
+ if (SUCCEEDED(hr))
+ attach(h);
+ return hr;
+ }
+
+
+ ///
+ /// Queries the object for another interface
+ ///
+ /// \sa [IUnknown::QueryInterface method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521.aspx)
+ ///
+ template
+ HRESULT query_interface(_Out_ _Other **h) const
+ {
+ assert(h);
+ assert(m_h);
+ return m_h->QueryInterface(__uuidof(_Other), (void**)h);
+ }
+
+
+ ///
+ /// Queries the object for another interface
+ ///
+ /// \sa [IUnknown::QueryInterface method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682521.aspx)
+ ///
+ template
+ HRESULT query_interface(_Out_ com_obj<_Other> &h) const
+ {
+ assert(m_h);
+ _Other *_h;
+ HRESULT hr = m_h->QueryInterface(__uuidof(_Other), (void**)&_h);
+ if (SUCCEEDED(hr))
+ h.attach(_h);
+ return hr;
+ }
+
+ protected:
+ ///
+ /// Releases the object by decrementing reference counter
+ ///
+ /// \sa [IUnknown::Release method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682317.aspx)
+ ///
+ virtual void free_internal()
+ {
+ m_h->Release();
+ }
+
+
+ ///
+ /// Duplicates the object by incrementing the reference counter
+ ///
+ /// \sa [IUnknown::AddRef method](https://msdn.microsoft.com/en-us/library/windows/desktop/ms691379.aspx)
+ ///
+ /// \param[in] h Object handle of existing object
+ ///
+ /// \return Duplicated object handle
+ ///
+ virtual handle_type duplicate_internal(_In_ handle_type h) const
+ {
+ h->AddRef();
+ return h;
+ }
+ };
+
+
+ ///
+ /// BSTR string wrapper
+ ///
+ class WINSTD_API bstr : public dplhandle
+ {
+ DPLHANDLE_IMPL(bstr)
+
+ public:
+ ///
+ /// Constructs BSTR from OLE string
+ ///
+ inline bstr(_In_ LPCOLESTR src)
+ {
+ m_h = SysAllocString(src);
+ }
+
+ ///
+ /// Constructs BSTR from OLE string with length
+ ///
+ inline bstr(_In_ LPCOLESTR src, _In_ UINT len)
+ {
+ m_h = SysAllocStringLen(src, len);
+ }
+
+ ///
+ /// Constructs BSTR from std::basic_string
+ ///
+ template
+ inline bstr(_In_ const std::basic_string &src)
+ {
+ m_h = SysAllocStringLen(src.c_str(), (UINT)src.length());
+ }
+
+ ///
+ /// Destroys the string
+ ///
+ /// \sa [SysFreeString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221481.aspx)
+ ///
+ virtual ~bstr();
+
+ ///
+ /// Returns the length of the string
+ ///
+ /// \sa [SysStringLen function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221240.aspx)
+ ///
+ inline UINT length() const
+ {
+ return SysStringLen(m_h);
+ }
+
+ protected:
+ ///
+ /// Destroys the string
+ ///
+ /// \sa [SysFreeString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221481.aspx)
+ ///
+ virtual void free_internal();
+
+ ///
+ /// Duplicates the string
+ ///
+ /// \param[in] h Existing string
+ ///
+ /// \return Duplicated string
+ ///
+ /// \sa [SysAllocString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221458.aspx)
+ ///
+ virtual handle_type duplicate_internal(_In_ handle_type h) const;
+ };
+
+
+ ///
+ /// VARIANT struct wrapper
+ ///
+ class WINSTD_API variant : public VARIANT
+ {
+ public:
+ ///
+ /// Constructs blank VARIANT
+ ///
+ inline variant()
+ {
+ VariantInit(this);
+ }
+
+ ///
+ /// Constructs VARIANT from another
+ ///
+ inline variant(_In_ const VARIANT& varSrc)
+ {
+ vt = VT_EMPTY;
+ HRESULT hr = VariantCopy(this, &varSrc);
+ if (FAILED(hr))
+ throw winstd::com_runtime_error(hr, "VariantCopy failed.");
+ }
+
+ ///
+ /// Moves VARIANT from another
+ ///
+ inline variant(_Inout_ VARIANT&& varSrc)
+ {
+ memcpy(this, &varSrc, sizeof(VARIANT));
+ varSrc.vt = VT_EMPTY;
+ }
+
+ ///
+ /// Constructs VARIANT from bool
+ ///
+ inline variant(_In_ bool bSrc)
+ {
+ vt = VT_BOOL;
+ boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
+ }
+
+ ///
+ /// Constructs VARIANT from character
+ ///
+ inline variant(_In_ char cSrc)
+ {
+ vt = VT_I1;
+ cVal = cSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from byte
+ ///
+ inline variant(_In_ unsigned char nSrc)
+ {
+ vt = VT_UI1;
+ bVal = nSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from short
+ ///
+ inline variant(_In_ short nSrc)
+ {
+ vt = VT_I2;
+ iVal = nSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from unsigned short
+ ///
+ inline variant(_In_ unsigned short nSrc)
+ {
+ vt = VT_UI2;
+ uiVal = nSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from integer
+ ///
+ inline variant(_In_ int nSrc, _In_ VARTYPE vtSrc = VT_I4)
+ {
+ assert(vtSrc == VT_I4 || vtSrc == VT_INT);
+ vt = vtSrc;
+ intVal = nSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from unsigned integer
+ ///
+ inline variant(_In_ unsigned int nSrc, _In_ VARTYPE vtSrc = VT_UI4)
+ {
+ assert(vtSrc == VT_UI4 || vtSrc == VT_UINT);
+ vt = vtSrc;
+ uintVal= nSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from long
+ ///
+ inline variant(_In_ long nSrc, _In_ VARTYPE vtSrc = VT_I4)
+ {
+ assert(vtSrc == VT_I4 || vtSrc == VT_ERROR);
+ vt = vtSrc;
+ lVal = nSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from unsigned long
+ ///
+ inline variant(_In_ unsigned long nSrc)
+ {
+ vt = VT_UI4;
+ ulVal = nSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from float
+ ///
+ inline variant(_In_ float fltSrc)
+ {
+ vt = VT_R4;
+ fltVal = fltSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from double or variant date
+ ///
+ inline variant(_In_ double dblSrc, _In_ VARTYPE vtSrc = VT_R8)
+ {
+ assert(vtSrc == VT_R8 || vtSrc == VT_DATE);
+ vt = vtSrc;
+ dblVal = dblSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from 64-bit integer
+ ///
+ inline variant(_In_ long long nSrc)
+ {
+ vt = VT_I8;
+ llVal = nSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from unsigned integer
+ ///
+ inline variant(_In_ unsigned long long nSrc)
+ {
+ vt = VT_UI8;
+ ullVal = nSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from CY (64-bit integer)
+ ///
+ inline variant(_In_ CY cySrc)
+ {
+ vt = VT_CY;
+ cyVal.Hi = cySrc.Hi;
+ cyVal.Lo = cySrc.Lo;
+ }
+
+ ///
+ /// Constructs VARIANT from OLE string
+ ///
+ inline variant(_In_z_ LPCOLESTR lpszSrc)
+ {
+ vt = VT_EMPTY;
+ *this = lpszSrc;
+ }
+
+ ///
+ /// Constructs VARIANT from BSTR
+ ///
+ inline variant(_In_z_ BSTR bstr)
+ {
+ vt = VT_EMPTY;
+ *this = bstr;
+ }
+
+ ///
+ /// Constructs VARIANT from IDispatch
+ ///
+ inline variant(_In_opt_ IDispatch* pSrc)
+ {
+ vt = VT_DISPATCH;
+ pdispVal = pSrc;
+
+ if (pdispVal != NULL)
+ pdispVal->AddRef();
+ }
+
+ ///
+ /// Constructs VARIANT from IUnknown
+ ///
+ inline variant(_In_opt_ IUnknown* pSrc)
+ {
+ vt = VT_UNKNOWN;
+ punkVal = pSrc;
+
+ if (punkVal != NULL)
+ punkVal->AddRef();
+ }
+
+ ///
+ /// Constructs VARIANT from SAFEARRAY
+ ///
+ inline variant(_In_ const SAFEARRAY *pSrc)
+ {
+ assert(pSrc != NULL);
+
+ LPSAFEARRAY pCopy;
+ HRESULT hRes = SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy);
+ if (SUCCEEDED(hRes)) {
+ SafeArrayGetVartype((LPSAFEARRAY)pSrc, &vt);
+ vt |= VT_ARRAY;
+ parray = pCopy;
+ } else
+ assert(0);
+ }
+
+ ///
+ /// Destroys VARIANT
+ ///
+ virtual ~variant();
+
+ ///
+ /// Copy from another VARIANT
+ ///
+ inline variant& operator=(_In_ const VARIANT& varSrc)
+ {
+ if (this != &varSrc) {
+ HRESULT hr = VariantCopy(this, &varSrc);
+ if (FAILED(hr))
+ throw winstd::com_runtime_error(hr, "VariantCopy failed.");
+ }
+ return *this;
+ }
+
+ ///
+ /// Moves from another VARIANT
+ ///
+ inline variant& operator=(_Inout_ VARIANT&& varSrc)
+ {
+ if (this != &varSrc) {
+ VariantClear(this);
+ memcpy(this, &varSrc, sizeof(VARIANT));
+ varSrc.vt = VT_EMPTY;
+ }
+ return *this;
+ }
+
+ ///
+ /// Copy from bool value
+ ///
+ inline variant& operator=(_In_ bool bSrc)
+ {
+ if (vt != VT_BOOL) {
+ VariantClear(this);
+ vt = VT_BOOL;
+ }
+ boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
+ return *this;
+ }
+
+ ///
+ /// Copy from char value
+ ///
+ inline variant& operator=(_In_ char cSrc)
+ {
+ if (vt != VT_I1) {
+ VariantClear(this);
+ vt = VT_I1;
+ }
+ cVal = cSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned char value
+ ///
+ inline variant& operator=(_In_ unsigned char nSrc)
+ {
+ if (vt != VT_UI1) {
+ VariantClear(this);
+ vt = VT_UI1;
+ }
+ bVal = nSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from short value
+ ///
+ inline variant& operator=(_In_ short nSrc)
+ {
+ if (vt != VT_I2) {
+ VariantClear(this);
+ vt = VT_I2;
+ }
+ iVal = nSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned short value
+ ///
+ inline variant& operator=(_In_ unsigned short nSrc)
+ {
+ if (vt != VT_UI2) {
+ VariantClear(this);
+ vt = VT_UI2;
+ }
+ uiVal = nSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from int value
+ ///
+ inline variant& operator=(_In_ int nSrc)
+ {
+ if (vt != VT_I4) {
+ VariantClear(this);
+ vt = VT_I4;
+ }
+ intVal = nSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned int value
+ ///
+ inline variant& operator=(_In_ unsigned int nSrc)
+ {
+ if (vt != VT_UI4) {
+ VariantClear(this);
+ vt = VT_UI4;
+ }
+ uintVal= nSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from long value
+ ///
+ inline variant& operator=(_In_ long nSrc)
+ {
+ if (vt != VT_I4) {
+ VariantClear(this);
+ vt = VT_I4;
+ }
+ lVal = nSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned long value
+ ///
+ inline variant& operator=(_In_ unsigned long nSrc)
+ {
+ if (vt != VT_UI4) {
+ VariantClear(this);
+ vt = VT_UI4;
+ }
+ ulVal = nSrc;
+ return *this;
+ }
+
+
+ ///
+ /// Copy from long long value
+ ///
+ inline variant& operator=(_In_ long long nSrc)
+ {
+ if (vt != VT_I8) {
+ VariantClear(this);
+ vt = VT_I8;
+ }
+ llVal = nSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned long long value
+ ///
+ inline variant& operator=(_In_ unsigned long long nSrc)
+ {
+ if (vt != VT_UI8) {
+ VariantClear(this);
+ vt = VT_UI8;
+ }
+ ullVal = nSrc;
+
+ return *this;
+ }
+
+ ///
+ /// Copy from float value
+ ///
+ inline variant& operator=(_In_ float fltSrc)
+ {
+ if (vt != VT_R4) {
+ VariantClear(this);
+ vt = VT_R4;
+ }
+ fltVal = fltSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from double value
+ ///
+ inline variant& operator=(_In_ double dblSrc)
+ {
+ if (vt != VT_R8) {
+ VariantClear(this);
+ vt = VT_R8;
+ }
+ dblVal = dblSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from CY value
+ ///
+ inline variant& operator=(_In_ CY cySrc)
+ {
+ if (vt != VT_CY) {
+ VariantClear(this);
+ vt = VT_CY;
+ }
+ cyVal.Hi = cySrc.Hi;
+ cyVal.Lo = cySrc.Lo;
+ return *this;
+ }
+
+ ///
+ /// Copy from OLE string value
+ ///
+ inline variant& operator=(_In_z_ LPCOLESTR lpszSrc)
+ {
+ VariantClear(this);
+ vt = VT_BSTR;
+ bstrVal = SysAllocString(lpszSrc);
+ return *this;
+ }
+
+ ///
+ /// Copy from IDispatch
+ ///
+ inline variant& operator=(_Inout_opt_ IDispatch* pSrc)
+ {
+ VariantClear(this);
+ vt = VT_DISPATCH;
+ pdispVal = pSrc;
+ if (pdispVal != NULL)
+ pdispVal->AddRef();
+ return *this;
+ }
+
+ ///
+ /// Copy from IUnknown
+ ///
+ inline variant& operator=(_Inout_opt_ IUnknown* pSrc)
+ {
+ VariantClear(this);
+ vt = VT_UNKNOWN;
+ punkVal = pSrc;
+ if (punkVal != NULL)
+ punkVal->AddRef();
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned char reference
+ ///
+ inline variant& operator=(_In_ unsigned char* pbSrc)
+ {
+ if (vt != (VT_UI1|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_UI1|VT_BYREF;
+ }
+ pbVal = pbSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from short reference
+ ///
+ inline variant& operator=(_In_ short* pnSrc)
+ {
+ if (vt != (VT_I2|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_I2|VT_BYREF;
+ }
+ piVal = pnSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned short reference
+ ///
+ inline variant& operator=(_In_ unsigned short* pnSrc)
+ {
+ if (vt != (VT_UI2|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_UI2|VT_BYREF;
+ }
+ puiVal = pnSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from int reference
+ ///
+ inline variant& operator=(_In_ int* pnSrc)
+ {
+ if (vt != (VT_I4|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_I4|VT_BYREF;
+ }
+ pintVal = pnSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned int reference
+ ///
+ inline variant& operator=(_In_ unsigned int* pnSrc)
+ {
+ if (vt != (VT_UI4|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_UI4|VT_BYREF;
+ }
+ puintVal = pnSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from long reference
+ ///
+ inline variant& operator=(_In_ long* pnSrc)
+ {
+ if (vt != (VT_I4|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_I4|VT_BYREF;
+ }
+ plVal = pnSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned long reference
+ ///
+ inline variant& operator=(_In_ unsigned long* pnSrc)
+ {
+ if (vt != (VT_UI4|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_UI4|VT_BYREF;
+ }
+ pulVal = pnSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from long long reference
+ ///
+ inline variant& operator=(_In_ long long* pnSrc)
+ {
+ if (vt != (VT_I8|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_I8|VT_BYREF;
+ }
+ pllVal = pnSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from unsigned long long reference
+ ///
+ inline variant& operator=(_In_ unsigned long long* pnSrc)
+ {
+ if (vt != (VT_UI8|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_UI8|VT_BYREF;
+ }
+ pullVal = pnSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from float reference
+ ///
+ inline variant& operator=(_In_ float* pfSrc)
+ {
+ if (vt != (VT_R4|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_R4|VT_BYREF;
+ }
+ pfltVal = pfSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from double reference
+ ///
+ inline variant& operator=(_In_ double* pfSrc)
+ {
+ if (vt != (VT_R8|VT_BYREF)) {
+ VariantClear(this);
+ vt = VT_R8|VT_BYREF;
+ }
+ pdblVal = pfSrc;
+ return *this;
+ }
+
+ ///
+ /// Copy from SAFEARRAY
+ ///
+ inline variant& operator=(_In_ const SAFEARRAY *pSrc)
+ {
+ assert(pSrc != NULL);
+ VariantClear(this);
+
+ LPSAFEARRAY pCopy;
+ HRESULT hr = SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy);
+ if (SUCCEEDED(hr)) {
+ SafeArrayGetVartype((LPSAFEARRAY)pSrc, &vt);
+ vt |= VT_ARRAY;
+ parray = pCopy;
+ } else
+ assert(0);
+
+ return *this;
+ }
+
+ public:
+ ///
+ /// Is variant equal to?
+ ///
+ /// \param[in] varSrc Variant to compare against
+ /// \return
+ /// - Non zero when variant is equal to \p varSrc;
+ /// - Zero otherwise.
+ ///
+ inline bool operator==(_In_ const VARIANT& varSrc) const
+ {
+ if (vt == VT_NULL && varSrc.vt == VT_NULL) return true;
+ if (vt != varSrc.vt) return false;
+ return compare(static_cast(*this), varSrc, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_EQ);
+ }
+
+ ///
+ /// Is variant not equal to?
+ ///
+ /// \param[in] varSrc Variant to compare against
+ /// \return
+ /// - Non zero when variant is not equal to \p varSrc;
+ /// - Zero otherwise.
+ ///
+ inline bool operator!=(_In_ const VARIANT& varSrc) const
+ {
+ return !operator==(varSrc);
+ }
+
+ ///
+ /// Is variant less than?
+ ///
+ /// \param[in] varSrc Variant to compare against
+ /// \return
+ /// - Non zero when variant is less than \p varSrc;
+ /// - Zero otherwise.
+ ///
+ inline bool operator<(_In_ const VARIANT& varSrc) const
+ {
+ if (vt == VT_NULL && varSrc.vt == VT_NULL) return false;
+ return compare(static_cast(*this), varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_LT);
+ }
+
+ ///
+ /// Is variant greater than?
+ ///
+ /// \param[in] varSrc Variant to compare against
+ /// \return
+ /// - Non zero when variant is greater than \p varSrc;
+ /// - Zero otherwise.
+ ///
+ inline bool operator>(_In_ const VARIANT& varSrc) const
+ {
+ if (vt == VT_NULL && varSrc.vt == VT_NULL) return false;
+ return compare(static_cast(*this), varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_GT);
+ }
+
+ ///
+ /// Is variant less than or equal to?
+ ///
+ /// \param[in] varSrc Variant to compare against
+ /// \return
+ /// - Non zero when variant is less than or equal to \p varSrc;
+ /// - Zero otherwise.
+ ///
+ inline bool operator<=(_In_ const VARIANT& varSrc) const
+ {
+ return !operator>(varSrc);
+ }
+
+ ///
+ /// Is variant greater than or equal to?
+ ///
+ /// \param[in] varSrc Variant to compare against
+ /// \return
+ /// - Non zero when variant is greater than or equal to \p varSrc;
+ /// - Zero otherwise.
+ ///
+ inline bool operator>=(_In_ const VARIANT& varSrc) const
+ {
+ return !operator<(varSrc);
+ }
+
+ ///
+ /// Converts a variant from one type to another.
+ ///
+ /// \sa [VariantChangeType function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms221258.aspx)
+ ///
+ inline HRESULT change_type(_In_ VARTYPE _vt, _In_opt_ USHORT wFlags = 0)
+ {
+ return VariantChangeType(this, this, wFlags, _vt);
+ }
+
+ private:
+ /// \cond internal
+ inline HRESULT compare(_In_ const VARIANT &varLeft, _In_ const VARIANT &varRight, _In_ LCID lcid, _In_ ULONG dwFlags) const
+ {
+ switch(vt) {
+ case VT_I1: return varLeft.cVal == varRight.cVal ? VARCMP_EQ : varLeft.cVal > varRight.cVal ? VARCMP_GT : VARCMP_LT;
+ case VT_UI2: return varLeft.uiVal == varRight.uiVal ? VARCMP_EQ : varLeft.uiVal > varRight.uiVal ? VARCMP_GT : VARCMP_LT;
+ case VT_UI4: return varLeft.uintVal == varRight.uintVal ? VARCMP_EQ : varLeft.uintVal > varRight.uintVal ? VARCMP_GT : VARCMP_LT;
+ case VT_UI8: return varLeft.ullVal == varRight.ullVal ? VARCMP_EQ : varLeft.ullVal > varRight.ullVal ? VARCMP_GT : VARCMP_LT;
+ default: return VarCmp(const_cast(&varLeft), const_cast(&varRight), lcid, dwFlags);
+ }
+ }
+ /// \endcond
+ };
+
+
+ ///
+ /// Context scope automatic COM (un)initialization
+ ///
+ class WINSTD_API com_initializer
+ {
+ public:
+ ///
+ /// Initializes the COM library on the current thread and identifies the concurrency model as single-thread apartment (STA).
+ ///
+ /// \sa [CoInitialize function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms678543.aspx)
+ ///
+ inline com_initializer(_In_opt_ LPVOID 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.
+ ///
+ /// \sa [CoInitializeEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms695279.aspx)
+ ///
+ inline com_initializer(_In_opt_ LPVOID pvReserved, _In_ DWORD dwCoInit)
+ {
+ m_result = CoInitializeEx(pvReserved, dwCoInit);
+ }
+
+
+ ///
+ /// Uninitializes COM.
+ ///
+ /// \sa [CoUninitialize function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms688715.aspx)
+ ///
+ virtual ~com_initializer();
+
+
+ ///
+ /// Return result of `CoInitialize()` call.
+ ///
+ /// \sa [CoInitialize function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms678543.aspx)
+ ///
+ inline HRESULT status() const
+ {
+ return m_result;
+ }
+
+ protected:
+ HRESULT m_result; ///< Result of CoInitialize call
+ };
+
+ /// @}
+}
diff --git a/include/WinStd/Common.h b/include/WinStd/Common.h
index b0f21b15..68bb7d85 100644
--- a/include/WinStd/Common.h
+++ b/include/WinStd/Common.h
@@ -1,1955 +1,1955 @@
-/*
- Copyright 1991-2018 Amebis
- Copyright 2016 GÉANT
-
- This file is part of WinStd.
-
- Setup is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Setup is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Setup. If not, see .
-*/
-
-///
-/// \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
-///
-
-#include
-
-#include
-
-#include
-#include
-#include
-
-/// \addtogroup WinStdGeneral
-/// @{
-
-///
-/// Public function calling convention
-///
-#ifndef WINSTD_API
-#if defined(WINSTD_DLL)
-#define WINSTD_API __declspec(dllexport)
-#elif defined(WINSTD_DLLIMP)
-#define WINSTD_API __declspec(dllimport)
-#else
-#define WINSTD_API
-#endif
-#endif
-
-///
-/// Class/struct with no virtual table declaration
-///
-/// Use for storing flat data.
-///
-/// This macro bypasses Doxygen limitation to parse class/struct declarations with parentheses.
-///
-#define WINSTD_NOVTABLE __declspec(novtable)
-
-///
-/// "L" stringizing macro
-///
-#ifndef __L
-#define __L(x) L ## x
-#endif
-
-///
-/// Makes string Unicode
-///
-#ifndef _L
-#define _L(x) __L(x)
-#endif
-
-///
-/// Stringizing macro helper
-///
-#define STRING_IMPL(x) #x
-
-///
-/// Stringizing macro
-///
-#define STRING(x) STRING_IMPL(x)
-
-///
-/// Declares a class as non-copyable
-///
-#define WINSTD_NONCOPYABLE(C) \
-private: \
- inline C (_In_ const C &h); \
- inline C& operator=(_In_ const C &h);
-
-/// @}
-
-/// \addtogroup WinStdSysHandles
-/// @{
-
-///
-/// Implements default constructors and operators to prevent their auto-generation by compiler.
-///
-#define HANDLE_IMPL(C) \
-public: \
- inline C ( ) { } \
- inline C (_In_ handle_type h) : handle( h ) { } \
- inline C (_Inout_ C &&h) : handle(std::move(h)) { } \
- inline C& operator=(_In_ handle_type h) { handle::operator=( h ); return *this; } \
- inline C& operator=(_Inout_ C &&h) { handle::operator=(std::move(h)); return *this; } \
-WINSTD_NONCOPYABLE(C)
-
-///
-/// Implements default constructors and operators to prevent their auto-generation by compiler.
-///
-#define DPLHANDLE_IMPL(C) \
-public: \
- inline C ( ) { } \
- inline C (_In_ handle_type h) : dplhandle( h ) { } \
- inline C (_In_ const C &h) : dplhandle(duplicate_internal(h.m_h)) { } \
- inline C (_Inout_ C &&h) : dplhandle(std::move (h )) { } \
- inline C& operator=(_In_ handle_type h) { dplhandle::operator=( h ); return *this; } \
- inline C& operator=(_In_ const C &h) { dplhandle::operator=( h ); return *this; } \
- inline C& operator=(_Inout_ C &&h) { dplhandle::operator=(std::move(h)); return *this; } \
-private:
-
-/// @}
-
-
-#ifndef _FormatMessage_format_string_
-#define _FormatMessage_format_string_
-#endif
-
-
-namespace winstd
-{
- /// \addtogroup WinStdStrFormat
- /// @{
-
- ///
- /// Multi-byte / Wide-character string (according to _UNICODE)
- ///
-#ifdef _UNICODE
- typedef std::wstring tstring;
-#else
- typedef std::string tstring;
-#endif
-
- /// @}
-
- template struct LocalFree_delete;
- template struct LocalFree_delete<_Ty[]>;
- template> class ref_unique_ptr;
- template class ref_unique_ptr<_Ty[], _Dx>;
- template class handle;
- template class dplhandle;
- template class vector_queue;
- template class num_runtime_error;
- class WINSTD_API 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 inline ref_unique_ptr<_Ty, _Dx> get_ptr(_Inout_ std::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 inline ref_unique_ptr<_Ty[], _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty[], _Dx> &owner);
-
- /// @}
-
-
- /// \addtogroup WinStdStrFormat
- /// @{
-
- template, 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, std::allocator > string_printf;
-
- ///
- /// Wide character implementation of a class to support string formatting using `printf()` style templates
- ///
- typedef basic_string_printf, std::allocator > 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 _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, std::allocator > string_msg;
-
- ///
- /// Wide character implementation of a class to support string formatting using `FormatMessage()` style templates
- ///
- typedef basic_string_msg, std::allocator > 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 _Ax = std::allocator<_Elem> > class basic_string_guid;
-
- class WINSTD_API string_guid;
- class WINSTD_API 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 sanitizing_allocator;
-
- ///
- /// 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, sanitizing_allocator > 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, sanitizing_allocator > 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
-/// @{
-
-///
-/// Formats string using `printf()`.
-///
-/// \param[out] str Buffer to receive string
-/// \param[in ] capacity Size of `str` in characters
-/// \param[in ] format String template using `printf()` style
-/// \param[in ] arg Arguments to `format`
-///
-/// \returns Number of characters in result.
-///
-#if _MSC_VER <= 1600
-inline int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const char *format, _In_ va_list arg);
-#endif
-
-///
-/// Formats string using `printf()`.
-///
-/// \param[out] str Buffer to receive string
-/// \param[in ] capacity Size of `str` in characters
-/// \param[in ] format String template using `printf()` style
-/// \param[in ] arg Arguments to `format`
-///
-/// \returns Number of characters in result.
-///
-inline 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);
-
-///
-/// Formats string using `printf()`.
-///
-/// \param[out] str Formatted string
-/// \param[in ] format String template using `printf()` style
-/// \param[in ] arg Arguments to `format`
-///
-/// \returns Number of characters in result.
-///
-template inline int vsprintf(_Out_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, _In_ va_list arg);
-
-///
-/// Formats string using `printf()`.
-///
-/// \param[out] str Formatted string
-/// \param[in ] format String template using `printf()` style
-///
-/// \returns Number of characters in result.
-///
-template inline int sprintf(_Out_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, ...);
-
-///
-/// Formats a message string.
-///
-/// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
-///
-template inline DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Out_ std::basic_string &str, _In_opt_ va_list *Arguments);
-
-///
-/// Formats a message string.
-///
-/// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
-///
-template inline DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Out_ std::basic_string &str, _In_opt_ va_list *Arguments);
-
-/// @}
-
-#pragma once
-
-#include
-
-#include
-#include
-
-
-/// \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
-
-/// @}
-
-
-namespace winstd
-{
- /// \addtogroup WinStdGeneral
- /// @{
-
- ///
- /// Deleter for unique_ptr using LocalFree
- ///
- template
- struct LocalFree_delete
- {
- typedef LocalFree_delete<_Ty> _Myt; ///< This type
-
- ///
- /// Default construct
- ///
- LocalFree_delete() {}
-
- ///
- /// Construct from another LocalFree_delete
- ///
- template LocalFree_delete(const LocalFree_delete<_Ty2>&) {}
-
- ///
- /// Delete a pointer
- ///
- /// \sa [LocalFree function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366730.aspx)
- ///
- void operator()(_Ty *_Ptr) const
- {
- LocalFree(_Ptr);
- }
- };
-
-
- ///
- /// Deleter for unique_ptr to array of unknown size using LocalFree
- ///
- template
- struct LocalFree_delete<_Ty[]>
- {
- typedef LocalFree_delete<_Ty> _Myt; ///< This type
-
- ///
- /// Default construct
- ///
- LocalFree_delete() {}
-
- ///
- /// Delete a pointer
- ///
- void operator()(_Ty *_Ptr) const
- {
- LocalFree(_Ptr);
- }
-
- ///
- /// Delete a pointer of another type
- ///
- /// \sa [LocalFree function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366730.aspx)
- ///
- template
- void operator()(_Other *) const
- {
- LocalFree(_Ptr);
- }
- };
-
-
- ///
- /// Helper class for returning pointers to std::unique_ptr
- ///
- template
- class ref_unique_ptr
- {
- public:
- ///
- /// Takes ownership of the pointer
- ///
- /// \param[inout] owner Object to attach helper to
- ///
- inline ref_unique_ptr(_Inout_ std::unique_ptr<_Ty, _Dx> &owner) :
- m_own(owner),
- m_ptr(owner.release())
- {}
-
- ///
- /// Moves object
- ///
- /// \param[inout] other Source object
- ///
- inline ref_unique_ptr(_Inout_ ref_unique_ptr<_Ty, _Dx> &&other) :
- m_own(other.m_own),
- m_ptr(other.m_ptr)
- {
- other.m_ptr = nullptr;
- }
-
- ///
- /// Returns ownership of the pointer
- ///
- inline ~ref_unique_ptr()
- {
- if (m_ptr != nullptr)
- m_own.reset(m_ptr);
- }
-
- ///
- /// Operator for pointer-to-pointer parameters by value use-cases.
- ///
- /// \return Pointer to the pointer
- ///
- inline operator typename _Ty**()
- {
- return &m_ptr;
- }
-
- ///
- /// Operator for reverence-to-pointer parameters by value use-cases.
- ///
- /// \return Reference to the pointer
- ///
- inline operator typename _Ty*&()
- {
- return m_ptr;
- }
-
- protected:
- std::unique_ptr<_Ty, _Dx> &m_own; ///< Original owner of the pointer
- _Ty *m_ptr; ///< Pointer
- };
-
-
- ///
- /// Helper class for returning pointers to std::unique_ptr
- /// (specialization for arrays)
- ///
- template
- class ref_unique_ptr<_Ty[], _Dx>
- {
- public:
- ///
- /// Takes ownership of the pointer
- ///
- /// \param[inout] owner Object to attach helper to
- ///
- inline ref_unique_ptr(_Inout_ std::unique_ptr<_Ty[], _Dx> &owner) :
- m_own(owner),
- m_ptr(owner.release())
- {}
-
- ///
- /// Moves object
- ///
- /// \param[inout] other Source object
- ///
- inline ref_unique_ptr(_Inout_ ref_unique_ptr<_Ty[], _Dx> &&other) :
- m_own(other.m_own),
- m_ptr(other.m_ptr)
- {
- other.m_ptr = nullptr;
- }
-
- ///
- /// Returns ownership of the pointer
- ///
- inline ~ref_unique_ptr()
- {
- if (m_ptr != nullptr)
- m_own.reset(m_ptr);
- }
-
- ///
- /// Operator for pointer-to-pointer parameters by value use-cases.
- ///
- /// \return Pointer to the pointer
- ///
- inline operator typename _Ty**()
- {
- return &m_ptr;
- }
-
- ///
- /// Operator for reverence-to-pointer parameters by value use-cases.
- ///
- /// \return Reference to the pointer
- ///
- inline operator typename _Ty*&()
- {
- return m_ptr;
- }
-
- protected:
- std::unique_ptr<_Ty[], _Dx> &m_own; ///< Original owner of the pointer
- _Ty *m_ptr; ///< Pointer
- };
-
- template
- inline ref_unique_ptr<_Ty, _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty, _Dx> &owner)
- {
- return ref_unique_ptr<_Ty, _Dx>(owner);
- }
-
- template
- inline ref_unique_ptr<_Ty[], _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty[], _Dx> &owner)
- {
- return ref_unique_ptr<_Ty[], _Dx>(owner);
- }
-
- /// @}
-
-
- /// \addtogroup WinStdSysHandles
- /// @{
-
- ///
- /// Base abstract template class to support generic object handle keeping
- ///
- /// It provides basic operators and methods common to all descendands of this class establishing a base to ease the replacement of native object handle type with classes in object-oriented approach.
- ///
- template
- class handle
- {
- public:
- ///
- /// Datatype of the object handle this template class handles
- ///
- typedef T handle_type;
-
- ///
- /// Initializes a new class instance with the object handle set to NULL.
- ///
- inline handle() : m_h(NULL)
- {
- }
-
- ///
- /// Initializes a new class instance with an already available object handle.
- ///
- /// \param[in] h Initial object handle value
- ///
- inline handle(_In_ handle_type h) : m_h(h)
- {
- }
-
- ///
- /// Move constructor
- ///
- /// \param[inout] h A rvalue reference of another object
- ///
- inline handle(_Inout_ handle &&h)
- {
- // Transfer handle.
- m_h = h.m_h;
- h.m_h = NULL;
- }
-
- private:
- // This class is noncopyable.
- handle(_In_ const handle &h);
- handle& operator=(_In_ const handle &h);
-
- public:
- ///
- /// Attaches already available object handle.
- ///
- /// \param[in] h Object handle value
- ///
- inline handle& operator=(_In_ handle_type h)
- {
- attach(h);
- return *this;
- }
-
- ///
- /// Move assignment
- ///
- /// \param[inout] h A rvalue reference of another object
- ///
- inline handle& operator=(_Inout_ handle &&h)
- {
- if (this != std::addressof(h)) {
- // Transfer handle.
- if (m_h)
- free_internal();
- m_h = h.m_h;
- h.m_h = NULL;
- }
- return *this;
- }
-
- ///
- /// Auto-typecasting operator
- ///
- /// \return Object handle
- ///
- inline operator handle_type() const
- {
- return m_h;
- }
-
- ///
- /// Returns the object handle value when the object handle is a pointer to a value (class, struct, etc.).
- ///
- /// \return Object handle value
- ///
- inline handle_type*& operator*() const
- {
- assert(m_h != NULL);
- return *m_h;
- }
-
- ///
- /// Returns the object handle reference.
- /// \return Object handle reference
- ///
- inline handle_type* operator&()
- {
- assert(m_h == NULL);
- return &m_h;
- }
-
- ///
- /// Provides object handle member access when the object handle is a pointer to a class or struct.
- ///
- /// \return Object handle
- ///
- inline handle_type operator->() const
- {
- assert(m_h != NULL);
- return m_h;
- }
-
- ///
- /// Tests if the object handle is NULL.
- ///
- /// \return
- /// - Non zero when object handle is NULL;
- /// - Zero otherwise.
- ///
- inline bool operator!() const
- {
- return m_h == NULL;
- }
-
- ///
- /// Is handle less than?
- ///
- /// \param[in] h Object handle to compare against
- /// \return
- /// - Non zero when object handle is less than h;
- /// - Zero otherwise.
- ///
- inline bool operator<(_In_ handle_type h) const
- {
- return m_h < h;
- }
-
- ///
- /// Is handle less than or equal to?
- ///
- /// \param[in] h Object handle to compare against
- /// \return
- /// - Non zero when object handle is less than or equal to h;
- /// - Zero otherwise.
- ///
- inline bool operator<=(_In_ handle_type h) const
- {
- return !operator>(h);
- }
-
- ///
- /// Is handle greater than or equal to?
- ///
- /// \param[in] h Object handle to compare against
- /// \return
- /// - Non zero when object handle is greater than or equal to h;
- /// - Zero otherwise.
- ///
- inline bool operator>=(_In_ handle_type h) const
- {
- return !operator<(h);
- }
-
- ///
- /// Is handle greater than?
- ///
- /// \param[in] h Object handle to compare against
- /// \return
- /// - Non zero when object handle is greater than h;
- /// - Zero otherwise.
- ///
- inline bool operator>(_In_ handle_type h) const
- {
- return h < m_h;
- }
-
- ///
- /// Is handle not equal to?
- ///
- /// \param[in] h Object handle to compare against
- /// \return
- /// - Non zero when object handle is not equal to h;
- /// - Zero otherwise.
- ///
- inline bool operator!=(_In_ handle_type h) const
- {
- return !operator==(h);
- }
-
- ///
- /// Is handle equal to?
- ///
- /// \param[in] h Object handle to compare against
- /// \return
- /// - Non zero when object handle is equal to h;
- /// - Zero otherwise.
- ///
- inline bool operator==(_In_ handle_type h) const
- {
- return m_h == h;
- }
-
- ///
- /// Sets a new object handle for the class
- ///
- /// When the current object handle of the class is non-NULL, the object is destroyed first.
- ///
- /// \param[in] h New object handle
- ///
- inline void attach(_In_ handle_type h)
- {
- if (m_h)
- free_internal();
- m_h = h;
- }
-
- ///
- /// Dismisses the object handle from this class
- ///
- /// \return Object handle
- ///
- inline handle_type detach()
- {
- handle_type h = m_h;
- m_h = NULL;
- return h;
- }
-
- ///
- /// Destroys the object
- ///
- inline void free()
- {
- if (m_h) {
- free_internal();
- m_h = NULL;
- }
- }
-
- /// @}
-
- protected:
- ///
- /// Abstract member function that must be implemented by child classes to do the actual object destruction.
- ///
- virtual void free_internal() = 0;
-
- protected:
- handle_type m_h; ///< Object handle
- };
-
-
- ///
- /// Base abstract template class to support object handle keeping for objects that support handle duplication
- ///
- template
- class dplhandle : public handle
- {
- public:
- ///
- /// Initializes a new class instance with the object handle set to NULL.
- ///
- inline dplhandle()
- {
- }
-
- ///
- /// Initializes a new class instance with an already available object handle.
- ///
- /// \param[in] h Initial object handle value
- ///
- inline dplhandle(_In_ handle_type h) : handle(h)
- {
- }
-
- ///
- /// Copy constructor
- ///
- /// \param[inout] h A reference of another object
- ///
- inline dplhandle(_In_ const dplhandle &h) : handle(internal_duplicate(h.m_h))
- {
- }
-
- ///
- /// Move constructor
- ///
- /// \param[inout] h A rvalue reference of another object
- ///
- inline dplhandle(_Inout_ dplhandle &&h) : handle(std::move(h))
- {
- }
-
- ///
- /// Attaches already available object handle.
- ///
- /// \param[in] h Object handle value
- ///
- inline dplhandle& operator=(_In_ handle_type h)
- {
- handle::operator=(h);
- return *this;
- }
-
- ///
- /// Duplicates the object.
- ///
- /// \param[in] h Object
- ///
- inline dplhandle& operator=(_In_ const dplhandle &h)
- {
- if (this != std::addressof(h)) {
- if (h.m_h) {
- handle_type h_new = duplicate_internal(h.m_h);
- if (h_new) {
- if (m_h)
- free_internal();
-
- m_h = h_new;
- } else
- assert(0); // Could not duplicate the handle
- } else {
- if (m_h)
- free_internal();
-
- m_h = NULL;
- }
- }
- return *this;
- }
-
- ///
- /// Moves the object.
- ///
- /// \param[inout] h A rvalue reference of another object
- ///
- inline dplhandle& operator=(_Inout_ dplhandle &&h)
- {
- handle::operator=(std::move(h));
- return *this;
- }
-
- ///
- /// Duplicates and returns a new object handle.
- ///
- /// \return Duplicated object handle
- ///
- inline handle_type duplicate() const
- {
- return m_h ? duplicate_internal(m_h) : NULL;
- }
-
- ///
- /// Duplicates an object handle and sets a new object handle.
- ///
- /// \param[in] h Object handle of existing object
- ///
- /// \return
- /// - true when duplication succeeds;
- /// - false when duplication fails. In case of failure obtaining the extended error information is object type specific (for example: `GetLastError()`).
- ///
- inline bool attach_duplicated(_In_ handle_type h)
- {
- if (m_h)
- free_internal();
-
- return h ? (m_h = duplicate_internal(h)) != NULL : (m_h = NULL, true);
- }
-
- protected:
- ///
- /// Abstract member function that must be implemented by child classes to do the actual object handle duplication.
- ///
- /// \param[in] h Object handle of existing object
- ///
- /// \return Duplicated object handle
- ///
- virtual handle_type duplicate_internal(_In_ handle_type h) const = 0;
- };
-
- /// @}
-
- /// \addtogroup WinStdGeneral
- /// @{
-
- ///
- /// Helper class to allow limited size FIFO queues implemented as vector of elements
- ///
- template
- class vector_queue
- {
- public:
- ///
- /// Type to measure element count and indices in
- ///
- typedef size_t size_type;
-
- ///
- /// Element type
- ///
- typedef T value_type;
-
- ///
- /// Reference to element type
- ///
- typedef T& reference;
-
- ///
- /// Constant reference to element type
- ///
- typedef const T& const_reference;
-
- ///
- /// Pointer to element
- ///
- typedef T* pointer;
-
- ///
- /// Constant pointer to element
- ///
- typedef const T* const_pointer;
-
- public:
- ///
- /// Construct queue of fixed size.
- ///
- /// \param[in] size_max Maximum number of elements. Please note this cannot be changed later.
- ///
- inline vector_queue(_In_ size_type size_max) :
- m_data(new value_type[size_max]),
- m_head(0),
- m_count(0),
- m_size_max(size_max)
- {
- }
-
- ///
- /// Copies existing queue.
- ///
- /// \param[in] other Queue to copy from
- ///
- inline vector_queue(_In_ const vector_queue &other) :
- m_data(new value_type[other.m_size_max]),
- m_head(other.m_head),
- m_count(other.m_count),
- m_size_max(other.m_size_max)
- {
- // Copy elements.
- for (size_type i = 0; i < m_count; i++) {
- size_type i_l = abs(i);
- m_data[i_l] = other.m_data[i_l];
- }
- }
-
- ///
- /// Destroys the queue
- ///
- virtual ~vector_queue()
- {
- if (m_data) delete [] m_data;
- }
-
- ///
- /// Moves existing queue.
- ///
- /// \param[inout] other Queue to move
- ///
- inline vector_queue(_Inout_ vector_queue &&other) :
- m_data (std::move(other.m_data )),
- m_head (std::move(other.m_head )),
- m_count (std::move(other.m_count )),
- m_size_max(std::move(other.m_size_max))
- {
- // Reset other to consistent state.
- other.m_data = NULL;
- other.m_head = 0;
- other.m_count = 0;
- other.m_size_max = 0;
- }
-
- ///
- /// Copies existing queue.
- ///
- /// \param[in] other Queue to copy from
- ///
- inline vector_queue& operator=(_In_ const vector_queue &other)
- {
- if (this != std::addressof(other)) {
- m_head = other.m_head;
- m_count = other.m_count;
- m_size_max = other.m_size_max;
-
- // Copy elements.
- if (m_data) delete [] m_data;
- m_data = new value_type[other.m_size_max];
- for (size_type i = 0; i < m_count; i++) {
- size_type i_l = abs(i);
- m_data[i_l] = other.m_data[i_l];
- }
- }
-
- return *this;
- }
-
- ///
- /// Moves existing queue.
- ///
- /// \param[inout] other Queue to move
- ///
- inline vector_queue& operator=(_Inout_ vector_queue &&other)
- {
- if (this != std::addressof(other)) {
- m_data = std::move(other.m_data );
- m_head = std::move(other.m_head );
- m_count = std::move(other.m_count );
- m_size_max = std::move(other.m_size_max);
-
- // Reset other to consistent state.
- other.m_data = NULL;
- other.m_head = 0;
- other.m_count = 0;
- other.m_size_max = 0;
- }
-
- return *this;
- }
-
- ///
- /// Returns the number of elements in the vector.
- ///
- inline size_type size() const
- {
- return m_count;
- }
-
- ///
- /// Returns the number of elements that the queue can contain before overwriting head ones.
- ///
- inline size_type capacity() const
- {
- return m_size_max;
- }
-
- ///
- /// Erases the elements of the queue.
- ///
- inline void clear()
- {
- m_count = 0;
- }
-
- ///
- /// Tests if the queue is empty.
- ///
- inline bool empty() const
- {
- return m_count == 0;
- }
-
- ///
- /// Returns a reference to the element at a specified location in the queue.
- ///
- /// \param[in] pos The subscript or position number of the element to reference in the queue.
- ///
- inline reference at(_In_ size_type pos)
- {
- if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
- return m_data[abs(pos)];
- }
-
- ///
- /// Returns a reference to the element at a specified location in the queue.
- ///
- /// \param[in] pos The subscript or position number of the element to reference in the queue.
- ///
- inline reference operator[](_In_ size_type pos)
- {
- if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
- return m_data[abs(pos)];
- }
-
- ///
- /// Returns a constant reference to the element at a specified location in the queue.
- ///
- /// \param[in] pos The subscript or position number of the element to reference in the queue.
- ///
- inline const_reference at(_In_ size_type pos) const
- {
- if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
- return m_data[abs(pos)];
- }
-
- ///
- /// Returns a constant reference to the element at a specified location in the queue.
- ///
- /// \param[in] pos The subscript or position number of the element to reference in the queue.
- ///
- inline const_reference operator[](_In_ size_type pos) const
- {
- if (pos >= m_count) throw std::invalid_argument("Invalid subscript");
- return m_data[abs(pos)];
- }
-
- ///
- /// Returns a reference to the element at the absolute location in the queue.
- ///
- /// \note Absolute means "measured from the beginning of the storage".
- ///
- /// \param[in] pos The absolute subscript or position number of the element to reference in the queue.
- ///
- inline reference at_abs(_In_ size_type pos)
- {
- if (pos >= m_size_max) throw std::invalid_argument("Invalid subscript");
- return m_data[pos];
- }
-
- ///
- /// Returns a constant reference to the element at the absolute location in the queue: measured from the beginning of the storage.
- ///
- /// \note Absolute means "measured from the beginning of the storage".
- ///
- /// \param[in] pos The absolute subscript or position number of the element to reference in the queue.
- ///
- inline const_reference at_abs(_In_ size_type pos) const
- {
- if (pos >= m_size_max) throw std::invalid_argument("Invalid subscript");
- return m_data[pos];
- }
-
- ///
- /// Copies an existing element to the end of the queue, overriding the first one when queue is out of space.
- ///
- /// \param[in] v Element to copy to the end of the queue.
- ///
- /// \returns The absolute subscript or position number the element was copied to.
- ///
- inline size_type push_back(_In_ const value_type &v)
- {
- if (m_count < m_size_max) {
- size_type pos = abs(m_count);
- m_data[pos] = v;
- m_count++;
- return pos;
- } else {
- size_type pos = m_head;
- m_data[pos] = v;
- m_head = abs(1);
- return pos;
- }
- }
-
- ///
- /// Moves the element to the end of the queue, overriding the first one when queue is out of space.
- ///
- /// \param[in] v Element to move to the end of the queue.
- ///
- /// \returns The absolute subscript or position number the element was moved to.
- ///
- inline size_type push_back(_Inout_ value_type&&v)
- {
- if (m_count < m_size_max) {
- size_type pos = abs(m_count);
- m_data[pos] = std::move(v);
- m_count++;
- return pos;
- } else {
- size_type pos = m_head;
- m_data[pos] = std::move(v);
- m_head = abs(1);
- return pos;
- }
- }
-
- ///
- /// Removes (dequeues) the last element of the queue.
- ///
- inline void pop_back()
- {
- if (!m_count) throw std::invalid_argument("Empty storage");
- m_count--;
- }
-
- ///
- /// Copies an existing element to the head of the queue, overriding the last one when queue is out of space and moving all others one place right.
- ///
- /// \param[in] v Element to copy to the head of the queue.
- ///
- /// \returns The absolute subscript or position number the element was copied to.
- ///
- inline size_type push_front(_In_ const value_type &v)
- {
- m_head = abs(-1);
- if (m_count < m_size_max)
- m_count++;
- m_data[m_head] = v;
- return m_head;
- }
-
- ///
- /// Moves the element to the head of the queue, overriding the last one when queue is out of space and moving all others one place right.
- ///
- /// \param[in] v Element to move to the head of the queue.
- ///
- /// \returns The absolute subscript or position number the element was moved to.
- ///
- inline size_type push_front(_Inout_ value_type&&v)
- {
- m_head = abs(-1);
- if (m_count < m_size_max)
- m_count++;
- m_data[m_head] = std::move(v);
- return m_head;
- }
-
- ///
- /// Removes (dequeues) the head element of the queue.
- ///
- inline void pop_front()
- {
- if (!m_count) throw std::invalid_argument("Empty storage");
- m_head = abs(1);
- m_count--;
- }
-
- ///
- /// Returns a reference to the head element in the queue.
- ///
- inline reference front()
- {
- if (!m_count) throw std::invalid_argument("Empty storage");
- return m_data[m_head];
- }
-
- ///
- /// Returns a constant reference to the head element in the queue.
- ///
- inline const_reference front() const
- {
- if (!m_count) throw std::invalid_argument("Empty storage");
- return m_data[m_head];
- }
-
- ///
- /// Returns a reference to the last element in the queue.
- ///
- inline reference back()
- {
- return m_data[tail()];
- }
-
- ///
- /// Returns a constant reference to the last element in the queue.
- ///
- inline const_reference back() const
- {
- return m_data[tail()];
- }
-
- ///
- /// Returns absolute subscript or position number of the head element in the queue. The element does not need to exist.
- ///
- inline size_type head() const
- {
- return m_head;
- }
-
- ///
- /// Returns absolute subscript or position number of the last element in the queue. The element must exist.
- ///
- inline size_type tail() const
- {
- if (!m_count) throw std::invalid_argument("Empty storage");
- return abs(m_count - 1);
- }
-
- ///
- /// Returns absolute subscript or position number of the given element in the queue.
- inline size_type abs(_In_ size_type pos) const
- {
- return (m_head + pos) % m_size_max;
- }
-
- protected:
- value_type *m_data; ///< Underlying data container
- size_type m_head; ///< Index of the first element
- size_type m_count; ///< Number of elements
- size_type m_size_max; ///< Maximum size
- };
-
- /// @}
-
- /// \addtogroup WinStdExceptions
- /// @{
-
- ///
- /// Numerical runtime error
- ///
- template
- class num_runtime_error : public std::runtime_error
- {
- public:
- typedef _Tn error_type; ///< Error number type
-
- public:
- ///
- /// Constructs an exception
- ///
- /// \param[in] num Numeric error code
- /// \param[in] msg Error message
- ///
- inline num_runtime_error(_In_ error_type num, _In_ const std::string& msg) :
- m_num(num),
- runtime_error(msg.c_str())
- {
- }
-
-
- ///
- /// Constructs an exception
- ///
- /// \param[in] num Numeric error code
- /// \param[in] msg Error message
- ///
- inline num_runtime_error(_In_ error_type num, _In_z_ const char *msg) :
- m_num(num),
- runtime_error(msg)
- {
- }
-
-
- ///
- /// Copies an exception
- ///
- /// \param[in] other Exception to copy from
- ///
- inline num_runtime_error(const num_runtime_error<_Tn> &other) :
- m_num(other.m_num),
- runtime_error(other)
- {
- }
-
-
- ///
- /// Copies an exception
- ///
- /// \param[in] other Exception to copy from
- ///
- inline num_runtime_error& operator=(const num_runtime_error<_Tn> &other)
- {
- if (this != addressof(other)) {
- *(runtime_error*)this = other;
- m_num = other.m_num;
- }
-
- return *this;
- }
-
-
- ///
- /// Returns the Windows error number
- ///
- inline error_type number() const
- {
- return m_num;
- }
-
- protected:
- error_type m_num; ///< Numeric error code
- };
-
-
- ///
- /// Windows runtime error
- ///
- class WINSTD_API win_runtime_error : public num_runtime_error
- {
- public:
- ///
- /// Constructs an exception
- ///
- /// \param[in] num Windows error code
- /// \param[in] msg Error message
- ///
- inline win_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error(num, msg.c_str())
- {
- }
-
-
- ///
- /// Constructs an exception
- ///
- /// \param[in] num Windows error code
- /// \param[in] msg Error message
- ///
- inline win_runtime_error(_In_ error_type num, _In_z_ const char *msg) : num_runtime_error(num, msg)
- {
- }
-
-
- ///
- /// Constructs an exception using `GetLastError()`
- ///
- /// \param[in] msg Error message
- ///
- inline win_runtime_error(_In_ const std::string& msg) : num_runtime_error(GetLastError(), msg.c_str())
- {
- }
-
-
- ///
- /// Constructs an exception using `GetLastError()`
- ///
- /// \param[in] msg Error message
- ///
- inline win_runtime_error(_In_z_ const char *msg) : num_runtime_error(GetLastError(), msg)
- {
- }
-
-
- ///
- /// Copies an exception
- ///
- /// \param[in] other Exception to copy from
- ///
- inline win_runtime_error(const win_runtime_error &other) : num_runtime_error(other)
- {
- }
- };
-
- /// @}
-
- /// \addtogroup WinStdStrFormat
- /// @{
-
- ///
- /// Base template class to support string formatting using `printf()` style templates
- ///
- template
- class basic_string_printf : public std::basic_string<_Elem, _Traits, _Ax>
- {
- public:
- /// \name Initializing string using template in memory
- /// @{
-
- ///
- /// Initializes a new string and formats its contents using `printf()` style template.
- ///
- /// \param[in] format String template using `printf()` style
- ///
- inline basic_string_printf(_In_z_ _Printf_format_string_ const _Elem *format, ...)
- {
- va_list arg;
- va_start(arg, format);
- vsprintf(*this, format, arg);
- va_end(arg);
- }
-
- /// @}
-
- /// \name Initializing string using template in resources
- /// @{
-
- ///
- /// Initializes a new string and formats its contents using `printf()` style template in resources.
- ///
- /// \param[in] hInstance Resource module handle
- /// \param[in] nFormatID Resource ID of the string template using `printf()` style
- ///
- inline basic_string_printf(_In_ HINSTANCE hInstance, _In_ UINT nFormatID, ...)
- {
- _Myt format;
- ATLENSURE(format.LoadString(hInstance, nFormatID));
-
- va_list arg;
- va_start(arg, nFormatID);
- vsprintf(*this, format, arg);
- va_end(arg);
- }
-
- ///
- /// Initializes a new string and formats its contents using `printf()` style template in resources.
- ///
- /// \param[in] hInstance Resource module handle
- /// \param[in] wLanguageID Resource language
- /// \param[in] nFormatID Resource ID of the string template using `printf()` style
- ///
- inline basic_string_printf(_In_ HINSTANCE hInstance, _In_ WORD wLanguageID, _In_ UINT nFormatID, ...)
- {
- _Myt format;
- ATLENSURE(format.LoadString(hInstance, nFormatID, wLanguageID));
-
- va_list arg;
- va_start(arg, nFormatID);
- vsprintf(*this, format, arg);
- va_end(arg);
- }
-
- /// }@
- };
-
-
- ///
- /// Base template class to support string formatting using `FormatMessage()` style templates
- ///
- template
- class basic_string_msg : public std::basic_string<_Elem, _Traits, _Ax>
- {
- public:
- /// \name Initializing string using template in memory
- /// @{
-
- ///
- /// Initializes a new string and formats its contents using `FormatMessage()` style template.
- ///
- /// \param[in] format String template using `FormatMessage()` style
- ///
- inline basic_string_msg(_In_z_ _FormatMessage_format_string_ const _Elem *format, ...)
- {
- va_list arg;
- va_start(arg, format);
- FormatMessage(FORMAT_MESSAGE_FROM_STRING, format, 0, 0, *this, &arg);
- va_end(arg);
- }
-
- /// @}
-
- /// \name Initializing string using template in resources
- /// @{
-
- ///
- /// Initializes a new string and formats its contents using `FormatMessage()` style template in resources.
- ///
- /// \param[in] hInstance Resource module handle
- /// \param[in] nFormatID Resource ID of the string template using `FormatMessage()` style
- ///
- inline basic_string_msg(_In_ HINSTANCE hInstance, _In_ UINT nFormatID, ...)
- {
- _Myt format(GetManager());
- ATLENSURE(format.LoadString(hInstance, nFormatID));
-
- va_list arg;
- va_start(arg, nFormatID);
- FormatMessage(FORMAT_MESSAGE_FROM_STRING, format, 0, 0, *this, &arg);
- va_end(arg);
- }
-
- ///
- /// Initializes a new string and formats its contents using `FormatMessage()` style template in resources.
- ///
- /// \param[in] hInstance Resource module handle
- /// \param[in] wLanguageID Resource language
- /// \param[in] nFormatID Resource ID of the string template using `FormatMessage()` style
- ///
- inline basic_string_msg(_In_ HINSTANCE hInstance, _In_ WORD wLanguageID, _In_ UINT nFormatID, ...)
- {
- _Myt format(GetManager());
- ATLENSURE(format.LoadString(hInstance, nFormatID, wLanguageID));
-
- va_list arg;
- va_start(arg, nFormatID);
- FormatMessage(FORMAT_MESSAGE_FROM_STRING, format, 0, 0, *this, &arg);
- va_end(arg);
- }
-
- /// @}
-
-
- ///
- /// Initializes a new string and formats its contents using `FormatMessage()` style.
- ///
- /// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
- ///
- inline basic_string_msg(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _In_opt_ va_list *Arguments)
- {
- FormatMessage(dwFlags & ~FORMAT_MESSAGE_ARGUMENT_ARRAY, lpSource, dwMessageId, dwLanguageId, *this, Arguments);
- }
-
-
- ///
- /// Initializes a new string and formats its contents using `FormatMessage()` style.
- ///
- /// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
- ///
- inline basic_string_msg(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _In_opt_ DWORD_PTR *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.
- ///
- /// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
- ///
- inline basic_string_msg(_In_ DWORD dwFlags, _In_z_ LPCTSTR pszFormat, _In_opt_ va_list *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.
- ///
- /// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
- ///
- inline basic_string_msg(_In_ DWORD dwFlags, _In_z_ LPCTSTR pszFormat, _In_opt_ DWORD_PTR *Arguments)
- {
- FormatMessage(dwFlags | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING, pszFormat, 0, 0, *this, (va_list*)Arguments);
- }
- };
-
-
- ///
- /// Base template class to support converting GUID to string
- ///
- template
- class basic_string_guid : public std::basic_string<_Elem, _Traits, _Ax>
- {
- public:
- /// \name Initializing string using template in memory
- /// @{
-
- ///
- /// Initializes a new string and formats its contents to string representation of given GUID.
- ///
- /// \param[in] guid GUID to convert
- /// \param[in] format A `printf()` syntax template to convert GUID to string (i.e. `"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"`)
- ///
- inline basic_string_guid(_In_ const GUID &guid, _In_opt_z_ _Printf_format_string_ const _Elem *format)
- {
- sprintf<_Elem, _Traits, _Ax>(*this, format,
- guid.Data1,
- guid.Data2,
- guid.Data3,
- guid.Data4[0], guid.Data4[1],
- guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
- }
-
- /// @}
- };
-
-
- ///
- /// Single-byte character implementation of a class to support converting GUID to string
- ///
- class WINSTD_API string_guid : public basic_string_guid, std::allocator >
- {
- public:
- /// \name Initializing string using template in memory
- /// @{
-
- ///
- /// Initializes a new string and formats its contents to string representation of given GUID.
- ///
- /// \param[in] guid GUID to convert
- ///
- inline string_guid(_In_ const GUID &guid) :
- basic_string_guid, std::allocator >(guid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}")
- {
- }
-
- /// @}
- };
-
-
- ///
- /// Wide character implementation of a class to support converting GUID to string
- ///
- class WINSTD_API wstring_guid : public basic_string_guid, std::allocator >
- {
- public:
- /// \name Initializing string using template in memory
- /// @{
-
- ///
- /// Initializes a new string and formats its contents to string representation of given GUID.
- ///
- /// \param[in] guid GUID to convert
- ///
- inline wstring_guid(_In_ const GUID &guid) :
- basic_string_guid, std::allocator >(guid, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}")
- {
- }
-
- /// @}
- };
-
- /// @}
-
- /// \addtogroup WinStdMemSanitize
- /// @{
-
- // winstd::sanitizing_allocator::destroy() member generates _Ptr parameter not used warning for primitive datatypes _Ty.
- #pragma warning(push)
- #pragma warning(disable: 4100)
-
- ///
- /// An allocator template that sanitizes each memory block before it is destroyed or reallocated
- ///
- /// \note
- /// `sanitizing_allocator` introduces a performance penalty. However, it provides an additional level of security.
- /// Use for security sensitive data memory storage only.
- ///
- template
- class sanitizing_allocator : public std::allocator<_Ty>
- {
- public:
- typedef std::allocator<_Ty> _Mybase; ///< Base type
-
- ///
- /// Convert this type to sanitizing_allocator<_Other>
- ///
- template
- struct rebind
- {
- typedef sanitizing_allocator<_Other> other; ///< Other type
- };
-
-
- ///
- /// Construct default allocator
- ///
- inline sanitizing_allocator() : _Mybase()
- {
- }
-
-
- ///
- /// Construct by copying
- ///
- inline sanitizing_allocator(_In_ const sanitizing_allocator<_Ty> &_Othr) : _Mybase(_Othr)
- {
- }
-
-
- ///
- /// Construct from a related allocator
- ///
- template
- inline sanitizing_allocator(_In_ const sanitizing_allocator<_Other> &_Othr) : _Mybase(_Othr)
- {
- }
-
-
- ///
- /// Deallocate object at _Ptr sanitizing its content first
- ///
- inline void deallocate(_In_ pointer _Ptr, _In_ size_type _Size)
- {
- // Sanitize then free.
- SecureZeroMemory(_Ptr, _Size);
- _Mybase::deallocate(_Ptr, _Size);
- }
- };
-
- #pragma warning(pop)
-
- /// @}
-}
-
-
-// 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(push)
-#pragma warning(disable: 4995)
-#pragma warning(disable: 4996)
-
-#if _MSC_VER <= 1600
-
-inline 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
-
-
-inline 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)
-{
- return _vsnwprintf(str, capacity, format, arg);
-}
-
-
-template
-inline int vsprintf(_Out_ 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.
- std::unique_ptr<_Elem[]> buf_dyn(new _Elem[capacity]);
- count = vsnprintf(buf_dyn.get(), capacity - 1, format, arg);
- if (count >= 0) {
- str.assign(buf_dyn.get(), count);
- break;
- }
- }
- }
-
- return count;
-}
-
-#pragma warning(pop)
-
-
-template
-inline int sprintf(_Out_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, ...)
-{
- va_list arg;
- va_start(arg, format);
- int res = vsprintf(str, format, arg);
- va_end(arg);
- return res;
-}
-
-
-template
-inline DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Out_ std::basic_string &str, _In_opt_ va_list *Arguments)
-{
- std::unique_ptr > lpBuffer;
- DWORD dwResult = FormatMessageA(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER, lpSource, dwMessageId, dwLanguageId, reinterpret_cast((LPSTR*)get_ptr(lpBuffer)), 0, Arguments);
- if (dwResult)
- str.assign(lpBuffer.get(), dwResult);
- return dwResult;
-}
-
-
-template
-inline DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Out_ std::basic_string &str, _In_opt_ va_list *Arguments)
-{
- std::unique_ptr > lpBuffer;
- DWORD dwResult = FormatMessageW(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER, lpSource, dwMessageId, dwLanguageId, reinterpret_cast((LPWSTR*)get_ptr(lpBuffer)), 0, Arguments);
- if (dwResult)
- str.assign(lpBuffer.get(), dwResult);
- return dwResult;
-}
+/*
+ Copyright 1991-2018 Amebis
+ Copyright 2016 GÉANT
+
+ This file is part of WinStd.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+///
+/// \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
+///
+
+#include
+
+#include
+
+#include
+#include
+#include
+
+/// \addtogroup WinStdGeneral
+/// @{
+
+///
+/// Public function calling convention
+///
+#ifndef WINSTD_API
+#if defined(WINSTD_DLL)
+#define WINSTD_API __declspec(dllexport)
+#elif defined(WINSTD_DLLIMP)
+#define WINSTD_API __declspec(dllimport)
+#else
+#define WINSTD_API
+#endif
+#endif
+
+///
+/// Class/struct with no virtual table declaration
+///
+/// Use for storing flat data.
+///
+/// This macro bypasses Doxygen limitation to parse class/struct declarations with parentheses.
+///
+#define WINSTD_NOVTABLE __declspec(novtable)
+
+///
+/// "L" stringizing macro
+///
+#ifndef __L
+#define __L(x) L ## x
+#endif
+
+///
+/// Makes string Unicode
+///
+#ifndef _L
+#define _L(x) __L(x)
+#endif
+
+///
+/// Stringizing macro helper
+///
+#define STRING_IMPL(x) #x
+
+///
+/// Stringizing macro
+///
+#define STRING(x) STRING_IMPL(x)
+
+///
+/// Declares a class as non-copyable
+///
+#define WINSTD_NONCOPYABLE(C) \
+private: \
+ inline C (_In_ const C &h); \
+ inline C& operator=(_In_ const C &h);
+
+/// @}
+
+/// \addtogroup WinStdSysHandles
+/// @{
+
+///
+/// Implements default constructors and operators to prevent their auto-generation by compiler.
+///
+#define HANDLE_IMPL(C) \
+public: \
+ inline C ( ) { } \
+ inline C (_In_ handle_type h) : handle( h ) { } \
+ inline C (_Inout_ C &&h) noexcept : handle(std::move(h)) { } \
+ inline C& operator=(_In_ handle_type h) { handle::operator=( h ); return *this; } \
+ inline C& operator=(_Inout_ C &&h) noexcept { handle::operator=(std::move(h)); return *this; } \
+WINSTD_NONCOPYABLE(C)
+
+///
+/// Implements default constructors and operators to prevent their auto-generation by compiler.
+///
+#define DPLHANDLE_IMPL(C) \
+public: \
+ inline C ( ) { } \
+ inline C (_In_ handle_type h) : dplhandle( h ) { } \
+ inline C (_In_ const C &h) : dplhandle(duplicate_internal(h.m_h)) { } \
+ inline C (_Inout_ C &&h) noexcept : dplhandle(std::move (h )) { } \
+ inline C& operator=(_In_ handle_type h) { dplhandle::operator=( h ); return *this; } \
+ inline C& operator=(_In_ const C &h) { dplhandle::operator=( h ); return *this; } \
+ inline C& operator=(_Inout_ C &&h) noexcept { dplhandle::operator=(std::move(h)); return *this; } \
+private:
+
+/// @}
+
+
+#ifndef _FormatMessage_format_string_
+#define _FormatMessage_format_string_
+#endif
+
+
+namespace winstd
+{
+ /// \addtogroup WinStdStrFormat
+ /// @{
+
+ ///
+ /// Multi-byte / Wide-character string (according to _UNICODE)
+ ///
+#ifdef _UNICODE
+ typedef std::wstring tstring;
+#else
+ typedef std::string tstring;
+#endif
+
+ /// @}
+
+ template struct LocalFree_delete;
+ template struct LocalFree_delete<_Ty[]>;
+ template> class ref_unique_ptr;
+ template class ref_unique_ptr<_Ty[], _Dx>;
+ template class handle;
+ template class dplhandle;
+ template class vector_queue;
+ template class num_runtime_error;
+ class WINSTD_API 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 inline ref_unique_ptr<_Ty, _Dx> get_ptr(_Inout_ std::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 inline ref_unique_ptr<_Ty[], _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty[], _Dx> &owner);
+
+ /// @}
+
+
+ /// \addtogroup WinStdStrFormat
+ /// @{
+
+ template, 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, std::allocator > string_printf;
+
+ ///
+ /// Wide character implementation of a class to support string formatting using `printf()` style templates
+ ///
+ typedef basic_string_printf, std::allocator > 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 _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, std::allocator > string_msg;
+
+ ///
+ /// Wide character implementation of a class to support string formatting using `FormatMessage()` style templates
+ ///
+ typedef basic_string_msg, std::allocator > 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 _Ax = std::allocator<_Elem> > class basic_string_guid;
+
+ class WINSTD_API string_guid;
+ class WINSTD_API 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 sanitizing_allocator;
+
+ ///
+ /// 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, sanitizing_allocator > 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, sanitizing_allocator > 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
+/// @{
+
+///
+/// Formats string using `printf()`.
+///
+/// \param[out] str Buffer to receive string
+/// \param[in ] capacity Size of `str` in characters
+/// \param[in ] format String template using `printf()` style
+/// \param[in ] arg Arguments to `format`
+///
+/// \returns Number of characters in result.
+///
+#if _MSC_VER <= 1600
+inline int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_ const char *format, _In_ va_list arg);
+#endif
+
+///
+/// Formats string using `printf()`.
+///
+/// \param[out] str Buffer to receive string
+/// \param[in ] capacity Size of `str` in characters
+/// \param[in ] format String template using `printf()` style
+/// \param[in ] arg Arguments to `format`
+///
+/// \returns Number of characters in result.
+///
+inline 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);
+
+///
+/// Formats string using `printf()`.
+///
+/// \param[out] str Formatted string
+/// \param[in ] format String template using `printf()` style
+/// \param[in ] arg Arguments to `format`
+///
+/// \returns Number of characters in result.
+///
+template inline int vsprintf(_Out_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, _In_ va_list arg);
+
+///
+/// Formats string using `printf()`.
+///
+/// \param[out] str Formatted string
+/// \param[in ] format String template using `printf()` style
+///
+/// \returns Number of characters in result.
+///
+template inline int sprintf(_Out_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_ const _Elem *format, ...);
+
+///
+/// Formats a message string.
+///
+/// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
+///
+template inline DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Out_ std::basic_string &str, _In_opt_ va_list *Arguments);
+
+///
+/// Formats a message string.
+///
+/// \sa [FormatMessage function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351.aspx)
+///
+template inline DWORD FormatMessage(_In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Out_ std::basic_string &str, _In_opt_ va_list *Arguments);
+
+/// @}
+
+#pragma once
+
+#include
+
+#include
+#include
+
+
+/// \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
+
+/// @}
+
+
+namespace winstd
+{
+ /// \addtogroup WinStdGeneral
+ /// @{
+
+ ///
+ /// Deleter for unique_ptr using LocalFree
+ ///
+ template
+ struct LocalFree_delete
+ {
+ typedef LocalFree_delete<_Ty> _Myt; ///< This type
+
+ ///
+ /// Default construct
+ ///
+ LocalFree_delete() {}
+
+ ///
+ /// Construct from another LocalFree_delete
+ ///
+ template LocalFree_delete(const LocalFree_delete<_Ty2>&) {}
+
+ ///
+ /// Delete a pointer
+ ///
+ /// \sa [LocalFree function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366730.aspx)
+ ///
+ void operator()(_Ty *_Ptr) const
+ {
+ LocalFree(_Ptr);
+ }
+ };
+
+
+ ///
+ /// Deleter for unique_ptr to array of unknown size using LocalFree
+ ///
+ template
+ struct LocalFree_delete<_Ty[]>
+ {
+ typedef LocalFree_delete<_Ty> _Myt; ///< This type
+
+ ///
+ /// Default construct
+ ///
+ LocalFree_delete() {}
+
+ ///
+ /// Delete a pointer
+ ///
+ void operator()(_Ty *_Ptr) const
+ {
+ LocalFree(_Ptr);
+ }
+
+ ///
+ /// Delete a pointer of another type
+ ///
+ /// \sa [LocalFree function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366730.aspx)
+ ///
+ template
+ void operator()(_Other *) const
+ {
+ LocalFree(_Ptr);
+ }
+ };
+
+
+ ///
+ /// Helper class for returning pointers to std::unique_ptr
+ ///
+ template
+ class ref_unique_ptr
+ {
+ public:
+ ///
+ /// Takes ownership of the pointer
+ ///
+ /// \param[inout] owner Object to attach helper to
+ ///
+ inline ref_unique_ptr(_Inout_ std::unique_ptr<_Ty, _Dx> &owner) :
+ m_own(owner),
+ m_ptr(owner.release())
+ {}
+
+ ///
+ /// Moves object
+ ///
+ /// \param[inout] other Source object
+ ///
+ inline ref_unique_ptr(_Inout_ ref_unique_ptr<_Ty, _Dx> &&other) :
+ m_own(other.m_own),
+ m_ptr(other.m_ptr)
+ {
+ other.m_ptr = nullptr;
+ }
+
+ ///
+ /// Returns ownership of the pointer
+ ///
+ inline ~ref_unique_ptr()
+ {
+ if (m_ptr != nullptr)
+ m_own.reset(m_ptr);
+ }
+
+ ///
+ /// Operator for pointer-to-pointer parameters by value use-cases.
+ ///
+ /// \return Pointer to the pointer
+ ///
+ inline operator typename _Ty**()
+ {
+ return &m_ptr;
+ }
+
+ ///
+ /// Operator for reverence-to-pointer parameters by value use-cases.
+ ///
+ /// \return Reference to the pointer
+ ///
+ inline operator typename _Ty*&()
+ {
+ return m_ptr;
+ }
+
+ protected:
+ std::unique_ptr<_Ty, _Dx> &m_own; ///< Original owner of the pointer
+ _Ty *m_ptr; ///< Pointer
+ };
+
+
+ ///
+ /// Helper class for returning pointers to std::unique_ptr
+ /// (specialization for arrays)
+ ///
+ template
+ class ref_unique_ptr<_Ty[], _Dx>
+ {
+ public:
+ ///
+ /// Takes ownership of the pointer
+ ///
+ /// \param[inout] owner Object to attach helper to
+ ///
+ inline ref_unique_ptr(_Inout_ std::unique_ptr<_Ty[], _Dx> &owner) :
+ m_own(owner),
+ m_ptr(owner.release())
+ {}
+
+ ///
+ /// Moves object
+ ///
+ /// \param[inout] other Source object
+ ///
+ inline ref_unique_ptr(_Inout_ ref_unique_ptr<_Ty[], _Dx> &&other) :
+ m_own(other.m_own),
+ m_ptr(other.m_ptr)
+ {
+ other.m_ptr = nullptr;
+ }
+
+ ///
+ /// Returns ownership of the pointer
+ ///
+ inline ~ref_unique_ptr()
+ {
+ if (m_ptr != nullptr)
+ m_own.reset(m_ptr);
+ }
+
+ ///
+ /// Operator for pointer-to-pointer parameters by value use-cases.
+ ///
+ /// \return Pointer to the pointer
+ ///
+ inline operator typename _Ty**()
+ {
+ return &m_ptr;
+ }
+
+ ///
+ /// Operator for reverence-to-pointer parameters by value use-cases.
+ ///
+ /// \return Reference to the pointer
+ ///
+ inline operator typename _Ty*&()
+ {
+ return m_ptr;
+ }
+
+ protected:
+ std::unique_ptr<_Ty[], _Dx> &m_own; ///< Original owner of the pointer
+ _Ty *m_ptr; ///< Pointer
+ };
+
+ template
+ inline ref_unique_ptr<_Ty, _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty, _Dx> &owner)
+ {
+ return ref_unique_ptr<_Ty, _Dx>(owner);
+ }
+
+ template
+ inline ref_unique_ptr<_Ty[], _Dx> get_ptr(_Inout_ std::unique_ptr<_Ty[], _Dx> &owner)
+ {
+ return ref_unique_ptr<_Ty[], _Dx>(owner);
+ }
+
+ /// @}
+
+
+ /// \addtogroup WinStdSysHandles
+ /// @{
+
+ ///
+ /// Base abstract template class to support generic object handle keeping
+ ///
+ /// It provides basic operators and methods common to all descendands of this class establishing a base to ease the replacement of native object handle type with classes in object-oriented approach.
+ ///
+ template
+ class handle
+ {
+ public:
+ ///
+ /// Datatype of the object handle this template class handles
+ ///
+ typedef T handle_type;
+
+ ///
+ /// Initializes a new class instance with the object handle set to NULL.
+ ///
+ inline handle() : m_h(NULL)
+ {
+ }
+
+ ///
+ /// Initializes a new class instance with an already available object handle.
+ ///
+ /// \param[in] h Initial object handle value
+ ///
+ inline handle(_In_ handle_type h) : m_h(h)
+ {
+ }
+
+ ///
+ /// Move constructor
+ ///
+ /// \param[inout] h A rvalue reference of another object
+ ///
+ inline handle(_Inout_ handle &&h) noexcept
+ {
+ // Transfer handle.
+ m_h = h.m_h;
+ h.m_h = NULL;
+ }
+
+ private:
+ // This class is noncopyable.
+ handle(_In_ const handle &h);
+ handle& operator=(_In_ const handle &h);
+
+ public:
+ ///
+ /// Attaches already available object handle.
+ ///
+ /// \param[in] h Object handle value
+ ///
+ inline handle& operator=(_In_ handle_type h)
+ {
+ attach(h);
+ return *this;
+ }
+
+ ///
+ /// Move assignment
+ ///
+ /// \param[inout] h A rvalue reference of another object
+ ///
+ inline handle& operator=(_Inout_ handle &&h) noexcept
+ {
+ if (this != std::addressof(h)) {
+ // Transfer handle.
+ if (m_h)
+ free_internal();
+ m_h = h.m_h;
+ h.m_h = NULL;
+ }
+ return *this;
+ }
+
+ ///
+ /// Auto-typecasting operator
+ ///
+ /// \return Object handle
+ ///
+ inline operator handle_type() const
+ {
+ return m_h;
+ }
+
+ ///
+ /// Returns the object handle value when the object handle is a pointer to a value (class, struct, etc.).
+ ///
+ /// \return Object handle value
+ ///
+ inline handle_type*& operator*() const
+ {
+ assert(m_h != NULL);
+ return *m_h;
+ }
+
+ ///
+ /// Returns the object handle reference.
+ /// \return Object handle reference
+ ///
+ inline handle_type* operator&()
+ {
+ assert(m_h == NULL);
+ return &m_h;
+ }
+
+ ///
+ /// Provides object handle member access when the object handle is a pointer to a class or struct.
+ ///
+ /// \return Object handle
+ ///
+ inline handle_type operator->() const
+ {
+ assert(m_h != NULL);
+ return m_h;
+ }
+
+ ///
+ /// Tests if the object handle is NULL.
+ ///
+ /// \return
+ /// - Non zero when object handle is NULL;
+ /// - Zero otherwise.
+ ///
+ inline bool operator!() const
+ {
+ return m_h == NULL;
+ }
+
+ ///
+ /// Is handle less than?
+ ///
+ /// \param[in] h Object handle to compare against
+ /// \return
+ /// - Non zero when object handle is less than h;
+ /// - Zero otherwise.
+ ///
+ inline bool operator<(_In_ handle_type h) const
+ {
+ return m_h < h;
+ }
+
+ ///
+ /// Is handle less than or equal to?
+ ///
+ /// \param[in] h Object handle to compare against
+ /// \return
+ /// - Non zero when object handle is less than or equal to h;
+ /// - Zero otherwise.
+ ///
+ inline bool operator<=(_In_ handle_type h) const
+ {
+ return !operator>(h);
+ }
+
+ ///
+ /// Is handle greater than or equal to?
+ ///
+ /// \param[in] h Object handle to compare against
+ /// \return
+ /// - Non zero when object handle is greater than or equal to h;
+ /// - Zero otherwise.
+ ///
+ inline bool operator>=(_In_ handle_type h) const
+ {
+ return !operator<(h);
+ }
+
+ ///
+ /// Is handle greater than?
+ ///
+ /// \param[in] h Object handle to compare against
+ /// \return
+ /// - Non zero when object handle is greater than h;
+ /// - Zero otherwise.
+ ///
+ inline bool operator>(_In_ handle_type h) const
+ {
+ return h < m_h;
+ }
+
+ ///
+ /// Is handle not equal to?
+ ///
+ /// \param[in] h Object handle to compare against
+ /// \return
+ /// - Non zero when object handle is not equal to h;
+ /// - Zero otherwise.
+ ///
+ inline bool operator!=(_In_ handle_type h) const
+ {
+ return !operator==(h);
+ }
+
+ ///
+ /// Is handle equal to?
+ ///
+ /// \param[in] h Object handle to compare against
+ /// \return
+ /// - Non zero when object handle is equal to h;
+ /// - Zero otherwise.
+ ///
+ inline bool operator==(_In_ handle_type h) const
+ {
+ return m_h == h;
+ }
+
+ ///
+ /// Sets a new object handle for the class
+ ///
+ /// When the current object handle of the class is non-NULL, the object is destroyed first.
+ ///
+ /// \param[in] h New object handle
+ ///
+ inline void attach(_In_ handle_type h)
+ {
+ if (m_h)
+ free_internal();
+ m_h = h;
+ }
+
+ ///
+ /// Dismisses the object handle from this class
+ ///
+ /// \return Object handle
+ ///
+ inline handle_type detach()
+ {
+ handle_type h = m_h;
+ m_h = NULL;
+ return h;
+ }
+
+ ///
+ /// Destroys the object
+ ///
+ inline void free()
+ {
+ if (m_h) {
+ free_internal();
+ m_h = NULL;
+ }
+ }
+
+ /// @}
+
+ protected:
+ ///
+ /// Abstract member function that must be implemented by child classes to do the actual object destruction.
+ ///
+ virtual void free_internal() = 0;
+
+ protected:
+ handle_type m_h; ///< Object handle
+ };
+
+
+ ///
+ /// Base abstract template class to support object handle keeping for objects that support handle duplication
+ ///
+ template
+ class dplhandle : public handle
+ {
+ public:
+ ///
+ /// Initializes a new class instance with the object handle set to NULL.
+ ///
+ inline dplhandle()
+ {
+ }
+
+ ///
+ /// Initializes a new class instance with an already available object handle.
+ ///
+ /// \param[in] h Initial object handle value
+ ///
+ inline dplhandle(_In_ handle_type h) : handle(h)
+ {
+ }
+
+ ///
+ /// Copy constructor
+ ///
+ /// \param[inout] h A reference of another object
+ ///
+ inline dplhandle(_In_ const dplhandle &h) : handle(internal_duplicate(h.m_h))
+ {
+ }
+
+ ///
+ /// Move constructor
+ ///
+ /// \param[inout] h A rvalue reference of another object
+ ///
+ inline dplhandle