COM: Add helper for SAFEARRAY creation

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2025-01-15 15:00:25 +01:00
parent b0cf45a0f1
commit f33010e6b6

View File

@ -34,7 +34,8 @@ namespace winstd
/// \param[in] msg Error message /// \param[in] msg Error message
/// ///
com_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error<HRESULT>(num, msg) com_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error<HRESULT>(num, msg)
{} {
}
/// ///
/// Constructs an exception /// Constructs an exception
@ -43,7 +44,8 @@ namespace winstd
/// \param[in] msg Error message /// \param[in] msg Error message
/// ///
com_runtime_error(_In_ error_type num, _In_opt_z_ const char* msg = nullptr) : num_runtime_error<HRESULT>(num, msg) com_runtime_error(_In_ error_type num, _In_opt_z_ const char* msg = nullptr) : num_runtime_error<HRESULT>(num, msg)
{} {
}
}; };
/// @} /// @}
@ -1460,6 +1462,58 @@ namespace winstd
/// \addtogroup WinStdCOMHelpers /// \addtogroup WinStdCOMHelpers
/// @{ /// @{
///
/// Builds SAFEARRAY of uniform data
///
/// \param[in] vt Type of array element
/// \param[in] array Pointer to data
/// \param[in] columns Number of columns. When 1, SafeArrayCreateVector is used; when >1, SafeArrayCreate is used.
/// \param[in] rows Number of rows
///
/// \return Returns SAFEARRAY
///
inline _Ret_notnull_ LPSAFEARRAY BuildSAFEARRAY(_In_ VARTYPE vt, _In_opt_ LPCVOID array, _In_ ULONG columns, _In_ ULONG rows)
{
const size_t n = columns * rows;
if (!array && n)
throw std::invalid_argument("array is NULL");
safearray sa;
if (columns == 1) {
// Make vector when one column only.
sa = SafeArrayCreateVector(vt, 0, rows);
}
else {
// Make 2-dimensional array when more columns.
SAFEARRAYBOUND dim[2] = {
{ columns, 0 },
{ rows, 0 }
};
sa = SafeArrayCreate(vt, 2, dim);
}
if (!sa)
throw std::bad_alloc();
size_t elem_size;
switch (vt) {
case VT_UI4:
case VT_I4: elem_size = 4; break;
case VT_UI2:
case VT_I2:
case VT_BOOL: elem_size = 2; break;
case VT_UI1:
case VT_I1: elem_size = 1; break;
default: throw std::invalid_argument("unsupported type");
};
{
safearray_accessor<void> saa(sa);
memcpy(saa.data(), array, elem_size * n);
}
return sa.detach();
}
/// ///
/// Builds VBARRAY of uniform data /// Builds VBARRAY of uniform data
/// ///
@ -1476,7 +1530,7 @@ namespace winstd
if (!array && n) if (!array && n)
throw std::invalid_argument("array is NULL"); throw std::invalid_argument("array is NULL");
LPSAFEARRAY sa; safearray sa;
if (columns == 1) { if (columns == 1) {
// Make vector when one column only. // Make vector when one column only.
sa = SafeArrayCreateVector(VT_VARIANT, 0, rows); sa = SafeArrayCreateVector(VT_VARIANT, 0, rows);
@ -1536,7 +1590,7 @@ namespace winstd
VARIANT var; VARIANT var;
V_VT(&var) = VT_ARRAY | VT_VARIANT; V_VT(&var) = VT_ARRAY | VT_VARIANT;
V_ARRAY(&var) = sa; V_ARRAY(&var) = sa.detach();
return var; return var;
} }
@ -1560,7 +1614,7 @@ namespace winstd
if (!array && rows) if (!array && rows)
throw std::invalid_argument("array is NULL"); throw std::invalid_argument("array is NULL");
LPSAFEARRAY sa; safearray sa;
if constexpr (columns == 1) { if constexpr (columns == 1) {
// Make vector when one column only. // Make vector when one column only.
sa = SafeArrayCreateVector(VT_VARIANT, 0, rows); sa = SafeArrayCreateVector(VT_VARIANT, 0, rows);
@ -1590,7 +1644,7 @@ namespace winstd
VARIANT var; VARIANT var;
V_VT(&var) = VT_ARRAY | VT_VARIANT; V_VT(&var) = VT_ARRAY | VT_VARIANT;
V_ARRAY(&var) = sa; V_ARRAY(&var) = sa.detach();
return var; return var;
} }
@ -1614,7 +1668,7 @@ namespace winstd
// Allocate. // Allocate.
size_t pallete_size = sizeof(RGBQUAD) * bmh.biClrUsed; size_t pallete_size = sizeof(RGBQUAD) * bmh.biClrUsed;
LPSAFEARRAY sa = SafeArrayCreateVector(VT_UI1, 0, static_cast<ULONG>(sizeof(BITMAPFILEHEADER) + sizeof(bmh) + pallete_size + bmh.biSizeImage)); safearray sa = SafeArrayCreateVector(VT_UI1, 0, static_cast<ULONG>(sizeof(BITMAPFILEHEADER) + sizeof(bmh) + pallete_size + bmh.biSizeImage));
if (!sa) if (!sa)
throw std::bad_alloc(); throw std::bad_alloc();
@ -1642,7 +1696,7 @@ namespace winstd
VARIANT var; VARIANT var;
V_VT(&var) = VT_ARRAY | VT_UI1; V_VT(&var) = VT_ARRAY | VT_UI1;
V_ARRAY(&var) = sa; V_ARRAY(&var) = sa.detach();
return var; return var;
} }