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_intel.hxx" 43 44 using namespace rtl; 45 using namespace com::sun::star::uno; 46 47 namespace 48 { 49 50 extern "C" { 51 void callVirtualMethod( 52 void * pAdjustedThisPtr, 53 sal_Int32 nVtableIndex, 54 void * pRegisterReturn, 55 typelib_TypeClass eReturnType, 56 sal_Int32 * pStackLongs, 57 sal_Int32 nStackLongs 58 ); 59 } 60 61 //================================================================================================== 62 static inline void cpp_call( 63 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, 64 bridges::cpp_uno::shared::VtableSlot aVtableSlot, 65 typelib_TypeDescriptionReference * pReturnTypeRef, 66 sal_Int32 nParams, typelib_MethodParameter * pParams, 67 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) 68 { 69 // max space for: [complex ret ptr], values|ptr ... 70 char * pCppStack = (char *)alloca( ((nParams+3) * sizeof(sal_Int64)) ); 71 char * pCppStackStart = pCppStack; 72 73 // return 74 typelib_TypeDescription * pReturnTypeDescr = 0; 75 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 76 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); 77 78 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion 79 80 void * pReturnSpace = 0; 81 82 if (pReturnTypeDescr) 83 { 84 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 85 { 86 pCppReturn = pUnoReturn; // direct way for simple types 87 } 88 else 89 { 90 // complex return via ptr 91 pCppReturn = *(void **)pCppStack 92 = (bridges::cpp_uno::shared::relatesToInterfaceType( 93 pReturnTypeDescr ) 94 ? alloca( pReturnTypeDescr->nSize ) 95 : pUnoReturn); // direct way 96 pCppStack += sizeof(void *); 97 } 98 } 99 // push this 100 void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI()) 101 + aVtableSlot.offset; 102 *(void**)pCppStack = pAdjustedThisPtr; 103 pCppStack += sizeof( void* ); 104 105 const int nMaxParams = 32; 106 // args 107 void * args_buffer[3 * nMaxParams]; 108 void ** pCppArgs = (void **)(nParams > nMaxParams ? rtl_allocateMemory( 3 * sizeof(void *) * nParams ) : args_buffer); 109 // indizes of values this have to be converted (interface conversion cpp<=>uno) 110 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); 111 // type descriptions for reconversions 112 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); 113 114 sal_Int32 nTempIndizes = 0; 115 116 const int nTempBufferSize = 256; 117 sal_Int32 nTempBufferPos = 0; 118 long params_buffer[nTempBufferSize]; 119 120 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 121 { 122 const typelib_MethodParameter & rParam = pParams[nPos]; 123 typelib_TypeDescription * pParamTypeDescr = 0; 124 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 125 126 if (!rParam.bOut 127 && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 128 { 129 pCppArgs[ nPos ] = pCppStack; 130 uno_copyAndConvertData( pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr, 131 pThis->getBridge()->getUno2Cpp() ); 132 133 switch (pParamTypeDescr->eTypeClass) 134 { 135 case typelib_TypeClass_HYPER: 136 case typelib_TypeClass_UNSIGNED_HYPER: 137 case typelib_TypeClass_DOUBLE: 138 pCppStack += sizeof(sal_Int32); // extra long 139 } 140 // no longer needed 141 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 142 } 143 else // ptr to complex value | ref 144 { 145 if (! rParam.bIn) // is pure out 146 { 147 // cpp out is constructed mem, uno out is not! 148 if (pParamTypeDescr->nSize > (sizeof(long) * (nTempBufferSize - nTempBufferPos))) 149 { 150 uno_constructData( 151 *(void **)pCppStack = pCppArgs[nPos] = rtl_allocateMemory( pParamTypeDescr->nSize ), 152 pParamTypeDescr ); 153 pTempIndizes[nTempIndizes] = nPos | 0x80000000; // default constructed for cpp call 154 } 155 else 156 { 157 uno_constructData( 158 *(void **)pCppStack = pCppArgs[nPos] = (params_buffer + nTempBufferPos), 159 pParamTypeDescr ); 160 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call 161 nTempBufferPos += (pParamTypeDescr->nSize / sizeof(long)) +1; 162 } 163 // will be released at reconversion 164 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 165 } 166 // is in/inout 167 else if (bridges::cpp_uno::shared::relatesToInterfaceType( 168 pParamTypeDescr )) 169 { 170 if (pParamTypeDescr->nSize > (sizeof(long)*(nTempBufferSize - nTempBufferPos))) 171 { 172 uno_copyAndConvertData( 173 *(void **)pCppStack = pCppArgs[nPos] = rtl_allocateMemory( pParamTypeDescr->nSize ), 174 pUnoArgs[nPos], pParamTypeDescr, 175 pThis->getBridge()->getUno2Cpp() ); 176 pTempIndizes[nTempIndizes] = nPos | 0x80000000; // has to be reconverted 177 } 178 else 179 { 180 uno_copyAndConvertData( 181 *(void **)pCppStack = pCppArgs[nPos] = (params_buffer + nTempBufferPos), 182 pUnoArgs[nPos], pParamTypeDescr, 183 pThis->getBridge()->getUno2Cpp() ); 184 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 185 nTempBufferPos += (pParamTypeDescr->nSize / sizeof(long)) +1; 186 } 187 // will be released at reconversion 188 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 189 } 190 else // direct way 191 { 192 *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; 193 // no longer needed 194 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 195 } 196 } 197 pCppStack += sizeof(sal_Int32); // standard parameter length 198 } 199 200 try 201 { 202 int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32); 203 if( nStackLongs & 1 ) 204 // stack has to be 8 byte aligned 205 nStackLongs++; 206 207 callVirtualMethod( 208 pAdjustedThisPtr, aVtableSlot.index, 209 pCppReturn, 210 pReturnTypeDescr->eTypeClass, 211 (sal_Int32 *)pCppStackStart, 212 nStackLongs 213 ); 214 215 // NO exception occured... 216 *ppUnoExc = 0; 217 218 // reconvert temporary params 219 for ( ; nTempIndizes--; ) 220 { 221 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 222 sal_Bool bAllocated = (nIndex & 0x80000000) != 0; 223 nIndex &= 0x7fffffff; 224 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes]; 225 226 if (pParams[nIndex].bIn) 227 { 228 if (pParams[nIndex].bOut) // inout 229 { 230 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value 231 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 232 pThis->getBridge()->getCpp2Uno() ); 233 } 234 } 235 else // pure out 236 { 237 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 238 pThis->getBridge()->getCpp2Uno() ); 239 } 240 // destroy temp cpp param => cpp: every param was constructed 241 uno_destructData( 242 pCppArgs[nIndex], pParamTypeDescr, 243 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 244 245 if (bAllocated) 246 rtl_freeMemory( pCppArgs[nIndex] ); 247 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 248 } 249 // return value 250 if (pCppReturn && pUnoReturn != pCppReturn) 251 { 252 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr, 253 pThis->getBridge()->getCpp2Uno() ); 254 uno_destructData( 255 pCppReturn, pReturnTypeDescr, 256 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 257 } 258 } 259 catch( ... ) 260 { 261 void* pExc = __Crun::ex_get(); 262 const char* pName = __Cimpl::ex_name(); 263 264 // get exception 265 CPPU_CURRENT_NAMESPACE::cc50_solaris_intel_fillUnoException( 266 pExc, pName, *ppUnoExc, 267 pThis->getBridge()->getCpp2Uno()); 268 269 // temporary params 270 for ( ; nTempIndizes--; ) 271 { 272 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 273 sal_Bool bAllocated = (nIndex & 0x80000000) != 0; 274 nIndex &= 0x7fffffff; 275 // destroy temp cpp param => cpp: every param was constructed 276 uno_destructData( 277 pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 278 reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); 279 if (bAllocated) 280 rtl_freeMemory( pCppArgs[nIndex] ); 281 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 282 } 283 // return type 284 if (pReturnTypeDescr) 285 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 286 } 287 288 if (pCppArgs != (void **)args_buffer) 289 rtl_freeMemory( pCppArgs ); 290 if (pReturnSpace) 291 rtl_freeMemory( pReturnSpace ); 292 } 293 294 } 295 296 namespace bridges { namespace cpp_uno { namespace shared { 297 298 void unoInterfaceProxyDispatch( 299 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, 300 void * pReturn, void * pArgs[], uno_Any ** ppException ) 301 { 302 // is my surrogate 303 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis 304 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); 305 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr; 306 307 switch (pMemberDescr->eTypeClass) 308 { 309 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 310 { 311 VtableSlot aVtableSlot( 312 getVtableSlot( 313 reinterpret_cast< 314 typelib_InterfaceAttributeTypeDescription const * >( 315 pMemberDescr))); 316 if (pReturn) 317 { 318 // dependent dispatch 319 cpp_call( 320 pThis, aVtableSlot, 321 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, 322 0, 0, // no params 323 pReturn, pArgs, ppException ); 324 } 325 else 326 { 327 // is SET 328 typelib_MethodParameter aParam; 329 aParam.pTypeRef = 330 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; 331 aParam.bIn = sal_True; 332 aParam.bOut = sal_False; 333 334 typelib_TypeDescriptionReference * pReturnTypeRef = 0; 335 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); 336 typelib_typedescriptionreference_new( 337 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); 338 339 // dependent dispatch 340 aVtableSlot.index += 1; // get, then set method 341 cpp_call( 342 pThis, aVtableSlot, 343 pReturnTypeRef, 344 1, &aParam, 345 pReturn, pArgs, ppException ); 346 347 typelib_typedescriptionreference_release( pReturnTypeRef ); 348 } 349 350 break; 351 } 352 case typelib_TypeClass_INTERFACE_METHOD: 353 { 354 VtableSlot aVtableSlot( 355 getVtableSlot( 356 reinterpret_cast< 357 typelib_InterfaceMethodTypeDescription const * >( 358 pMemberDescr))); 359 switch (aVtableSlot.index) 360 { 361 // standard calls 362 case 1: // acquire uno interface 363 (*pUnoI->acquire)( pUnoI ); 364 *ppException = 0; 365 break; 366 case 2: // release uno interface 367 (*pUnoI->release)( pUnoI ); 368 *ppException = 0; 369 break; 370 case 0: // queryInterface() opt 371 { 372 typelib_TypeDescription * pTD = 0; 373 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); 374 if (pTD) 375 { 376 uno_Interface * pInterface = 0; 377 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( 378 pThis->pBridge->getUnoEnv(), 379 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); 380 381 if (pInterface) 382 { 383 ::uno_any_construct( 384 reinterpret_cast< uno_Any * >( pReturn ), 385 &pInterface, pTD, 0 ); 386 (*pInterface->release)( pInterface ); 387 TYPELIB_DANGER_RELEASE( pTD ); 388 *ppException = 0; 389 break; 390 } 391 TYPELIB_DANGER_RELEASE( pTD ); 392 } 393 } // else perform queryInterface() 394 default: 395 // dependent dispatch 396 cpp_call( 397 pThis, aVtableSlot, 398 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, 399 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, 400 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, 401 pReturn, pArgs, ppException ); 402 } 403 break; 404 } 405 default: 406 { 407 ::com::sun::star::uno::RuntimeException aExc( 408 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), 409 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); 410 411 Type const & rExcType = ::getCppuType( &aExc ); 412 // binary identical null reference 413 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); 414 } 415 } 416 } 417 418 } } } 419