LibreOffice Module basic (master) 1
dllmgr-x64.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#if defined(_WIN32)
23#include <prewin.h>
24#include <postwin.h>
25#endif
26
27#include <algorithm>
28#include <cstddef>
29#include <map>
30#include <string_view>
31#include <vector>
32
33#include <basic/sbx.hxx>
34#include <basic/sbxvar.hxx>
35#include <comphelper/string.hxx>
36#include <runtime.hxx>
37#include <osl/thread.h>
38#include <osl/diagnose.h>
39#include <rtl/ref.hxx>
40#include <rtl/string.hxx>
41#include <rtl/ustring.hxx>
42#include <sal/log.hxx>
45#include <o3tl/string_view.hxx>
46
47#undef max
48
49#include "dllmgr.hxx"
50
51using namespace css;
52
53/* Open issues:
54
55 Missing support for functions returning structs (see TODO in call()).
56
57 Missing support for additional data types (64 bit integers, Any, ...; would
58 trigger assert(false) in various switches).
59
60 It is assumed that the variables passed into SbiDllMgr::Call to represent
61 the arguments and return value have types that exactly match the Declare
62 statement; it would be better if this code had access to the function
63 signature from the Declare statement, so that it could convert the passed
64 variables accordingly.
65*/
66
67namespace {
68
69char * address(std::vector< char > & blob) {
70 return blob.empty() ? nullptr : blob.data();
71}
72
73ErrCode convert(OUString const & source, OString * target) {
74 return
75 source.convertToString(
76 target, osl_getThreadTextEncoding(),
77 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
78 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
80 //TODO: more specific errcode?
81}
82
83ErrCode convert(char const * source, sal_Int32 length, OUString * target) {
84 return
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))
91 //TODO: more specific errcode?
92}
93
94struct UnmarshalData {
95 UnmarshalData(SbxVariable * theVariable, void * theBuffer):
96 variable(theVariable), buffer(theBuffer) {}
97
98 SbxVariable * variable;
99 void * buffer;
100};
101
102struct StringData: public UnmarshalData {
103 StringData(SbxVariable * theVariable, void * theBuffer, bool theSpecial):
104 UnmarshalData(theVariable, theBuffer), special(theSpecial) {}
105
106 bool special;
107};
108
109class MarshalData {
110public:
111 MarshalData() = default;
112 MarshalData(const MarshalData&) = delete;
113 const MarshalData& operator=(const MarshalData&) = delete;
114
115 std::vector< char > * newBlob() {
116 blobs_.push_back(std::vector< char >());
117 return &blobs_.back();
118 }
119
120 std::vector< UnmarshalData > unmarshal;
121
122 std::vector< StringData > unmarshalStrings;
123
124private:
125 std::vector< std::vector< char > > blobs_;
126};
127
128std::size_t align(std::size_t address, std::size_t alignment) {
129 // alignment = 2^k for some k >= 0
130 return (address + (alignment - 1)) & ~(alignment - 1);
131}
132
133char * align(
134 std::vector< char > & blob, std::size_t alignment, std::size_t offset,
135 std::size_t add)
136{
137 std::vector< char >::size_type n = blob.size();
138 n = align(n - offset, alignment) + offset; //TODO: overflow in align()
139 blob.resize(n + add); //TODO: overflow
140 return address(blob) + n;
141}
142
143template< typename T > void add(
144 std::vector< char > & blob, T const & data, std::size_t alignment,
145 std::size_t offset)
146{
147 *reinterpret_cast< T * >(align(blob, alignment, offset, sizeof (T))) = data;
148}
149
150std::size_t alignment(SbxVariable const * variable) {
151 assert(variable != nullptr);
152 if ((variable->GetType() & SbxARRAY) == 0) {
153 switch (variable->GetType()) {
154 case SbxINTEGER:
155 return 2;
156 case SbxLONG:
157 case SbxSINGLE:
158 case SbxSTRING:
159 return 4;
160 case SbxDOUBLE:
161 return 8;
162 case SbxOBJECT:
163 {
164 std::size_t n = 1;
165 SbxObject* pobj = dynamic_cast<SbxObject*>(variable->GetObject());
166 assert(pobj);
167 SbxArray* props = pobj->GetProperties();
168 for (sal_uInt32 i = 0; i < props->Count(); ++i)
169 {
170 n = std::max(n, alignment(props->Get(i)));
171 }
172 return n;
173 }
174 case SbxBOOL:
175 case SbxBYTE:
176 return 1;
177 default:
178 assert(false);
179 return 1;
180 }
181 } else {
182 SbxDimArray * arr = dynamic_cast<SbxDimArray*>( variable->GetObject() );
183 assert(arr);
184 sal_Int32 dims = arr->GetDims();
185 std::vector< sal_Int32 > low(dims);
186 for (sal_Int32 i = 0; i < dims; ++i) {
187 sal_Int32 up;
188 arr->GetDim(i + 1, low[i], up);
189 }
190 return alignment(arr->Get(low.data()));
191 }
192}
193
194ErrCode marshal(
195 bool outer, SbxVariable * variable, bool special,
196 std::vector< char > & blob, std::size_t offset, MarshalData & data);
197
198ErrCode marshalString(
199 SbxVariable * variable, bool special, MarshalData & data, void ** buffer)
200{
201 assert(variable != nullptr && buffer != nullptr);
202 OString str;
203 ErrCode e = convert(variable->GetOUString(), &str);
204 if (e != ERRCODE_NONE) {
205 return e;
206 }
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));
211 return ERRCODE_NONE;
212}
213
214ErrCode marshalStruct(
215 SbxVariable const * variable, std::vector< char > & blob, std::size_t offset,
216 MarshalData & data)
217{
218 assert(variable != nullptr);
219 SbxObject* pobj = dynamic_cast<SbxObject*>(variable->GetObject());
220 assert(pobj);
221 SbxArray* props = pobj->GetProperties();
222 for (sal_uInt32 i = 0; i < props->Count(); ++i)
223 {
224 ErrCode e = marshal(false, props->Get(i), false, blob, offset, data);
225 if (e != ERRCODE_NONE) {
226 return e;
227 }
228 }
229 return ERRCODE_NONE;
230}
231
232ErrCode marshalArray(
233 SbxVariable const * variable, std::vector< char > & blob, std::size_t offset,
234 MarshalData & data)
235{
236 assert(variable != nullptr);
237 SbxDimArray * arr = dynamic_cast<SbxDimArray*>( variable->GetObject() );
238 assert(arr);
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]);
244 }
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) {
248 return e;
249 }
250 sal_Int32 i = dims - 1;
251 while (idx[i] == up[i]) {
252 idx[i] = low[i];
253 if (i == 0) {
254 return ERRCODE_NONE;
255 }
256 --i;
257 }
258 ++idx[i];
259 }
260}
261
262// 8-aligned structs are only 4-aligned on stack, so alignment of members in
263// such structs must take that into account via "offset"
264ErrCode marshal(
265 bool outer, SbxVariable * variable, bool special,
266 std::vector< char > & blob, std::size_t offset, MarshalData & data)
267{
268 assert(variable != nullptr);
269
270 SbxDataType eVarType = variable->GetType();
271 bool bByVal = !(variable->GetFlags() & SbxFlagBits::Reference);
272 if( !bByVal && !SbiRuntime::isVBAEnabled() && eVarType == SbxSTRING )
273 bByVal = true;
274
275 if (bByVal) {
276 if ((eVarType & SbxARRAY) == 0) {
277 switch (eVarType) {
278 case SbxINTEGER:
279 add(blob, variable->GetInteger(), outer ? 8 : 2, offset);
280 break;
281 case SbxLONG:
282 add(blob, variable->GetLong(), outer ? 8 : 4, offset);
283 break;
284 case SbxSINGLE:
285 add(blob, variable->GetSingle(), outer ? 8 : 4, offset);
286 break;
287 case SbxDOUBLE:
288 add(blob, variable->GetDouble(), 8, offset);
289 break;
290 case SbxSTRING:
291 {
292 void * p;
293 ErrCode e = marshalString(variable, special, data, &p);
294 if (e != ERRCODE_NONE) {
295 return e;
296 }
297 add(blob, p, 8, offset);
298 break;
299 }
300 case SbxOBJECT:
301 {
302 align(blob, outer ? 8 : alignment(variable), offset, 0);
303 ErrCode e = marshalStruct(variable, blob, offset, data);
304 if (e != ERRCODE_NONE) {
305 return e;
306 }
307 break;
308 }
309 case SbxBOOL:
310 add(blob, variable->GetBool(), outer ? 8 : 1, offset);
311 break;
312 case SbxBYTE:
313 add(blob, variable->GetByte(), outer ? 8 : 1, offset);
314 break;
315 default:
316 assert(false);
317 break;
318 }
319 } else {
320 ErrCode e = marshalArray(variable, blob, offset, data);
321 if (e != ERRCODE_NONE) {
322 return e;
323 }
324 }
325 } else {
326 if ((eVarType & SbxARRAY) == 0) {
327 switch (eVarType) {
328 case SbxINTEGER:
329 case SbxLONG:
330 case SbxSINGLE:
331 case SbxDOUBLE:
332 case SbxBOOL:
333 case SbxBYTE:
334 add(blob, variable->data(), 8, offset);
335 break;
336 case SbxSTRING:
337 {
338 void * p;
339 ErrCode e = marshalString(variable, special, data, &p);
340 if (e != ERRCODE_NONE) {
341 return e;
342 }
343 std::vector< char >* blob2 = data.newBlob();
344 add(*blob2, p, 8, 0);
345 add(blob, address(*blob2), 8, offset);
346 break;
347 }
348 case SbxOBJECT:
349 {
350 std::vector< char > * blob2 = data.newBlob();
351 ErrCode e = marshalStruct(variable, *blob2, 0, data);
352 if (e != ERRCODE_NONE) {
353 return e;
354 }
355 void * p = address(*blob2);
356 if (outer) {
357 data.unmarshal.push_back(UnmarshalData(variable, p));
358 }
359 add(blob, p, 8, offset);
360 break;
361 }
362 default:
363 assert(false);
364 break;
365 }
366 } else {
367 std::vector< char > * blob2 = data.newBlob();
368 ErrCode e = marshalArray(variable, *blob2, 0, data);
369 if (e != ERRCODE_NONE) {
370 return e;
371 }
372 void * p = address(*blob2);
373 if (outer) {
374 data.unmarshal.push_back(UnmarshalData(variable, p));
375 }
376 add(blob, p, 8, offset);
377 }
378 }
379 return ERRCODE_NONE;
380}
381
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);
385 return *p;
386}
387
388void const * unmarshal(SbxVariable * variable, void const * data) {
389 assert(variable != nullptr);
390 if ((variable->GetType() & SbxARRAY) == 0) {
391 switch (variable->GetType()) {
392 case SbxINTEGER:
393 variable->PutInteger(read< sal_Int16 >(&data));
394 break;
395 case SbxLONG:
396 variable->PutLong(read< sal_Int32 >(&data));
397 break;
398 case SbxSINGLE:
399 variable->PutSingle(read< float >(&data));
400 break;
401 case SbxDOUBLE:
402 variable->PutDouble(read< double >(&data));
403 break;
404 case SbxSTRING:
405 read< char * >(&data); // handled by unmarshalString
406 break;
407 case SbxOBJECT:
408 {
409 data = reinterpret_cast< void const * >(
410 align(
411 reinterpret_cast< sal_uIntPtr >(data),
412 alignment(variable)));
413 SbxObject* pobj = dynamic_cast<SbxObject*>(variable->GetObject());
414 assert(pobj);
415 SbxArray* props = pobj->GetProperties();
416 for (sal_uInt32 i = 0; i < props->Count(); ++i)
417 {
418 data = unmarshal(props->Get(i), data);
419 }
420 break;
421 }
422 case SbxBOOL:
423 variable->PutBool(read< sal_Bool >(&data));
424 break;
425 case SbxBYTE:
426 variable->PutByte(read< sal_uInt8 >(&data));
427 break;
428 default:
429 assert(false);
430 break;
431 }
432 } else {
433 SbxDimArray * arr = dynamic_cast<SbxDimArray*>( variable->GetObject() );
434 assert(arr);
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]);
440 }
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]) {
445 idx[i] = low[i];
446 if (i == 0) {
447 goto done;
448 }
449 --i;
450 }
451 ++idx[i];
452 }
453 done:;
454 }
455 return data;
456}
457
458ErrCode unmarshalString(StringData const & data, SbxVariable const & result) {
459 OUString str;
460 if (data.buffer != nullptr) {
461 char const * p = static_cast< char const * >(data.buffer);
462 sal_Int32 len;
463 if (data.special) {
464 len = static_cast< sal_Int32 >(result.GetULong());
465 if (len < 0) { // i.e., DWORD result >= 2^31
467 //TODO: more specific errcode?
468 }
469 } else {
470 len = rtl_str_getLength(p);
471 }
472 ErrCode e = convert(p, len, &str);
473 if (e != ERRCODE_NONE) {
474 return e;
475 }
476 }
477 data.variable->PutString(str);
478 return ERRCODE_NONE;
479}
480
481struct ProcData {
482 OString name;
483 FARPROC proc;
484};
485
486ErrCode call(
487 std::u16string_view dll, ProcData const & proc, SbxArray * arguments,
488 SbxVariable & result)
489{
490 if (arguments && arguments->Count() > 20)
492
493 std::vector< char > stack;
494 MarshalData data;
495
496 // For DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
497 // from kernel32, upon return, filled lpBuffer length is result DWORD, which
498 // requires special handling in unmarshalString; other functions might
499 // require similar treatment, too:
500 bool special =
501 o3tl::equalsIgnoreAsciiCase(dll, u"KERNEL32.DLL") &&
502 (proc.name == "GetLogicalDriveStringsA");
503 for (sal_uInt32 i = 1; i < (arguments == nullptr ? 0 : arguments->Count()); ++i)
504 {
505 ErrCode e = marshal(true, arguments->Get(i), special && i == 2, stack, stack.size(),
506 data);
507 if (e != ERRCODE_NONE) {
508 return e;
509 }
510 align(stack, 8, 0, 0);
511 }
512
513 stack.resize(20*8);
514
515 // We fake all calls as being to a varargs function,
516 // as this means any floating-point argument among the first four
517 // ones will end up in a XMM register where the callee expects it.
518
519 sal_Int64 iRetVal = 0;
520 double dRetVal = 0.0;
521
522 switch (result.GetType()) {
523 case SbxEMPTY:
524 case SbxINTEGER:
525 case SbxLONG:
526 case SbxSTRING:
527 case SbxOBJECT:
528 case SbxBOOL:
529 case SbxBYTE:
530 {
531 auto p = reinterpret_cast<sal_Int64 (*)(...)>(proc.proc);
532 auto const st = reinterpret_cast<double *>(stack.data());
533 iRetVal
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]);
536 break;
537 }
538 case SbxSINGLE:
539 case SbxDOUBLE:
540 {
541 auto p = reinterpret_cast<double (*)(...)>(proc.proc);
542 auto const st = reinterpret_cast<double*>(stack.data());
543 dRetVal
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]);
546 break;
547 }
548 default:
549 break;
550 }
551
552 switch (result.GetType()) {
553 case SbxEMPTY:
554 break;
555 case SbxINTEGER:
556 result.PutInteger(static_cast< sal_Int16 >(iRetVal));
557 break;
558 case SbxLONG:
559 result.PutLong(static_cast< sal_Int32 >(iRetVal));
560 break;
561 case SbxSINGLE:
562 result.PutSingle(static_cast< float >(dRetVal));
563 break;
564 case SbxDOUBLE:
565 result.PutDouble(dRetVal);
566 break;
567 case SbxSTRING:
568 {
569 char const * s1 = reinterpret_cast< char const * >(iRetVal);
570 OUString s2;
571 ErrCode e = convert(s1, rtl_str_getLength(s1), &s2);
572 if (e != ERRCODE_NONE) {
573 return e;
574 }
575 result.PutString(s2);
576 break;
577 }
578 case SbxOBJECT:
579 //TODO
580 break;
581 case SbxBOOL:
582 result.PutBool(bool(iRetVal));
583 break;
584 case SbxBYTE:
585 result.PutByte(static_cast< sal_uInt8 >(iRetVal));
586 break;
587 default:
588 assert(false);
589 break;
590 }
591 for (sal_uInt32 i = 1; i < (arguments == nullptr ? 0 : arguments->Count()); ++i)
592 {
593 arguments->Get(i)->ResetFlag(SbxFlagBits::Reference);
594 //TODO: skipped for errors?!?
595 }
596 for (auto const& elem : data.unmarshal)
597 {
598 unmarshal(elem.variable, elem.buffer);
599 }
600 for (auto const& elem : data.unmarshalStrings)
601 {
602 ErrCode e = unmarshalString(elem, result);
603 if (e != ERRCODE_NONE) {
604 return e;
605 }
606 }
607 return ERRCODE_NONE;
608}
609
610ErrCode getProcData(HMODULE handle, OUString const & name, ProcData * proc)
611{
612 assert(proc != nullptr);
613 if (name.getLength() != 0 && name[0] == '@') { //TODO: "@" vs. "#"???
614 sal_Int32 n = o3tl::toInt32(name.subView(1)); //TODO: handle bad input
615 if (n <= 0 || n > 0xFFFF) {
616 return ERRCODE_BASIC_BAD_ARGUMENT; //TODO: more specific errcode?
617 }
618 FARPROC p = GetProcAddress(handle, reinterpret_cast< LPCSTR >(n));
619 if (p != nullptr) {
620 proc->name = "#" + OString::number(n);
621 proc->proc = p;
622 return ERRCODE_NONE;
623 }
624 } else {
625 OString name8;
626 ErrCode e = convert(name, &name8);
627 if (e != ERRCODE_NONE) {
628 return e;
629 }
630 FARPROC p = GetProcAddress(handle, name8.getStr());
631 if (p != nullptr) {
632 proc->name = name8;
633 proc->proc = p;
634 return ERRCODE_NONE;
635 }
636 sal_Int32 i = name8.indexOf('#');
637 if (i != -1) {
638 name8 = name8.copy(0, i);
639 p = GetProcAddress(handle, name8.getStr());
640 if (p != nullptr) {
641 proc->name = name8;
642 proc->proc = p;
643 return ERRCODE_NONE;
644 }
645 }
646 OString real("_" + name8);
647 p = GetProcAddress(handle, real.getStr());
648 if (p != nullptr) {
649 proc->name = real;
650 proc->proc = p;
651 return ERRCODE_NONE;
652 }
653 real = name8 + "A";
654 p = GetProcAddress(handle, real.getStr());
655 if (p != nullptr) {
656 proc->name = real;
657 proc->proc = p;
658 return ERRCODE_NONE;
659 }
660 }
662}
663
664struct Dll: public salhelper::SimpleReferenceObject {
665private:
666 typedef std::map< OUString, ProcData > Procs;
667
668 virtual ~Dll() override;
669
670public:
671 Dll(): handle(nullptr) {}
672
673 ErrCode getProc(OUString const & name, ProcData * proc);
674
675 HMODULE handle;
676 Procs procs;
677};
678
679Dll::~Dll() {
680 if (handle != nullptr && !FreeLibrary(handle)) {
681 SAL_WARN("basic", "FreeLibrary(" << handle << ") failed with " << GetLastError());
682 }
683}
684
685ErrCode Dll::getProc(OUString const & name, ProcData * proc) {
686 Procs::iterator i(procs.find(name));
687 if (i != procs.end()) {
688 *proc = i->second;
689 return ERRCODE_NONE;
690 }
691 ErrCode e = getProcData(handle, name, proc);
692 if (e == ERRCODE_NONE) {
693 procs.emplace(name, *proc);
694 }
695 return e;
696}
697
698OUString fullDllName(OUString const & name) {
699 OUString full(name);
700 if (full.indexOf('.') == -1) {
701 full += ".DLL";
702 }
703 return full;
704}
705
706}
707
709private:
710 typedef std::map< OUString, ::rtl::Reference< Dll > > Dlls;
711
712public:
713 Impl() = default;
714 Impl(const Impl&) = delete;
715 const Impl& operator=(const Impl&) = delete;
716
717 Dll * getDll(OUString const & name);
718
720};
721
722Dll * SbiDllMgr::Impl::getDll(OUString const & name) {
723 Dlls::iterator i(dlls.find(name));
724 if (i == dlls.end()) {
725 i = dlls.emplace(name, new Dll).first;
726 HMODULE h = LoadLibraryW(o3tl::toW(name.getStr()));
727 if (h == nullptr) {
728 dlls.erase(i);
729 return nullptr;
730 }
731 i->second->handle = h;
732 }
733 return i->second.get();
734}
735
737 std::u16string_view function, std::u16string_view library,
738 SbxArray * arguments, SbxVariable & result, bool cdeclConvention)
739{
740 if (cdeclConvention) {
742 }
743 OUString dllName(fullDllName(OUString(library)));
744 Dll * dll = impl_->getDll(dllName);
745 if (dll == nullptr) {
747 }
748 ProcData proc;
749 ErrCode e = dll->getProc(OUString(function), &proc);
750 if (e != ERRCODE_NONE) {
751 return e;
752 }
753 return call(dllName, proc, arguments, result);
754}
755
756void SbiDllMgr::FreeDll(OUString const & library) {
757 impl_->dlls.erase(library);
758}
759
761
762SbiDllMgr::~SbiDllMgr() {}
763
764/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ErrCode Call(std::u16string_view function, std::u16string_view library, SbxArray *arguments, SbxVariable &result, bool cdeclConvention)
Definition: dllmgr-none.cxx:94
void FreeDll(OUString const &library)
static bool isVBAEnabled()
Definition: runtime.cxx:115
Definition: sbx.hxx:95
sal_uInt32 Count() const
Definition: sbxarray.cxx:87
SbxFlagBits GetFlags() const
Definition: sbxcore.hxx:105
SbxArray * GetProperties()
Definition: sbxobj.hxx:79
OUString GetOUString() const
Definition: sbxvalue.cxx:380
bool PutDouble(double)
SbxBase * GetObject() const
Definition: sbxvar.hxx:157
SbxValues * data()
Definition: sbxvar.hxx:138
bool PutByte(sal_uInt8)
bool PutSingle(float)
bool PutBool(bool)
Definition: sbxvalue.cxx:543
sal_uInt8 GetByte() const
Definition: sbxvar.hxx:158
bool GetBool() const
Definition: sbxvar.hxx:153
bool PutInteger(sal_Int16)
sal_Int32 GetLong() const
Definition: sbxvar.hxx:142
sal_Int16 GetInteger() const
Definition: sbxvar.hxx:141
float GetSingle() const
Definition: sbxvar.hxx:149
bool PutLong(sal_Int32)
double GetDouble() const
Definition: sbxvar.hxx:150
virtual SbxDataType GetType() const override
Definition: sbxvar.cxx:321
#define ERRCODE_NONE
const char * name
const sal_uInt16 idx[]
void * p
sal_Int64 n
DECL_LISTENERMULTIPLEXER_END void SAL_CALL up(const css::awt::SpinEvent &rEvent) override
#define SAL_WARN(area, stream)
convert
int i
arr
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
dictionary props
sal_Int32 h
#define ERRCODE_BASIC_PROC_UNDEFINED
Definition: sberrors.hxx:32
#define ERRCODE_BASIC_BAD_ARGUMENT
Definition: sberrors.hxx:26
#define ERRCODE_BASIC_NOT_IMPLEMENTED
Definition: sberrors.hxx:80
#define ERRCODE_BASIC_BAD_DLL_LOAD
Definition: sberrors.hxx:64
SbxBOOL
Definition: sbxdef.hxx:215
SbxDataType
Definition: sbxdef.hxx:37
@ SbxOBJECT
Definition: sbxdef.hxx:47
@ SbxLONG
Definition: sbxdef.hxx:41
@ SbxARRAY
Definition: sbxdef.hxx:80
@ SbxBYTE
Definition: sbxdef.hxx:55
@ SbxEMPTY
Definition: sbxdef.hxx:38
@ SbxSINGLE
Definition: sbxdef.hxx:42
@ SbxSTRING
Definition: sbxdef.hxx:46
@ SbxINTEGER
Definition: sbxdef.hxx:40
@ SbxDOUBLE
Definition: sbxdef.hxx:43
Impl()=default
std::map< OUString, ::rtl::Reference< Dll > > Dlls
Definition: dllmgr-x64.cxx:710
const Impl & operator=(const Impl &)=delete
Dll * getDll(OUString const &name)
Definition: dllmgr-x64.cxx:722
Impl(const Impl &)=delete
unsigned char sal_uInt8
Any result