Use native line endings

This commit is contained in:
Simon Rozman 2025-05-26 14:49:17 +02:00
parent 666d362075
commit ca791f1663
3 changed files with 584 additions and 584 deletions

View File

@ -1,311 +1,311 @@
/* /*
SPDX-License-Identifier: MIT SPDX-License-Identifier: MIT
Copyright © 1991-2025 Amebis Copyright © 1991-2025 Amebis
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
/// \defgroup WinStdMSIAPI Microsoft Installer API /// \defgroup WinStdMSIAPI Microsoft Installer API
#pragma once #pragma once
#include "Common.h" #include "Common.h"
#include <MsiQuery.h> #include <MsiQuery.h>
#include <string> #include <string>
#include <vector> #include <vector>
/// \addtogroup WinStdMSIAPI /// \addtogroup WinStdMSIAPI
/// @{ /// @{
/// @copydoc MsiGetPropertyW() /// @copydoc MsiGetPropertyW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue) static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
assert(0); // TODO: Test this code. assert(0); // TODO: Test this code.
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)]; char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
UINT uiResult; UINT uiResult;
// Try with stack buffer first. // Try with stack buffer first.
uiResult = ::MsiGetPropertyA(hInstall, szName, szStackBuffer, &dwSize); uiResult = ::MsiGetPropertyA(hInstall, szName, szStackBuffer, &dwSize);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} else if (uiResult == ERROR_MORE_DATA) { } else if (uiResult == ERROR_MORE_DATA) {
// Allocate buffer on heap to read the string data into and read it. // Allocate buffer on heap to read the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiGetPropertyA(hInstall, szName, &sValue[0], &dwSize); return ::MsiGetPropertyA(hInstall, szName, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return uiResult; return uiResult;
} }
} }
/// ///
/// Gets the value for an installer property and stores it in a std::wstring string. /// 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) /// \sa [MsiGetProperty function](https://msdn.microsoft.com/en-us/library/aa370134.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{ {
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)]; wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
UINT uiResult; UINT uiResult;
// Try with stack buffer first. // Try with stack buffer first.
uiResult = ::MsiGetPropertyW(hInstall, szName, szStackBuffer, &dwSize); uiResult = ::MsiGetPropertyW(hInstall, szName, szStackBuffer, &dwSize);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} else if (uiResult == ERROR_MORE_DATA) { } else if (uiResult == ERROR_MORE_DATA) {
// Allocate buffer on heap to read the string data into and read it. // Allocate buffer on heap to read the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiGetPropertyW(hInstall, szName, &sValue[0], &dwSize); return ::MsiGetPropertyW(hInstall, szName, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return uiResult; return uiResult;
} }
} }
/// @copydoc MsiRecordGetStringW() /// @copydoc MsiRecordGetStringW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue) static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
assert(0); // TODO: Test this code. assert(0); // TODO: Test this code.
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)]; char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
UINT uiResult; UINT uiResult;
// Try with stack buffer first. // Try with stack buffer first.
uiResult = ::MsiRecordGetStringA(hRecord, iField, szStackBuffer, &dwSize); uiResult = ::MsiRecordGetStringA(hRecord, iField, szStackBuffer, &dwSize);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} else if (uiResult == ERROR_MORE_DATA) { } else if (uiResult == ERROR_MORE_DATA) {
// Allocate buffer on heap to read the string data into and read it. // Allocate buffer on heap to read the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiRecordGetStringA(hRecord, iField, &sValue[0], &dwSize); return ::MsiRecordGetStringA(hRecord, iField, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return uiResult; return uiResult;
} }
} }
/// ///
/// Returns the string value of a record field and stores it in a std::wstring string. /// 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) /// \sa [MsiRecordGetString function](https://msdn.microsoft.com/en-us/library/aa370368.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{ {
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)]; wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
UINT uiResult; UINT uiResult;
// Try with stack buffer first. // Try with stack buffer first.
uiResult = ::MsiRecordGetStringW(hRecord, iField, szStackBuffer, &dwSize); uiResult = ::MsiRecordGetStringW(hRecord, iField, szStackBuffer, &dwSize);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} else if (uiResult == ERROR_MORE_DATA) { } else if (uiResult == ERROR_MORE_DATA) {
// Allocate buffer on heap to read the string data into and read it. // Allocate buffer on heap to read the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiRecordGetStringW(hRecord, iField, &sValue[0], &dwSize); return ::MsiRecordGetStringW(hRecord, iField, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return uiResult; return uiResult;
} }
} }
/// @copydoc MsiFormatRecordW() /// @copydoc MsiFormatRecordW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiFormatRecordA(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue) static UINT MsiFormatRecordA(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
assert(0); // TODO: Test this code. assert(0); // TODO: Test this code.
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)]; char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
UINT uiResult; UINT uiResult;
// Try with stack buffer first. // Try with stack buffer first.
uiResult = ::MsiFormatRecordA(hInstall, hRecord, szStackBuffer, &dwSize); uiResult = ::MsiFormatRecordA(hInstall, hRecord, szStackBuffer, &dwSize);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} else if (uiResult == ERROR_MORE_DATA) { } else if (uiResult == ERROR_MORE_DATA) {
// Allocate buffer on heap to format the string data into and read it. // Allocate buffer on heap to format the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiFormatRecordA(hInstall, hRecord, &sValue[0], &dwSize); return ::MsiFormatRecordA(hInstall, hRecord, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return uiResult; return uiResult;
} }
} }
/// ///
/// Formats record field data and properties using a format string and stores it in a std::wstring string. /// 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) /// \sa [MsiFormatRecord function](https://msdn.microsoft.com/en-us/library/aa370109.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiFormatRecordW(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) 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)]; wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
UINT uiResult; UINT uiResult;
// Try with stack buffer first. // Try with stack buffer first.
uiResult = ::MsiFormatRecordW(hInstall, hRecord, szStackBuffer, &dwSize); uiResult = ::MsiFormatRecordW(hInstall, hRecord, szStackBuffer, &dwSize);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} else if (uiResult == ERROR_MORE_DATA) { } else if (uiResult == ERROR_MORE_DATA) {
// Allocate buffer on heap to format the string data into and read it. // Allocate buffer on heap to format the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiFormatRecordW(hInstall, hRecord, &sValue[0], &dwSize); return ::MsiFormatRecordW(hInstall, hRecord, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return uiResult; return uiResult;
} }
} }
/// ///
/// Reads bytes from a record stream field into a std::vector buffer. /// Reads bytes from a record stream field into a std::vector buffer.
/// ///
/// \sa [MsiRecordReadStream function](https://msdn.microsoft.com/en-us/library/aa370370.aspx) /// \sa [MsiRecordReadStream function](https://msdn.microsoft.com/en-us/library/aa370370.aspx)
/// ///
template<class _Ty, class _Ax> template<class _Ty, class _Ax>
static UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::vector<_Ty, _Ax> &binData) static UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::vector<_Ty, _Ax> &binData)
{ {
assert(0); // TODO: Test this code. assert(0); // TODO: Test this code.
DWORD dwSize = 0; DWORD dwSize = 0;
UINT uiResult; UINT uiResult;
// Query the actual data length first. // Query the actual data length first.
uiResult = ::MsiRecordReadStream(hRecord, iField, NULL, &dwSize); uiResult = ::MsiRecordReadStream(hRecord, iField, NULL, &dwSize);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
binData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty)); binData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
return ::MsiRecordReadStream(hRecord, iField, reinterpret_cast<char*>(binData.data()), &dwSize); return ::MsiRecordReadStream(hRecord, iField, reinterpret_cast<char*>(binData.data()), &dwSize);
} else { } else {
// Return error code. // Return error code.
return uiResult; return uiResult;
} }
} }
/// @copydoc MsiGetTargetPathW() /// @copydoc MsiGetTargetPathW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Out_ std::basic_string<char, _Traits, _Ax> &sValue) static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Out_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
assert(0); // TODO: Test this code. assert(0); // TODO: Test this code.
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)]; char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
UINT uiResult; UINT uiResult;
// Try with stack buffer first. // Try with stack buffer first.
uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szStackBuffer, &dwSize); uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szStackBuffer, &dwSize);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} else if (uiResult == ERROR_MORE_DATA) { } else if (uiResult == ERROR_MORE_DATA) {
// Allocate buffer on heap to format the string data into and read it. // Allocate buffer on heap to format the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiGetTargetPathA(hInstall, szFolder, &sValue[0], &dwSize); return ::MsiGetTargetPathA(hInstall, szFolder, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return uiResult; return uiResult;
} }
} }
/// ///
/// Returns the full target path for a folder in the Directory table and stores it in a std::wstring string. /// 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) /// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{ {
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)]; wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
UINT uiResult; UINT uiResult;
// Try with stack buffer first. // Try with stack buffer first.
uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szStackBuffer, &dwSize); uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szStackBuffer, &dwSize);
if (uiResult == ERROR_SUCCESS) { if (uiResult == ERROR_SUCCESS) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} else if (uiResult == ERROR_MORE_DATA) { } else if (uiResult == ERROR_MORE_DATA) {
// Allocate buffer on heap to format the string data into and read it. // Allocate buffer on heap to format the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiGetTargetPathW(hInstall, szFolder, &sValue[0], &dwSize); return ::MsiGetTargetPathW(hInstall, szFolder, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return uiResult; return uiResult;
} }
} }
/// @copydoc MsiGetComponentPathW() /// @copydoc MsiGetComponentPathW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue) static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
{ {
char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)]; char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
INSTALLSTATE state; INSTALLSTATE state;
// Try with stack buffer first. // Try with stack buffer first.
state = ::MsiGetComponentPathA(szProduct, szComponent, szStackBuffer, &dwSize); state = ::MsiGetComponentPathA(szProduct, szComponent, szStackBuffer, &dwSize);
if (state >= INSTALLSTATE_BROKEN) { if (state >= INSTALLSTATE_BROKEN) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return state; return state;
} else if (state == INSTALLSTATE_MOREDATA) { } else if (state == INSTALLSTATE_MOREDATA) {
// Allocate buffer on heap to format the string data into and read it. // Allocate buffer on heap to format the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiGetComponentPathA(szProduct, szComponent, &sValue[0], &dwSize); return ::MsiGetComponentPathA(szProduct, szComponent, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return state; 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. /// 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) /// \sa [MsiGetComponentPath function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa370112.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue) static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
{ {
wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)]; wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
DWORD dwSize = _countof(szStackBuffer); DWORD dwSize = _countof(szStackBuffer);
INSTALLSTATE state; INSTALLSTATE state;
// Try with stack buffer first. // Try with stack buffer first.
state = ::MsiGetComponentPathW(szProduct, szComponent, szStackBuffer, &dwSize); state = ::MsiGetComponentPathW(szProduct, szComponent, szStackBuffer, &dwSize);
if (state >= INSTALLSTATE_BROKEN) { if (state >= INSTALLSTATE_BROKEN) {
// Copy from stack. // Copy from stack.
sValue.assign(szStackBuffer, dwSize); sValue.assign(szStackBuffer, dwSize);
return state; return state;
} else if (state == INSTALLSTATE_MOREDATA) { } else if (state == INSTALLSTATE_MOREDATA) {
// Allocate buffer on heap to format the string data into and read it. // Allocate buffer on heap to format the string data into and read it.
sValue.resize(dwSize++); sValue.resize(dwSize++);
return ::MsiGetComponentPathW(szProduct, szComponent, &sValue[0], &dwSize); return ::MsiGetComponentPathW(szProduct, szComponent, &sValue[0], &dwSize);
} else { } else {
// Return error code. // Return error code.
return state; return state;
} }
} }
/// @} /// @}

View File

@ -1,88 +1,88 @@
/* /*
SPDX-License-Identifier: MIT SPDX-License-Identifier: MIT
Copyright © 1991-2025 Amebis Copyright © 1991-2025 Amebis
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
/// \defgroup WinStdShellWAPI Shell API /// \defgroup WinStdShellWAPI Shell API
#pragma once #pragma once
#include "Common.h" #include "Common.h"
#include <Shlwapi.h> #include <Shlwapi.h>
#include <string> #include <string>
/// \addtogroup WinStdShellWAPI /// \addtogroup WinStdShellWAPI
/// @{ /// @{
/// @copydoc PathCanonicalizeW() /// @copydoc PathCanonicalizeW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOL PathCanonicalizeA(_Inout_ std::basic_string<char, _Traits, _Ax> &sValue, _In_ LPCSTR pszPath) static BOOL PathCanonicalizeA(_Inout_ std::basic_string<char, _Traits, _Ax> &sValue, _In_ LPCSTR pszPath)
{ {
char szBuffer[MAX_PATH + 1]; char szBuffer[MAX_PATH + 1];
BOOL bResult = ::PathCanonicalizeA(szBuffer, pszPath); BOOL bResult = ::PathCanonicalizeA(szBuffer, pszPath);
sValue.assign(szBuffer, bResult ? MAX_PATH : 0); sValue.assign(szBuffer, bResult ? MAX_PATH : 0);
return bResult; return bResult;
} }
/// ///
/// Simplifies a path by removing navigation elements such as "." and ".." to produce a direct, well-formed path, and stores it in a std::wstring string. /// 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) /// \sa [PathCanonicalize function](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773569.aspx)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static BOOL PathCanonicalizeW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, _In_ LPCWSTR pszPath) static BOOL PathCanonicalizeW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, _In_ LPCWSTR pszPath)
{ {
wchar_t szBuffer[MAX_PATH + 1]; wchar_t szBuffer[MAX_PATH + 1];
BOOL bResult = ::PathCanonicalizeW(szBuffer, pszPath); BOOL bResult = ::PathCanonicalizeW(szBuffer, pszPath);
sValue.assign(szBuffer, bResult ? MAX_PATH : 0); sValue.assign(szBuffer, bResult ? MAX_PATH : 0);
return bResult; return bResult;
} }
/// @copydoc PathRemoveBackslashW() /// @copydoc PathRemoveBackslashW()
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static void PathRemoveBackslashA(_Inout_ std::basic_string<char, _Traits, _Ax>& sValue) static void PathRemoveBackslashA(_Inout_ std::basic_string<char, _Traits, _Ax>& sValue)
{ {
char szBuffer[MAX_PATH + 1]; char szBuffer[MAX_PATH + 1];
size_t len = sValue.length(); size_t len = sValue.length();
if (len < _countof(szBuffer)) { if (len < _countof(szBuffer)) {
memcpy(szBuffer, sValue.c_str(), len); memcpy(szBuffer, sValue.c_str(), len);
szBuffer[len] = 0; szBuffer[len] = 0;
PathRemoveBackslashA(szBuffer); PathRemoveBackslashA(szBuffer);
sValue.assign(szBuffer); sValue.assign(szBuffer);
} }
else { else {
std::unique_ptr<char[]> buf(new char[len + 1]); std::unique_ptr<char[]> buf(new char[len + 1]);
memcpy(buf.get(), sValue.c_str(), len); memcpy(buf.get(), sValue.c_str(), len);
buf[len] = 0; buf[len] = 0;
PathRemoveBackslashA(buf.get()); PathRemoveBackslashA(buf.get());
sValue.assign(buf.get()); sValue.assign(buf.get());
} }
} }
/// ///
/// Removes the trailing backslash from a given path. /// Removes the trailing backslash from a given path.
/// ///
/// \sa [PathRemoveBackslashW function](https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathremovebackslashw) /// \sa [PathRemoveBackslashW function](https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathremovebackslashw)
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static void PathRemoveBackslashW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& sValue) static void PathRemoveBackslashW(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& sValue)
{ {
wchar_t szBuffer[MAX_PATH + 1]; wchar_t szBuffer[MAX_PATH + 1];
size_t len = sValue.length(); size_t len = sValue.length();
if (len < _countof(szBuffer)) { if (len < _countof(szBuffer)) {
wmemcpy(szBuffer, sValue.c_str(), len); wmemcpy(szBuffer, sValue.c_str(), len);
szBuffer[len] = 0; szBuffer[len] = 0;
PathRemoveBackslashW(szBuffer); PathRemoveBackslashW(szBuffer);
sValue.assign(szBuffer); sValue.assign(szBuffer);
} }
else { else {
std::unique_ptr<wchar_t[]> buf(new wchar_t[len + 1]); std::unique_ptr<wchar_t[]> buf(new wchar_t[len + 1]);
wmemcpy(buf.get(), sValue.c_str(), len); wmemcpy(buf.get(), sValue.c_str(), len);
buf[len] = 0; buf[len] = 0;
PathRemoveBackslashW(buf.get()); PathRemoveBackslashW(buf.get());
sValue.assign(buf.get()); sValue.assign(buf.get());
} }
} }
/// @} /// @}

View File

@ -1,185 +1,185 @@
/* /*
SPDX-License-Identifier: MIT SPDX-License-Identifier: MIT
Copyright © 1991-2025 Amebis Copyright © 1991-2025 Amebis
Copyright © 2016 GÉANT Copyright © 2016 GÉANT
*/ */
/// \defgroup WinStdWLANAPI WLAN API /// \defgroup WinStdWLANAPI WLAN API
#pragma once #pragma once
#include "Common.h" #include "Common.h"
#include <wlanapi.h> #include <wlanapi.h>
#include <string> #include <string>
/// \addtogroup WinStdWLANAPI /// \addtogroup WinStdWLANAPI
/// @{ /// @{
/// \cond internal /// \cond internal
// Must not statically link to Wlanapi.dll as it is not available on Windows // Must not statically link to Wlanapi.dll as it is not available on Windows
// without a WLAN interface. // without a WLAN interface.
extern DWORD (WINAPI *pfnWlanReasonCodeToString)(__in DWORD dwReasonCode, __in DWORD dwBufferSize, __in_ecount(dwBufferSize) PWCHAR pStringBuffer, __reserved PVOID pReserved); extern DWORD (WINAPI *pfnWlanReasonCodeToString)(__in DWORD dwReasonCode, __in DWORD dwBufferSize, __in_ecount(dwBufferSize) PWCHAR pStringBuffer, __reserved PVOID pReserved);
/// \endcond /// \endcond
/// ///
/// Retrieves a string that describes a specified reason code and stores it in a std::wstring string. /// 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) /// \sa [WlanReasonCodeToString function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706768.aspx)
/// ///
/// \note /// \note
/// Since Wlanapi.dll is not always present, the `pfnWlanReasonCodeToString` pointer to `WlanReasonCodeToString()` /// Since Wlanapi.dll is not always present, the `pfnWlanReasonCodeToString` pointer to `WlanReasonCodeToString()`
/// function must be loaded dynamically. /// function must be loaded dynamically.
/// ///
template<class _Traits, class _Ax> template<class _Traits, class _Ax>
static DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, __reserved PVOID pReserved) static DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue, __reserved PVOID pReserved)
{ {
SIZE_T sSize = 0; SIZE_T sSize = 0;
if (!::pfnWlanReasonCodeToString) if (!::pfnWlanReasonCodeToString)
return ERROR_CALL_NOT_IMPLEMENTED; return ERROR_CALL_NOT_IMPLEMENTED;
for (;;) { for (;;) {
// Increment size and allocate buffer. // Increment size and allocate buffer.
sSize = SIZETAdd(sSize, 1024); sSize = SIZETAdd(sSize, 1024);
if (sSize > DWORD_MAX) if (sSize > DWORD_MAX)
throw std::runtime_error("Data too big"); throw std::runtime_error("Data too big");
sValue.resize(sSize - 1); sValue.resize(sSize - 1);
// Try! // Try!
DWORD dwResult = ::pfnWlanReasonCodeToString(dwReasonCode, static_cast<DWORD>(sSize), &sValue[0], pReserved); DWORD dwResult = ::pfnWlanReasonCodeToString(dwReasonCode, static_cast<DWORD>(sSize), &sValue[0], pReserved);
if (dwResult == ERROR_SUCCESS) { if (dwResult == ERROR_SUCCESS) {
SIZE_T sLength = wcsnlen(&sValue[0], sSize); SIZE_T sLength = wcsnlen(&sValue[0], sSize);
if (sLength < sSize - 1) { if (sLength < sSize - 1) {
// Buffer was long enough. // Buffer was long enough.
sValue.resize(sLength); sValue.resize(sLength);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
} else { } else {
// Return error code. // Return error code.
return dwResult; return dwResult;
} }
} }
} }
/// @} /// @}
namespace winstd namespace winstd
{ {
/// \addtogroup WinStdWLANAPI /// \addtogroup WinStdWLANAPI
/// @{ /// @{
/// ///
/// Deleter for unique_ptr using WlanFreeMemory /// Deleter for unique_ptr using WlanFreeMemory
/// ///
template <class _Ty> struct WlanFreeMemory_delete template <class _Ty> struct WlanFreeMemory_delete
{ {
typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type
/// ///
/// Default construct /// Default construct
/// ///
WlanFreeMemory_delete() {} WlanFreeMemory_delete() {}
/// ///
/// Construct from another WlanFreeMemory_delete /// Construct from another WlanFreeMemory_delete
/// ///
template <class _Ty2> WlanFreeMemory_delete(const WlanFreeMemory_delete<_Ty2>&) {} template <class _Ty2> WlanFreeMemory_delete(const WlanFreeMemory_delete<_Ty2>&) {}
/// ///
/// Delete a pointer /// Delete a pointer
/// ///
void operator()(_Ty *_Ptr) const void operator()(_Ty *_Ptr) const
{ {
WlanFreeMemory(_Ptr); WlanFreeMemory(_Ptr);
} }
}; };
/// ///
/// Deleter for unique_ptr to array of unknown size using WlanFreeMemory /// Deleter for unique_ptr to array of unknown size using WlanFreeMemory
/// ///
template <class _Ty> struct WlanFreeMemory_delete<_Ty[]> template <class _Ty> struct WlanFreeMemory_delete<_Ty[]>
{ {
typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type
/// ///
/// Default construct /// Default construct
/// ///
WlanFreeMemory_delete() {} WlanFreeMemory_delete() {}
/// ///
/// Delete a pointer /// Delete a pointer
/// ///
void operator()(_Ty *_Ptr) const void operator()(_Ty *_Ptr) const
{ {
WlanFreeMemory(_Ptr); WlanFreeMemory(_Ptr);
} }
/// ///
/// Delete a pointer of another type /// Delete a pointer of another type
/// ///
template<class _Other> template<class _Other>
void operator()(_Other *) const void operator()(_Other *) const
{ {
WlanFreeMemory(_Ptr); WlanFreeMemory(_Ptr);
} }
}; };
/// ///
/// WLAN handle wrapper /// WLAN handle wrapper
/// ///
/// \sa [WlanOpenHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706759.aspx) /// \sa [WlanOpenHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706759.aspx)
/// ///
class wlan_handle : public handle<HANDLE, NULL> class wlan_handle : public handle<HANDLE, NULL>
{ {
WINSTD_HANDLE_IMPL(wlan_handle, HANDLE, NULL) WINSTD_HANDLE_IMPL(wlan_handle, HANDLE, NULL)
public: public:
/// ///
/// Closes a connection to the server. /// Closes a connection to the server.
/// ///
/// \sa [WlanCloseHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706610(v=vs.85).aspx) /// \sa [WlanCloseHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706610(v=vs.85).aspx)
/// ///
virtual ~wlan_handle() virtual ~wlan_handle()
{ {
if (m_h != invalid) if (m_h != invalid)
free_internal(); free_internal();
} }
protected: protected:
/// ///
/// Closes a connection to the server. /// Closes a connection to the server.
/// ///
/// \sa [WlanCloseHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706610(v=vs.85).aspx) /// \sa [WlanCloseHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706610(v=vs.85).aspx)
/// ///
void free_internal() noexcept override void free_internal() noexcept override
{ {
WlanCloseHandle(m_h, NULL); WlanCloseHandle(m_h, NULL);
} }
}; };
/// @} /// @}
} }
/// \addtogroup WinStdWLANAPI /// \addtogroup WinStdWLANAPI
/// @{ /// @{
/// ///
/// Opens a connection to the server. /// Opens a connection to the server.
/// ///
/// \sa [WlanOpenHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706759.aspx) /// \sa [WlanOpenHandle function](https://msdn.microsoft.com/en-us/library/windows/desktop/ms706759.aspx)
/// ///
#pragma warning(suppress: 4505) // Don't warn on unused code #pragma warning(suppress: 4505) // Don't warn on unused code
static DWORD WlanOpenHandle( static DWORD WlanOpenHandle(
_In_ DWORD dwClientVersion, _In_ DWORD dwClientVersion,
_Reserved_ PVOID pReserved, _Reserved_ PVOID pReserved,
_Out_ PDWORD pdwNegotiatedVersion, _Out_ PDWORD pdwNegotiatedVersion,
_Inout_ winstd::wlan_handle &handle) _Inout_ winstd::wlan_handle &handle)
{ {
HANDLE h; HANDLE h;
DWORD dwResult = WlanOpenHandle(dwClientVersion, pReserved, pdwNegotiatedVersion, &h); DWORD dwResult = WlanOpenHandle(dwClientVersion, pReserved, pdwNegotiatedVersion, &h);
if (dwResult == ERROR_SUCCESS) if (dwResult == ERROR_SUCCESS)
handle.attach(h); handle.attach(h);
return dwResult; return dwResult;
} }
/// @} /// @}