merge the formfield patch from ooo-build
[ooovba.git] / basic / source / runtime / dllmgr.cxx
blob3e85432da82b2e56538e9f34debf42e57ae5410f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dllmgr.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
34 #include <stdlib.h>
35 #ifdef OS2
36 #define INCL_DOSMODULEMGR
37 #include <svpm.h>
38 #endif
40 #if defined( WIN ) || defined( WNT )
41 #ifndef _SVWIN_H
42 #undef WB_LEFT
43 #undef WB_RIGHT
44 #include <tools/svwin.h>
45 #endif
46 #endif
47 #include <tools/debug.hxx>
48 #include <tools/string.hxx>
49 #include <tools/errcode.hxx>
50 #include <basic/sbxvar.hxx>
51 #include <basic/sbx.hxx>
53 #if defined(WIN)
54 typedef HINSTANCE SbiDllHandle;
55 typedef FARPROC SbiDllProc;
56 #elif defined(WNT)
57 typedef HMODULE SbiDllHandle;
58 typedef int(*SbiDllProc)();
59 #elif defined(OS2)
60 typedef HMODULE SbiDllHandle;
61 typedef PFN SbiDllProc;
62 #else
63 typedef void* SbiDllHandle;
64 typedef void* SbiDllProc;
65 #endif
67 #define _DLLMGR_CXX
68 #include "dllmgr.hxx"
69 #include <basic/sberrors.hxx>
71 #ifndef WINAPI
72 #ifdef WNT
73 #define WINAPI __far __pascal
74 #endif
75 #endif
77 extern "C" {
78 #if defined(INTEL) && (defined(WIN) || defined(WNT))
80 extern INT16 WINAPI CallINT( SbiDllProc, char *stack, short nstack);
81 extern INT32 WINAPI CallLNG( SbiDllProc, char *stack, short nstack);
82 #ifndef WNT
83 extern float WINAPI CallSNG( SbiDllProc, char *stack, short nstack);
84 #endif
85 extern double WINAPI CallDBL( SbiDllProc, char *stack, short nstack);
86 extern char* WINAPI CallSTR( SbiDllProc, char *stack, short nstack);
87 // extern CallFIX( SbiDllProc, char *stack, short nstack);
89 #else
91 INT16 CallINT( SbiDllProc, char *, short ) { return 0; }
92 INT32 CallLNG( SbiDllProc, char *, short ) { return 0; }
93 float CallSNG( SbiDllProc, char *, short ) { return 0; }
94 double CallDBL( SbiDllProc, char *, short) { return 0; }
95 char* CallSTR( SbiDllProc, char *, short ) { return 0; }
96 #endif
99 SV_IMPL_OP_PTRARR_SORT(ImplDllArr,ByteStringPtr)
101 /* mit Optimierung An stuerzt unter Win95 folgendes Makro ab:
102 declare Sub MessageBeep Lib "user32" (ByVal long)
103 sub main
104 MessageBeep( 1 )
105 end sub
107 #if defined (WNT) && defined (MSC)
108 //#pragma optimize ("", off)
109 #endif
112 // ***********************************************************************
115 class ImplSbiProc : public ByteString
117 SbiDllProc pProc;
118 ImplSbiProc();
119 ImplSbiProc( const ImplSbiProc& );
121 public:
122 ImplSbiProc( const ByteString& rName, SbiDllProc pFunc )
123 : ByteString( rName ) { pProc = pFunc; }
124 SbiDllProc GetProc() const { return pProc; }
128 // ***********************************************************************
131 class ImplSbiDll : public ByteString
133 ImplDllArr aProcArr;
134 SbiDllHandle hDLL;
136 ImplSbiDll( const ImplSbiDll& );
137 public:
138 ImplSbiDll( const ByteString& rName, SbiDllHandle hHandle )
139 : ByteString( rName ) { hDLL = hHandle; }
140 ~ImplSbiDll();
141 SbiDllHandle GetHandle() const { return hDLL; }
142 SbiDllProc GetProc( const ByteString& rName ) const;
143 void InsertProc( const ByteString& rName, SbiDllProc pProc );
146 ImplSbiDll::~ImplSbiDll()
148 USHORT nCount = aProcArr.Count();
149 for( USHORT nCur = 0; nCur < nCount; nCur++ )
151 ImplSbiProc* pProc = (ImplSbiProc*)aProcArr.GetObject( nCur );
152 delete pProc;
156 SbiDllProc ImplSbiDll::GetProc( const ByteString& rName ) const
158 USHORT nPos;
159 BOOL bRet = aProcArr.Seek_Entry( (ByteStringPtr)&rName, &nPos );
160 if( bRet )
162 ImplSbiProc* pImplProc = (ImplSbiProc*)aProcArr.GetObject(nPos);
163 return pImplProc->GetProc();
165 return (SbiDllProc)0;
168 void ImplSbiDll::InsertProc( const ByteString& rName, SbiDllProc pProc )
170 DBG_ASSERT(aProcArr.Seek_Entry((ByteStringPtr)&rName,0)==0,"InsertProc: Already in table");
171 ImplSbiProc* pImplProc = new ImplSbiProc( rName, pProc );
172 aProcArr.Insert( (ByteStringPtr)pImplProc );
177 // ***********************************************************************
180 SbiDllMgr::SbiDllMgr( const SbiDllMgr& )
184 SbiDllMgr::SbiDllMgr()
188 SbiDllMgr::~SbiDllMgr()
190 USHORT nCount = aDllArr.Count();
191 for( USHORT nCur = 0; nCur < nCount; nCur++ )
193 ImplSbiDll* pDll = (ImplSbiDll*)aDllArr.GetObject( nCur );
194 FreeDllHandle( pDll->GetHandle() );
195 delete pDll;
199 void SbiDllMgr::FreeDll( const ByteString& rDllName )
201 USHORT nPos;
202 BOOL bRet = aDllArr.Seek_Entry( (ByteStringPtr)&rDllName, &nPos );
203 if( bRet )
205 ImplSbiDll* pDll = (ImplSbiDll*)aDllArr.GetObject(nPos);
206 FreeDllHandle( pDll->GetHandle() );
207 delete pDll;
208 aDllArr.Remove( nPos, 1 );
213 ImplSbiDll* SbiDllMgr::GetDll( const ByteString& rDllName )
215 USHORT nPos;
216 ImplSbiDll* pDll = 0;
217 BOOL bRet = aDllArr.Seek_Entry( (ByteStringPtr)&rDllName, &nPos );
218 if( bRet )
219 pDll = (ImplSbiDll*)aDllArr.GetObject(nPos);
220 else
222 SbiDllHandle hDll = CreateDllHandle( rDllName );
223 if( hDll )
225 pDll = new ImplSbiDll( rDllName, hDll );
226 aDllArr.Insert( (ByteStringPtr)pDll );
229 return pDll;
232 SbiDllProc SbiDllMgr::GetProc( ImplSbiDll* pDll, const ByteString& rProcName )
234 DBG_ASSERT(pDll,"GetProc: No dll-ptr");
235 SbiDllProc pProc;
236 pProc = pDll->GetProc( rProcName );
237 if( !pProc )
239 pProc = GetProcAddr( pDll->GetHandle(), rProcName );
240 if( pProc )
241 pDll->InsertProc( rProcName, pProc );
243 return pProc;
247 SbError SbiDllMgr::Call( const char* pProcName, const char* pDllName,
248 SbxArray* pArgs, SbxVariable& rResult, BOOL bCDecl )
250 DBG_ASSERT(pProcName&&pDllName,"Call: Bad parms");
251 SbError nSbErr = 0;
252 ByteString aDllName( pDllName );
253 CheckDllName( aDllName );
254 ImplSbiDll* pDll = GetDll( aDllName );
255 if( pDll )
257 SbiDllProc pProc = GetProc( pDll, pProcName );
258 if( pProc )
260 if( bCDecl )
261 nSbErr = CallProcC( pProc, pArgs, rResult );
262 else
263 nSbErr = CallProc( pProc, pArgs, rResult );
265 else
266 nSbErr = SbERR_PROC_UNDEFINED;
268 else
269 nSbErr = SbERR_BAD_DLL_LOAD;
270 return nSbErr;
273 // ***********************************************************************
274 // ******************* abhaengige Implementationen ***********************
275 // ***********************************************************************
277 void SbiDllMgr::CheckDllName( ByteString& rDllName )
279 #if defined(WIN) || defined(WNT) || defined(OS2)
280 if( rDllName.Search('.') == STRING_NOTFOUND )
281 rDllName += ".DLL";
282 #else
283 (void)rDllName;
284 #endif
288 SbiDllHandle SbiDllMgr::CreateDllHandle( const ByteString& rDllName )
290 (void)rDllName;
292 #if defined(UNX)
293 SbiDllHandle hLib=0;
294 #else
295 SbiDllHandle hLib;
296 #endif
298 #if defined(WIN)
299 hLib = LoadLibrary( (const char*)rDllName );
300 if( (ULONG)hLib < 32 )
301 hLib = 0;
303 #elif defined(WNT)
304 hLib = LoadLibrary( rDllName.GetBuffer() );
305 if( !(ULONG)hLib )
307 #ifdef DBG_UTIL
308 ULONG nLastErr;
309 nLastErr = GetLastError();
310 #endif
311 hLib = 0;
314 #elif defined(OS2)
315 char cErr[ 100 ];
316 if( DosLoadModule( (PSZ) cErr, 100, (const char*)rDllName.GetBuffer(), &hLib ) )
317 hLib = 0;
318 #endif
319 return hLib;
322 void SbiDllMgr::FreeDllHandle( SbiDllHandle hLib )
324 #if defined(WIN) || defined(WNT)
325 if( hLib )
326 FreeLibrary ((HINSTANCE) hLib);
327 #elif defined(OS2)
328 if( hLib )
329 DosFreeModule( (HMODULE) hLib );
330 #else
331 (void)hLib;
332 #endif
335 SbiDllProc SbiDllMgr::GetProcAddr(SbiDllHandle hLib, const ByteString& rProcName)
337 char buf1 [128] = "";
338 char buf2 [128] = "";
340 SbiDllProc pProc = 0;
341 int nOrd = 0;
343 // Ordinal?
344 if( rProcName.GetBuffer()[0] == '@' )
345 nOrd = atoi( rProcName.GetBuffer()+1 );
347 // Moegliche Parameter weg:
348 DBG_ASSERT( sizeof(buf1) > rProcName.Len(),
349 "SbiDllMgr::GetProcAddr: buffer to small!" );
350 strncpy( buf1, rProcName.GetBuffer(), sizeof(buf1)-1 );
351 char *p = strchr( buf1, '#' );
352 if( p )
353 *p = 0;
355 DBG_ASSERT( sizeof(buf2) > strlen(buf1) + 1,
356 "SbiDllMgr::GetProcAddr: buffer to small!" );
357 strncpy( buf2, "_", sizeof(buf2)-1 );
358 strncat( buf2, buf1, sizeof(buf2)-1-strlen(buf2) );
360 #if defined(WIN) || defined(WNT)
361 if( nOrd > 0 )
362 pProc = (SbiDllProc)GetProcAddress( hLib, (char*)(long) nOrd );
363 else
365 // 2. mit Parametern:
366 pProc = (SbiDllProc)GetProcAddress ( hLib, rProcName.GetBuffer() );
367 // 3. nur der Name:
368 if (!pProc)
369 pProc = (SbiDllProc)GetProcAddress( hLib, buf1 );
370 // 4. der Name mit Underline vorweg:
371 if( !pProc )
372 pProc = (SbiDllProc)GetProcAddress( hLib, buf2 );
375 #elif defined(OS2)
376 PSZ pp;
377 APIRET rc;
378 // 1. Ordinal oder mit Parametern:
379 rc = DosQueryProcAddr( hLib, nOrd, pp = (char*)rProcName.GetBuffer(), &pProc );
380 // 2. nur der Name:
381 if( rc )
382 rc = DosQueryProcAddr( hLib, 0, pp = (PSZ)buf1, &pProc );
383 // 3. der Name mit Underline vorweg:
384 if( rc )
385 rc = DosQueryProcAddr( hLib, 0, pp = (PSZ)buf2, &pProc );
386 if( rc )
387 pProc = NULL;
388 else
390 // 16-bit oder 32-bit?
391 ULONG nInfo = 0;
392 if( DosQueryProcType( hLib, nOrd, pp, &nInfo ) )
393 nInfo = 0;;
395 #else
396 (void)hLib;
397 #endif
398 return pProc;
401 SbError SbiDllMgr::CallProc( SbiDllProc pProc, SbxArray* pArgs,
402 SbxVariable& rResult )
404 // ByteString aStr("Calling DLL at ");
405 // aStr += (ULONG)pProc;
406 // InfoBox( 0, aStr ).Execute();
407 INT16 nInt16; int nInt; INT32 nInt32; double nDouble;
408 char* pStr;
410 USHORT nSize;
411 char* pStack = (char*)CreateStack( pArgs, nSize );
412 switch( rResult.GetType() )
414 case SbxINTEGER:
415 nInt16 = CallINT(pProc, pStack, (short)nSize );
416 rResult.PutInteger( nInt16 );
417 break;
419 case SbxUINT:
420 case SbxUSHORT:
421 nInt16 = (INT16)CallINT(pProc, pStack, (short)nSize );
422 rResult.PutUShort( (USHORT)nInt16 );
423 break;
425 case SbxERROR:
426 nInt16 = (INT16)CallINT(pProc, pStack, (short)nSize );
427 rResult.PutErr( (USHORT)nInt16 );
428 break;
430 case SbxINT:
431 nInt = CallINT(pProc, pStack, (short)nSize );
432 rResult.PutInt( nInt );
433 break;
435 case SbxLONG:
436 nInt32 = CallLNG(pProc, pStack, (short)nSize );
437 rResult.PutLong( nInt32 );
438 break;
440 case SbxULONG:
441 nInt32 = CallINT(pProc, pStack, (short)nSize );
442 rResult.PutULong( (ULONG)nInt32 );
443 break;
445 #ifndef WNT
446 case SbxSINGLE:
448 float nSingle = CallSNG(pProc, pStack, (short)nSize );
449 rResult.PutSingle( nSingle );
450 break;
452 #endif
454 case SbxDOUBLE:
455 #ifdef WNT
456 case SbxSINGLE:
457 #endif
458 nDouble = CallDBL(pProc, pStack, (short)nSize );
459 rResult.PutDouble( nDouble );
460 break;
462 case SbxDATE:
463 nDouble = CallDBL(pProc, pStack, (short)nSize );
464 rResult.PutDate( nDouble );
465 break;
467 case SbxCHAR:
468 case SbxBYTE:
469 case SbxBOOL:
470 nInt16 = CallINT(pProc, pStack, (short)nSize );
471 rResult.PutByte( (BYTE)nInt16 );
472 break;
474 case SbxSTRING:
475 case SbxLPSTR:
476 pStr = CallSTR(pProc, pStack, (short)nSize );
477 rResult.PutString( String::CreateFromAscii( pStr ) );
478 break;
480 case SbxNULL:
481 case SbxEMPTY:
482 nInt16 = CallINT(pProc, pStack, (short)nSize );
483 // Rueckgabe nur zulaessig, wenn variant!
484 if( !rResult.IsFixed() )
485 rResult.PutInteger( nInt16 );
486 break;
488 case SbxCURRENCY:
489 case SbxOBJECT:
490 case SbxDATAOBJECT:
491 default:
492 CallINT(pProc, pStack, (short)nSize );
493 break;
495 delete [] pStack;
497 if( pArgs )
499 // die Laengen aller uebergebenen Strings anpassen
500 USHORT nCount = pArgs->Count();
501 for( USHORT nCur = 1; nCur < nCount; nCur++ )
503 SbxVariable* pVar = pArgs->Get( nCur );
504 BOOL bIsString = ( pVar->GetType() == SbxSTRING ) ||
505 ( pVar->GetType() == SbxLPSTR );
507 if( pVar->GetFlags() & SBX_REFERENCE )
509 pVar->ResetFlag( SBX_REFERENCE ); // Sbx moechte es so
510 if( bIsString )
512 ByteString aByteStr( (char*)pVar->GetUserData() );
513 String aStr( aByteStr, gsl_getSystemTextEncoding() );
514 pVar->PutString( aStr );
517 if( bIsString )
519 delete (char*)(pVar->GetUserData());
520 pVar->SetUserData( 0 );
524 return 0;
527 SbError SbiDllMgr::CallProcC( SbiDllProc pProc, SbxArray* pArgs,
528 SbxVariable& rResult )
530 (void)pProc;
531 (void)pArgs;
532 (void)rResult;
534 DBG_ERROR("C calling convention not supported");
535 return SbERR_BAD_ARGUMENT;
538 void* SbiDllMgr::CreateStack( SbxArray* pArgs, USHORT& rSize )
540 if( !pArgs )
542 rSize = 0;
543 return 0;
545 char* pStack = new char[ 2048 ];
546 char* pTop = pStack;
547 USHORT nCount = pArgs->Count();
548 // erstes Element ueberspringen
549 #ifndef WIN
550 for( USHORT nCur = 1; nCur < nCount; nCur++ )
551 #else
552 // unter 16-Bit Windows anders rum (OS/2 ?????)
553 for( USHORT nCur = nCount-1; nCur >= 1; nCur-- )
554 #endif
556 SbxVariable* pVar = pArgs->Get( nCur );
557 // AB 22.1.1996, Referenz
558 if( pVar->GetFlags() & SBX_REFERENCE ) // Es ist eine Referenz
560 switch( pVar->GetType() )
562 case SbxINTEGER:
563 case SbxUINT:
564 case SbxINT:
565 case SbxUSHORT:
566 case SbxLONG:
567 case SbxULONG:
568 case SbxSINGLE:
569 case SbxDOUBLE:
570 case SbxCHAR:
571 case SbxBYTE:
572 case SbxBOOL:
573 *((void**)pTop) = (void*)&(pVar->aData);
574 pTop += sizeof( void* );
575 break;
577 case SbxSTRING:
578 case SbxLPSTR:
580 USHORT nLen = 256;
581 ByteString rStr( pVar->GetString(), gsl_getSystemTextEncoding() );
582 if( rStr.Len() > 255 )
583 nLen = rStr.Len() + 1;
585 char* pStr = new char[ nLen ];
586 strcpy( pStr, rStr.GetBuffer() ); // #100211# - checked
587 // ist nicht so sauber, aber wir sparen ein Pointerarray
588 DBG_ASSERT(sizeof(UINT32)>=sizeof(char*),"Gleich krachts im Basic");
589 pVar->SetUserData( (sal_uIntPtr)pStr );
590 *((const char**)pTop) = pStr;
591 pTop += sizeof( char* );
593 break;
595 case SbxNULL:
596 case SbxEMPTY:
597 case SbxERROR:
598 case SbxDATE:
599 case SbxCURRENCY:
600 case SbxOBJECT:
601 case SbxDATAOBJECT:
602 default:
603 break;
606 else
608 // ByVal
609 switch( pVar->GetType() )
611 case SbxINTEGER:
612 case SbxUINT:
613 case SbxINT:
614 case SbxUSHORT:
615 *((INT16*)pTop) = pVar->GetInteger();
616 pTop += sizeof( INT16 );
617 break;
619 case SbxLONG:
620 case SbxULONG:
621 *((INT32*)pTop) = pVar->GetLong();
622 pTop += sizeof( INT32 );
623 break;
625 case SbxSINGLE:
626 *((float*)pTop) = pVar->GetSingle();
627 pTop += sizeof( float );
628 break;
630 case SbxDOUBLE:
631 *((double*)pTop) = pVar->GetDouble();
632 pTop += sizeof( double );
633 break;
635 case SbxSTRING:
636 case SbxLPSTR:
638 char* pStr = new char[ pVar->GetString().Len() + 1 ];
639 ByteString aByteStr( pVar->GetString(), gsl_getSystemTextEncoding() );
640 strcpy( pStr, aByteStr.GetBuffer() ); // #100211# - checked
641 // ist nicht so sauber, aber wir sparen ein Pointerarray
642 DBG_ASSERT(sizeof(UINT32)>=sizeof(char*),"Gleich krachts im Basic");
643 pVar->SetUserData( (sal_uIntPtr)pStr );
644 *((const char**)pTop) = pStr;
645 pTop += sizeof( char* );
647 break;
649 case SbxCHAR:
650 case SbxBYTE:
651 case SbxBOOL:
652 *((BYTE*)pTop) = pVar->GetByte();
653 pTop += sizeof( BYTE );
654 break;
656 case SbxNULL:
657 case SbxEMPTY:
658 case SbxERROR:
659 case SbxDATE:
660 case SbxCURRENCY:
661 case SbxOBJECT:
662 case SbxDATAOBJECT:
663 default:
664 break;
668 rSize = (USHORT)((ULONG)pTop - (ULONG)pStack);
669 return pStack;