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