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 <malloc.h> 32 33 #include <com/sun/star/uno/genfunc.hxx> 34 #include <uno/data.h> 35 36 #include "bridges/cpp_uno/shared/bridge.hxx" 37 #include "bridges/cpp_uno/shared/types.hxx" 38 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" 39 #include "bridges/cpp_uno/shared/vtables.hxx" 40 41 #include "msci.hxx" 42 43 using namespace ::rtl; 44 using namespace ::com::sun::star::uno; 45 46 namespace 47 { 48 49 //================================================================================================== 50 inline static void callVirtualMethod( 51 void * pAdjustedThisPtr, sal_Int32 nVtableIndex, 52 void * pRegisterReturn, typelib_TypeClass eReturnTypeClass, 53 sal_Int32 * pStackLongs, sal_Int32 nStackLongs ) 54 { 55 // parameter list is mixed list of * and values 56 // reference parameters are pointers 57 58 OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" ); 59 OSL_ENSURE( (sizeof(void *) == 4) && 60 (sizeof(sal_Int32) == 4), "### unexpected size of int!" ); 61 62 __asm 63 { 64 mov eax, nStackLongs 65 test eax, eax 66 je Lcall 67 // copy values 68 mov ecx, eax 69 shl eax, 2 // sizeof(sal_Int32) == 4 70 add eax, pStackLongs // params stack space 71 Lcopy: sub eax, 4 72 push dword ptr [eax] 73 dec ecx 74 jne Lcopy 75 Lcall: 76 // call 77 mov ecx, pAdjustedThisPtr 78 push ecx // this ptr 79 mov edx, [ecx] // pvft 80 mov eax, nVtableIndex 81 shl eax, 2 // sizeof(void *) == 4 82 add edx, eax 83 call [edx] // interface method call must be __cdecl!!! 84 85 // register return 86 mov ecx, eReturnTypeClass 87 cmp ecx, typelib_TypeClass_VOID 88 je Lcleanup 89 mov ebx, pRegisterReturn 90 // int32 91 cmp ecx, typelib_TypeClass_LONG 92 je Lint32 93 cmp ecx, typelib_TypeClass_UNSIGNED_LONG 94 je Lint32 95 cmp ecx, typelib_TypeClass_ENUM 96 je Lint32 97 // int8 98 cmp ecx, typelib_TypeClass_BOOLEAN 99 je Lint8 100 cmp ecx, typelib_TypeClass_BYTE 101 je Lint8 102 // int16 103 cmp ecx, typelib_TypeClass_CHAR 104 je Lint16 105 cmp ecx, typelib_TypeClass_SHORT 106 je Lint16 107 cmp ecx, typelib_TypeClass_UNSIGNED_SHORT 108 je Lint16 109 // float 110 cmp ecx, typelib_TypeClass_FLOAT 111 je Lfloat 112 // double 113 cmp ecx, typelib_TypeClass_DOUBLE 114 je Ldouble 115 // int64 116 cmp ecx, typelib_TypeClass_HYPER 117 je Lint64 118 cmp ecx, typelib_TypeClass_UNSIGNED_HYPER 119 je Lint64 120 jmp Lcleanup // no simple type 121 Lint8: 122 mov byte ptr [ebx], al 123 jmp Lcleanup 124 Lint16: 125 mov word ptr [ebx], ax 126 jmp Lcleanup 127 Lfloat: 128 fstp dword ptr [ebx] 129 jmp Lcleanup 130 Ldouble: 131 fstp qword ptr [ebx] 132 jmp Lcleanup 133 Lint64: 134 mov dword ptr [ebx], eax 135 mov dword ptr [ebx+4], edx 136 jmp Lcleanup 137 Lint32: 138 mov dword ptr [ebx], eax 139 jmp Lcleanup 140 Lcleanup: 141 // cleanup stack (obsolete though because of function) 142 mov eax, nStackLongs 143 shl eax, 2 // sizeof(sal_Int32) == 4 144 add eax, 4 // this ptr 145 add esp, eax 146 } 147 } 148 149 //================================================================================================== 150 static void cpp_call( 151 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, 152 bridges::cpp_uno::shared::VtableSlot aVtableSlot, 153 typelib_TypeDescriptionReference * pReturnTypeRef, 154 sal_Int32 nParams, typelib_MethodParameter * pParams, 155 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) throw () 156 { 157 // max space for: [complex ret ptr], values|ptr ... 158 char * pCppStack = (char *)alloca( sizeof(sal_Int32) + (nParams * sizeof(sal_Int64)) ); 159 char * pCppStackStart = pCppStack; 160 161 // return 162 typelib_TypeDescription * pReturnTypeDescr = 0; 163 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); 164 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); 165 166 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion 167 168 if (pReturnTypeDescr) 169 { 170 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) 171 { 172 pCppReturn = pUnoReturn; // direct way for simple types 173 } 174 else 175 { 176 // complex return via ptr 177 pCppReturn = *(void **)pCppStack 178 = (bridges::cpp_uno::shared::relatesToInterfaceType( 179 pReturnTypeDescr ) 180 ? alloca( pReturnTypeDescr->nSize ) 181 : pUnoReturn); // direct way 182 pCppStack += sizeof(void *); 183 } 184 } 185 186 // stack space 187 188 OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" ); 189 // args 190 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams ); 191 // indizes of values this have to be converted (interface conversion cpp<=>uno) 192 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams); 193 // type descriptions for reconversions 194 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams)); 195 196 sal_Int32 nTempIndizes = 0; 197 198 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 199 { 200 const typelib_MethodParameter & rParam = pParams[nPos]; 201 typelib_TypeDescription * pParamTypeDescr = 0; 202 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); 203 204 if (!rParam.bOut 205 && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) 206 { 207 ::uno_copyAndConvertData( 208 pCppArgs[nPos] = pCppStack, pUnoArgs[nPos], pParamTypeDescr, 209 pThis->getBridge()->getUno2Cpp() ); 210 211 switch (pParamTypeDescr->eTypeClass) 212 { 213 case typelib_TypeClass_HYPER: 214 case typelib_TypeClass_UNSIGNED_HYPER: 215 case typelib_TypeClass_DOUBLE: 216 pCppStack += sizeof(sal_Int32); // extra long 217 break; 218 default: 219 break; 220 } 221 // no longer needed 222 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 223 } 224 else // ptr to complex value | ref 225 { 226 if (! rParam.bIn) // is pure out 227 { 228 // cpp out is constructed mem, uno out is not! 229 ::uno_constructData( 230 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 231 pParamTypeDescr ); 232 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call 233 // will be released at reconversion 234 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 235 } 236 // is in/inout 237 else if (bridges::cpp_uno::shared::relatesToInterfaceType( 238 pParamTypeDescr )) 239 { 240 ::uno_copyAndConvertData( 241 *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ), 242 pUnoArgs[nPos], pParamTypeDescr, 243 pThis->getBridge()->getUno2Cpp() ); 244 245 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted 246 // will be released at reconversion 247 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr; 248 } 249 else // direct way 250 { 251 *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos]; 252 // no longer needed 253 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 254 } 255 } 256 pCppStack += sizeof(sal_Int32); // standard parameter length 257 } 258 259 __try 260 { 261 // pCppI is msci this pointer 262 callVirtualMethod( 263 reinterpret_cast< void ** >(pThis->getCppI()) + aVtableSlot.offset, 264 aVtableSlot.index, 265 pCppReturn, pReturnTypeDescr->eTypeClass, 266 (sal_Int32 *)pCppStackStart, 267 (pCppStack - pCppStackStart) / sizeof(sal_Int32) ); 268 } 269 __except (CPPU_CURRENT_NAMESPACE::msci_filterCppException( 270 GetExceptionInformation(), 271 *ppUnoExc, pThis->getBridge()->getCpp2Uno() )) 272 { 273 // *ppUnoExc was constructed by filter function 274 // temporary params 275 while (nTempIndizes--) 276 { 277 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 278 // destroy temp cpp param => cpp: every param was constructed 279 ::uno_destructData( 280 pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 281 cpp_release ); 282 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] ); 283 } 284 // return type 285 if (pReturnTypeDescr) 286 { 287 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 288 } 289 // end here 290 return; 291 } 292 293 // NO exception occured 294 *ppUnoExc = 0; 295 296 // reconvert temporary params 297 while (nTempIndizes--) 298 { 299 sal_Int32 nIndex = pTempIndizes[nTempIndizes]; 300 typelib_TypeDescription * pParamTypeDescr = 301 ppTempParamTypeDescr[nTempIndizes]; 302 303 if (pParams[nIndex].bIn) 304 { 305 if (pParams[nIndex].bOut) // inout 306 { 307 ::uno_destructData( 308 pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value 309 ::uno_copyAndConvertData( 310 pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 311 pThis->getBridge()->getCpp2Uno() ); 312 } 313 } 314 else // pure out 315 { 316 ::uno_copyAndConvertData( 317 pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr, 318 pThis->getBridge()->getCpp2Uno() ); 319 } 320 // destroy temp cpp param => cpp: every param was constructed 321 ::uno_destructData( 322 pCppArgs[nIndex], pParamTypeDescr, cpp_release ); 323 324 TYPELIB_DANGER_RELEASE( pParamTypeDescr ); 325 } 326 // return value 327 if (pCppReturn && pUnoReturn != pCppReturn) 328 { 329 ::uno_copyAndConvertData( 330 pUnoReturn, pCppReturn, pReturnTypeDescr, 331 pThis->getBridge()->getCpp2Uno() ); 332 ::uno_destructData( 333 pCppReturn, pReturnTypeDescr, cpp_release ); 334 } 335 // return type 336 if (pReturnTypeDescr) 337 { 338 TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); 339 } 340 } 341 342 } 343 344 namespace bridges { namespace cpp_uno { namespace shared { 345 346 void unoInterfaceProxyDispatch( 347 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, 348 void * pReturn, void * pArgs[], uno_Any ** ppException ) 349 { 350 // is my surrogate 351 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis 352 = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); 353 354 switch (pMemberDescr->eTypeClass) 355 { 356 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 357 { 358 VtableSlot aVtableSlot( 359 getVtableSlot( 360 reinterpret_cast< 361 typelib_InterfaceAttributeTypeDescription const * >( 362 pMemberDescr))); 363 if (pReturn) 364 { 365 // dependent dispatch 366 cpp_call( 367 pThis, aVtableSlot, 368 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, 369 0, 0, // no params 370 pReturn, pArgs, ppException ); 371 } 372 else 373 { 374 // is SET 375 typelib_MethodParameter aParam; 376 aParam.pTypeRef = 377 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; 378 aParam.bIn = sal_True; 379 aParam.bOut = sal_False; 380 381 typelib_TypeDescriptionReference * pReturnTypeRef = 0; 382 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); 383 typelib_typedescriptionreference_new( 384 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); 385 386 // dependent dispatch 387 aVtableSlot.index += 1; // get, then set method 388 cpp_call( 389 pThis, aVtableSlot, 390 pReturnTypeRef, 391 1, &aParam, 392 pReturn, pArgs, ppException ); 393 394 typelib_typedescriptionreference_release( pReturnTypeRef ); 395 } 396 397 break; 398 } 399 case typelib_TypeClass_INTERFACE_METHOD: 400 { 401 VtableSlot aVtableSlot( 402 getVtableSlot( 403 reinterpret_cast< 404 typelib_InterfaceMethodTypeDescription const * >( 405 pMemberDescr))); 406 switch (aVtableSlot.index) 407 { 408 // standard calls 409 case 1: // acquire uno interface 410 (*pUnoI->acquire)( pUnoI ); 411 *ppException = 0; 412 break; 413 case 2: // release uno interface 414 (*pUnoI->release)( pUnoI ); 415 *ppException = 0; 416 break; 417 case 0: // queryInterface() opt 418 { 419 typelib_TypeDescription * pTD = 0; 420 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); 421 if (pTD) 422 { 423 uno_Interface * pInterface = 0; 424 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( 425 pThis->pBridge->getUnoEnv(), 426 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); 427 428 if (pInterface) 429 { 430 ::uno_any_construct( 431 reinterpret_cast< uno_Any * >( pReturn ), 432 &pInterface, pTD, 0 ); 433 (*pInterface->release)( pInterface ); 434 TYPELIB_DANGER_RELEASE( pTD ); 435 *ppException = 0; 436 break; 437 } 438 TYPELIB_DANGER_RELEASE( pTD ); 439 } 440 } // else perform queryInterface() 441 default: 442 // dependent dispatch 443 cpp_call( 444 pThis, aVtableSlot, 445 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, 446 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, 447 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, 448 pReturn, pArgs, ppException ); 449 } 450 break; 451 } 452 default: 453 { 454 ::com::sun::star::uno::RuntimeException aExc( 455 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), 456 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); 457 458 Type const & rExcType = ::getCppuType( &aExc ); 459 // binary identical null reference 460 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); 461 } 462 } 463 } 464 465 } } } 466