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