/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include "precompiled_bridges.hxx" #include "sal/config.h" #include #include #include #include "bridges/cpp_uno/shared/bridge.hxx" #include "bridges/cpp_uno/shared/types.hxx" #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx" #include "bridges/cpp_uno/shared/vtables.hxx" #include "com/sun/star/uno/Exception.hpp" #include "com/sun/star/uno/genfunc.hxx" #include "osl/diagnose.h" #include "rtl/ustring.h" #include "rtl/ustring.hxx" #include "sal/alloca.h" #include "sal/types.h" #include "typelib/typeclass.h" #include "typelib/typedescription.h" #include "uno/any2.h" #include "uno/data.h" #include "callvirtualmethod.hxx" #include "exceptions.hxx" #include "fp.hxx" #include "isdirectreturntype.hxx" namespace { namespace css = com::sun::star; void storeFpRegsToStruct(typelib_TypeDescription * type, void * data) { for (typelib_CompoundTypeDescription * t = reinterpret_cast< typelib_CompoundTypeDescription * >(type); t != NULL; t = t->pBaseTypeDescription) { for (sal_Int32 i = 0; i < t->nMembers; ++i) { switch (t->ppTypeRefs[i]->eTypeClass) { case typelib_TypeClass_FLOAT: switch (t->pMemberOffsets[i]) { case 0: fp_storef0(reinterpret_cast< float * >(data)); break; case 4: fp_storef1(reinterpret_cast< float * >(data) + 1); break; case 8: fp_storef2(reinterpret_cast< float * >(data) + 2); break; case 12: fp_storef3(reinterpret_cast< float * >(data) + 3); break; case 16: fp_storef4(reinterpret_cast< float * >(data) + 4); break; case 20: fp_storef5(reinterpret_cast< float * >(data) + 5); break; case 24: fp_storef6(reinterpret_cast< float * >(data) + 6); break; case 28: fp_storef7(reinterpret_cast< float * >(data) + 7); break; default: OSL_ASSERT(false); break; } break; case typelib_TypeClass_DOUBLE: switch (t->pMemberOffsets[i]) { case 0: fp_stored0(reinterpret_cast< double * >(data)); break; case 8: fp_stored2(reinterpret_cast< double * >(data) + 1); break; case 16: fp_stored4(reinterpret_cast< double * >(data) + 2); break; case 24: fp_stored6(reinterpret_cast< double * >(data) + 3); break; default: OSL_ASSERT(false); break; } break; case typelib_TypeClass_STRUCT: { typelib_TypeDescription * td = NULL; TYPELIB_DANGER_GET(&td, t->ppTypeRefs[i]); storeFpRegsToStruct(td, data); TYPELIB_DANGER_RELEASE(td); break; } } } } } void call( bridges::cpp_uno::shared::UnoInterfaceProxy * proxy, bridges::cpp_uno::shared::VtableSlot slot, typelib_TypeDescriptionReference * returnType, sal_Int32 count, typelib_MethodParameter * parameters, void * returnValue, void ** arguments, uno_Any ** exception) { bool directRet = bridges::cpp_uno::cc5_solaris_sparc64::isDirectReturnType( returnType); long * stack = static_cast< long * >( alloca( std::max< sal_Int32 >(count + (directRet ? 1 : 2), 4) * sizeof (long))); sal_Int32 sp = 0; typelib_TypeDescription * rtd = NULL; TYPELIB_DANGER_GET(&rtd, returnType); bool retconv = bridges::cpp_uno::shared::relatesToInterfaceType(rtd); OSL_ASSERT(!(directRet && retconv)); void * ret; if (!directRet) { ret = retconv ? alloca(rtd->nSize) : returnValue; stack[sp++] = reinterpret_cast< long >(ret); } unsigned long ** thisPtr = reinterpret_cast< unsigned long ** >( proxy->getCppI()) + slot.offset; stack[sp++] = reinterpret_cast< long >(thisPtr); void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *))); typelib_TypeDescription ** ptds = static_cast< typelib_TypeDescription ** >( alloca(count * sizeof (typelib_TypeDescription *))); for (sal_Int32 i = 0; i < count; ++i) { if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef)) { cppArgs[i] = NULL; switch (parameters[i].pTypeRef->eTypeClass) { case typelib_TypeClass_BOOLEAN: stack[sp] = *static_cast< sal_Bool * >(arguments[i]); break; case typelib_TypeClass_BYTE: stack[sp] = *static_cast< sal_Int8 * >(arguments[i]); break; case typelib_TypeClass_SHORT: stack[sp] = *static_cast< sal_Int16 * >(arguments[i]); break; case typelib_TypeClass_UNSIGNED_SHORT: stack[sp] = *static_cast< sal_uInt16 * >(arguments[i]); break; case typelib_TypeClass_LONG: case typelib_TypeClass_ENUM: stack[sp] = *static_cast< sal_Int32 * >(arguments[i]); break; case typelib_TypeClass_UNSIGNED_LONG: stack[sp] = *static_cast< sal_uInt32 * >(arguments[i]); break; case typelib_TypeClass_HYPER: stack[sp] = *static_cast< sal_Int64 * >(arguments[i]); break; case typelib_TypeClass_UNSIGNED_HYPER: stack[sp] = *static_cast< sal_uInt64 * >(arguments[i]); break; case typelib_TypeClass_FLOAT: { float * f = static_cast< float * >(arguments[i]); switch (sp) { case 1: fp_loadf3(f); break; case 2: fp_loadf5(f); break; case 3: fp_loadf7(f); break; case 4: fp_loadf9(f); break; case 5: fp_loadf11(f); break; case 6: fp_loadf13(f); break; case 7: fp_loadf15(f); break; case 8: fp_loadf17(f); break; case 9: fp_loadf19(f); break; case 10: fp_loadf21(f); break; case 11: fp_loadf23(f); break; case 12: fp_loadf25(f); break; case 13: fp_loadf27(f); break; case 14: fp_loadf29(f); break; case 15: fp_loadf31(f); break; default: reinterpret_cast< float * >(stack + sp)[1] = *f; break; } break; } case typelib_TypeClass_DOUBLE: { double * d = static_cast< double * >(arguments[i]); switch (sp) { case 1: fp_loadd2(d); break; case 2: fp_loadd4(d); break; case 3: fp_loadd6(d); break; case 4: fp_loadd8(d); break; case 5: fp_loadd10(d); break; case 6: fp_loadd12(d); break; case 7: fp_loadd14(d); break; case 8: fp_loadd16(d); break; case 9: fp_loadd18(d); break; case 10: fp_loadd20(d); break; case 11: fp_loadd22(d); break; case 12: fp_loadd24(d); break; case 13: fp_loadd26(d); break; case 14: fp_loadd28(d); break; case 15: fp_loadd30(d); break; default: *reinterpret_cast< double * >(stack + sp) = *d; break; } break; } case typelib_TypeClass_CHAR: stack[sp] = *static_cast< sal_Unicode * >(arguments[i]); break; default: OSL_ASSERT(false); break; } } else { typelib_TypeDescription * ptd = NULL; TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef); if (!parameters[i].bIn) { cppArgs[i] = alloca(ptd->nSize); uno_constructData(cppArgs[i], ptd); ptds[i] = ptd; *reinterpret_cast< void ** >(stack + sp) = cppArgs[i]; } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) { cppArgs[i] = alloca(ptd->nSize); uno_copyAndConvertData( cppArgs[i], arguments[i], ptd, proxy->getBridge()->getUno2Cpp()); ptds[i] = ptd; *reinterpret_cast< void ** >(stack + sp) = cppArgs[i]; } else { cppArgs[i] = NULL; *reinterpret_cast< void ** >(stack + sp) = arguments[i]; TYPELIB_DANGER_RELEASE(ptd); } } ++sp; } try { callVirtualMethod( (*thisPtr)[slot.index + 2], stack, std::max< sal_Int32 >(sp - 6, 0) * sizeof (long)); } catch (css::uno::Exception &) { void * exc = __Crun::ex_get(); char const * name = __Cimpl::ex_name(); bridges::cpp_uno::cc5_solaris_sparc64::fillUnoException( exc, name, *exception, proxy->getBridge()->getCpp2Uno()); for (sal_Int32 i = 0; i < count; ++i) { if (cppArgs[i] != NULL) { uno_destructData( cppArgs[i], ptds[i], reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); TYPELIB_DANGER_RELEASE(ptds[i]); } } TYPELIB_DANGER_RELEASE(rtd); return; } *exception = NULL; for (sal_Int32 i = 0; i < count; ++i) { if (cppArgs[i] != NULL) { if (parameters[i].bOut) { if (parameters[i].bIn) { uno_destructData(arguments[i], ptds[i], NULL); } uno_copyAndConvertData( arguments[i], cppArgs[i], ptds[i], proxy->getBridge()->getCpp2Uno()); } uno_destructData( cppArgs[i], ptds[i], reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); TYPELIB_DANGER_RELEASE(ptds[i]); } } if (directRet) { switch (rtd->eTypeClass) { case typelib_TypeClass_FLOAT: fp_storef0(reinterpret_cast< float * >(returnValue)); break; case typelib_TypeClass_DOUBLE: fp_stored0(reinterpret_cast< double * >(returnValue)); break; case typelib_TypeClass_STRUCT: storeFpRegsToStruct(rtd, stack); // fall through case typelib_TypeClass_ANY: std::memcpy(returnValue, stack, rtd->nSize); break; default: OSL_ASSERT(rtd->nSize <= 8); std::memcpy( returnValue, reinterpret_cast< char * >(stack) + (8 - rtd->nSize), rtd->nSize); break; } } else if (retconv) { uno_copyAndConvertData( returnValue, ret, rtd, proxy->getBridge()->getCpp2Uno()); uno_destructData( ret, rtd, reinterpret_cast< uno_ReleaseFunc >(css::uno::cpp_release)); } TYPELIB_DANGER_RELEASE(rtd); } } namespace bridges { namespace cpp_uno { namespace shared { void unoInterfaceProxyDispatch( uno_Interface * pUnoI, typelib_TypeDescription const * pMemberDescr, void * pReturn, void * pArgs[], uno_Any ** ppException) { bridges::cpp_uno::shared::UnoInterfaceProxy * proxy = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); switch (pMemberDescr->eTypeClass) { case typelib_TypeClass_INTERFACE_ATTRIBUTE: { VtableSlot slot( getVtableSlot( reinterpret_cast< typelib_InterfaceAttributeTypeDescription const * >( pMemberDescr))); if (pReturn != NULL) { // Getter: call( proxy, slot, (reinterpret_cast< typelib_InterfaceAttributeTypeDescription const * >( pMemberDescr)->pAttributeTypeRef), 0, NULL, pReturn, pArgs, ppException); } else { // Setter: typelib_MethodParameter param = { NULL, (reinterpret_cast< typelib_InterfaceAttributeTypeDescription const * >( pMemberDescr)->pAttributeTypeRef), true, false }; typelib_TypeDescriptionReference * rtd = NULL; typelib_typedescriptionreference_new( &rtd, typelib_TypeClass_VOID, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("void")).pData); slot.index += 1; call(proxy, slot, rtd, 1, ¶m, pReturn, pArgs, ppException); typelib_typedescriptionreference_release(rtd); } break; } case typelib_TypeClass_INTERFACE_METHOD: { VtableSlot slot( getVtableSlot( reinterpret_cast< typelib_InterfaceMethodTypeDescription const * >( pMemberDescr))); switch (slot.index) { case 1: pUnoI->acquire(pUnoI); *ppException = NULL; break; case 2: pUnoI->release(pUnoI); *ppException = NULL; break; case 0: { typelib_TypeDescription * td = NULL; TYPELIB_DANGER_GET( &td, reinterpret_cast< css::uno::Type * >( pArgs[0])->getTypeLibType()); if (td != NULL) { uno_Interface * ifc = NULL; proxy->pBridge->getUnoEnv()->getRegisteredInterface( proxy->pBridge->getUnoEnv(), reinterpret_cast< void ** >(&ifc), proxy->oid.pData, (reinterpret_cast< typelib_InterfaceTypeDescription * >(td))); if (ifc != NULL) { uno_any_construct( reinterpret_cast< uno_Any * >(pReturn), &ifc, td, NULL); ifc->release(ifc); TYPELIB_DANGER_RELEASE(td); *ppException = NULL; break; } TYPELIB_DANGER_RELEASE(td); } } // fall through default: call( proxy, slot, (reinterpret_cast< typelib_InterfaceMethodTypeDescription const * >( pMemberDescr)->pReturnTypeRef), (reinterpret_cast< typelib_InterfaceMethodTypeDescription const * >( pMemberDescr)->nParams), (reinterpret_cast< typelib_InterfaceMethodTypeDescription const * >( pMemberDescr)->pParams), pReturn, pArgs, ppException); } break; } default: OSL_ASSERT(false); break; } } } } }