1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_bridges.hxx" 30 31 #include <sal/alloca.h> 32 33 #include <com/sun/star/uno/genfunc.hxx> 34 #include "com/sun/star/uno/RuntimeException.hpp" 35 #include <uno/data.h> 36 37 #include "bridges/cpp_uno/shared/bridge.hxx" 38 #include "bridges/cpp_uno/shared/types.hxx" 39 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" 40 #include "bridges/cpp_uno/shared/vtables.hxx" 41 42 #include "cc50_solaris_sparc.hxx" 43 44 using namespace rtl; 45 using namespace com::sun::star::uno; 46 47 namespace 48 { 49 50 extern "C" void callVirtualMethod( 51 void * pAdjustedThisPtr, 52 sal_Int32 nVtableIndex, 53 void * pRegisterReturn, 54 typelib_TypeClass eReturnType, 55 sal_Int32 * pStackLongs, 56 sal_Int32 nStackLongs 57 ); 58 59 //================================================================================================== 60 static void cpp_call( 61 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, 62 bridges::cpp_uno::shared::VtableSlot aVtableSlot, 63 typelib_TypeDescriptionReference * pReturnTypeRef, 64 sal_Int32 nParams, typelib_MethodParameter * pParams, 65 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) 66 { 67 // pCppI is cc50_solaris_sparc this pointer 68 OSL_ENSURE( pThis, "### no interface given!" ); 69 70 // max space for: [complex ret ptr], values|ptr ... 71 char * pCppStack = (char *)alloca( ((nParams+3) * sizeof(sal_Int64)) ); 72 char * pCppStackStart = pCppStack; 73 74 // return 75 typelib_TypeDescription * pReturnTypeDescr = 0; 76 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 77 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); 78 79 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion 80 81 if (pReturnTypeDescr) 82 { 83 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 84 { 85 pCppReturn = pUnoReturn; // direct way for simple types 86 } 87 else 88 { 89 // complex return via ptr 90 pCppReturn = *(void **)pCppStack 91 = (bridges::cpp_uno::shared::relatesToInterfaceType( 92 pReturnTypeDescr ) 93 ? alloca( pReturnTypeDescr->nSize ) 94 : pUnoReturn); // direct way 95 pCppStack += sizeof(void *); 96 } 97 } 98 // push this 99 void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) 100 + aVtableSlot.offset; 101 *(void**)pCppStack = pAdjustedThisPtr; 102 pCppStack += sizeof( void* ); 103 104 // args 105 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); 106 // indizes of values this have to be converted (interface conversion cpp<=>uno) 107 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); 108 // type descriptions for reconversions 109 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); 110 111 sal_Int32 nTempIndizes = 0; 112 113 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 114 { 115 const typelib_MethodParameter & rParam = pParams[nPos]; 116 typelib_TypeDescription * pParamTypeDescr = 0; 117 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 118 119 if (!rParam.bOut 120 && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 121 { 122 pCppArgs[ nPos ] = CPPU_CURRENT_NAMESPACE::adjustPointer( 123 pCppStack, pParamTypeDescr ); 124 uno_copyAndConvertData( pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr, 125 pThis->getBridge()->getUno2Cpp() ); 126 127 switch (pParamTypeDescr->eTypeClass) 128 { 129 case typelib_TypeClass_HYPER: 130 case typelib_TypeClass_UNSIGNED_HYPER: 131 case typelib_TypeClass_DOUBLE: 132 pCppStack += sizeof(sal_Int32); // extra long 133 } 134 // no longer needed 135 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 136 } 137 else // ptr to complex value | ref 138 { 139 if (! rParam.bIn) // is pure out 140 { 141 // cpp out is constructed mem, uno out is not! 142 uno_constructData( 143 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 144 pParamTypeDescr ); 145 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call 146 // will be released at reconversion 147 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 148 } 149 // is in/inout 150 else if (bridges::cpp_uno::shared::relatesToInterfaceType( 151 pParamTypeDescr )) 152 { 153 uno_copyAndConvertData( 154 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 155 pUnoArgs[nPos], pParamTypeDescr, 156 pThis->getBridge()->getUno2Cpp() ); 157 158 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 159 // will be released at reconversion 160 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 161 } 162 else // direct way 163 { 164 *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; 165 // no longer needed 166 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 167 } 168 } 169 pCppStack += sizeof(sal_Int32); // standard parameter length 170 } 171 172 // seems that EH registration for callVirtualMethod is not really 173 // necessary 174 175 // static unsigned long* pFrameInfo = NULL; 176 177 // if( ! pFrameInfo ) 178 // { 179 // pFrameInfo = new unsigned long[ 7 ]; 180 // pFrameInfo[ 0 ] = 0x40000000 | (((unsigned long)__Crun::ex_rethrow_q) >> 2); 181 // pFrameInfo[ 1 ] = 0x01000000; 182 // pFrameInfo[ 2 ] = (unsigned long)callVirtualMethodExceptionHandler; 183 // pFrameInfo[ 3 ] = 0; 184 // pFrameInfo[ 4 ] = (unsigned long)pFrameInfo - (unsigned long)callVirtualMethodExceptionHandler; 185 // pFrameInfo[ 5 ] = 0; 186 // pFrameInfo[ 6 ] = 0; 187 // _ex_register( pFrameInfo+2, 1 ); 188 // } 189 190 try 191 { 192 int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32); 193 if( nStackLongs & 1 ) 194 // stack has to be 8 byte aligned 195 nStackLongs++; 196 197 callVirtualMethod( 198 pAdjustedThisPtr, 199 aVtableSlot.index, 200 pCppReturn, 201 pReturnTypeDescr->eTypeClass, 202 (sal_Int32 *)pCppStackStart, 203 nStackLongs 204 ); 205 206 // NO exception occured... 207 *ppUnoExc = 0; 208 209 // reconvert temporary params 210 for ( ; nTempIndizes--; ) 211 { 212 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 213 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 214 215 if (pParams[nIndex].bIn) 216 { 217 if (pParams[nIndex].bOut) // inout 218 { 219 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value 220 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 221 pThis->getBridge()->getCpp2Uno() ); 222 } 223 } 224 else // pure out 225 { 226 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 227 pThis->getBridge()->getCpp2Uno() ); 228 } 229 // destroy temp cpp param => cpp: every param was constructed 230 uno_destructData( 231 pCppArgs[nIndex], pParamTypeDescr, 232 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 233 234 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 235 } 236 // return value 237 if (pCppReturn && pUnoReturn != pCppReturn) 238 { 239 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, 240 pThis->getBridge()->getCpp2Uno() ); 241 uno_destructData( 242 pCppReturn, pReturnTypeDescr, 243 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 244 } 245 } 246 catch( ... ) 247 { 248 void* pExc = __Crun::ex_get(); 249 const char* pName = __Cimpl::ex_name(); 250 251 // get exception 252 CPPU_CURRENT_NAMESPACE::cc50_solaris_sparc_fillUnoException( 253 pExc, pName, *ppUnoExc, pThis->getBridge()->getCpp2Uno()); 254 255 // temporary params 256 for ( ; nTempIndizes--; ) 257 { 258 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 259 // destroy temp cpp param => cpp: every param was constructed 260 uno_destructData( 261 pCppArgs[nIndex], 262 ppTempParamTypeDescr[nTempIndizes], 263 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 264 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 265 } 266 // return type 267 if (pReturnTypeDescr) 268 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 269 } 270 } 271 272 } 273 274 namespace bridges { namespace cpp_uno { namespace shared { 275 276 void unoInterfaceProxyDispatch( 277 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, 278 void * pReturn, void * pArgs[], uno_Any ** ppException ) 279 { 280 // is my surrogate 281 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis 282 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); 283 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; 284 285 switch (pMemberDescr->eTypeClass) 286 { 287 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 288 { 289 VtableSlot aVtableSlot( 290 getVtableSlot( 291 reinterpret_cast< 292 typelib_InterfaceAttributeTypeDescription const * >( 293 pMemberDescr))); 294 if (pReturn) 295 { 296 // dependent dispatch 297 cpp_call( 298 pThis, aVtableSlot, 299 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, 300 0, 0, // no params 301 pReturn, pArgs, ppException ); 302 } 303 else 304 { 305 // is SET 306 typelib_MethodParameter aParam; 307 aParam.pTypeRef = 308 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; 309 aParam.bIn = sal_True; 310 aParam.bOut = sal_False; 311 312 typelib_TypeDescriptionReference * pReturnTypeRef = 0; 313 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); 314 typelib_typedescriptionreference_new( 315 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); 316 317 // dependent dispatch 318 aVtableSlot.index += 1; // get, then set method 319 cpp_call( 320 pThis, aVtableSlot, 321 pReturnTypeRef, 322 1, &aParam, 323 pReturn, pArgs, ppException ); 324 325 typelib_typedescriptionreference_release( pReturnTypeRef ); 326 } 327 328 break; 329 } 330 case typelib_TypeClass_INTERFACE_METHOD: 331 { 332 VtableSlot aVtableSlot( 333 getVtableSlot( 334 reinterpret_cast< 335 typelib_InterfaceMethodTypeDescription const * >( 336 pMemberDescr))); 337 switch (aVtableSlot.index) 338 { 339 // standard calls 340 case 1: // acquire uno interface 341 (*pUnoI->acquire)( pUnoI ); 342 *ppException = 0; 343 break; 344 case 2: // release uno interface 345 (*pUnoI->release)( pUnoI ); 346 *ppException = 0; 347 break; 348 case 0: // queryInterface() opt 349 { 350 typelib_TypeDescription * pTD = 0; 351 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); 352 if (pTD) 353 { 354 uno_Interface * pInterface = 0; 355 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( 356 pThis->pBridge->getUnoEnv(), 357 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); 358 359 if (pInterface) 360 { 361 ::uno_any_construct( 362 reinterpret_cast< uno_Any * >( pReturn ), 363 &pInterface, pTD, 0 ); 364 (*pInterface->release)( pInterface ); 365 TYPELIB_DANGER_RELEASE( pTD ); 366 *ppException = 0; 367 break; 368 } 369 TYPELIB_DANGER_RELEASE( pTD ); 370 } 371 } // else perform queryInterface() 372 default: 373 // dependent dispatch 374 cpp_call( 375 pThis, aVtableSlot, 376 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, 377 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, 378 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, 379 pReturn, pArgs, ppException ); 380 } 381 break; 382 } 383 default: 384 { 385 ::com::sun::star::uno::RuntimeException aExc( 386 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), 387 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); 388 389 Type const & rExcType = ::getCppuType( &aExc ); 390 // binary identical null reference 391 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); 392 } 393 } 394 } 395 396 } } } 397