Initial version forked from https://github.com/Amebis/atlex.git
This commit is contained in:
615
include/WinStd/Common.h
Normal file
615
include/WinStd/Common.h
Normal file
@@ -0,0 +1,615 @@
|
||||
/*
|
||||
Copyright 1991-2016 Amebis
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
||||
#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
|
||||
|
||||
|
||||
// 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)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
|
||||
///
|
||||
/// 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<class _Elem, class _Traits, class _Ax>
|
||||
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.
|
||||
auto buf = std::unique_ptr<_Elem[]>(new _Elem[capacity]);
|
||||
count = vsnprintf(buf.get(), capacity - 1, format, arg);
|
||||
if (count >= 0) {
|
||||
str.assign(buf.get(), count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Formats string using `printf()`.
|
||||
///
|
||||
/// \param[out] str Formatted string
|
||||
/// \param[in ] format String template using `printf()` style
|
||||
///
|
||||
/// \returns Number of characters in result.
|
||||
///
|
||||
template<class _Elem, class _Traits, class _Ax>
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
namespace winstd
|
||||
{
|
||||
///
|
||||
/// \defgroup WinStdSysHandles System Handles
|
||||
/// Simplifies work with object handles of various type
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// 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 T> 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 available object handle.
|
||||
///
|
||||
/// \param[in] h Initial object handle value
|
||||
///
|
||||
inline handle(_In_opt_ handle_type h) : m_h(h)
|
||||
{
|
||||
}
|
||||
|
||||
/// \name Operators for transparent usage of this class
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Comparison operators
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// 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_opt_ 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_opt_ handle_type h) const
|
||||
{
|
||||
return m_h <= 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_opt_ handle_type h) const
|
||||
{
|
||||
return m_h >= 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_opt_ handle_type h) const
|
||||
{
|
||||
return m_h > 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_opt_ 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_opt_ 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_opt_ 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 T>
|
||||
class dplhandle : public handle<T>
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// 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_opt_ handle_type h)
|
||||
{
|
||||
if (m_h)
|
||||
free_internal();
|
||||
|
||||
return h ? (m_h = duplicate_internal(h)) != NULL : (m_h = NULL, TRUE);
|
||||
}
|
||||
|
||||
//
|
||||
// Do not allow = operators. They are semantically ambigious:
|
||||
// Do they attach the class to the existing instance of object, or do they duplicate it?
|
||||
// To avoid confusion, user should use attach() and Duplicate() methods explicitly.
|
||||
//
|
||||
//inline const dplhandle<T>& operator=(_In_ const handle_type src)
|
||||
//{
|
||||
// attach(src ? duplicate_internal(src) : NULL);
|
||||
// return *this;
|
||||
//}
|
||||
|
||||
//inline const dplhandle<T>& operator=(_In_ const dplhandle<T> &src)
|
||||
//{
|
||||
// attach(src.m_h ? duplicate_internal(src.m_h) : NULL);
|
||||
// return *this;
|
||||
//}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
///
|
||||
/// \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)(string_printf("%i is less than %i.\n", 1, 5));
|
||||
/// \endcode
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Base template class to support string formatting using `printf()` style templates
|
||||
///
|
||||
template<class _Elem, class _Traits = char_traits<_Elem>, class _Ax = allocator<_Elem> >
|
||||
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
|
||||
///
|
||||
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
|
||||
///
|
||||
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
|
||||
///
|
||||
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);
|
||||
}
|
||||
|
||||
/// }@
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// Single-byte character implementation of a class to support string formatting using `printf()` style templates
|
||||
///
|
||||
typedef basic_string_printf<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > string_printf;
|
||||
|
||||
|
||||
///
|
||||
/// Wide character implementation of a class to support string formatting using `printf()` style templates
|
||||
///
|
||||
typedef basic_string_printf<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>> wstring_printf;
|
||||
|
||||
|
||||
///
|
||||
/// Base template class to support string formatting using `FormatMessage()` style templates
|
||||
///
|
||||
template<class _Elem, class _Traits = char_traits<_Elem>, class _Ax = allocator<_Elem> >
|
||||
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
|
||||
///
|
||||
basic_string_msg(_In_z_ _FormatMessage_format_string_ const _Elem *format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
FormatMessageV(format, &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
|
||||
///
|
||||
basic_string_msg(_In_ HINSTANCE hInstance, _In_ UINT nFormatID, ...)
|
||||
{
|
||||
_Myt format(GetManager());
|
||||
ATLENSURE(format.LoadString(hInstance, nFormatID));
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, nFormatID);
|
||||
FormatMessageV(format, &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
|
||||
///
|
||||
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);
|
||||
FormatMessageV(format, &arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
///
|
||||
/// Single-byte character implementation of a class to support string formatting using `FormatMessage()` style templates
|
||||
///
|
||||
typedef basic_string_msg<char, std::char_traits<char>, std::allocator<char> > string_msg;
|
||||
|
||||
///
|
||||
/// Wide character implementation of a class to support string formatting using `FormatMessage()` style templates
|
||||
///
|
||||
typedef basic_string_msg<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > wstring_msg;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \defgroup WinStdMemSanitize Auto-sanitize Memory Management
|
||||
/// Sanitizes memory before dismissed
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// 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 _Ty>
|
||||
class sanitizing_allocator : public std::allocator<_Ty> {
|
||||
public:
|
||||
///
|
||||
/// Sanitizes memory before freeing it
|
||||
///
|
||||
/// \param[in] p Pointer to heap memory block
|
||||
///
|
||||
void deallocate(_In_ pointer p, _In_ size_type count)
|
||||
{
|
||||
// Sanitize then free.
|
||||
SecureZeroMemory(p, sizeof(_Ty)*count);
|
||||
std::allocator<_Ty>::deallocate(p, count);
|
||||
}
|
||||
};
|
||||
|
||||
/// @}
|
||||
}
|
492
include/WinStd/Crypt.h
Normal file
492
include/WinStd/Crypt.h
Normal file
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
Copyright 1991-2016 Amebis
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <WinCrypt.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
///
|
||||
/// \defgroup WinStdCryptoAPI Cryptography API
|
||||
/// Integrates WinStd classes with Microsoft Cryptography API
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Obtains the subject or issuer name from a certificate [CERT_CONTEXT](https://msdn.microsoft.com/en-us/library/windows/desktop/aa377189.aspx) structure and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [CertGetNameString function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx)
|
||||
///
|
||||
inline DWORD CertGetNameStringA(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwType, _In_ DWORD dwFlags, _In_ void *pvTypePara, _Out_ std::string &sNameString)
|
||||
{
|
||||
// Query the final string length first.
|
||||
DWORD dwSize = ::CertGetNameStringA(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
|
||||
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[dwSize]);
|
||||
dwSize = ::CertGetNameStringA(pCertContext, dwType, dwFlags, pvTypePara, szBuffer.get(), dwSize);
|
||||
sNameString.assign(szBuffer.get(), dwSize);
|
||||
return dwSize;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Obtains the subject or issuer name from a certificate [CERT_CONTEXT](https://msdn.microsoft.com/en-us/library/windows/desktop/aa377189.aspx) structure and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [CertGetNameString function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx)
|
||||
///
|
||||
inline DWORD CertGetNameStringW(_In_ PCCERT_CONTEXT pCertContext, _In_ DWORD dwType, _In_ DWORD dwFlags, _In_ void *pvTypePara, _Out_ std::wstring &sNameString)
|
||||
{
|
||||
// Query the final string length first.
|
||||
DWORD dwSize = ::CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, NULL, 0);
|
||||
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[dwSize]);
|
||||
dwSize = ::CertGetNameStringW(pCertContext, dwType, dwFlags, pvTypePara, szBuffer.get(), dwSize);
|
||||
sNameString.assign(szBuffer.get(), dwSize);
|
||||
return dwSize;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Retrieves data that governs the operations of a hash object. The actual hash value can be retrieved by using this function.
|
||||
///
|
||||
/// \sa [CryptGetHashParam function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379947.aspx)
|
||||
///
|
||||
inline BOOL CryptGetHashParam(_In_ HCRYPTHASH hHash, _In_ DWORD dwParam, _Out_ std::vector<BYTE> &aData, _In_ DWORD dwFlags)
|
||||
{
|
||||
DWORD dwHashSize;
|
||||
|
||||
if (CryptGetHashParam(hHash, dwParam, NULL, &dwHashSize, dwFlags)) {
|
||||
aData.resize(dwHashSize);
|
||||
if (CryptGetHashParam(hHash, dwParam, aData.data(), &dwHashSize, dwFlags))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
aData.clear();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Exports a cryptographic key or a key pair from a cryptographic service provider (CSP) in a secure manner.
|
||||
///
|
||||
/// \sa [CryptExportKey function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379931.aspx)
|
||||
///
|
||||
inline BOOL CryptExportKey(_In_ HCRYPTKEY hKey, _In_ HCRYPTKEY hExpKey, _In_ DWORD dwBlobType, _In_ DWORD dwFlags, _Out_ std::vector<BYTE> &aData)
|
||||
{
|
||||
DWORD dwKeyBLOBSize;
|
||||
|
||||
if (CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, NULL, &dwKeyBLOBSize)) {
|
||||
aData.resize(dwKeyBLOBSize);
|
||||
if (CryptExportKey(hKey, hExpKey, dwBlobType, dwFlags, aData.data(), &dwKeyBLOBSize))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
aData.clear();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
namespace winstd
|
||||
{
|
||||
/// \addtogroup ATLCryptoAPI
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// PCCERT_CONTEXT wrapper class
|
||||
///
|
||||
class cert_context : public dplhandle<PCCERT_CONTEXT>
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Destroys the certificate context.
|
||||
///
|
||||
/// \sa [CertFreeCertificateContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376075.aspx)
|
||||
///
|
||||
virtual ~cert_context()
|
||||
{
|
||||
if (m_h)
|
||||
CertFreeCertificateContext(m_h);
|
||||
}
|
||||
|
||||
///
|
||||
/// Creates the certificate context.
|
||||
///
|
||||
/// \return
|
||||
/// - TRUE when creation succeeds;
|
||||
/// - FALSE when creation fails. For extended error information, call `GetLastError()`.
|
||||
/// \sa [CertCreateCertificateContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376033.aspx)
|
||||
///
|
||||
inline BOOL create(_In_ DWORD dwCertEncodingType, _In_ const BYTE *pbCertEncoded, _In_ DWORD cbCertEncoded)
|
||||
{
|
||||
handle_type h = CertCreateCertificateContext(dwCertEncodingType, pbCertEncoded, cbCertEncoded);
|
||||
if (h) {
|
||||
attach(h);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Destroys the certificate context.
|
||||
///
|
||||
/// \sa [CertFreeCertificateContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376075.aspx)
|
||||
///
|
||||
virtual void free_internal()
|
||||
{
|
||||
CertFreeCertificateContext(m_h);
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates the certificate context.
|
||||
///
|
||||
/// \param[in] h Object handle of existing certificate context
|
||||
///
|
||||
/// \return Duplicated certificate context handle
|
||||
///
|
||||
/// \sa [CertDuplicateCertificateContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376045.aspx)
|
||||
///
|
||||
virtual handle_type duplicate_internal(_In_ handle_type h) const
|
||||
{
|
||||
return CertDuplicateCertificateContext(h);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// PCCERT_CHAIN_CONTEXT wrapper class
|
||||
///
|
||||
class cert_chain_context : public dplhandle<PCCERT_CHAIN_CONTEXT>
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Destroys the certificate chain context.
|
||||
///
|
||||
/// \sa [CertFreeCertificateChain function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376073.aspx)
|
||||
///
|
||||
virtual ~cert_chain_context()
|
||||
{
|
||||
if (m_h)
|
||||
CertFreeCertificateChain(m_h);
|
||||
}
|
||||
|
||||
///
|
||||
/// Creates the certificate chain context.
|
||||
///
|
||||
/// \return
|
||||
/// - TRUE when creation succeeds;
|
||||
/// - FALSE when creation fails. For extended error information, call `GetLastError()`.
|
||||
/// \sa [CertGetCertificateChain function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376078.aspx)
|
||||
///
|
||||
inline BOOL create(_In_opt_ HCERTCHAINENGINE hChainEngine, _In_ PCCERT_CONTEXT pCertContext, _In_opt_ LPFILETIME pTime, _In_opt_ HCERTSTORE hAdditionalStore, _In_ PCERT_CHAIN_PARA pChainPara, _In_ DWORD dwFlags, __reserved LPVOID pvReserved)
|
||||
{
|
||||
handle_type h;
|
||||
if (CertGetCertificateChain(hChainEngine, pCertContext, pTime, hAdditionalStore, pChainPara, dwFlags, pvReserved, &h)) {
|
||||
attach(h);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Destroys the certificate chain context.
|
||||
///
|
||||
/// \sa [CertFreeCertificateChain function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376073.aspx)
|
||||
///
|
||||
virtual void free_internal()
|
||||
{
|
||||
CertFreeCertificateChain(m_h);
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates the certificate chain context.
|
||||
///
|
||||
/// \param[in] h Object handle of existing certificate chain context
|
||||
///
|
||||
/// \return Duplicated certificate chain context handle
|
||||
///
|
||||
/// \sa [CertDuplicateCertificateContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376045.aspx)
|
||||
///
|
||||
virtual handle_type duplicate_internal(_In_ handle_type h) const
|
||||
{
|
||||
return CertDuplicateCertificateChain(h);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HCERTSTORE wrapper class
|
||||
///
|
||||
class cert_store : public handle<HCERTSTORE>
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Closes the certificate store.
|
||||
///
|
||||
/// \sa [CertCloseStore function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376026.aspx)
|
||||
///
|
||||
virtual ~cert_store()
|
||||
{
|
||||
if (m_h)
|
||||
CertCloseStore(m_h, 0);
|
||||
}
|
||||
|
||||
///
|
||||
/// Opens the certificate store.
|
||||
///
|
||||
/// \return
|
||||
/// - TRUE when creation succeeds;
|
||||
/// - FALSE when creation fails. For extended error information, call `GetLastError()`.
|
||||
/// \sa [CertOpenStore function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376559.aspx)
|
||||
///
|
||||
inline BOOL create(_In_ LPCSTR lpszStoreProvider, _In_ DWORD dwEncodingType, _In_opt_ HCRYPTPROV_LEGACY hCryptProv, _In_ DWORD dwFlags, _In_opt_ const void *pvPara)
|
||||
{
|
||||
handle_type h = CertOpenStore(lpszStoreProvider, dwEncodingType, hCryptProv, dwFlags, pvPara);
|
||||
if (h) {
|
||||
attach(h);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Closes the certificate store.
|
||||
///
|
||||
/// \sa [CertCloseStore function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa376026.aspx)
|
||||
///
|
||||
virtual void free_internal()
|
||||
{
|
||||
CertCloseStore(m_h, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HCRYPTPROV wrapper class
|
||||
///
|
||||
class crypt_prov : public handle<HCRYPTPROV>
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Releases the cryptographi context.
|
||||
///
|
||||
/// \sa [CryptReleaseContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380268.aspx)
|
||||
///
|
||||
virtual ~crypt_prov()
|
||||
{
|
||||
if (m_h)
|
||||
CryptReleaseContext(m_h, 0);
|
||||
}
|
||||
|
||||
///
|
||||
/// Acquires the cryptographic context.
|
||||
///
|
||||
/// \return
|
||||
/// - TRUE when creation succeeds;
|
||||
/// - FALSE when creation fails. For extended error information, call `GetLastError()`.
|
||||
/// \sa [CryptAcquireContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379886.aspx)
|
||||
///
|
||||
inline BOOL create(_In_opt_ LPCTSTR szContainer, _In_opt_ LPCTSTR szProvider, _In_ DWORD dwProvType, _In_ DWORD dwFlags)
|
||||
{
|
||||
handle_type h;
|
||||
if (CryptAcquireContext(&h, szContainer, szProvider, dwProvType, dwFlags)) {
|
||||
attach(h);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Releases the cryptographic context.
|
||||
///
|
||||
/// \sa [CryptReleaseContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380268.aspx)
|
||||
///
|
||||
virtual void free_internal()
|
||||
{
|
||||
CryptReleaseContext(m_h, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HCRYPTHASH wrapper class
|
||||
///
|
||||
class crypt_hash : public dplhandle<HCRYPTHASH>
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Destroys the hash context.
|
||||
///
|
||||
/// \sa [CryptDestroyHash function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379917.aspx)
|
||||
///
|
||||
virtual ~crypt_hash()
|
||||
{
|
||||
if (m_h)
|
||||
CryptDestroyHash(m_h);
|
||||
}
|
||||
|
||||
///
|
||||
/// Creates the hash context.
|
||||
///
|
||||
/// \return
|
||||
/// - TRUE when creation succeeds;
|
||||
/// - FALSE when creation fails. For extended error information, call `GetLastError()`.
|
||||
/// \sa [CryptCreateHash function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379908.aspx)
|
||||
///
|
||||
inline BOOL create(_In_ HCRYPTPROV hProv, _In_ ALG_ID Algid, _In_ HCRYPTKEY hKey, _In_ DWORD dwFlags)
|
||||
{
|
||||
handle_type h;
|
||||
if (CryptCreateHash(hProv, Algid, hKey, dwFlags, &h)) {
|
||||
attach(h);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Destroys the hash context.
|
||||
///
|
||||
/// \sa [CryptDestroyHash function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379917.aspx)
|
||||
///
|
||||
virtual void free_internal()
|
||||
{
|
||||
CryptDestroyHash(m_h);
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates the hash context.
|
||||
///
|
||||
/// \param[in] h Object handle of existing hash context
|
||||
///
|
||||
/// \return Duplicated hash context handle
|
||||
///
|
||||
/// \sa [CryptDuplicateHash function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379919.aspx)
|
||||
///
|
||||
virtual handle_type duplicate_internal(_In_ handle_type h) const
|
||||
{
|
||||
handle_type hNew = NULL;
|
||||
return CryptDuplicateHash(h, NULL, 0, &hNew) ? hNew : NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HCRYPTKEY wrapper class
|
||||
///
|
||||
class crypt_key : public dplhandle<HCRYPTKEY>
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Destroys the key.
|
||||
///
|
||||
/// \sa [CryptDestroyKey function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379918.aspx)
|
||||
///
|
||||
virtual ~crypt_key()
|
||||
{
|
||||
if (m_h)
|
||||
CryptDestroyKey(m_h);
|
||||
}
|
||||
|
||||
///
|
||||
/// Generates the key.
|
||||
///
|
||||
/// \sa [CryptGenKey function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379941.aspx)
|
||||
///
|
||||
inline BOOL generate(_In_ HCRYPTPROV hProv, _In_ ALG_ID Algid, _In_ DWORD dwFlags)
|
||||
{
|
||||
handle_type h;
|
||||
if (CryptGenKey(hProv, Algid, dwFlags, &h)) {
|
||||
attach(h);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
///
|
||||
/// Imports the key.
|
||||
///
|
||||
/// \sa [CryptImportKey function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380207.aspx)
|
||||
///
|
||||
inline BOOL import(_In_ HCRYPTPROV hProv, __in_bcount(dwDataLen) CONST BYTE *pbData, _In_ DWORD dwDataLen, _In_ HCRYPTKEY hPubKey, _In_ DWORD dwFlags)
|
||||
{
|
||||
handle_type h;
|
||||
if (CryptImportKey(hProv, pbData, dwDataLen, hPubKey, dwFlags, &h)) {
|
||||
attach(h);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
///
|
||||
/// Imports the public key.
|
||||
///
|
||||
/// \sa [CryptImportPublicKeyInfo function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380209.aspx)
|
||||
///
|
||||
inline BOOL import_public(_In_ HCRYPTPROV hCryptProv, _In_ DWORD dwCertEncodingType, _In_ PCERT_PUBLIC_KEY_INFO pInfo)
|
||||
{
|
||||
handle_type h;
|
||||
if (CryptImportPublicKeyInfo(hCryptProv, dwCertEncodingType, pInfo, &h)) {
|
||||
attach(h);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Destroys the key.
|
||||
///
|
||||
/// \sa [CryptDestroyKey function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379918.aspx)
|
||||
///
|
||||
virtual void free_internal()
|
||||
{
|
||||
CryptDestroyKey(m_h);
|
||||
}
|
||||
|
||||
///
|
||||
/// Duplicates the key.
|
||||
///
|
||||
/// \param[in] h Object handle of existing key
|
||||
///
|
||||
/// \return Duplicated key handle
|
||||
///
|
||||
/// \sa [CryptDuplicateKey function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379920.aspx)
|
||||
///
|
||||
virtual handle_type duplicate_internal(_In_ handle_type h) const
|
||||
{
|
||||
handle_type hNew = NULL;
|
||||
return CryptDuplicateKey(h, NULL, 0, &hNew) ? hNew : NULL;
|
||||
}
|
||||
};
|
||||
|
||||
/// @}
|
||||
}
|
60
include/WinStd/EAP.h
Normal file
60
include/WinStd/EAP.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 1991-2016 Amebis
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <eaptypes.h>
|
||||
|
||||
|
||||
namespace winstd
|
||||
{
|
||||
///
|
||||
/// \defgroup WinStdEAPAPI Extensible Authentication Protocol API
|
||||
/// Integrates WinStd classes with Microsoft EAP API
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// EAP_ATTRIBUTE wrapper class
|
||||
///
|
||||
class eap_attr : public EAP_ATTRIBUTE
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Initializes a new EAP attribute set to eatReserved.
|
||||
///
|
||||
eap_attr()
|
||||
{
|
||||
eaType = eatReserved;
|
||||
dwLength = 0;
|
||||
pValue = NULL;
|
||||
}
|
||||
|
||||
///
|
||||
/// Destroys the EAP attribute.
|
||||
///
|
||||
~eap_attr()
|
||||
{
|
||||
if (pValue)
|
||||
delete pValue;
|
||||
}
|
||||
};
|
||||
|
||||
/// @}
|
||||
}
|
297
include/WinStd/MSI.h
Normal file
297
include/WinStd/MSI.h
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
Copyright 1991-2016 Amebis
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <MsiQuery.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
///
|
||||
/// \defgroup WinStdMSIAPI Microsoft Installer API
|
||||
/// Integrates WinStd classes with Microsoft Installer API
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Gets the value for an installer property and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [MsiGetProperty function](https://msdn.microsoft.com/en-us/library/aa370134.aspx)
|
||||
///
|
||||
inline UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_ LPCSTR szName, _Out_ std::string &sValue)
|
||||
{
|
||||
CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiGetPropertyA(hInstall, szName, szStackBuffer, &dwSize);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return NO_ERROR;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[++dwSize]);
|
||||
uiResult = ::MsiGetPropertyA(hInstall, szName, szBuffer.get(), &dwSize);
|
||||
sValue.assign(szBuffer.get(), uiResult == NO_ERROR ? dwSize : 0);
|
||||
return uiResult;
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Gets the value for an installer property and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [MsiGetProperty function](https://msdn.microsoft.com/en-us/library/aa370134.aspx)
|
||||
///
|
||||
inline UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_ LPCWSTR szName, _Out_ std::wstring &sValue)
|
||||
{
|
||||
WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiGetPropertyW(hInstall, szName, szStackBuffer, &dwSize);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return NO_ERROR;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[++dwSize]);
|
||||
uiResult = ::MsiGetPropertyW(hInstall, szName, szBuffer.get(), &dwSize);
|
||||
sValue.assign(szBuffer.get(), uiResult == NO_ERROR ? dwSize : 0);
|
||||
return uiResult;
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Returns the string value of a record field and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [MsiRecordGetString function](https://msdn.microsoft.com/en-us/library/aa370368.aspx)
|
||||
///
|
||||
inline UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Out_ std::string &sValue)
|
||||
{
|
||||
CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiRecordGetStringA(hRecord, iField, szStackBuffer, &dwSize);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return NO_ERROR;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[++dwSize]);
|
||||
uiResult = ::MsiRecordGetStringA(hRecord, iField, szBuffer.get(), &dwSize);
|
||||
sValue.assign(szBuffer.get(), uiResult == NO_ERROR ? dwSize : 0);
|
||||
return uiResult;
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Returns the string value of a record field and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [MsiRecordGetString function](https://msdn.microsoft.com/en-us/library/aa370368.aspx)
|
||||
///
|
||||
inline UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Out_ std::wstring &sValue)
|
||||
{
|
||||
WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiRecordGetStringW(hRecord, iField, szStackBuffer, &dwSize);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return NO_ERROR;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[++dwSize]);
|
||||
uiResult = ::MsiRecordGetStringW(hRecord, iField, szBuffer.get(), &dwSize);
|
||||
sValue.assign(szBuffer.get(), uiResult == NO_ERROR ? dwSize : 0);
|
||||
return uiResult;
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Formats record field data and properties using a format string and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [MsiFormatRecord function](https://msdn.microsoft.com/en-us/library/aa370109.aspx)
|
||||
///
|
||||
inline UINT MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, std::string &sValue)
|
||||
{
|
||||
CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiFormatRecordA(hInstall, hRecord, szStackBuffer, &dwSize);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return NO_ERROR;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[++dwSize]);
|
||||
uiResult = ::MsiFormatRecordA(hInstall, hRecord, szBuffer.get(), &dwSize);
|
||||
sValue.assign(szBuffer.get(), uiResult == NO_ERROR ? dwSize : 0);
|
||||
return uiResult;
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Formats record field data and properties using a format string and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [MsiFormatRecord function](https://msdn.microsoft.com/en-us/library/aa370109.aspx)
|
||||
///
|
||||
inline UINT MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, std::wstring &sValue)
|
||||
{
|
||||
WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiFormatRecordW(hInstall, hRecord, szStackBuffer, &dwSize);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return NO_ERROR;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[++dwSize]);
|
||||
uiResult = ::MsiFormatRecordW(hInstall, hRecord, szBuffer.get(), &dwSize);
|
||||
sValue.assign(szBuffer.get(), uiResult == NO_ERROR ? dwSize : 0);
|
||||
return uiResult;
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Reads bytes from a record stream field into a std::vector<BYTE> buffer.
|
||||
///
|
||||
/// \sa [MsiRecordReadStream function](https://msdn.microsoft.com/en-us/library/aa370370.aspx)
|
||||
///
|
||||
inline UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Out_ std::vector<BYTE> &binData)
|
||||
{
|
||||
DWORD dwSize = 0;
|
||||
UINT uiResult;
|
||||
|
||||
// Query the actual data length first.
|
||||
uiResult = ::MsiRecordReadStream(hRecord, iField, NULL, &dwSize);
|
||||
if (uiResult == NO_ERROR) {
|
||||
binData.resize(dwSize);
|
||||
return ::MsiRecordReadStream(hRecord, iField, (char*)binData.data(), &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Returns the full target path for a folder in the Directory table and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
|
||||
///
|
||||
inline UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_ LPCSTR szFolder, _Out_ std::string &sValue)
|
||||
{
|
||||
CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szStackBuffer, &dwSize);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return NO_ERROR;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[++dwSize]);
|
||||
uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szBuffer.get(), &dwSize);
|
||||
sValue.assign(szBuffer.get(), uiResult == NO_ERROR ? dwSize : 0);
|
||||
return uiResult;
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Returns the full target path for a folder in the Directory table and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
|
||||
///
|
||||
inline UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_ LPCWSTR szFolder, _Out_ std::wstring &sValue)
|
||||
{
|
||||
WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szStackBuffer, &dwSize);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return NO_ERROR;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[++dwSize]);
|
||||
uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szBuffer.get(), &dwSize);
|
||||
sValue.assign(szBuffer.get(), uiResult == NO_ERROR ? dwSize : 0);
|
||||
return uiResult;
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
94
include/WinStd/Sec.h
Normal file
94
include/WinStd/Sec.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright 1991-2016 Amebis
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Security.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
///
|
||||
/// \defgroup WinStdSecurityAPI Security API
|
||||
/// Integrates WinStd classes with Microsoft Security API
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Retrieves the name of the user or other security principal associated with the calling thread and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [GetUserNameEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx)
|
||||
///
|
||||
BOOLEAN GetUserNameExA(_In_ EXTENDED_NAME_FORMAT NameFormat, _Out_ std::string &sName)
|
||||
{
|
||||
CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
|
||||
ULONG ulSize = _countof(szStackBuffer);
|
||||
|
||||
// Try with stack buffer first.
|
||||
if (::GetUserNameExA(NameFormat, szStackBuffer, &ulSize)) {
|
||||
// Copy from stack.
|
||||
sName.assign(szStackBuffer, ulSize);
|
||||
return TRUE;
|
||||
} else {
|
||||
if (::GetLastError() == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap and retry.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[ulSize]);
|
||||
if (::GetUserNameExA(NameFormat, szBuffer.get(), &ulSize)) {
|
||||
sName.assign(szBuffer.get(), ulSize);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sName.clear();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Retrieves the name of the user or other security principal associated with the calling thread and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [GetUserNameEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx)
|
||||
///
|
||||
BOOLEAN GetUserNameExW(_In_ EXTENDED_NAME_FORMAT NameFormat, _Out_ std::wstring &sName)
|
||||
{
|
||||
WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
|
||||
ULONG ulSize = _countof(szStackBuffer);
|
||||
|
||||
// Try with stack buffer first.
|
||||
if (::GetUserNameExW(NameFormat, szStackBuffer, &ulSize)) {
|
||||
// Copy from stack.
|
||||
sName.assign(szStackBuffer, ulSize);
|
||||
return TRUE;
|
||||
} else {
|
||||
if (::GetLastError() == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap and retry.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[ulSize]);
|
||||
if (::GetUserNameExW(NameFormat, szBuffer.get(), &ulSize)) {
|
||||
sName.assign(szBuffer.get(), ulSize);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sName.clear();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/// @}
|
59
include/WinStd/Shell.h
Normal file
59
include/WinStd/Shell.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright 1991-2016 Amebis
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atlstr.h>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
///
|
||||
/// \defgroup WinStdShellWAPI Shell API
|
||||
/// Integrates WinStd classes with Microsoft Shell API
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Simplifies a path by removing navigation elements such as "." and ".." to produce a direct, well-formed path, and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [PathCanonicalize function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773569.aspx)
|
||||
///
|
||||
inline BOOL PathCanonicalizeA(__out std::string &sValue, __in LPCSTR pszPath)
|
||||
{
|
||||
// Allocate buffer on heap and read into it.
|
||||
CHAR szBuffer[MAX_PATH + 1];
|
||||
BOOL bResult = ::PathCanonicalizeA(szBuffer, pszPath);
|
||||
sValue.assign(szBuffer, bResult ? MAX_PATH : 0);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Simplifies a path by removing navigation elements such as "." and ".." to produce a direct, well-formed path, and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [PathCanonicalize function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773569.aspx)
|
||||
///
|
||||
inline BOOL PathCanonicalizeW(__out std::wstring &sValue, __in LPCWSTR pszPath)
|
||||
{
|
||||
WCHAR szBuffer[MAX_PATH + 1];
|
||||
BOOL bResult = ::PathCanonicalizeW(szBuffer, pszPath);
|
||||
sValue.assign(szBuffer, bResult ? MAX_PATH : 0);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
/// @}
|
70
include/WinStd/ShlWAPIi.h
Normal file
70
include/WinStd/ShlWAPIi.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright 1991-2016 Amebis
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atlstr.h>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
///
|
||||
/// \defgroup ATLShellWAPI Shell API
|
||||
/// Integrates ATL classes with Microsoft Shell API
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Simplifies a path by removing navigation elements such as "." and ".." to produce a direct, well-formed path, and stores it in a ATL::CAtlStringA string.
|
||||
///
|
||||
/// \sa [PathCanonicalize function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773569.aspx)
|
||||
///
|
||||
inline BOOL PathCanonicalizeA(__out ATL::CAtlStringA &sValue, __in LPCSTR pszPath)
|
||||
{
|
||||
// Allocate buffer on heap and read into it.
|
||||
LPSTR szBuffer = sValue.GetBuffer(MAX_PATH);
|
||||
if (!szBuffer) {
|
||||
::SetLastError(ERROR_OUTOFMEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
BOOL bResult = ::PathCanonicalizeA(szBuffer, pszPath);
|
||||
sValue.ReleaseBuffer(bResult ? (int)strnlen(szBuffer, MAX_PATH) : 0);
|
||||
sValue.FreeExtra();
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Simplifies a path by removing navigation elements such as "." and ".." to produce a direct, well-formed path, and stores it in a ATL::CAtlStringW string.
|
||||
///
|
||||
/// \sa [PathCanonicalize function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773569.aspx)
|
||||
///
|
||||
inline BOOL PathCanonicalizeW(__out ATL::CAtlStringW &sValue, __in LPCWSTR pszPath)
|
||||
{
|
||||
// Allocate buffer on heap and read into it.
|
||||
LPWSTR szBuffer = sValue.GetBuffer(MAX_PATH);
|
||||
if (!szBuffer) {
|
||||
::SetLastError(ERROR_OUTOFMEMORY);
|
||||
return FALSE;
|
||||
}
|
||||
BOOL bResult = ::PathCanonicalizeW(szBuffer, pszPath);
|
||||
sValue.ReleaseBuffer(bResult ? (int)wcsnlen(szBuffer, MAX_PATH) : 0);
|
||||
sValue.FreeExtra();
|
||||
return bResult;
|
||||
}
|
||||
|
||||
/// @}
|
73
include/WinStd/WLAN.h
Normal file
73
include/WinStd/WLAN.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
Copyright 1991-2016 Amebis
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atlstr.h>
|
||||
#include <wlanapi.h>
|
||||
|
||||
|
||||
// Must not statically link to Wlanapi.dll as it is not available on Windows
|
||||
// without a WLAN interface.
|
||||
extern DWORD (WINAPI *pfnWlanReasonCodeToString)(__in DWORD dwReasonCode, __in DWORD dwBufferSize, __in_ecount(dwBufferSize) PWCHAR pStringBuffer, __reserved PVOID pReserved);
|
||||
|
||||
|
||||
///
|
||||
/// \defgroup WinStdWLANAPI WLAN API
|
||||
/// Integrates WinStd classes with Microsoft WLAN API
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Retrieves a string that describes a specified reason code and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [WlanReasonCodeToString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706768.aspx)
|
||||
///
|
||||
/// \note
|
||||
/// Since Wlanapi.dll is not always present, the \c pfnWlanReasonCodeToString pointer to \c WlanReasonCodeToString
|
||||
/// function must be loaded dynamically.
|
||||
///
|
||||
inline DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Out_ std::wstring &sValue, __reserved PVOID pReserved)
|
||||
{
|
||||
DWORD dwSize = 0;
|
||||
|
||||
if (!::pfnWlanReasonCodeToString)
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
|
||||
for (;;) {
|
||||
// Increment size and allocate buffer.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[dwSize += 1024]);
|
||||
|
||||
// Try!
|
||||
DWORD dwResult = ::pfnWlanReasonCodeToString(dwReasonCode, dwSize, szBuffer.get(), pReserved);
|
||||
if (dwResult == NO_ERROR) {
|
||||
DWORD dwLength = (DWORD)wcsnlen(szBuffer.get(), dwSize);
|
||||
if (dwLength < dwSize) {
|
||||
// Buffer was long enough.
|
||||
sValue.assign(szBuffer.get(), dwLength);
|
||||
return NO_ERROR;
|
||||
}
|
||||
} else {
|
||||
// Return error code.
|
||||
return dwResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
574
include/WinStd/Win.h
Normal file
574
include/WinStd/Win.h
Normal file
@@ -0,0 +1,574 @@
|
||||
/*
|
||||
Copyright 1991-2016 Amebis
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
///
|
||||
/// \defgroup WinStdWinAPI Windows API
|
||||
/// Integrates WinStd classes with Microsoft Windows API
|
||||
///
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Retrieves the fully qualified path for the file that contains the specified module and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [GetModuleFileName function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683197.aspx)
|
||||
///
|
||||
inline DWORD GetModuleFileNameA(_In_opt_ HMODULE hModule, _Out_ std::string &sValue)
|
||||
{
|
||||
CHAR szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
|
||||
|
||||
// Try with stack buffer first.
|
||||
DWORD dwResult = ::GetModuleFileNameA(hModule, szBuffer, _countof(szBuffer));
|
||||
if (dwResult < _countof(szBuffer)) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szBuffer, dwResult);
|
||||
return dwResult;
|
||||
} else {
|
||||
for (DWORD dwCapacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR);; dwCapacity *= 2) {
|
||||
// Allocate on heap and retry.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[dwCapacity]);
|
||||
dwResult = ::GetModuleFileNameA(hModule, szBuffer.get(), dwCapacity);
|
||||
if (dwResult < dwCapacity) {
|
||||
sValue.assign(szBuffer.get(), dwResult);
|
||||
return dwResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Retrieves the fully qualified path for the file that contains the specified module and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [GetModuleFileName function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683197.aspx)
|
||||
///
|
||||
inline DWORD GetModuleFileNameW(_In_opt_ HMODULE hModule, _Out_ std::wstring &sValue)
|
||||
{
|
||||
WCHAR szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
|
||||
|
||||
// Try with stack buffer first.
|
||||
DWORD dwResult = ::GetModuleFileNameW(hModule, szBuffer, _countof(szBuffer));
|
||||
if (dwResult < _countof(szBuffer)) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szBuffer, dwResult);
|
||||
return dwResult;
|
||||
} else {
|
||||
for (DWORD dwCapacity = 2*WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR);; dwCapacity *= 2) {
|
||||
// Allocate on heap and retry.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[dwCapacity]);
|
||||
dwResult = ::GetModuleFileNameW(hModule, szBuffer.get(), dwCapacity);
|
||||
if (dwResult < dwCapacity) {
|
||||
sValue.assign(szBuffer.get(), dwResult);
|
||||
return dwResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Copies the text of the specified window's title bar (if it has one) into a std::string string.
|
||||
///
|
||||
/// \sa [GetWindowText function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633520.aspx)
|
||||
///
|
||||
inline int GetWindowTextA(_In_ HWND hWnd, _Out_ std::string &sValue)
|
||||
{
|
||||
int iResult;
|
||||
|
||||
// Query the final string length first.
|
||||
iResult = ::GetWindowTextLengthA(hWnd);
|
||||
if (iResult > 0) {
|
||||
if (++iResult < WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)) {
|
||||
// Read string data to stack.
|
||||
CHAR szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
|
||||
iResult = ::GetWindowTextA(hWnd, szBuffer, _countof(szBuffer));
|
||||
sValue.assign(szBuffer, iResult);
|
||||
} else {
|
||||
// Allocate buffer on heap and read the string data into it.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[++iResult]);
|
||||
iResult = ::GetWindowTextA(hWnd, szBuffer.get(), iResult);
|
||||
sValue.assign(szBuffer.get(), iResult);
|
||||
}
|
||||
return iResult;
|
||||
}
|
||||
|
||||
sValue.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Copies the text of the specified window's title bar (if it has one) into a std::wstring string.
|
||||
///
|
||||
/// \sa [GetWindowText function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633520.aspx)
|
||||
///
|
||||
inline int GetWindowTextW(_In_ HWND hWnd, _Out_ std::wstring &sValue)
|
||||
{
|
||||
int iResult;
|
||||
|
||||
// Query the final string length first.
|
||||
iResult = ::GetWindowTextLengthW(hWnd);
|
||||
if (iResult > 0) {
|
||||
if (++iResult < WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)) {
|
||||
// Read string data to stack.
|
||||
WCHAR szBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
|
||||
iResult = ::GetWindowTextW(hWnd, szBuffer, _countof(szBuffer));
|
||||
sValue.assign(szBuffer, iResult);
|
||||
} else {
|
||||
// Allocate buffer on heap and read the string data into it.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[++iResult]);
|
||||
iResult = ::GetWindowTextW(hWnd, szBuffer.get(), iResult);
|
||||
sValue.assign(szBuffer.get(), iResult);
|
||||
}
|
||||
return iResult;
|
||||
}
|
||||
|
||||
sValue.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Retrieves version information for the specified file and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [GetFileVersionInfo function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms647003.aspx)
|
||||
///
|
||||
inline BOOL GetFileVersionInfoA(_In_ LPCSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<BYTE> &aValue)
|
||||
{
|
||||
// Get version info size.
|
||||
DWORD dwVerInfoSize = ::GetFileVersionInfoSizeA(lptstrFilename, &dwHandle);
|
||||
if (dwVerInfoSize != 0) {
|
||||
// Read version info.
|
||||
aValue.resize(dwVerInfoSize);
|
||||
return ::GetFileVersionInfoA(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Retrieves version information for the specified file and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [GetFileVersionInfo function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms647003.aspx)
|
||||
///
|
||||
inline BOOL GetFileVersionInfoW(_In_ LPCWSTR lptstrFilename, __reserved DWORD dwHandle, _Out_ std::vector<BYTE> &aValue)
|
||||
{
|
||||
// Get version info size.
|
||||
DWORD dwVerInfoSize = ::GetFileVersionInfoSizeW(lptstrFilename, &dwHandle);
|
||||
if (dwVerInfoSize != 0) {
|
||||
// Read version info.
|
||||
aValue.resize(dwVerInfoSize);
|
||||
return ::GetFileVersionInfoW(lptstrFilename, dwHandle, dwVerInfoSize, aValue.data());
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Expands environment-variable strings, replaces them with the values defined for the current user, and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [ExpandEnvironmentStrings function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724265.aspx)
|
||||
///
|
||||
inline DWORD ExpandEnvironmentStringsW(_In_ LPCSTR lpSrc, std::string &sValue)
|
||||
{
|
||||
for (DWORD dwSizeOut = (DWORD)strlen(lpSrc) + 0x100;;) {
|
||||
DWORD dwSizeIn = dwSizeOut;
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[dwSizeIn + 2]); // Note: ANSI version requires one extra char.
|
||||
dwSizeOut = ::ExpandEnvironmentStringsA(lpSrc, szBuffer.get(), dwSizeIn);
|
||||
if (dwSizeOut == 0) {
|
||||
// Error.
|
||||
break;
|
||||
} else if (dwSizeOut <= dwSizeIn) {
|
||||
// The buffer was sufficient.
|
||||
sValue.assign(szBuffer.get(), dwSizeOut);
|
||||
return dwSizeOut;
|
||||
}
|
||||
}
|
||||
|
||||
sValue.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Expands environment-variable strings, replaces them with the values defined for the current user, and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [ExpandEnvironmentStrings function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724265.aspx)
|
||||
///
|
||||
inline DWORD ExpandEnvironmentStringsW(_In_ LPCWSTR lpSrc, std::wstring &sValue)
|
||||
{
|
||||
for (DWORD dwSizeOut = (DWORD)wcslen(lpSrc) + 0x100;;) {
|
||||
DWORD dwSizeIn = dwSizeOut;
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[dwSizeIn + 1]);
|
||||
dwSizeOut = ::ExpandEnvironmentStringsW(lpSrc, szBuffer.get(), dwSizeIn);
|
||||
if (dwSizeOut == 0) {
|
||||
// Error.
|
||||
break;
|
||||
} else if (dwSizeOut <= dwSizeIn) {
|
||||
// The buffer was sufficient.
|
||||
sValue.assign(szBuffer.get(), dwSizeOut);
|
||||
return dwSizeOut;
|
||||
}
|
||||
}
|
||||
|
||||
sValue.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Formats GUID and stores it in a std::string string.
|
||||
///
|
||||
/// \param[in ] lpGuid Pointer to GUID
|
||||
/// \param[out] str String to store the result to
|
||||
///
|
||||
inline VOID GuidToString(_In_ LPCGUID lpGuid, _Out_ std::string &str)
|
||||
{
|
||||
sprintf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
||||
lpGuid->Data1,
|
||||
lpGuid->Data2,
|
||||
lpGuid->Data3,
|
||||
lpGuid->Data4[0], lpGuid->Data4[1],
|
||||
lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Formats GUID and stores it in a std::wstring string.
|
||||
///
|
||||
/// \param[in ] lpGuid Pointer to GUID
|
||||
/// \param[out] str String to store the result to
|
||||
///
|
||||
inline VOID GuidToString(_In_ LPCGUID lpGuid, _Out_ std::wstring &str)
|
||||
{
|
||||
sprintf(str, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
||||
lpGuid->Data1,
|
||||
lpGuid->Data2,
|
||||
lpGuid->Data3,
|
||||
lpGuid->Data4[0], lpGuid->Data4[1],
|
||||
lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Queries for a string value in the registry and stores it in a std::string string.
|
||||
///
|
||||
/// `REG_EXPAND_SZ` are expanded using `ExpandEnvironmentStrings()` before storing to sValue.
|
||||
///
|
||||
/// \param[in ] hReg A handle to an open registry key. The key must have been opened with the KEY_QUERY_VALUE access right.
|
||||
/// \param[in ] pszName The name of the registry value. If lpValueName is NULL or an empty string, "", the function retrieves the type and data for the key's unnamed or default value, if any.
|
||||
/// \param[out] sValue String to store the value to
|
||||
///
|
||||
/// \return
|
||||
/// - `ERROR_SUCCESS` when query succeeds;
|
||||
/// - `ERROR_INVALID_DATA` when the registy value type is not `REG_SZ`, `REG_MULTI_SZ`, or `REG_EXPAND_SZ`;
|
||||
/// - `ERROR_OUTOFMEMORY` when the memory allocation for the sValue buffer fails;
|
||||
/// - Error code when query fails. See `RegQueryValueEx()` for the list of error codes.
|
||||
///
|
||||
/// \sa [RegQueryValueEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724911.aspx)
|
||||
/// \sa [ExpandEnvironmentStrings function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724265.aspx)
|
||||
///
|
||||
inline LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCSTR pszName, _Out_ std::string &sValue)
|
||||
{
|
||||
LSTATUS lResult;
|
||||
BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
|
||||
DWORD dwSize = sizeof(aStackBuffer), dwType;
|
||||
|
||||
// Try with stack buffer first.
|
||||
lResult = ::RegQueryValueExA(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
|
||||
if (lResult == ERROR_SUCCESS) {
|
||||
if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
|
||||
// The value is REG_SZ or REG_MULTI_SZ.
|
||||
sValue.assign((CHAR*)aStackBuffer, dwSize / sizeof(CHAR));
|
||||
} else if (dwType == REG_EXPAND_SZ) {
|
||||
// The value is REG_EXPAND_SZ. Expand it from stack buffer.
|
||||
if (::ExpandEnvironmentStringsW((const CHAR*)aStackBuffer, sValue) == 0)
|
||||
lResult = ::GetLastError();
|
||||
} else {
|
||||
// The value is not a string type.
|
||||
lResult = ERROR_INVALID_DATA;
|
||||
}
|
||||
} else if (lResult == ERROR_MORE_DATA) {
|
||||
if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
|
||||
// The value is REG_SZ or REG_MULTI_SZ. Read it now.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[dwSize / sizeof(CHAR)]);
|
||||
if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, (LPBYTE)szBuffer.get(), &dwSize)) == ERROR_SUCCESS)
|
||||
sValue.assign(szBuffer.get(), dwSize / sizeof(CHAR));
|
||||
else
|
||||
sValue.clear();
|
||||
} else if (dwType == REG_EXPAND_SZ) {
|
||||
// The value is REG_EXPAND_SZ. Read it and expand environment variables.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[dwSize / sizeof(CHAR)]);
|
||||
if ((lResult = ::RegQueryValueExA(hReg, pszName, NULL, NULL, (LPBYTE)szBuffer.get(), &dwSize)) == ERROR_SUCCESS) {
|
||||
if (::ExpandEnvironmentStringsW(szBuffer.get(), sValue) == 0)
|
||||
lResult = ::GetLastError();
|
||||
} else
|
||||
sValue.clear();
|
||||
} else {
|
||||
// The value is not a string type.
|
||||
lResult = ERROR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Queries for a string value in the registry and stores it in a std::wstring string.
|
||||
///
|
||||
/// `REG_EXPAND_SZ` are expanded using `ExpandEnvironmentStrings()` before storing to sValue.
|
||||
///
|
||||
/// \param[in ] hReg A handle to an open registry key. The key must have been opened with the KEY_QUERY_VALUE access right.
|
||||
/// \param[in ] pszName The name of the registry value. If lpValueName is NULL or an empty string, "", the function retrieves the type and data for the key's unnamed or default value, if any.
|
||||
/// \param[out] sValue String to store the value to
|
||||
///
|
||||
/// \return
|
||||
/// - `ERROR_SUCCESS` when query succeeds;
|
||||
/// - `ERROR_INVALID_DATA` when the registy value type is not `REG_SZ`, `REG_MULTI_SZ`, or `REG_EXPAND_SZ`;
|
||||
/// - `ERROR_OUTOFMEMORY` when the memory allocation for the sValue buffer fails;
|
||||
/// - Error code when query fails. See `RegQueryValueEx()` for the list of error codes.
|
||||
///
|
||||
/// \sa [RegQueryValueEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724911.aspx)
|
||||
/// \sa [ExpandEnvironmentStrings function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724265.aspx)
|
||||
///
|
||||
inline LSTATUS RegQueryStringValue(_In_ HKEY hReg, _In_z_ LPCWSTR pszName, _Out_ std::wstring &sValue)
|
||||
{
|
||||
LSTATUS lResult;
|
||||
BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
|
||||
DWORD dwSize = sizeof(aStackBuffer), dwType;
|
||||
|
||||
// Try with stack buffer first.
|
||||
lResult = ::RegQueryValueExW(hReg, pszName, NULL, &dwType, aStackBuffer, &dwSize);
|
||||
if (lResult == ERROR_SUCCESS) {
|
||||
if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
|
||||
// The value is REG_SZ or REG_MULTI_SZ.
|
||||
sValue.assign((WCHAR*)aStackBuffer, dwSize / sizeof(WCHAR));
|
||||
} else if (dwType == REG_EXPAND_SZ) {
|
||||
// The value is REG_EXPAND_SZ. Expand it from stack buffer.
|
||||
if (::ExpandEnvironmentStringsW((const WCHAR*)aStackBuffer, sValue) == 0)
|
||||
lResult = ::GetLastError();
|
||||
} else {
|
||||
// The value is not a string type.
|
||||
lResult = ERROR_INVALID_DATA;
|
||||
}
|
||||
} else if (lResult == ERROR_MORE_DATA) {
|
||||
if (dwType == REG_SZ || dwType == REG_MULTI_SZ) {
|
||||
// The value is REG_SZ or REG_MULTI_SZ. Read it now.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[dwSize / sizeof(WCHAR)]);
|
||||
if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, (LPBYTE)szBuffer.get(), &dwSize)) == ERROR_SUCCESS)
|
||||
sValue.assign(szBuffer.get(), dwSize / sizeof(WCHAR));
|
||||
else
|
||||
sValue.clear();
|
||||
} else if (dwType == REG_EXPAND_SZ) {
|
||||
// The value is REG_EXPAND_SZ. Read it and expand environment variables.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[dwSize / sizeof(WCHAR)]);
|
||||
if ((lResult = ::RegQueryValueExW(hReg, pszName, NULL, NULL, (LPBYTE)szBuffer.get(), &dwSize)) == ERROR_SUCCESS) {
|
||||
if (::ExpandEnvironmentStringsW(szBuffer.get(), sValue) == 0)
|
||||
lResult = ::GetLastError();
|
||||
} else
|
||||
sValue.clear();
|
||||
} else {
|
||||
// The value is not a string type.
|
||||
lResult = ERROR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Retrieves the type and data for the specified value name associated with an open registry key and stores the data in a std::vector<BYTE> buffer.
|
||||
///
|
||||
/// \sa [RegQueryValueEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724911.aspx)
|
||||
///
|
||||
inline LSTATUS RegQueryValueExA(_In_ HKEY hKey, _In_opt_ LPCSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<BYTE> &aData)
|
||||
{
|
||||
LSTATUS lResult;
|
||||
BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
|
||||
DWORD dwSize = sizeof(aStackBuffer);
|
||||
|
||||
// Try with stack buffer first.
|
||||
lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, NULL, aStackBuffer, &dwSize);
|
||||
if (lResult == ERROR_SUCCESS) {
|
||||
// Allocate buffer on heap, copy from stack buffer.
|
||||
aData.resize(dwSize);
|
||||
memcpy(aData.data(), aStackBuffer, dwSize);
|
||||
} else if (lResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap and retry.
|
||||
aData.resize(dwSize);
|
||||
if ((lResult = RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, aData.data(), &dwSize)) != ERROR_SUCCESS)
|
||||
aData.clear();
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Retrieves the type and data for the specified value name associated with an open registry key and stores the data in a std::vector<BYTE> buffer.
|
||||
///
|
||||
/// \sa [RegQueryValueEx function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724911.aspx)
|
||||
///
|
||||
inline LSTATUS RegQueryValueExW(_In_ HKEY hKey, _In_opt_ LPCWSTR lpValueName, __reserved LPDWORD lpReserved, _Out_opt_ LPDWORD lpType, _Out_ std::vector<BYTE> &aData)
|
||||
{
|
||||
LSTATUS lResult;
|
||||
BYTE aStackBuffer[WINSTD_STACK_BUFFER_BYTES];
|
||||
DWORD dwSize = sizeof(aStackBuffer);
|
||||
|
||||
// Try with stack buffer first.
|
||||
lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, NULL, aStackBuffer, &dwSize);
|
||||
if (lResult == ERROR_SUCCESS) {
|
||||
// Allocate buffer on heap, copy from stack buffer.
|
||||
aData.resize(dwSize);
|
||||
memcpy(aData.data(), aStackBuffer, dwSize);
|
||||
} else if (lResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap and retry.
|
||||
aData.resize(dwSize);
|
||||
if ((lResult = RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, aData.data(), &dwSize)) != ERROR_SUCCESS)
|
||||
aData.clear();
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
|
||||
///
|
||||
/// Loads the specified string from the specified key and subkey, and stores it in a std::string string.
|
||||
///
|
||||
/// \sa [RegLoadMUIString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724890.aspx)
|
||||
///
|
||||
inline LSTATUS RegLoadMUIStringA(_In_ HKEY hKey, _In_opt_ LPCSTR pszValue, _Out_ std::string &sOut, _In_ DWORD Flags, _In_opt_ LPCSTR pszDirectory)
|
||||
{
|
||||
LSTATUS lResult;
|
||||
CHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(CHAR)];
|
||||
DWORD dwSize;
|
||||
|
||||
Flags &= ~REG_MUI_STRING_TRUNCATE;
|
||||
|
||||
// Try with stack buffer first.
|
||||
lResult = RegLoadMUIStringA(hKey, pszValue, szStackBuffer, _countof(szStackBuffer), &dwSize, Flags, pszDirectory);
|
||||
if (lResult == ERROR_SUCCESS) {
|
||||
// Copy from stack buffer.
|
||||
sOut.assign(szStackBuffer, dwSize);
|
||||
} else if (lResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap and retry.
|
||||
auto szBuffer = std::unique_ptr<CHAR[]>(new CHAR[dwSize + 1]);
|
||||
sOut.assign(szBuffer.get(), (lResult = RegLoadMUIStringA(hKey, pszValue, szBuffer.get(), dwSize, &dwSize, Flags, pszDirectory)) == ERROR_SUCCESS ? dwSize : 0);
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Loads the specified string from the specified key and subkey, and stores it in a std::wstring string.
|
||||
///
|
||||
/// \sa [RegLoadMUIString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724890.aspx)
|
||||
///
|
||||
inline LSTATUS RegLoadMUIStringW(_In_ HKEY hKey, _In_opt_ LPCWSTR pszValue, _Out_ std::wstring &sOut, _In_ DWORD Flags, _In_opt_ LPCWSTR pszDirectory)
|
||||
{
|
||||
LSTATUS lResult;
|
||||
WCHAR szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(WCHAR)];
|
||||
DWORD dwSize;
|
||||
|
||||
Flags &= ~REG_MUI_STRING_TRUNCATE;
|
||||
|
||||
// Try with stack buffer first.
|
||||
lResult = RegLoadMUIStringW(hKey, pszValue, szStackBuffer, _countof(szStackBuffer), &dwSize, Flags, pszDirectory);
|
||||
if (lResult == ERROR_SUCCESS) {
|
||||
// Copy from stack buffer.
|
||||
sOut.assign(szStackBuffer, dwSize);
|
||||
} else if (lResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap and retry.
|
||||
auto szBuffer = std::unique_ptr<WCHAR[]>(new WCHAR[dwSize + 1]);
|
||||
sOut.assign(szBuffer.get(), (lResult = RegLoadMUIStringW(hKey, pszValue, szBuffer.get(), dwSize, &dwSize, Flags, pszDirectory)) == ERROR_SUCCESS ? dwSize : 0);
|
||||
}
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
namespace winstd
|
||||
{
|
||||
/// \addtogroup ATLWinAPI
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Module handle wrapper
|
||||
///
|
||||
class CAtlLibrary : public handle<HMODULE>
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Frees the module.
|
||||
///
|
||||
/// \sa [FreeLibrary](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683152.aspx)
|
||||
///
|
||||
virtual ~CAtlLibrary()
|
||||
{
|
||||
if (m_h)
|
||||
FreeLibrary(m_h);
|
||||
}
|
||||
|
||||
///
|
||||
/// Loads the specified module into the address space of the calling process.
|
||||
///
|
||||
/// \sa [LoadLibraryEx](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179.aspx)
|
||||
///
|
||||
inline BOOL Load(_In_ LPCTSTR lpFileName, __reserved handle_type hFile, _In_ DWORD dwFlags)
|
||||
{
|
||||
handle_type h = LoadLibraryEx(lpFileName, hFile, dwFlags);
|
||||
if (h) {
|
||||
attach(h);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Frees the module.
|
||||
///
|
||||
/// \sa [FreeLibrary](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683152.aspx)
|
||||
///
|
||||
virtual void free_internal()
|
||||
{
|
||||
FreeLibrary(m_h);
|
||||
}
|
||||
};
|
||||
|
||||
/// @}
|
||||
}
|
Reference in New Issue
Block a user