Use native line endings
This commit is contained in:
parent
666d362075
commit
ca791f1663
@ -1,311 +1,311 @@
|
||||
/*
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright © 1991-2025 Amebis
|
||||
Copyright © 2016 GÉANT
|
||||
*/
|
||||
|
||||
/// \defgroup WinStdMSIAPI Microsoft Installer API
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include <MsiQuery.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/// \addtogroup WinStdMSIAPI
|
||||
/// @{
|
||||
|
||||
/// @copydoc MsiGetPropertyW()
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
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 == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetPropertyA(hInstall, szName, &sValue[0], &dwSize);
|
||||
} 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)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiGetPropertyW(hInstall, szName, szStackBuffer, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetPropertyW(hInstall, szName, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc MsiRecordGetStringW()
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
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 == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiRecordGetStringA(hRecord, iField, &sValue[0], &dwSize);
|
||||
} 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)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiRecordGetStringW(hRecord, iField, szStackBuffer, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiRecordGetStringW(hRecord, iField, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc MsiFormatRecordW()
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiFormatRecordA(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
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 == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiFormatRecordA(hInstall, hRecord, &sValue[0], &dwSize);
|
||||
} 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)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiFormatRecordW(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiFormatRecordW(hInstall, hRecord, szStackBuffer, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiFormatRecordW(hInstall, hRecord, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Reads bytes from a record stream field into a std::vector buffer.
|
||||
///
|
||||
/// \sa [MsiRecordReadStream function](https://msdn.microsoft.com/en-us/library/aa370370.aspx)
|
||||
///
|
||||
template<class _Ty, class _Ax>
|
||||
static UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::vector<_Ty, _Ax> &binData)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
DWORD dwSize = 0;
|
||||
UINT uiResult;
|
||||
|
||||
// Query the actual data length first.
|
||||
uiResult = ::MsiRecordReadStream(hRecord, iField, NULL, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
binData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
|
||||
return ::MsiRecordReadStream(hRecord, iField, reinterpret_cast<char*>(binData.data()), &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc MsiGetTargetPathW()
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Out_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
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 == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetTargetPathA(hInstall, szFolder, &sValue[0], &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::wstring string.
|
||||
///
|
||||
/// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szStackBuffer, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetTargetPathW(hInstall, szFolder, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc MsiGetComponentPathW()
|
||||
template<class _Traits, class _Ax>
|
||||
static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
INSTALLSTATE state;
|
||||
|
||||
// Try with stack buffer first.
|
||||
state = ::MsiGetComponentPathA(szProduct, szComponent, szStackBuffer, &dwSize);
|
||||
if (state >= INSTALLSTATE_BROKEN) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return state;
|
||||
} else if (state == INSTALLSTATE_MOREDATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetComponentPathA(szProduct, szComponent, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns the full path to an installed component. If the key path for the component is a registry key then the registry key is returned.
|
||||
///
|
||||
/// \sa [MsiGetComponentPath function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa370112.aspx)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
INSTALLSTATE state;
|
||||
|
||||
// Try with stack buffer first.
|
||||
state = ::MsiGetComponentPathW(szProduct, szComponent, szStackBuffer, &dwSize);
|
||||
if (state >= INSTALLSTATE_BROKEN) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return state;
|
||||
} else if (state == INSTALLSTATE_MOREDATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetComponentPathW(szProduct, szComponent, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
/*
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright © 1991-2025 Amebis
|
||||
Copyright © 2016 GÉANT
|
||||
*/
|
||||
|
||||
/// \defgroup WinStdMSIAPI Microsoft Installer API
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include <MsiQuery.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/// \addtogroup WinStdMSIAPI
|
||||
/// @{
|
||||
|
||||
/// @copydoc MsiGetPropertyW()
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
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 == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetPropertyA(hInstall, szName, &sValue[0], &dwSize);
|
||||
} 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)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiGetPropertyW(hInstall, szName, szStackBuffer, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetPropertyW(hInstall, szName, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc MsiRecordGetStringW()
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
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 == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiRecordGetStringA(hRecord, iField, &sValue[0], &dwSize);
|
||||
} 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)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiRecordGetStringW(hRecord, iField, szStackBuffer, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to read the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiRecordGetStringW(hRecord, iField, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc MsiFormatRecordW()
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiFormatRecordA(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
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 == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiFormatRecordA(hInstall, hRecord, &sValue[0], &dwSize);
|
||||
} 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)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiFormatRecordW(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiFormatRecordW(hInstall, hRecord, szStackBuffer, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiFormatRecordW(hInstall, hRecord, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Reads bytes from a record stream field into a std::vector buffer.
|
||||
///
|
||||
/// \sa [MsiRecordReadStream function](https://msdn.microsoft.com/en-us/library/aa370370.aspx)
|
||||
///
|
||||
template<class _Ty, class _Ax>
|
||||
static UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::vector<_Ty, _Ax> &binData)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
DWORD dwSize = 0;
|
||||
UINT uiResult;
|
||||
|
||||
// Query the actual data length first.
|
||||
uiResult = ::MsiRecordReadStream(hRecord, iField, NULL, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
binData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
|
||||
return ::MsiRecordReadStream(hRecord, iField, reinterpret_cast<char*>(binData.data()), &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc MsiGetTargetPathW()
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Out_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
assert(0); // TODO: Test this code.
|
||||
|
||||
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 == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetTargetPathA(hInstall, szFolder, &sValue[0], &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::wstring string.
|
||||
///
|
||||
/// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
UINT uiResult;
|
||||
|
||||
// Try with stack buffer first.
|
||||
uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szStackBuffer, &dwSize);
|
||||
if (uiResult == ERROR_SUCCESS) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return ERROR_SUCCESS;
|
||||
} else if (uiResult == ERROR_MORE_DATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetTargetPathW(hInstall, szFolder, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return uiResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// @copydoc MsiGetComponentPathW()
|
||||
template<class _Traits, class _Ax>
|
||||
static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
|
||||
{
|
||||
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
INSTALLSTATE state;
|
||||
|
||||
// Try with stack buffer first.
|
||||
state = ::MsiGetComponentPathA(szProduct, szComponent, szStackBuffer, &dwSize);
|
||||
if (state >= INSTALLSTATE_BROKEN) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return state;
|
||||
} else if (state == INSTALLSTATE_MOREDATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetComponentPathA(szProduct, szComponent, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns the full path to an installed component. If the key path for the component is a registry key then the registry key is returned.
|
||||
///
|
||||
/// \sa [MsiGetComponentPath function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa370112.aspx)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
|
||||
{
|
||||
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
|
||||
DWORD dwSize = _countof(szStackBuffer);
|
||||
INSTALLSTATE state;
|
||||
|
||||
// Try with stack buffer first.
|
||||
state = ::MsiGetComponentPathW(szProduct, szComponent, szStackBuffer, &dwSize);
|
||||
if (state >= INSTALLSTATE_BROKEN) {
|
||||
// Copy from stack.
|
||||
sValue.assign(szStackBuffer, dwSize);
|
||||
return state;
|
||||
} else if (state == INSTALLSTATE_MOREDATA) {
|
||||
// Allocate buffer on heap to format the string data into and read it.
|
||||
sValue.resize(dwSize++);
|
||||
return ::MsiGetComponentPathW(szProduct, szComponent, &sValue[0], &dwSize);
|
||||
} else {
|
||||
// Return error code.
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
@ -1,88 +1,88 @@
|
||||
/*
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright © 1991-2025 Amebis
|
||||
Copyright © 2016 GÉANT
|
||||
*/
|
||||
|
||||
/// \defgroup WinStdShellWAPI Shell API
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include <Shlwapi.h>
|
||||
#include <string>
|
||||
|
||||
/// \addtogroup WinStdShellWAPI
|
||||
/// @{
|
||||
|
||||
/// @copydoc PathCanonicalizeW()
|
||||
template<class _Traits, class _Ax>
|
||||
static BOOL PathCanonicalizeA(_Inout_ std::basic_string<char, _Traits, _Ax> &sValue, _In_ LPCSTR pszPath)
|
||||
{
|
||||
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)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static BOOL PathCanonicalizeW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, _In_ LPCWSTR pszPath)
|
||||
{
|
||||
wchar_t szBuffer[MAX_PATH + 1];
|
||||
BOOL bResult = ::PathCanonicalizeW(szBuffer, pszPath);
|
||||
sValue.assign(szBuffer, bResult ? MAX_PATH : 0);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
/// @copydoc PathRemoveBackslashW()
|
||||
template<class _Traits, class _Ax>
|
||||
static void PathRemoveBackslashA(_Inout_ std::basic_string<char, _Traits, _Ax>& sValue)
|
||||
{
|
||||
char szBuffer[MAX_PATH + 1];
|
||||
size_t len = sValue.length();
|
||||
if (len < _countof(szBuffer)) {
|
||||
memcpy(szBuffer, sValue.c_str(), len);
|
||||
szBuffer[len] = 0;
|
||||
PathRemoveBackslashA(szBuffer);
|
||||
sValue.assign(szBuffer);
|
||||
}
|
||||
else {
|
||||
std::unique_ptr<char[]> buf(new char[len + 1]);
|
||||
memcpy(buf.get(), sValue.c_str(), len);
|
||||
buf[len] = 0;
|
||||
PathRemoveBackslashA(buf.get());
|
||||
sValue.assign(buf.get());
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Removes the trailing backslash from a given path.
|
||||
///
|
||||
/// \sa [PathRemoveBackslashW function](https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathremovebackslashw)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static void PathRemoveBackslashW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& sValue)
|
||||
{
|
||||
wchar_t szBuffer[MAX_PATH + 1];
|
||||
size_t len = sValue.length();
|
||||
if (len < _countof(szBuffer)) {
|
||||
wmemcpy(szBuffer, sValue.c_str(), len);
|
||||
szBuffer[len] = 0;
|
||||
PathRemoveBackslashW(szBuffer);
|
||||
sValue.assign(szBuffer);
|
||||
}
|
||||
else {
|
||||
std::unique_ptr<wchar_t[]> buf(new wchar_t[len + 1]);
|
||||
wmemcpy(buf.get(), sValue.c_str(), len);
|
||||
buf[len] = 0;
|
||||
PathRemoveBackslashW(buf.get());
|
||||
sValue.assign(buf.get());
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
/*
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright © 1991-2025 Amebis
|
||||
Copyright © 2016 GÉANT
|
||||
*/
|
||||
|
||||
/// \defgroup WinStdShellWAPI Shell API
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include <Shlwapi.h>
|
||||
#include <string>
|
||||
|
||||
/// \addtogroup WinStdShellWAPI
|
||||
/// @{
|
||||
|
||||
/// @copydoc PathCanonicalizeW()
|
||||
template<class _Traits, class _Ax>
|
||||
static BOOL PathCanonicalizeA(_Inout_ std::basic_string<char, _Traits, _Ax> &sValue, _In_ LPCSTR pszPath)
|
||||
{
|
||||
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)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static BOOL PathCanonicalizeW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, _In_ LPCWSTR pszPath)
|
||||
{
|
||||
wchar_t szBuffer[MAX_PATH + 1];
|
||||
BOOL bResult = ::PathCanonicalizeW(szBuffer, pszPath);
|
||||
sValue.assign(szBuffer, bResult ? MAX_PATH : 0);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
/// @copydoc PathRemoveBackslashW()
|
||||
template<class _Traits, class _Ax>
|
||||
static void PathRemoveBackslashA(_Inout_ std::basic_string<char, _Traits, _Ax>& sValue)
|
||||
{
|
||||
char szBuffer[MAX_PATH + 1];
|
||||
size_t len = sValue.length();
|
||||
if (len < _countof(szBuffer)) {
|
||||
memcpy(szBuffer, sValue.c_str(), len);
|
||||
szBuffer[len] = 0;
|
||||
PathRemoveBackslashA(szBuffer);
|
||||
sValue.assign(szBuffer);
|
||||
}
|
||||
else {
|
||||
std::unique_ptr<char[]> buf(new char[len + 1]);
|
||||
memcpy(buf.get(), sValue.c_str(), len);
|
||||
buf[len] = 0;
|
||||
PathRemoveBackslashA(buf.get());
|
||||
sValue.assign(buf.get());
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Removes the trailing backslash from a given path.
|
||||
///
|
||||
/// \sa [PathRemoveBackslashW function](https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathremovebackslashw)
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static void PathRemoveBackslashW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& sValue)
|
||||
{
|
||||
wchar_t szBuffer[MAX_PATH + 1];
|
||||
size_t len = sValue.length();
|
||||
if (len < _countof(szBuffer)) {
|
||||
wmemcpy(szBuffer, sValue.c_str(), len);
|
||||
szBuffer[len] = 0;
|
||||
PathRemoveBackslashW(szBuffer);
|
||||
sValue.assign(szBuffer);
|
||||
}
|
||||
else {
|
||||
std::unique_ptr<wchar_t[]> buf(new wchar_t[len + 1]);
|
||||
wmemcpy(buf.get(), sValue.c_str(), len);
|
||||
buf[len] = 0;
|
||||
PathRemoveBackslashW(buf.get());
|
||||
sValue.assign(buf.get());
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
@ -1,185 +1,185 @@
|
||||
/*
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright © 1991-2025 Amebis
|
||||
Copyright © 2016 GÉANT
|
||||
*/
|
||||
|
||||
/// \defgroup WinStdWLANAPI WLAN API
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include <wlanapi.h>
|
||||
#include <string>
|
||||
|
||||
/// \addtogroup WinStdWLANAPI
|
||||
/// @{
|
||||
|
||||
/// \cond internal
|
||||
// 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);
|
||||
/// \endcond
|
||||
|
||||
///
|
||||
/// 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 `pfnWlanReasonCodeToString` pointer to `WlanReasonCodeToString()`
|
||||
/// function must be loaded dynamically.
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, __reserved PVOID pReserved)
|
||||
{
|
||||
SIZE_T sSize = 0;
|
||||
|
||||
if (!::pfnWlanReasonCodeToString)
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
|
||||
for (;;) {
|
||||
// Increment size and allocate buffer.
|
||||
sSize = SIZETAdd(sSize, 1024);
|
||||
if (sSize > DWORD_MAX)
|
||||
throw std::runtime_error("Data too big");
|
||||
sValue.resize(sSize - 1);
|
||||
|
||||
// Try!
|
||||
DWORD dwResult = ::pfnWlanReasonCodeToString(dwReasonCode, static_cast<DWORD>(sSize), &sValue[0], pReserved);
|
||||
if (dwResult == ERROR_SUCCESS) {
|
||||
SIZE_T sLength = wcsnlen(&sValue[0], sSize);
|
||||
if (sLength < sSize - 1) {
|
||||
// Buffer was long enough.
|
||||
sValue.resize(sLength);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
// Return error code.
|
||||
return dwResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
namespace winstd
|
||||
{
|
||||
/// \addtogroup WinStdWLANAPI
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Deleter for unique_ptr using WlanFreeMemory
|
||||
///
|
||||
template <class _Ty> struct WlanFreeMemory_delete
|
||||
{
|
||||
typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type
|
||||
|
||||
///
|
||||
/// Default construct
|
||||
///
|
||||
WlanFreeMemory_delete() {}
|
||||
|
||||
///
|
||||
/// Construct from another WlanFreeMemory_delete
|
||||
///
|
||||
template <class _Ty2> WlanFreeMemory_delete(const WlanFreeMemory_delete<_Ty2>&) {}
|
||||
|
||||
///
|
||||
/// Delete a pointer
|
||||
///
|
||||
void operator()(_Ty *_Ptr) const
|
||||
{
|
||||
WlanFreeMemory(_Ptr);
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// Deleter for unique_ptr to array of unknown size using WlanFreeMemory
|
||||
///
|
||||
template <class _Ty> struct WlanFreeMemory_delete<_Ty[]>
|
||||
{
|
||||
typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type
|
||||
|
||||
///
|
||||
/// Default construct
|
||||
///
|
||||
WlanFreeMemory_delete() {}
|
||||
|
||||
///
|
||||
/// Delete a pointer
|
||||
///
|
||||
void operator()(_Ty *_Ptr) const
|
||||
{
|
||||
WlanFreeMemory(_Ptr);
|
||||
}
|
||||
|
||||
///
|
||||
/// Delete a pointer of another type
|
||||
///
|
||||
template<class _Other>
|
||||
void operator()(_Other *) const
|
||||
{
|
||||
WlanFreeMemory(_Ptr);
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// WLAN handle wrapper
|
||||
///
|
||||
/// \sa [WlanOpenHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706759.aspx)
|
||||
///
|
||||
class wlan_handle : public handle<HANDLE, NULL>
|
||||
{
|
||||
WINSTD_HANDLE_IMPL(wlan_handle, HANDLE, NULL)
|
||||
|
||||
public:
|
||||
///
|
||||
/// Closes a connection to the server.
|
||||
///
|
||||
/// \sa [WlanCloseHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706610(v=vs.85).aspx)
|
||||
///
|
||||
virtual ~wlan_handle()
|
||||
{
|
||||
if (m_h != invalid)
|
||||
free_internal();
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Closes a connection to the server.
|
||||
///
|
||||
/// \sa [WlanCloseHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706610(v=vs.85).aspx)
|
||||
///
|
||||
void free_internal() noexcept override
|
||||
{
|
||||
WlanCloseHandle(m_h, NULL);
|
||||
}
|
||||
};
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
||||
/// \addtogroup WinStdWLANAPI
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Opens a connection to the server.
|
||||
///
|
||||
/// \sa [WlanOpenHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706759.aspx)
|
||||
///
|
||||
#pragma warning(suppress: 4505) // Don't warn on unused code
|
||||
static DWORD WlanOpenHandle(
|
||||
_In_ DWORD dwClientVersion,
|
||||
_Reserved_ PVOID pReserved,
|
||||
_Out_ PDWORD pdwNegotiatedVersion,
|
||||
_Inout_ winstd::wlan_handle &handle)
|
||||
{
|
||||
HANDLE h;
|
||||
DWORD dwResult = WlanOpenHandle(dwClientVersion, pReserved, pdwNegotiatedVersion, &h);
|
||||
if (dwResult == ERROR_SUCCESS)
|
||||
handle.attach(h);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
/// @}
|
||||
/*
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright © 1991-2025 Amebis
|
||||
Copyright © 2016 GÉANT
|
||||
*/
|
||||
|
||||
/// \defgroup WinStdWLANAPI WLAN API
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include <wlanapi.h>
|
||||
#include <string>
|
||||
|
||||
/// \addtogroup WinStdWLANAPI
|
||||
/// @{
|
||||
|
||||
/// \cond internal
|
||||
// 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);
|
||||
/// \endcond
|
||||
|
||||
///
|
||||
/// 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 `pfnWlanReasonCodeToString` pointer to `WlanReasonCodeToString()`
|
||||
/// function must be loaded dynamically.
|
||||
///
|
||||
template<class _Traits, class _Ax>
|
||||
static DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, __reserved PVOID pReserved)
|
||||
{
|
||||
SIZE_T sSize = 0;
|
||||
|
||||
if (!::pfnWlanReasonCodeToString)
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
|
||||
for (;;) {
|
||||
// Increment size and allocate buffer.
|
||||
sSize = SIZETAdd(sSize, 1024);
|
||||
if (sSize > DWORD_MAX)
|
||||
throw std::runtime_error("Data too big");
|
||||
sValue.resize(sSize - 1);
|
||||
|
||||
// Try!
|
||||
DWORD dwResult = ::pfnWlanReasonCodeToString(dwReasonCode, static_cast<DWORD>(sSize), &sValue[0], pReserved);
|
||||
if (dwResult == ERROR_SUCCESS) {
|
||||
SIZE_T sLength = wcsnlen(&sValue[0], sSize);
|
||||
if (sLength < sSize - 1) {
|
||||
// Buffer was long enough.
|
||||
sValue.resize(sLength);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
// Return error code.
|
||||
return dwResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
namespace winstd
|
||||
{
|
||||
/// \addtogroup WinStdWLANAPI
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Deleter for unique_ptr using WlanFreeMemory
|
||||
///
|
||||
template <class _Ty> struct WlanFreeMemory_delete
|
||||
{
|
||||
typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type
|
||||
|
||||
///
|
||||
/// Default construct
|
||||
///
|
||||
WlanFreeMemory_delete() {}
|
||||
|
||||
///
|
||||
/// Construct from another WlanFreeMemory_delete
|
||||
///
|
||||
template <class _Ty2> WlanFreeMemory_delete(const WlanFreeMemory_delete<_Ty2>&) {}
|
||||
|
||||
///
|
||||
/// Delete a pointer
|
||||
///
|
||||
void operator()(_Ty *_Ptr) const
|
||||
{
|
||||
WlanFreeMemory(_Ptr);
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// Deleter for unique_ptr to array of unknown size using WlanFreeMemory
|
||||
///
|
||||
template <class _Ty> struct WlanFreeMemory_delete<_Ty[]>
|
||||
{
|
||||
typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type
|
||||
|
||||
///
|
||||
/// Default construct
|
||||
///
|
||||
WlanFreeMemory_delete() {}
|
||||
|
||||
///
|
||||
/// Delete a pointer
|
||||
///
|
||||
void operator()(_Ty *_Ptr) const
|
||||
{
|
||||
WlanFreeMemory(_Ptr);
|
||||
}
|
||||
|
||||
///
|
||||
/// Delete a pointer of another type
|
||||
///
|
||||
template<class _Other>
|
||||
void operator()(_Other *) const
|
||||
{
|
||||
WlanFreeMemory(_Ptr);
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// WLAN handle wrapper
|
||||
///
|
||||
/// \sa [WlanOpenHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706759.aspx)
|
||||
///
|
||||
class wlan_handle : public handle<HANDLE, NULL>
|
||||
{
|
||||
WINSTD_HANDLE_IMPL(wlan_handle, HANDLE, NULL)
|
||||
|
||||
public:
|
||||
///
|
||||
/// Closes a connection to the server.
|
||||
///
|
||||
/// \sa [WlanCloseHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706610(v=vs.85).aspx)
|
||||
///
|
||||
virtual ~wlan_handle()
|
||||
{
|
||||
if (m_h != invalid)
|
||||
free_internal();
|
||||
}
|
||||
|
||||
protected:
|
||||
///
|
||||
/// Closes a connection to the server.
|
||||
///
|
||||
/// \sa [WlanCloseHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706610(v=vs.85).aspx)
|
||||
///
|
||||
void free_internal() noexcept override
|
||||
{
|
||||
WlanCloseHandle(m_h, NULL);
|
||||
}
|
||||
};
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
||||
/// \addtogroup WinStdWLANAPI
|
||||
/// @{
|
||||
|
||||
///
|
||||
/// Opens a connection to the server.
|
||||
///
|
||||
/// \sa [WlanOpenHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706759.aspx)
|
||||
///
|
||||
#pragma warning(suppress: 4505) // Don't warn on unused code
|
||||
static DWORD WlanOpenHandle(
|
||||
_In_ DWORD dwClientVersion,
|
||||
_Reserved_ PVOID pReserved,
|
||||
_Out_ PDWORD pdwNegotiatedVersion,
|
||||
_Inout_ winstd::wlan_handle &handle)
|
||||
{
|
||||
HANDLE h;
|
||||
DWORD dwResult = WlanOpenHandle(dwClientVersion, pReserved, pdwNegotiatedVersion, &h);
|
||||
if (dwResult == ERROR_SUCCESS)
|
||||
handle.attach(h);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
Loading…
x
Reference in New Issue
Block a user