1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dllmgr.cxx,v $
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"
36 #define INCL_DOSMODULEMGR
40 #if defined( WIN ) || defined( WNT )
44 #include <tools/svwin.h>
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>
54 typedef HINSTANCE SbiDllHandle
;
55 typedef FARPROC SbiDllProc
;
57 typedef HMODULE SbiDllHandle
;
58 typedef int(*SbiDllProc
)();
60 typedef HMODULE SbiDllHandle
;
61 typedef PFN SbiDllProc
;
63 typedef void* SbiDllHandle
;
64 typedef void* SbiDllProc
;
69 #include <basic/sberrors.hxx>
73 #define WINAPI __far __pascal
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
);
83 extern float WINAPI
CallSNG( SbiDllProc
, char *stack
, short nstack
);
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);
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; }
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)
107 #if defined (WNT) && defined (MSC)
108 //#pragma optimize ("", off)
112 // ***********************************************************************
115 class ImplSbiProc
: public ByteString
119 ImplSbiProc( const ImplSbiProc
& );
122 ImplSbiProc( const ByteString
& rName
, SbiDllProc pFunc
)
123 : ByteString( rName
) { pProc
= pFunc
; }
124 SbiDllProc
GetProc() const { return pProc
; }
128 // ***********************************************************************
131 class ImplSbiDll
: public ByteString
136 ImplSbiDll( const ImplSbiDll
& );
138 ImplSbiDll( const ByteString
& rName
, SbiDllHandle hHandle
)
139 : ByteString( rName
) { hDLL
= hHandle
; }
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
);
156 SbiDllProc
ImplSbiDll::GetProc( const ByteString
& rName
) const
159 BOOL bRet
= aProcArr
.Seek_Entry( (ByteStringPtr
)&rName
, &nPos
);
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() );
199 void SbiDllMgr::FreeDll( const ByteString
& rDllName
)
202 BOOL bRet
= aDllArr
.Seek_Entry( (ByteStringPtr
)&rDllName
, &nPos
);
205 ImplSbiDll
* pDll
= (ImplSbiDll
*)aDllArr
.GetObject(nPos
);
206 FreeDllHandle( pDll
->GetHandle() );
208 aDllArr
.Remove( nPos
, 1 );
213 ImplSbiDll
* SbiDllMgr::GetDll( const ByteString
& rDllName
)
216 ImplSbiDll
* pDll
= 0;
217 BOOL bRet
= aDllArr
.Seek_Entry( (ByteStringPtr
)&rDllName
, &nPos
);
219 pDll
= (ImplSbiDll
*)aDllArr
.GetObject(nPos
);
222 SbiDllHandle hDll
= CreateDllHandle( rDllName
);
225 pDll
= new ImplSbiDll( rDllName
, hDll
);
226 aDllArr
.Insert( (ByteStringPtr
)pDll
);
232 SbiDllProc
SbiDllMgr::GetProc( ImplSbiDll
* pDll
, const ByteString
& rProcName
)
234 DBG_ASSERT(pDll
,"GetProc: No dll-ptr");
236 pProc
= pDll
->GetProc( rProcName
);
239 pProc
= GetProcAddr( pDll
->GetHandle(), rProcName
);
241 pDll
->InsertProc( rProcName
, 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");
252 ByteString
aDllName( pDllName
);
253 CheckDllName( aDllName
);
254 ImplSbiDll
* pDll
= GetDll( aDllName
);
257 SbiDllProc pProc
= GetProc( pDll
, pProcName
);
261 nSbErr
= CallProcC( pProc
, pArgs
, rResult
);
263 nSbErr
= CallProc( pProc
, pArgs
, rResult
);
266 nSbErr
= SbERR_PROC_UNDEFINED
;
269 nSbErr
= SbERR_BAD_DLL_LOAD
;
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
)
288 SbiDllHandle
SbiDllMgr::CreateDllHandle( const ByteString
& rDllName
)
299 hLib
= LoadLibrary( (const char*)rDllName
);
300 if( (ULONG
)hLib
< 32 )
304 hLib
= LoadLibrary( rDllName
.GetBuffer() );
309 nLastErr
= GetLastError();
316 if( DosLoadModule( (PSZ
) cErr
, 100, (const char*)rDllName
.GetBuffer(), &hLib
) )
322 void SbiDllMgr::FreeDllHandle( SbiDllHandle hLib
)
324 #if defined(WIN) || defined(WNT)
326 FreeLibrary ((HINSTANCE
) hLib
);
329 DosFreeModule( (HMODULE
) hLib
);
335 SbiDllProc
SbiDllMgr::GetProcAddr(SbiDllHandle hLib
, const ByteString
& rProcName
)
337 char buf1
[128] = "";
338 char buf2
[128] = "";
340 SbiDllProc pProc
= 0;
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
, '#' );
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)
362 pProc
= (SbiDllProc
)GetProcAddress( hLib
, (char*)(long) nOrd
);
365 // 2. mit Parametern:
366 pProc
= (SbiDllProc
)GetProcAddress ( hLib
, rProcName
.GetBuffer() );
369 pProc
= (SbiDllProc
)GetProcAddress( hLib
, buf1
);
370 // 4. der Name mit Underline vorweg:
372 pProc
= (SbiDllProc
)GetProcAddress( hLib
, buf2
);
378 // 1. Ordinal oder mit Parametern:
379 rc
= DosQueryProcAddr( hLib
, nOrd
, pp
= (char*)rProcName
.GetBuffer(), &pProc
);
382 rc
= DosQueryProcAddr( hLib
, 0, pp
= (PSZ
)buf1
, &pProc
);
383 // 3. der Name mit Underline vorweg:
385 rc
= DosQueryProcAddr( hLib
, 0, pp
= (PSZ
)buf2
, &pProc
);
390 // 16-bit oder 32-bit?
392 if( DosQueryProcType( hLib
, nOrd
, pp
, &nInfo
) )
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
;
411 char* pStack
= (char*)CreateStack( pArgs
, nSize
);
412 switch( rResult
.GetType() )
415 nInt16
= CallINT(pProc
, pStack
, (short)nSize
);
416 rResult
.PutInteger( nInt16
);
421 nInt16
= (INT16
)CallINT(pProc
, pStack
, (short)nSize
);
422 rResult
.PutUShort( (USHORT
)nInt16
);
426 nInt16
= (INT16
)CallINT(pProc
, pStack
, (short)nSize
);
427 rResult
.PutErr( (USHORT
)nInt16
);
431 nInt
= CallINT(pProc
, pStack
, (short)nSize
);
432 rResult
.PutInt( nInt
);
436 nInt32
= CallLNG(pProc
, pStack
, (short)nSize
);
437 rResult
.PutLong( nInt32
);
441 nInt32
= CallINT(pProc
, pStack
, (short)nSize
);
442 rResult
.PutULong( (ULONG
)nInt32
);
448 float nSingle
= CallSNG(pProc
, pStack
, (short)nSize
);
449 rResult
.PutSingle( nSingle
);
458 nDouble
= CallDBL(pProc
, pStack
, (short)nSize
);
459 rResult
.PutDouble( nDouble
);
463 nDouble
= CallDBL(pProc
, pStack
, (short)nSize
);
464 rResult
.PutDate( nDouble
);
470 nInt16
= CallINT(pProc
, pStack
, (short)nSize
);
471 rResult
.PutByte( (BYTE
)nInt16
);
476 pStr
= CallSTR(pProc
, pStack
, (short)nSize
);
477 rResult
.PutString( String::CreateFromAscii( pStr
) );
482 nInt16
= CallINT(pProc
, pStack
, (short)nSize
);
483 // Rueckgabe nur zulaessig, wenn variant!
484 if( !rResult
.IsFixed() )
485 rResult
.PutInteger( nInt16
);
492 CallINT(pProc
, pStack
, (short)nSize
);
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
512 ByteString
aByteStr( (char*)pVar
->GetUserData() );
513 String
aStr( aByteStr
, gsl_getSystemTextEncoding() );
514 pVar
->PutString( aStr
);
519 delete (char*)(pVar
->GetUserData());
520 pVar
->SetUserData( 0 );
527 SbError
SbiDllMgr::CallProcC( SbiDllProc pProc
, SbxArray
* pArgs
,
528 SbxVariable
& rResult
)
534 DBG_ERROR("C calling convention not supported");
535 return SbERR_BAD_ARGUMENT
;
538 void* SbiDllMgr::CreateStack( SbxArray
* pArgs
, USHORT
& rSize
)
545 char* pStack
= new char[ 2048 ];
547 USHORT nCount
= pArgs
->Count();
548 // erstes Element ueberspringen
550 for( USHORT nCur
= 1; nCur
< nCount
; nCur
++ )
552 // unter 16-Bit Windows anders rum (OS/2 ?????)
553 for( USHORT nCur
= nCount
-1; nCur
>= 1; nCur
-- )
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() )
573 *((void**)pTop
) = (void*)&(pVar
->aData
);
574 pTop
+= sizeof( void* );
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* );
609 switch( pVar
->GetType() )
615 *((INT16
*)pTop
) = pVar
->GetInteger();
616 pTop
+= sizeof( INT16
);
621 *((INT32
*)pTop
) = pVar
->GetLong();
622 pTop
+= sizeof( INT32
);
626 *((float*)pTop
) = pVar
->GetSingle();
627 pTop
+= sizeof( float );
631 *((double*)pTop
) = pVar
->GetDouble();
632 pTop
+= sizeof( double );
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* );
652 *((BYTE
*)pTop
) = pVar
->GetByte();
653 pTop
+= sizeof( BYTE
);
668 rSize
= (USHORT
)((ULONG
)pTop
- (ULONG
)pStack
);