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