37#include <osl/thread.h>
38#include <osl/diagnose.h>
40#include <rtl/string.hxx>
41#include <rtl/ustring.hxx>
69char * address(std::vector< char > & blob) {
70 return blob.empty() ? nullptr : blob.data();
75 source.convertToString(
76 target, osl_getThreadTextEncoding(),
77 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
78 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
83ErrCode convert(
char const * source, sal_Int32 length, OUString * target) {
85 rtl_convertStringToUString(
86 &target->pData, source, length, osl_getThreadTextEncoding(),
87 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
88 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
89 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))
95 UnmarshalData(
SbxVariable * theVariable,
void * theBuffer):
96 variable(theVariable), buffer(theBuffer) {}
102struct StringData:
public UnmarshalData {
103 StringData(
SbxVariable * theVariable,
void * theBuffer,
bool theSpecial):
104 UnmarshalData(theVariable, theBuffer), special(theSpecial) {}
111 MarshalData() =
default;
112 MarshalData(
const MarshalData&) =
delete;
113 const MarshalData& operator=(
const MarshalData&) =
delete;
115 std::vector< char > * newBlob() {
116 blobs_.push_back(std::vector< char >());
117 return &blobs_.back();
120 std::vector< UnmarshalData > unmarshal;
122 std::vector< StringData > unmarshalStrings;
125 std::vector< std::vector< char > > blobs_;
128std::size_t align(std::size_t address, std::size_t alignment) {
130 return (address + (alignment - 1)) & ~(alignment - 1);
134 std::vector< char > & blob, std::size_t alignment, std::size_t offset,
137 std::vector< char >::size_type
n = blob.size();
138 n = align(n - offset, alignment) + offset;
139 blob.resize(n + add);
140 return address(blob) +
n;
143template<
typename T >
void add(
144 std::vector< char > & blob, T
const & data, std::size_t alignment,
147 *
reinterpret_cast< T *
>(align(blob, alignment, offset,
sizeof (T))) = data;
150std::size_t alignment(
SbxVariable const * variable) {
151 assert(variable !=
nullptr);
168 for (sal_uInt32 i = 0;
i <
props->Count(); ++
i)
170 n = std::max(n, alignment(
props->Get(i)));
184 sal_Int32 dims =
arr->GetDims();
185 std::vector< sal_Int32 > low(dims);
186 for (sal_Int32 i = 0;
i < dims; ++
i) {
188 arr->GetDim(i + 1, low[i], up);
190 return alignment(
arr->Get(low.data()));
196 std::vector< char > & blob, std::size_t offset, MarshalData & data);
199 SbxVariable * variable,
bool special, MarshalData & data,
void ** buffer)
201 assert(variable !=
nullptr && buffer !=
nullptr);
204 if (e != ERRCODE_NONE) {
207 std::vector< char > * blob = data.newBlob();
208 blob->insert(blob->begin(), str.getStr(), str.getStr() + str.getLength() + 1);
209 *buffer = address(*blob);
210 data.unmarshalStrings.push_back(StringData(variable, *buffer, special));
215 SbxVariable const * variable, std::vector< char > & blob, std::size_t offset,
218 assert(variable !=
nullptr);
222 for (sal_uInt32 i = 0;
i <
props->Count(); ++
i)
224 ErrCode e = marshal(
false,
props->Get(i),
false, blob, offset, data);
225 if (e != ERRCODE_NONE) {
233 SbxVariable const * variable, std::vector< char > & blob, std::size_t offset,
236 assert(variable !=
nullptr);
239 sal_Int32 dims =
arr->GetDims();
240 std::vector< sal_Int32 > low(dims);
241 std::vector< sal_Int32 >
up(dims);
242 for (sal_Int32 i = 0;
i < dims; ++
i) {
243 arr->GetDim(i + 1, low[i], up[i]);
245 for (std::vector< sal_Int32 > idx = low;;) {
246 ErrCode e = marshal(
false,
arr->Get(
idx.data()),
false, blob, offset, data);
247 if (e != ERRCODE_NONE) {
250 sal_Int32
i = dims - 1;
251 while (idx[i] == up[i]) {
266 std::vector< char > & blob, std::size_t offset, MarshalData & data)
268 assert(variable !=
nullptr);
279 add(blob, variable->
GetInteger(), outer ? 8 : 2, offset);
282 add(blob, variable->
GetLong(), outer ? 8 : 4, offset);
285 add(blob, variable->
GetSingle(), outer ? 8 : 4, offset);
288 add(blob, variable->
GetDouble(), 8, offset);
293 ErrCode e = marshalString(variable, special, data, &p);
294 if (e != ERRCODE_NONE) {
297 add(blob, p, 8, offset);
302 align(blob, outer ? 8 : alignment(variable), offset, 0);
303 ErrCode e = marshalStruct(variable, blob, offset, data);
304 if (e != ERRCODE_NONE) {
310 add(blob, variable->
GetBool(), outer ? 8 : 1, offset);
313 add(blob, variable->
GetByte(), outer ? 8 : 1, offset);
320 ErrCode e = marshalArray(variable, blob, offset, data);
321 if (e != ERRCODE_NONE) {
334 add(blob, variable->
data(), 8, offset);
339 ErrCode e = marshalString(variable, special, data, &p);
340 if (e != ERRCODE_NONE) {
343 std::vector< char >* blob2 = data.newBlob();
344 add(*blob2, p, 8, 0);
345 add(blob, address(*blob2), 8, offset);
350 std::vector< char > * blob2 = data.newBlob();
351 ErrCode e = marshalStruct(variable, *blob2, 0, data);
352 if (e != ERRCODE_NONE) {
355 void *
p = address(*blob2);
357 data.unmarshal.push_back(UnmarshalData(variable, p));
359 add(blob, p, 8, offset);
367 std::vector< char > * blob2 = data.newBlob();
368 ErrCode e = marshalArray(variable, *blob2, 0, data);
369 if (e != ERRCODE_NONE) {
372 void *
p = address(*blob2);
374 data.unmarshal.push_back(UnmarshalData(variable, p));
376 add(blob, p, 8, offset);
382template<
typename T > T read(
void const ** pointer) {
383 T
const *
p =
static_cast< T
const *
>(*pointer);
384 *pointer =
static_cast< void const *
>(
p + 1);
388void const * unmarshal(
SbxVariable * variable,
void const * data) {
389 assert(variable !=
nullptr);
393 variable->
PutInteger(read< sal_Int16 >(&data));
396 variable->
PutLong(read< sal_Int32 >(&data));
399 variable->
PutSingle(read< float >(&data));
402 variable->
PutDouble(read< double >(&data));
405 read< char * >(&data);
409 data =
reinterpret_cast< void const *
>(
411 reinterpret_cast< sal_uIntPtr
>(data),
412 alignment(variable)));
416 for (sal_uInt32 i = 0;
i <
props->Count(); ++
i)
418 data = unmarshal(
props->Get(i), data);
423 variable->
PutBool(read< sal_Bool >(&data));
426 variable->
PutByte(read< sal_uInt8 >(&data));
435 sal_Int32 dims =
arr->GetDims();
436 std::vector< sal_Int32 > low(dims);
437 std::vector< sal_Int32 >
up(dims);
438 for (sal_Int32 i = 0;
i < dims; ++
i) {
439 arr->GetDim(i + 1, low[i], up[i]);
441 for (std::vector< sal_Int32 > idx = low;;) {
442 data = unmarshal(
arr->Get(
idx.data()), data);
443 sal_Int32
i = dims - 1;
444 while (idx[i] == up[i]) {
460 if (data.buffer !=
nullptr) {
461 char const *
p =
static_cast< char const *
>(data.buffer);
464 len =
static_cast< sal_Int32
>(
result.GetULong());
470 len = rtl_str_getLength(p);
473 if (e != ERRCODE_NONE) {
477 data.variable->PutString(str);
487 std::u16string_view dll, ProcData
const & proc,
SbxArray * arguments,
490 if (arguments && arguments->
Count() > 20)
493 std::vector< char > stack;
502 (proc.name ==
"GetLogicalDriveStringsA");
503 for (sal_uInt32 i = 1;
i < (arguments ==
nullptr ? 0 : arguments->
Count()); ++
i)
505 ErrCode e = marshal(
true, arguments->Get(i), special && i == 2, stack, stack.size(),
507 if (e != ERRCODE_NONE) {
510 align(stack, 8, 0, 0);
519 sal_Int64 iRetVal = 0;
520 double dRetVal = 0.0;
522 switch (
result.GetType()) {
531 auto p =
reinterpret_cast<sal_Int64 (*)(...)
>(proc.proc);
532 auto const st =
reinterpret_cast<double *
>(stack.data());
534 =
p(st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7], st[8], st[9], st[10],
535 st[11], st[12], st[13], st[14], st[15], st[16], st[17], st[18], st[19]);
541 auto p =
reinterpret_cast<double (*)(...)
>(proc.proc);
542 auto const st =
reinterpret_cast<double*
>(stack.data());
544 =
p(st[0], st[1], st[2], st[3], st[4], st[5], st[6], st[7], st[8], st[9], st[10],
545 st[11], st[12], st[13], st[14], st[15], st[16], st[17], st[18], st[19]);
552 switch (
result.GetType()) {
556 result.PutInteger(
static_cast< sal_Int16
>(iRetVal));
559 result.PutLong(
static_cast< sal_Int32
>(iRetVal));
562 result.PutSingle(
static_cast< float >(dRetVal));
565 result.PutDouble(dRetVal);
569 char const * s1 =
reinterpret_cast< char const *
>(iRetVal);
572 if (e != ERRCODE_NONE) {
582 result.PutBool(
bool(iRetVal));
591 for (sal_uInt32 i = 1;
i < (arguments ==
nullptr ? 0 : arguments->Count()); ++
i)
596 for (
auto const& elem : data.unmarshal)
598 unmarshal(elem.variable, elem.buffer);
600 for (
auto const& elem : data.unmarshalStrings)
602 ErrCode e = unmarshalString(elem, result);
603 if (e != ERRCODE_NONE) {
610ErrCode getProcData(HMODULE handle, OUString
const & name, ProcData * proc)
612 assert(proc !=
nullptr);
613 if (
name.getLength() != 0 && name[0] ==
'@') {
615 if (n <= 0 || n > 0xFFFF) {
618 FARPROC
p = GetProcAddress(handle,
reinterpret_cast< LPCSTR
>(n));
620 proc->name =
"#" + OString::number(n);
627 if (e != ERRCODE_NONE) {
630 FARPROC
p = GetProcAddress(handle, name8.getStr());
636 sal_Int32
i = name8.indexOf(
'#');
638 name8 = name8.copy(0, i);
639 p = GetProcAddress(handle, name8.getStr());
646 OString real(
"_" + name8);
647 p = GetProcAddress(handle, real.getStr());
654 p = GetProcAddress(handle, real.getStr());
666 typedef std::map< OUString, ProcData > Procs;
668 virtual ~Dll()
override;
671 Dll(): handle(nullptr) {}
673 ErrCode getProc(OUString
const & name, ProcData * proc);
680 if (handle !=
nullptr && !FreeLibrary(handle)) {
681 SAL_WARN(
"basic",
"FreeLibrary(" << handle <<
") failed with " << GetLastError());
685ErrCode Dll::getProc(OUString
const & name, ProcData * proc) {
686 Procs::iterator
i(procs.find(name));
687 if (i != procs.end()) {
691 ErrCode e = getProcData(handle, name, proc);
692 if (e == ERRCODE_NONE) {
693 procs.emplace(name, *proc);
698OUString fullDllName(OUString
const & name) {
700 if (full.indexOf(
'.') == -1) {
710 typedef std::map< OUString, ::rtl::Reference< Dll > >
Dlls;
717 Dll *
getDll(OUString
const & name);
724 if (
i ==
dlls.end()) {
726 HMODULE
h = LoadLibraryW(o3tl::toW(
name.getStr()));
731 i->second->handle =
h;
733 return i->second.get();
737 std::u16string_view function, std::u16string_view library,
740 if (cdeclConvention) {
743 OUString dllName(fullDllName(OUString(library)));
744 Dll * dll = impl_->getDll(dllName);
745 if (dll ==
nullptr) {
749 ErrCode e = dll->getProc(OUString(function), &proc);
750 if (e != ERRCODE_NONE) {
753 return call(dllName, proc, arguments, result);
757 impl_->dlls.erase(library);
762SbiDllMgr::~SbiDllMgr() {}
ErrCode Call(std::u16string_view function, std::u16string_view library, SbxArray *arguments, SbxVariable &result, bool cdeclConvention)
void FreeDll(OUString const &library)
static bool isVBAEnabled()
SbxFlagBits GetFlags() const
SbxArray * GetProperties()
OUString GetOUString() const
SbxBase * GetObject() const
sal_uInt8 GetByte() const
bool PutInteger(sal_Int16)
sal_Int32 GetLong() const
sal_Int16 GetInteger() const
virtual SbxDataType GetType() const override
DECL_LISTENERMULTIPLEXER_END void SAL_CALL up(const css::awt::SpinEvent &rEvent) override
#define SAL_WARN(area, stream)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
#define ERRCODE_BASIC_PROC_UNDEFINED
#define ERRCODE_BASIC_BAD_ARGUMENT
#define ERRCODE_BASIC_NOT_IMPLEMENTED
#define ERRCODE_BASIC_BAD_DLL_LOAD
std::map< OUString, ::rtl::Reference< Dll > > Dlls
const Impl & operator=(const Impl &)=delete
Dll * getDll(OUString const &name)
Impl(const Impl &)=delete