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