diff --git a/include/WinStd/MSI.h b/include/WinStd/MSI.h index 0a098256..e5e4be88 100644 --- a/include/WinStd/MSI.h +++ b/include/WinStd/MSI.h @@ -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 -#include -#include - -/// \addtogroup WinStdMSIAPI -/// @{ - -/// @copydoc MsiGetPropertyW() -template -static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string &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 -static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string &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 -static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string &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 -static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string &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 -static UINT MsiFormatRecordA(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string &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 -static UINT MsiFormatRecordW(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string &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 -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(binData.data()), &dwSize); - } else { - // Return error code. - return uiResult; - } -} - -/// @copydoc MsiGetTargetPathW() -template -static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Out_ std::basic_string &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 -static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string &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 -static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string &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 -static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string &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 +#include +#include + +/// \addtogroup WinStdMSIAPI +/// @{ + +/// @copydoc MsiGetPropertyW() +template +static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string &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 +static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string &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 +static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string &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 +static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string &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 +static UINT MsiFormatRecordA(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string &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 +static UINT MsiFormatRecordW(_In_opt_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string &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 +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(binData.data()), &dwSize); + } else { + // Return error code. + return uiResult; + } +} + +/// @copydoc MsiGetTargetPathW() +template +static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Out_ std::basic_string &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 +static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string &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 +static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string &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 +static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string &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; + } +} + +/// @} diff --git a/include/WinStd/Shell.h b/include/WinStd/Shell.h index c17f9cb9..03ae2fb8 100644 --- a/include/WinStd/Shell.h +++ b/include/WinStd/Shell.h @@ -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 -#include - -/// \addtogroup WinStdShellWAPI -/// @{ - -/// @copydoc PathCanonicalizeW() -template -static BOOL PathCanonicalizeA(_Inout_ std::basic_string &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 -static BOOL PathCanonicalizeW(_Inout_ std::basic_string &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 -static void PathRemoveBackslashA(_Inout_ std::basic_string& 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 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 -static void PathRemoveBackslashW(_Inout_ std::basic_string& 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 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 +#include + +/// \addtogroup WinStdShellWAPI +/// @{ + +/// @copydoc PathCanonicalizeW() +template +static BOOL PathCanonicalizeA(_Inout_ std::basic_string &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 +static BOOL PathCanonicalizeW(_Inout_ std::basic_string &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 +static void PathRemoveBackslashA(_Inout_ std::basic_string& 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 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 +static void PathRemoveBackslashW(_Inout_ std::basic_string& 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 buf(new wchar_t[len + 1]); + wmemcpy(buf.get(), sValue.c_str(), len); + buf[len] = 0; + PathRemoveBackslashW(buf.get()); + sValue.assign(buf.get()); + } +} + +/// @} diff --git a/include/WinStd/WLAN.h b/include/WinStd/WLAN.h index 630eb973..0a069fb2 100644 --- a/include/WinStd/WLAN.h +++ b/include/WinStd/WLAN.h @@ -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 -#include - -/// \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 -static DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Inout_ std::basic_string &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(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 struct WlanFreeMemory_delete - { - typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type - - /// - /// Default construct - /// - WlanFreeMemory_delete() {} - - /// - /// Construct from another WlanFreeMemory_delete - /// - template 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 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 - 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 - { - 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 +#include + +/// \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 +static DWORD WlanReasonCodeToString(_In_ DWORD dwReasonCode, _Inout_ std::basic_string &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(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 struct WlanFreeMemory_delete + { + typedef WlanFreeMemory_delete<_Ty> _Myt; ///< This type + + /// + /// Default construct + /// + WlanFreeMemory_delete() {} + + /// + /// Construct from another WlanFreeMemory_delete + /// + template 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 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 + 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 + { + 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; +} + +/// @}