diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 14:29:57 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2000-09-18 14:29:57 +0000 |
commit | b525a3115f54576017a576ff842dede5e2e3545d (patch) | |
tree | c534b95a9e572b63896467624293a5ca1887d3a3 /bridges/source/cpp_uno/msvc_win32_intel | |
parent | 9399c662f36c385b0c705eb34e636a9aec450282 (diff) |
initial import
Diffstat (limited to 'bridges/source/cpp_uno/msvc_win32_intel')
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx | 563 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/except.cxx | 538 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/makefile.mk | 119 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/msci.hxx | 90 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx | 494 |
5 files changed, 1804 insertions, 0 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx new file mode 100644 index 000000000000..8b7ddf39098b --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx @@ -0,0 +1,563 @@ +/************************************************************************* + * + * $RCSfile: cpp2uno.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:28:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define LEAK_STATIC_DATA +// #define TRACE(x) OSL_TRACE(x) +#define TRACE(x) + +#pragma warning( disable : 4237 ) +#include <stl/list> +#include <malloc.h> +#ifndef _RTL_ALLOC_H_ +#include <rtl/alloc.h> +#endif +#ifndef _RTL_STRING_HXX_ +#include <rtl/string.hxx> +#endif + +#ifndef _TYPELIB_TYPEDESCRIPTION_HXX_ +#include <typelib/typedescription.hxx> +#endif +#ifndef _UNO_DATA_H_ +#include <uno/data.h> +#endif +#ifndef _BRIDGES_CPP_UNO_BRIDGE_HXX_ +#include <bridges/cpp_uno/bridge.hxx> +#endif +#ifndef _BRIDGES_CPP_UNO_TYPE_MISC_HXX_ +#include <bridges/cpp_uno/type_misc.hxx> +#endif + +#include "msci.hxx" + +using namespace std; +using namespace rtl; +using namespace osl; +using namespace com::sun::star::uno; + + +namespace CPPU_CURRENT_NAMESPACE +{ + +//================================================================================================== +static inline typelib_TypeClass cpp2uno_call( + cppu_cppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: ret, this, [complex return ptr], params + char * pCppStack = (char *)(pCallStack +2); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (cppu_isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + + pUnoReturn = (cppu_relatesToInterface( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + + // stack space + OSL_ENSHURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && cppu_isSimpleType( pParamTypeDescr )) // value + { + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndizes[nTempIndizes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (cppu_relatesToInterface( pParamTypeDescr )) + { + uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + &pThis->pBridge->aCpp2Uno ); + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->pUnoI->pDispatcher)( pThis->pUnoI, pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occured... + if (pUnoExc) + { + // destruct temporary in/inout params + while (nTempIndizes--) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + + msci_raiseException( &aUnoExc, &pThis->pBridge->aUno2Cpp ); // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occured... + { + // temporary params + while (nTempIndizes--) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + &pThis->pBridge->aUno2Cpp ); + } + // destroy temp uno param + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr, + &pThis->pBridge->aUno2Cpp ); + // destroy temp uno return + uno_destructData( pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + +//================================================================================================== +static typelib_TypeClass __cdecl cpp_mediate( + void ** pCallStack, sal_Int32 nVtableCall, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + OSL_ENSHURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" ); + + // pCallStack: ret adr, this, [ret *], params + // _this_ ptr is patched cppu_XInterfaceProxy object + cppu_cppInterfaceProxy * pThis = static_cast< cppu_cppInterfaceProxy * >( + reinterpret_cast< XInterface * >( pCallStack[1] ) ); + + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + OSL_ENSHURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + if (nVtableCall >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("illegal vtable index!") ), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nVtableCall]; + OSL_ENSHURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nVtableCall) + { + // is GET method + eRet = cpp2uno_call( + pThis, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pThis, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nVtableCall) + { + // standard XInterface vtable calls + case 1: // acquire() + pThis->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pThis->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() ); + OSL_ASSERT( pTD ); + + XInterface * pInterface = 0; + (*pThis->pBridge->pCppEnv->getRegisteredInterface)( + pThis->pBridge->pCppEnv, + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + uno_any_construct( reinterpret_cast< uno_Any * >( pCallStack[2] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = pCallStack[2]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pThis, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no member description found!") ), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +//================================================================================================== +class MediateVtables +{ + //---------------------------------------------------------------------------------------------- + struct DefaultRTTIEntry + { + sal_Int32 _n0, _n1, _n2; + type_info * _pRTTI; + + DefaultRTTIEntry() + : _n0( 0 ) + , _n1( 0 ) + , _n2( 0 ) + { _pRTTI = msci_getRTTI( "com.sun.star.uno.XInterface" ); } + }; + + typedef list<void * > t_pSpacesList; + + Mutex _aMutex; + t_pSpacesList _aSpaces; + + sal_Int32 _nCurrent; + const void * _pCurrent; + +public: + const void * getMediateVtable( sal_Int32 nSize ); + + MediateVtables( sal_Int32 nSize = 256 ) + : _nCurrent( 0 ) + , _pCurrent( 0 ) + { getMediateVtable( nSize ); } + ~MediateVtables(); +}; +//__________________________________________________________________________________________________ +MediateVtables::~MediateVtables() +{ + TRACE( "> calling ~MediateVtables(): freeing mediate vtables... <\n" ); + + MutexGuard aGuard( _aMutex ); + + // this MUST be the absolute last one which is called! + for ( t_pSpacesList::iterator iPos( _aSpaces.begin() ); iPos != _aSpaces.end(); ++iPos ) + { + rtl_freeMemory( *iPos ); + } +} + +//================================================================================================== +/** + * is called on incoming vtable calls + * (called by asm snippets) + */ +static __declspec(naked) void __cdecl cpp_vtable_call(void) +{ +__asm + { + sub esp, 8 // space for immediate return type + push esp + push eax // vtable index + mov eax, esp + add eax, 16 + push eax // original stack ptr + + call cpp_mediate + add esp, 12 + + cmp eax, typelib_TypeClass_FLOAT + je Lfloat + cmp eax, typelib_TypeClass_DOUBLE + je Ldouble + cmp eax, typelib_TypeClass_HYPER + je Lhyper + cmp eax, typelib_TypeClass_UNSIGNED_HYPER + je Lhyper + // rest is eax + pop eax + add esp, 4 + ret +Lhyper: + pop eax + pop edx + ret +Lfloat: + fld dword ptr [esp] + add esp, 8 + ret +Ldouble: + fld qword ptr [esp] + add esp, 8 + ret + } +} + +//__________________________________________________________________________________________________ +const void * MediateVtables::getMediateVtable( sal_Int32 nSize ) +{ + if (_nCurrent < nSize) + { + TRACE( "> need larger vtable! <\n" ); + + // dont ever guard each time, so ask twice when guarded + MutexGuard aGuard( _aMutex ); + if (_nCurrent < nSize) + { + nSize = (nSize +1) & 0xfffffffe; + char * pSpace = (char *)rtl_allocateMemory( ((1+nSize)*sizeof(void *)) + (nSize*12) ); + _aSpaces.push_back( pSpace ); + + // on index -1 write default rtti entry + static DefaultRTTIEntry s_defaultInterfaceRTTI; + *(void **)pSpace = &s_defaultInterfaceRTTI; + + void ** pvft = (void **)(pSpace + sizeof(void *)); + char * pCode = pSpace + ((1+nSize)*sizeof(void *)); + + // setup vft and code + for ( sal_Int32 nPos = 0; nPos < nSize; ++nPos ) + { + unsigned char * codeSnip = (unsigned char *)pCode + (nPos *12); + pvft[nPos] = codeSnip; + + /** + * vtable calls detonate on these code snippets + */ + // mov eax, nPos + *codeSnip++ = 0xb8; + *(sal_Int32 *)codeSnip = nPos; + codeSnip += sizeof(sal_Int32); + // jmp rel32 cpp_vtable_call + *codeSnip++ = 0xe9; + *(sal_Int32 *)codeSnip = ((unsigned char *)cpp_vtable_call) - codeSnip - sizeof(sal_Int32); + } + _pCurrent = pSpace + sizeof(void *); + _nCurrent = nSize; + } + } + return _pCurrent; +} + +//================================================================================================== +void SAL_CALL cppu_cppInterfaceProxy_patchVtable( + XInterface * pCppI, typelib_InterfaceTypeDescription * pTypeDescr ) +{ + static MediateVtables * s_pMediateVtables = 0; + if (! s_pMediateVtables) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pMediateVtables) + { +#ifdef LEAK_STATIC_DATA + s_pMediateVtables = new MediateVtables(); +#else + static MediateVtables s_aMediateVtables; + s_pMediateVtables = &s_aMediateVtables; +#endif + } + } + *(const void **)pCppI = s_pMediateVtables->getMediateVtable( + pTypeDescr->nMapFunctionIndexToMemberIndex ); +} + +} + +//################################################################################################## +extern "C" SAL_DLLEXPORT void SAL_CALL uno_initEnvironment( uno_Environment * pCppEnv ) +{ + CPPU_CURRENT_NAMESPACE::cppu_cppenv_initEnvironment( pCppEnv ); +} +//################################################################################################## +extern "C" SAL_DLLEXPORT void SAL_CALL uno_ext_getMapping( + uno_Mapping ** ppMapping, uno_Environment * pFrom, uno_Environment * pTo ) +{ + CPPU_CURRENT_NAMESPACE::cppu_ext_getMapping( ppMapping, pFrom, pTo ); +} + diff --git a/bridges/source/cpp_uno/msvc_win32_intel/except.cxx b/bridges/source/cpp_uno/msvc_win32_intel/except.cxx new file mode 100644 index 000000000000..9bab2d6bd5d5 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/except.cxx @@ -0,0 +1,538 @@ +/************************************************************************* + * + * $RCSfile: except.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:28:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#define LEAK_STATIC_DATA +#define TRACE(x) OSL_TRACE(x) +// #define TRACE(x) + +#pragma warning( disable : 4237 ) +#include <stl/hash_map> +#include <sal/config.h> +#include <malloc.h> +#include <new.h> +#include <typeinfo.h> +#ifndef _RTL_ALLOC_H_ +#include <rtl/alloc.h> +#endif + +#ifndef _RTL_STRBUF_HXX_ +#include <rtl/strbuf.hxx> +#endif + +#ifndef _BRIDGES_CPP_UNO_BRIDGE_HXX_ +#include <bridges/cpp_uno/bridge.hxx> +#endif +#ifndef _COM_SUN_STAR_UNO_ANY_HXX_ +#include <com/sun/star/uno/Any.hxx> +#endif + +#include "msci.hxx" + +#pragma pack(push, 8) + +using namespace com::sun::star::uno; +using namespace std; +using namespace osl; +using namespace rtl; + +namespace CPPU_CURRENT_NAMESPACE +{ + +//================================================================================================== +static inline OString toUNOname( const OString & rRTTIname ) +{ + OStringBuffer aRet( 64 ); + OString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@ + for ( sal_Int32 nToken = aStr.getTokenCount( '@' ); nToken--; ) + { + aRet.append( aStr.getToken( nToken, '@' ) ); + if (nToken) + aRet.append( '.' ); + } + return aRet.makeStringAndClear(); +} +//================================================================================================== +static inline OString toRTTIname( const OString & rUNOname ) +{ + OStringBuffer aRet( 64 ); + aRet.append( RTL_CONSTASCII_STRINGPARAM(".?AV") ); // class ".?AV"; struct ".?AU" + for ( sal_Int32 nToken = rUNOname.getTokenCount( '.' ); nToken--; ) + { + aRet.append( rUNOname.getToken( nToken, '.' ) ); + aRet.append( '@' ); + } + aRet.append( '@' ); + return aRet.makeStringAndClear(); +} + + +//################################################################################################## +//#### RTTI simulation ############################################################################# +//################################################################################################## + + +//================================================================================================== +struct FctOStringHash : public unary_function< const OString &, size_t > +{ + size_t operator()( const OString & rStr ) const + { return rStr.hashCode(); } +}; +typedef hash_map< OString, void *, FctOStringHash, equal_to< OString > > t_string2PtrMap; + +//================================================================================================== +class RTTInfos +{ + Mutex _aMutex; + t_string2PtrMap _allRTTI; + + static OString toRawName( const OString & rUNOname ); +public: + type_info * getRTTI( const OString & rUNOname ); + + RTTInfos(); + ~RTTInfos(); +}; + +//================================================================================================== +class __type_info +{ + friend type_info * RTTInfos::getRTTI( const OString & ); + friend sal_Int32 msci_filterCppException( LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * ); + +public: + virtual ~__type_info(); + + __type_info( void * m_data, const char * m_d_name ) + : _m_data( m_data ) + { ::strcpy( _m_d_name, m_d_name ); } + +private: + void * _m_data; + char _m_d_name[1]; +}; +//__________________________________________________________________________________________________ +__type_info::~__type_info() +{ +} +//__________________________________________________________________________________________________ +type_info * RTTInfos::getRTTI( const OString & rUNOname ) +{ + // a must be + OSL_ENSHURE( sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!" ); + + MutexGuard aGuard( _aMutex ); + const t_string2PtrMap::const_iterator iFind( _allRTTI.find( rUNOname ) ); + + // check if type is already available + if (iFind == _allRTTI.end()) + { + // insert new type_info + OString aRawName( toRTTIname( rUNOname ) ); + __type_info * pRTTI = new(rtl_allocateMemory( sizeof(__type_info) + aRawName.getLength() )) + __type_info( NULL, aRawName.getStr() ); + // put into map + _allRTTI[rUNOname] = pRTTI; + + return (type_info *)pRTTI; + } + else + { + return (type_info *)(*iFind).second; + } +} +//__________________________________________________________________________________________________ +RTTInfos::RTTInfos() +{ +} +//__________________________________________________________________________________________________ +RTTInfos::~RTTInfos() +{ + TRACE( "> freeing generated RTTI infos... <\n" ); + + MutexGuard aGuard( _aMutex ); + for ( t_string2PtrMap::const_iterator iPos( _allRTTI.begin() ); + iPos != _allRTTI.end(); ++iPos ) + { + __type_info * pType = (__type_info *)(*iPos).second; + pType->~__type_info(); // obsolete, but good style... + rtl_freeMemory( pType ); + } +} + + +//################################################################################################## +//#### Exception raising ########################################################################### +//################################################################################################## + + +//================================================================================================== +struct ObjectFunction +{ + char somecode[12]; + typelib_TypeDescription * _pTypeDescr; // type of object + + ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ); + ~ObjectFunction(); +}; +//__________________________________________________________________________________________________ +ObjectFunction::ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) + : _pTypeDescr( pTypeDescr ) +{ + typelib_typedescription_acquire( _pTypeDescr ); + + unsigned char * pCode = (unsigned char *)somecode; + // a must be! + OSL_ENSHURE( (void *)this == (void *)pCode, "### unexpected!" ); + + // push ObjectFunction this + *pCode++ = 0x68; + *(void **)pCode = this; + pCode += sizeof(void *); + // jmp rel32 fpFunc + *pCode++ = 0xe9; + *(sal_Int32 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int32); +} +//__________________________________________________________________________________________________ +ObjectFunction::~ObjectFunction() +{ + typelib_typedescription_release( _pTypeDescr ); +} + +//================================================================================================== +static void * __cdecl __copyConstruct( void * pExcThis, void * pSource, ObjectFunction * pThis ) +{ + uno_copyData( pExcThis, pSource, pThis->_pTypeDescr, cpp_acquire ); + return pExcThis; +} +//================================================================================================== +static void * __cdecl __destruct( void * pExcThis, ObjectFunction * pThis ) +{ + uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release ); + return pExcThis; +} + +// these are non virtual object methods; there is no this ptr on stack => ecx supplies _this_ ptr + +//================================================================================================== +static __declspec(naked) copyConstruct() +{ + __asm + { + // ObjectFunction this already on stack + push [esp+8] // source exc object this + push ecx // exc object + call __copyConstruct + add esp, 12 // + ObjectFunction this + ret 4 + } +} +//================================================================================================== +static __declspec(naked) destruct() +{ + __asm + { + // ObjectFunction this already on stack + push ecx // exc object + call __destruct + add esp, 8 // + ObjectFunction this + ret + } +} + +//================================================================================================== +struct ExceptionType +{ + sal_Int32 _n0; + type_info * _pTypeInfo; + sal_Int32 _n1, _n2, _n3, _n4; + ObjectFunction * _pCopyCtor; + sal_Int32 _n5; + + ExceptionType( typelib_TypeDescription * pTypeDescr ) + : _n0( 0 ) + , _n1( 0 ) + , _n2( -1 ) + , _n3( 0 ) + , _n4( pTypeDescr->nSize ) + , _pCopyCtor( new ObjectFunction( pTypeDescr, copyConstruct ) ) + , _n5( 0 ) + { _pTypeInfo = msci_getRTTI( OUStringToOString( pTypeDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); } + ~ExceptionType() + { delete _pCopyCtor; } +}; +//================================================================================================== +struct RaiseInfo +{ + sal_Int32 _n0; + ObjectFunction * _pDtor; + sal_Int32 _n2; + void * _types; + sal_Int32 _n3, _n4; + + RaiseInfo( typelib_TypeDescription * pTypeDescr ); + ~RaiseInfo(); +}; +//__________________________________________________________________________________________________ +RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) + : _n0( 0 ) + , _pDtor( new ObjectFunction( pTypeDescr, destruct ) ) + , _n2( 0 ) + , _n3( 0 ) + , _n4( 0 ) +{ + // a must be + OSL_ENSHURE( sizeof(sal_Int32) == sizeof(ExceptionType *), "### pointer size differs from sal_Int32!" ); + + typelib_CompoundTypeDescription * pCompTypeDescr; + + // info count + sal_Int32 nLen = 0; + for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr; + pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + ++nLen; + } + + // info count accompanied by type info ptrs: type, base type, base base type, ... + _types = rtl_allocateMemory( sizeof(sal_Int32) + (sizeof(ExceptionType *) * nLen) ); + *(sal_Int32 *)_types = nLen; + + ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1); + + sal_Int32 nPos = 0; + for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr; + pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + ppTypes[nPos++] = new ExceptionType( (typelib_TypeDescription *)pCompTypeDescr ); + } +} +//__________________________________________________________________________________________________ +RaiseInfo::~RaiseInfo() +{ + ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1); + for ( sal_Int32 nTypes = *(sal_Int32 *)_types; nTypes--; ) + delete ppTypes[nTypes]; + rtl_freeMemory( _types ); + + delete _pDtor; +} + +//================================================================================================== +class ExceptionInfos +{ + Mutex _aMutex; + t_string2PtrMap _allRaiseInfos; +public: + void raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); + + ExceptionInfos(); + ~ExceptionInfos(); +}; +//__________________________________________________________________________________________________ +ExceptionInfos::ExceptionInfos() +{ +} +//__________________________________________________________________________________________________ +ExceptionInfos::~ExceptionInfos() +{ + TRACE( "> freeing exception infos... <\n" ); + + MutexGuard aGuard( _aMutex ); + for ( t_string2PtrMap::const_iterator iPos( _allRaiseInfos.begin() ); + iPos != _allRaiseInfos.end(); ++iPos ) + { + delete (RaiseInfo *)(*iPos).second; + } +} +//__________________________________________________________________________________________________ +void ExceptionInfos::raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + + OSL_ENSHURE( pTypeDescr && (pTypeDescr->eTypeClass == typelib_TypeClass_STRUCT || + pTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION), + "### can only throw types of class exception/ structs" ); + + void * pCppExc = alloca( pTypeDescr->nSize ); + uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + // concatenate all types of exception for key + OUStringBuffer aKeyBuf; + typelib_CompoundTypeDescription * pCompTypeDescr; + for ( pCompTypeDescr = (typelib_CompoundTypeDescription *)pTypeDescr; + pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + aKeyBuf.append( ((typelib_TypeDescription *)pCompTypeDescr)->pTypeName ); + } + OString aKey( OUStringToOString( aKeyBuf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + + MutexGuard aGuard( _aMutex ); + const t_string2PtrMap::const_iterator iFind( _allRaiseInfos.find( aKey ) ); + + // a must be + OSL_ENSHURE( sizeof(sal_Int32) == sizeof(void *), "### pointer size differs from sal_Int32!" ); + DWORD arFilterArgs[3]; + arFilterArgs[0] = 0x19930520L; + arFilterArgs[1] = (DWORD)pCppExc; + arFilterArgs[2] = (DWORD)(iFind != _allRaiseInfos.end() + ? (*iFind).second // reuse existing info + : _allRaiseInfos[aKey] = new RaiseInfo( pTypeDescr )); // put into map + + // this is the last chance to release anything not affected by stack unwinding: + // destruct uno exception + uno_any_destruct( pUnoExc, 0 ); + + TYPELIB_DANGER_RELEASE( pTypeDescr ); + + RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs ); +} + + +//################################################################################################## +//#### exported #################################################################################### +//################################################################################################## + + +//################################################################################################## +type_info * msci_getRTTI( const OString & rUNOname ) +{ + static RTTInfos * s_pRTTIs = 0; + if (! s_pRTTIs) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pRTTIs) + { +#ifdef LEAK_STATIC_DATA + s_pRTTIs = new RTTInfos(); +#else + static RTTInfos s_aRTTIs; + s_pRTTIs = &s_aRTTIs; +#endif + } + } + return s_pRTTIs->getRTTI( rUNOname ); +} + +//################################################################################################## +void msci_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + static ExceptionInfos * s_pInfos = 0; + if (! s_pInfos) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pInfos) + { +#ifdef LEAK_STATIC_DATA + s_pInfos = new ExceptionInfos(); +#else + static ExceptionInfos s_allExceptionInfos; + s_pInfos = &s_allExceptionInfos; +#endif + } + } + s_pInfos->raiseException( pUnoExc, pUno2Cpp ); +} + +//################################################################################################## +sal_Int32 msci_filterCppException( + LPEXCEPTION_POINTERS pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + PEXCEPTION_RECORD pRecord = pPointers->ExceptionRecord; + if (pRecord->ExceptionCode == MSVC_ExceptionCode && + pRecord->ExceptionFlags == EXCEPTION_NONCONTINUABLE && + pRecord->NumberParameters == 3 && +// pRecord->ExceptionInformation[0] == 0x19930520 && + pRecord->ExceptionInformation[1] && + pRecord->ExceptionInformation[2]) + { + void * types = ((RaiseInfo *)pRecord->ExceptionInformation[2])->_types; + if (types && *(sal_Int32 *)types) // count + { + ExceptionType * pType = *(ExceptionType **)((sal_Int32 *)types +1); + if (pType && pType->_pTypeInfo) + { + OUString aUNOname( OStringToOUString( toUNOname( + ((__type_info *)pType->_pTypeInfo)->_m_d_name ), RTL_TEXTENCODING_ASCII_US ) ); + typelib_TypeDescription * pExcTypeDescr = 0; + typelib_typedescription_getByName( &pExcTypeDescr, aUNOname.pData ); + + if (pExcTypeDescr) + { + // construct uno exception any + uno_any_constructAndConvert( pUnoExc, (void *)pRecord->ExceptionInformation[1], + pExcTypeDescr, pCpp2Uno ); + uno_destructData( (void *)pRecord->ExceptionInformation[1], + pExcTypeDescr, cpp_release ); + typelib_typedescription_release( pExcTypeDescr ); + return EXCEPTION_EXECUTE_HANDLER; + } + } + } + } + return EXCEPTION_CONTINUE_SEARCH; +} + +} + +#pragma pack(pop) + diff --git a/bridges/source/cpp_uno/msvc_win32_intel/makefile.mk b/bridges/source/cpp_uno/msvc_win32_intel/makefile.mk new file mode 100644 index 000000000000..31435863d82a --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/makefile.mk @@ -0,0 +1,119 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 15:28:49 $ +# +# The Contents of this file are made available subject to the terms of +# either of the following licenses +# +# - GNU Lesser General Public License Version 2.1 +# - Sun Industry Standards Source License Version 1.1 +# +# Sun Microsystems Inc., October, 2000 +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2000 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# +# Sun Industry Standards Source License Version 1.1 +# ================================================= +# The contents of this file are subject to the Sun Industry Standards +# Source License Version 1.1 (the "License"); You may not use this file +# except in compliance with the License. You may obtain a copy of the +# License at http://www.openoffice.org/license.html. +# +# Software provided under this License is provided on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +# See the License for the specific provisions governing your rights and +# obligations concerning the Software. +# +# The Initial Developer of the Original Code is: Sun Microsystems, Inc. +# +# Copyright: 2000 by Sun Microsystems, Inc. +# +# All Rights Reserved. +# +# Contributor(s): _______________________________________ +# +# +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=msci_uno +TARGET=msci_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- +.IF "$(COM)" == "MSC" + +.IF "$(debug)" == "" +CFLAGS += /O2gityb2 /Gs +.ELSE +CFLAGS += /Ob0 +.ENDIF + +SLOFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/except.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB= i$(TARGET) + +SHL1OBJS= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/except.obj + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(MISC)$/$(SHL1TARGET).def: makefile.mk + @echo ------------------------------ + @echo Making: $@ + @echo LIBRARY $(SHL1TARGET) >$@ + @echo DESCRIPTION 'MS Visual C++ bridge to UNO' >>$@ + @echo DATA READ WRITE NONSHARED >>$@ + @echo EXPORTS >>$@ + @echo uno_initEnvironment @3 >>$@ + @echo uno_ext_getMapping @4 >>$@ + +.ENDIF + diff --git a/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx b/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx new file mode 100644 index 000000000000..c934158a9ac2 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/msci.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * $RCSfile: msci.hxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:28:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include <windows.h> + +#ifndef _RTL_STRING_HXX_ +#include <rtl/string.hxx> +#endif + +#define MSVC_ExceptionCode 0xe06d7363 + +class type_info; +typedef struct _uno_Any uno_Any; +typedef struct _uno_Mapping uno_Mapping; + +namespace CPPU_CURRENT_NAMESPACE +{ + +//================================================================================================== +type_info * msci_getRTTI( + const ::rtl::OString & rUNOname ); + +//================================================================================================== +sal_Int32 msci_filterCppException( + LPEXCEPTION_POINTERS pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ); + +//================================================================================================== +void msci_raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); + +} + diff --git a/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx b/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx new file mode 100644 index 000000000000..c0fa7227d3d5 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_intel/uno2cpp.cxx @@ -0,0 +1,494 @@ +/************************************************************************* + * + * $RCSfile: uno2cpp.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 15:28:49 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#pragma warning( disable : 4237 ) +#include <malloc.h> +#ifndef _RTL_ALLOC_H_ +#include <rtl/alloc.h> +#endif +#ifndef _RTL_STRING_HXX_ +#include <rtl/string.hxx> +#endif + +#ifndef _UNO_DATA_H_ +#include <uno/data.h> +#endif +#ifndef _BRIDGES_CPP_UNO_BRIDGE_HXX_ +#include <bridges/cpp_uno/bridge.hxx> +#endif +#ifndef _BRIDGES_CPP_UNO_TYPE_MISC_HXX_ +#include <bridges/cpp_uno/type_misc.hxx> +#endif + +#include "msci.hxx" + +using namespace rtl; +using namespace com::sun::star::uno; + +namespace CPPU_CURRENT_NAMESPACE +{ + +//================================================================================================== +inline static void callVirtualMethod( void * pThis, sal_Int32 nVtableIndex, + void * pRegisterReturn, typelib_TypeClass eReturnTypeClass, + sal_Int32 * pStackLongs, sal_Int32 nStackLongs ) +{ + // parameter list is mixed list of * and values + // reference parameters are pointers + + OSL_ENSHURE( pStackLongs && pThis, "### null ptr!" ); + OSL_ENSHURE( (sizeof(void *) == 4) && + (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); + +__asm + { + mov eax, nStackLongs + test eax, eax + je Lcall + // copy values + mov ecx, eax + shl eax, 2 // sizeof(sal_Int32) == 4 + add eax, pStackLongs // params stack space +Lcopy: sub eax, 4 + push dword ptr [eax] + dec ecx + jne Lcopy +Lcall: + // call + mov ecx, pThis + push ecx // this ptr + mov edx, [ecx] // pvft + mov eax, nVtableIndex + shl eax, 2 // sizeof(void *) == 4 + add edx, eax + call [edx] // interface method call must be __cdecl!!! + + // register return + mov ecx, eReturnTypeClass + cmp ecx, typelib_TypeClass_VOID + je Lcleanup + mov ebx, pRegisterReturn +// int32 + cmp ecx, typelib_TypeClass_LONG + je Lint32 + cmp ecx, typelib_TypeClass_UNSIGNED_LONG + je Lint32 + cmp ecx, typelib_TypeClass_ENUM + je Lint32 +// int8 + cmp ecx, typelib_TypeClass_BOOLEAN + je Lint8 + cmp ecx, typelib_TypeClass_BYTE + je Lint8 +// int16 + cmp ecx, typelib_TypeClass_CHAR + je Lint16 + cmp ecx, typelib_TypeClass_SHORT + je Lint16 + cmp ecx, typelib_TypeClass_UNSIGNED_SHORT + je Lint16 +// float + cmp ecx, typelib_TypeClass_FLOAT + je Lfloat +// double + cmp ecx, typelib_TypeClass_DOUBLE + je Ldouble +// int64 + cmp ecx, typelib_TypeClass_HYPER + je Lint64 + cmp ecx, typelib_TypeClass_UNSIGNED_HYPER + je Lint64 + jmp Lcleanup // no simple type +Lint8: + mov byte ptr [ebx], al + jmp Lcleanup +Lint16: + mov word ptr [ebx], ax + jmp Lcleanup +Lfloat: + fstp dword ptr [ebx] + jmp Lcleanup +Ldouble: + fstp qword ptr [ebx] + jmp Lcleanup +Lint64: + mov dword ptr [ebx], eax + mov dword ptr [ebx+4], edx + jmp Lcleanup +Lint32: + mov dword ptr [ebx], eax + jmp Lcleanup +Lcleanup: + // cleanup stack (obsolete though because of function) + mov eax, nStackLongs + shl eax, 2 // sizeof(sal_Int32) == 4 + add eax, 4 // this ptr + add esp, eax + } +} + +//================================================================================================== +inline static void cpp_call( + cppu_unoInterfaceProxy * pThis, + sal_Int32 nVtableCall, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + sal_Int32 nExceptions, typelib_TypeDescriptionReference ** ppExceptionRefs, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) +{ + // max space for: [complex ret ptr], values|ptr ... + char * pCppStack = (char *)alloca( sizeof(sal_Int32) + (nParams * sizeof(sal_Int64)) ); + char * pCppStackStart = pCppStack; + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSHURE( pReturnTypeDescr, "### expected return type description!" ); + + void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion + + if (pReturnTypeDescr) + { + if (cppu_isSimpleType( pReturnTypeDescr )) + { + pCppReturn = pUnoReturn; // direct way for simple types + } + else + { + // complex return via ptr + pCppReturn = *(void **)pCppStack = (cppu_relatesToInterface( pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pUnoReturn); // direct way + pCppStack += sizeof(void *); + } + } + + // stack space + + OSL_ENSHURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); + // args + void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); + // indizes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); + + sal_Int32 nTempIndizes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut && cppu_isSimpleType( pParamTypeDescr )) + { + uno_copyAndConvertData( pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, + &pThis->pBridge->aUno2Cpp ); + + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int32); // extra long + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + uno_constructData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + // is in/inout + else if (cppu_relatesToInterface( pParamTypeDescr )) + { + uno_copyAndConvertData( + *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + &pThis->pBridge->aUno2Cpp ); + + pTempIndizes[nTempIndizes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; + } + else // direct way + { + *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int32); // standard parameter length + } + + // only try-finally/ try-except statements possible... + __try + { + __try + { + // pCppI is msci this pointer + callVirtualMethod( + pThis->pCppI, nVtableCall, + pCppReturn, pReturnTypeDescr->eTypeClass, + (sal_Int32 *)pCppStackStart, (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); + + // NO exception occured... + *ppUnoExc = 0; + + // reconvert temporary params + while (nTempIndizes--) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + &pThis->pBridge->aCpp2Uno ); + } + } + else // pure out + { + uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, + &pThis->pBridge->aCpp2Uno ); + } + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (pCppReturn && pUnoReturn != pCppReturn) + { + uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, + &pThis->pBridge->aCpp2Uno ); + uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release ); + } + } + __except (msci_filterCppException( GetExceptionInformation(), + *ppUnoExc, &pThis->pBridge->aCpp2Uno )) + { + // *ppUnoExc is untouched and any was constructed by filter function + // __finally block will be called + return; + } + } + __finally + { + // cleanup of params was already done in reconversion loop iff no exception occured; + // this is quicker than getting all param descriptions twice! + // so cleanup only iff an exception occured: + if (*ppUnoExc) + { + // temporary params + while (nTempIndizes--) + { + sal_Int32 nIndex = pTempIndizes[nTempIndizes]; + // destroy temp cpp param => cpp: every param was constructed + uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release ); + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); + } + } + // return type + if (pReturnTypeDescr) + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +//================================================================================================== +void SAL_CALL cppu_unoInterfaceProxy_dispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + cppu_unoInterfaceProxy * pThis = static_cast< cppu_unoInterfaceProxy * >( pUnoI ); + typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSHURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); + + sal_Int32 nVtableCall = pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos]; + OSL_ENSHURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + + typelib_TypeDescriptionReference * pRuntimeExcRef = 0; + + if (pReturn) + { + // dependent dispatch + cpp_call( pThis, nVtableCall, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + 1, &pRuntimeExcRef, // RuntimeException + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + cpp_call( pThis, nVtableCall +1, // get, then set method + pReturnTypeRef, + 1, &aParam, + 1, &pRuntimeExcRef, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // determine vtable call index + sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition; + OSL_ENSHURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" ); + + sal_Int32 nVtableCall = pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos]; + OSL_ENSHURE( nVtableCall < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" ); + + switch (nVtableCall) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + OSL_ASSERT( pTD ); + + uno_Interface * pInterface = 0; + (*pThis->pBridge->pUnoEnv->getRegisteredInterface)( + pThis->pBridge->pUnoEnv, + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + uno_any_construct( reinterpret_cast< uno_Any * >( pReturn ), &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( pThis, nVtableCall, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nExceptions, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->ppExceptions, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + pThis->pCppI ); + + typelib_TypeDescription * pTD = 0; + const Type & rExcType = ::getCppuType( (const ::com::sun::star::uno::RuntimeException *)0 ); + TYPELIB_DANGER_GET( &pTD, rExcType.getTypeLibType() ); + uno_any_construct( *ppException, &aExc, pTD, 0 ); + TYPELIB_DANGER_RELEASE( pTD ); + } + } +} + +} + |