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
///
com_runtime_error(_In_ error_type num, _In_ const std::string& msg) : num_runtime_error<HRESULT>(num, msg)
{}
{
}
///
/// Constructs an exception
@ -43,7 +44,8 @@ namespace winstd
/// \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)
{}
{
}
};
/// @}
@ -1460,6 +1462,58 @@ namespace winstd
/// \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
///
@ -1476,7 +1530,7 @@ namespace winstd
if (!array && n)
throw std::invalid_argument("array is NULL");
LPSAFEARRAY sa;
safearray sa;
if (columns == 1) {
// Make vector when one column only.
sa = SafeArrayCreateVector(VT_VARIANT, 0, rows);
@ -1536,7 +1590,7 @@ namespace winstd
VARIANT var;
V_VT(&var) = VT_ARRAY | VT_VARIANT;
V_ARRAY(&var) = sa;
V_ARRAY(&var) = sa.detach();
return var;
}
@ -1560,7 +1614,7 @@ namespace winstd
if (!array && rows)
throw std::invalid_argument("array is NULL");
LPSAFEARRAY sa;
safearray sa;
if constexpr (columns == 1) {
// Make vector when one column only.
sa = SafeArrayCreateVector(VT_VARIANT, 0, rows);
@ -1590,7 +1644,7 @@ namespace winstd
VARIANT var;
V_VT(&var) = VT_ARRAY | VT_VARIANT;
V_ARRAY(&var) = sa;
V_ARRAY(&var) = sa.detach();
return var;
}
@ -1614,7 +1668,7 @@ namespace winstd
// Allocate.
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)
throw std::bad_alloc();
@ -1642,7 +1696,7 @@ namespace winstd
VARIANT var;
V_VT(&var) = VT_ARRAY | VT_UI1;
V_ARRAY(&var) = sa;
V_ARRAY(&var) = sa.detach();
return var;
}