diff options
Diffstat (limited to 'bridges/source/cpp_uno/msvc_win32_x86-64')
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm | 328 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx | 574 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/dllinit.cxx | 61 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx | 623 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk | 82 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx | 62 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx | 453 |
7 files changed, 2183 insertions, 0 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm b/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm new file mode 100644 index 000000000000..09f1177b9a9e --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm @@ -0,0 +1,328 @@ +; -*- Mode: text; tab-width: 8; indent-tabs-mode: nil comment-column: 32; comment-start: "; " comment-start-skip: "; *" -*- + +;************************************************************************* +;* +;* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +;* +;* Copyright 2000, 2011 Oracle and/or its affiliates. +;* +;* OpenOffice.org - a multi-platform office productivity suite +;* +;* This file is part of OpenOffice.org. +;* +;* OpenOffice.org is free software: you can redistribute it and/or modify +;* it under the terms of the GNU Lesser General Public License version 3 +;* only, as published by the Free Software Foundation. +;* +;* OpenOffice.org is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;* GNU Lesser General Public License version 3 for more details +;* (a copy is included in the LICENSE file that accompanied this code). +;* +;* You should have received a copy of the GNU Lesser General Public License +;* version 3 along with OpenOffice.org. If not, see +;* <http://www.openoffice.org/license.html> +;* for a copy of the LGPLv3 License. +;* +;************************************************************************ + +; Emacs asm-mode is not really ideal for the convention in this +; file. So I use text-mode with custom comment syntax... not really +; ideal either. Maybe I should just re-format this to match asm-mode's +; conventions? + +; NOTE: EXTREMELY UNFINISHED, I KNOW. WORK IN PROGRESS. + +; I really don't have a good high-level understanding of the big +; picture and what the actual task of the C++/UNO bridge is yet... I +; should debug the x86 version and see what is actually going on to +; get an understanding. + +; This is in a separate file for x86-64 as MSVC doesn't have in-line +; assembly for x64. The code here is still partly just a crude copy of +; the in-line x86 code from ../msvc_win32_intel that is totally +; pointless on x64. But parts have been properly changed into x64 +; calling convention and might even work. + +; Random web links and other documentation about low-level +; implementation details for the C++/UNO bridge on x64 Windows kept +; here: + +; Caolan's "Lazy Hackers Guide To Porting" is useful: +; http://wiki.services.openoffice.org/wiki/Lazy_Hackers_Guide_To_Porting + +; As for details about the x64 Windows calling convention, register +; usage, stack usage, exception handling etc, the official +; documentation (?) on MSDN is a bit fragmented and split up into a +; needlessly large number of short pages. But still: +; http://msdn.microsoft.com/en-us/library/7kcdt6fy%28v=VS.90%29.aspx + +; Also see Raymond Chen's blog post: +; http://blogs.msdn.com/b/oldnewthing/archive/2004/01/14/58579.aspx + +; This one is actually more readable: "Improving Automated Analysis of +; Windows x64 Binaries": +; http://www.uninformed.org/?v=4&a=1 + +; The bridge uses dynamic code generation. For exception handling and +; unwinding to work across that (as I assume we want?), one apparently +; needs to use either RtlAddFunctionTable() or +; RtlInstallFunctionTableCallback(). See Windows SDK documentation. + +; Random interesting discussion threads: +; http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/300bd6d3-9381-4d2d-8129-e48b392c05d8 + +; Ken Johnson's blog http://www.nynaeve.net/ has much interesting +; information, for instance: +; http://www.nynaeve.net/?p=11 + +; From <typelib/typeclass.h> +typelib_TypeClass_VOID = 0 +typelib_TypeClass_CHAR = 1 +typelib_TypeClass_BOOLEAN = 2 +typelib_TypeClass_BYTE = 3 +typelib_TypeClass_SHORT = 4 +typelib_TypeClass_UNSIGNED_SHORT = 5 +typelib_TypeClass_LONG = 6 +typelib_TypeClass_UNSIGNED_LONG = 7 +typelib_TypeClass_HYPER = 8 +typelib_TypeClass_UNSIGNED_HYPER = 9 +typelib_TypeClass_FLOAT = 10 +typelib_TypeClass_DOUBLE = 11 +typelib_TypeClass_ENUM = 15 + +extrn __copyConstruct : proc +extrn __destruct : proc +extrn cpp_mediate: proc + +.code + +; First we have three code snippets that aren't real functions, but +; "naked" (in x86 calling convention parlance) functions jumped to +; from code generated in C++. + +; I think that for x64 Windows we shouldn't be jumping so wildly from +; generated code snippets into fixed code snippets here. "Procedures" +; should be continuous in memory, or the unwinding information will be +; broken. (For dynamically generated code, that is dynamically +; registered unwind information, obviously.) + +; So instead of generating jumps into here, we should just make the +; C++ code copy the machine code that these three "naked" functions +; compile to after the snippet it is generating. Of course, that means +; the code here needs to be position independent, or (eek) that we +; would need to come up with some home-brewed minimal relocation +; mechanism. + +; Jumped to from code generated in except.cxx: ObjectFunction::ObjectFunction() + +copyConstruct proc + ; ObjectFunction this already on stack + push [rsp+8] ; source exc object this + push rcx ; exc object + call __copyConstruct + add rsp, 12 ; + ObjectFunction this + ret 4 +copyConstruct endp + +; Ditto + +destruct proc + ; ObjectFunction this already on stack + push rcx ; exc object + call __destruct + add rsp, 8 ; + ObjectFunction this + ret +destruct endp + +; Jumped to from code generated in cpp2uno.cxx:codeSnippet() + +cpp_vtable_call proc + sub rsp, 8 ; space for immediate return type + push rsp + push rdx ; vtable offset + push rax ; function index + mov rax, rsp + add rax, 20 + push rax ; original stack ptr + + call cpp_mediate + add rsp, 16 + + cmp rax, typelib_TypeClass_FLOAT + je Lfloat + cmp rax, typelib_TypeClass_DOUBLE + je Ldouble + cmp rax, typelib_TypeClass_HYPER + je Lhyper + cmp eax, typelib_TypeClass_UNSIGNED_HYPER + je Lhyper + ; rest is eax + pop rax + add rsp, 4 + ret +Lhyper: + pop rax + pop rdx + ret +Lfloat: + fld dword ptr [rsp] + add rsp, 8 + ret +Ldouble: + fld qword ptr [rsp] + add rsp, 8 + ret +cpp_vtable_call endp + +; Called from uno2cpp.cxx + +; This one is now hopefully proper x64 Windows code following the +; appropriate conventions and might actually work. + +; void callVirtualMethod( ; location on entry +; void * pAdjustedThisPtr, ; rcx +; sal_Int32 nVtableIndex, ; rdx +; void * pReturn, ; r8 +; typelib_TypeClass eReturnTypeClass, ; r9 +; sal_Int64 * pStack, ; ((4+1)*8)[rsp] +; sal_Int32 nStack ; ((5+1)*8)[rsp] +; sal_uInt64 *pGPR, ; ((6+1)*8)[rsp] +; double *pFPR) ; ((7+1)*8)[rsp] + +callVirtualMethod proc frame + ; Prologue + mov ((3+1)*8)[rsp], r9 + mov ((2+1)*8)[rsp], r8 + mov ((0+1)*8)[rsp], rcx + push rsi + .pushreg rsi + push rdi + .pushreg rdi + + ; Our stack frame size is 24 qwords (space for 20 parameters + ; to pass, plus the two pushed registers rsi and rdi, plus + ; return address, rounded up to 16 bytes) + + sub rsp, (20+1)*8 + .allocstack (20+1)*8 + .endprolog + + ; Stack parameters first + + ; nStack is number of qwords of stack space (including spilled + ; registers). If four or less, 4 is passed in anyway to make + ; code here simpler. + + mov rcx, ((24+5)*8)[rsp] ; nStack + sub rcx, 4 + jle Lxmmregs + + mov rsi, ((24+4)*8)[rsp] ; pStack + add rsi, 32 + lea rdi, 32[rsp] + rep movsq + +Lxmmregs: + ; Parameters passed in XMM registers + + ; We don't bother checking which actually needed, if any. + mov rax, ((24+7)*8)[rsp] ; pFPR + movsd xmm0, qword ptr [rax] + movsd xmm1, qword ptr 8[rax] + movsd xmm2, qword ptr 16[rax] + movsd xmm3, qword ptr 24[rax] + + ; Prepare pointer to function to call + mov rcx, ((24+0)*8)[rsp] + mov r12, [rcx] ; pAdjustedThisPtr->vtable + shl rdx, 3 ; nVtableIndex *= 8 + add r12, rdx + + ; Fill parameters passed in general purpose registers + mov rax, ((24+6)*8)[rsp] ; pGPR + mov rcx, (0*8)[rax] + mov rdx, (1*8)[rax] + mov r8, (2*8)[rax] + mov r9, (3*8)[rax] + + call qword ptr [r12] + + ; Test return type + mov r9, ((24+3)*8)[rsp] + cmp r9, typelib_TypeClass_VOID + je Lepilog + + ; int32 + cmp r9, typelib_TypeClass_LONG + je Lint32 + cmp r9, typelib_TypeClass_UNSIGNED_LONG + je Lint32 + cmp r9, typelib_TypeClass_ENUM + je Lint32 + + ; int8 + cmp r9, typelib_TypeClass_BOOLEAN + je Lint8 + cmp r9, typelib_TypeClass_BYTE + je Lint8 + + ; int16 + cmp r9, typelib_TypeClass_CHAR + je Lint16 + cmp r9, typelib_TypeClass_SHORT + je Lint16 + cmp r9, typelib_TypeClass_UNSIGNED_SHORT + je Lint16 + + ; int64 + cmp r9, typelib_TypeClass_HYPER + je Lint64 + cmp r9, typelib_TypeClass_UNSIGNED_HYPER + je Lint64 + + ; float + cmp r9, typelib_TypeClass_FLOAT + je Lfloat + + ; double + cmp r9, typelib_TypeClass_DOUBLE + je Ldouble + + jmp Lepilog ; no simple type + +Lint8: + mov byte ptr [r8], al + jmp Lepilog + +Lint16: + mov word ptr [r8], ax + jmp Lepilog + +Lint32: + mov dword ptr [r8], eax + jmp Lepilog + +Lint64: + mov qword ptr [r8], rax + jmp Lepilog + +Lfloat: + movss dword ptr [r8], xmm0 + jmp Lepilog + +Ldouble: + movsd qword ptr [r8], xmm0 + +Lepilog: + ; Epilogue + add rsp, (20+1)*8 + pop rdi + pop rsi + ret +callVirtualMethod endp + +end + +; vim:set shiftwidth=4 softtabstop=4 expandtab: diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx new file mode 100644 index 000000000000..a2310cbd8d7d --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx @@ -0,0 +1,574 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> +#include <typelib/typedescription.hxx> + +#include "bridges/cpp_uno/shared/bridge.hxx" +#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx" +#include "bridges/cpp_uno/shared/types.hxx" +#include "bridges/cpp_uno/shared/vtablefactory.hxx" + +#include "mscx.hxx" + +using namespace ::com::sun::star::uno; + +namespace +{ + +//================================================================================================== +static inline typelib_TypeClass cpp2uno_call( + bridges::cpp_uno::shared::CppInterfaceProxy * pThis, + const typelib_TypeDescription * pMemberTypeDescr, + typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return + sal_Int32 nParams, typelib_MethodParameter * pParams, + void ** pCallStack, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: ret, this, [complex return ptr], params + char * pCppStack = (char *)(pCallStack +2); + + // return + typelib_TypeDescription * pReturnTypeDescr = 0; + if (pReturnTypeRef) + { + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + } + + void * pUnoReturn = 0; + void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need + + if (pReturnTypeDescr) + { + if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr )) + { + pUnoReturn = pRegisterReturn; // direct way for simple types + } + else // complex return via ptr (pCppReturn) + { + pCppReturn = *(void **)pCppStack; + pCppStack += sizeof(void *); + + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( + pReturnTypeDescr ) + ? alloca( pReturnTypeDescr->nSize ) + : pCppReturn); // direct way + } + } + + // parameters + void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams ); + void ** pCppArgs = pUnoArgs + nParams; + // indexes of values this have to be converted (interface conversion cpp<=>uno) + sal_Int64 * pTempIndexes = (sal_Int64 *)(pUnoArgs + (2 * nParams)); + // type descriptions for reconversions + typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams)); + + sal_Int32 nTempIndexes = 0; + + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + // value + { + pCppArgs[nPos] = pCppStack; + pUnoArgs[nPos] = pCppStack; + switch (pParamTypeDescr->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + pCppStack += sizeof(sal_Int64); // extra qword + break; + default: + break; + } + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *(void **)pCppStack; + + if (! rParam.bIn) // is pure out + { + // uno out is unconstructed mem! + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ); + pTempIndexes[nTempIndexes] = nPos; + // will be released at reconversion + ppTempParamTypeDescr[nTempIndexes++] = pParamTypeDescr; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + ::uno_copyAndConvertData( + pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ), + *(void **)pCppStack, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + pTempIndexes[nTempIndexes] = nPos; // has to be reconverted + // will be released at reconversion + ppTempParamTypeDescr[nTempIndexes++] = pParamTypeDescr; + } + else // direct way + { + pUnoArgs[nPos] = *(void **)pCppStack; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + pCppStack += sizeof(sal_Int64); // standard parameter length + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any * pUnoExc = &aUnoExc; + + // invoke uno dispatch call + (*pThis->getUnoI()->pDispatcher)( + pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc ); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + while (nTempIndexes--) + { + sal_Int32 nIndex = pTempIndexes[nTempIndexes]; + + if (pParams[nIndex].bIn) // is in/inout => was constructed + { + ::uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndexes], 0 ); + } + TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndexes] ); + } + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + + CPPU_CURRENT_NAMESPACE::mscx_raiseException( + &aUnoExc, pThis->getBridge()->getUno2Cpp() ); + // has to destruct the any + // is here for dummy + return typelib_TypeClass_VOID; + } + else // else no exception occurred... + { + // temporary params + while (nTempIndexes--) + { + sal_Int32 nIndex = pTempIndexes[nTempIndexes]; + typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndexes]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + ::uno_destructData( + pCppArgs[nIndex], pParamTypeDescr, cpp_release ); + ::uno_copyAndConvertData( + pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + } + // destroy temp uno param + ::uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + ::uno_copyAndConvertData( + pCppReturn, pUnoReturn, pReturnTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + // destroy temp uno return + ::uno_destructData( + pUnoReturn, pReturnTypeDescr, 0 ); + } + // complex return ptr is set to eax + *(void **)pRegisterReturn = pCppReturn; + } + if (pReturnTypeDescr) + { + typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass; + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + return eRet; + } + else + return typelib_TypeClass_VOID; + } +} + +//================================================================================================== +typelib_TypeClass __cdecl cpp_mediate( + void ** pCallStack, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset, + sal_Int64 * pRegisterReturn /* space for register return */ ) +{ + // pCallStack: ret adr, this, [ret *], params + void * pThis = static_cast< char * >(pCallStack[1]) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy * pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( + pThis); + + typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr(); + OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, + "### illegal vtable index!" ); + if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex) + { + throw RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("illegal vtable index!") ), + (XInterface *)pThis ); + } + + // determine called method + sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" ); + + TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] ); + + typelib_TypeClass eRet; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { + // is GET method + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef, + 0, 0, // no params + pCallStack, pRegisterReturn ); + } + else + { + // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + 0, // indicates void return + 1, &aParam, + pCallStack, pRegisterReturn ); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + // standard XInterface vtable calls + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() ); + if (pTD) + { + XInterface * pInterface = 0; + (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)( + pCppI->getBridge()->getCppEnv(), + (void **)&pInterface, pCppI->getOid().pData, + (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pCallStack[2] ), + &pInterface, pTD, cpp_acquire ); + pInterface->release(); + TYPELIB_DANGER_RELEASE( pTD ); + *(void **)pRegisterReturn = pCallStack[2]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + eRet = cpp2uno_call( + pCppI, aMemberDescr.get(), + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams, + ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams, + pCallStack, pRegisterReturn ); + } + break; + } + default: + { + throw RuntimeException( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("no member description found!") ), + (XInterface *)pThis ); + // is here for dummy + eRet = typelib_TypeClass_VOID; + } + } + + return eRet; +} + +extern void *cpp_vtable_call; + +//================================================================================================== +int const codeSnippetSize = 28; + +// This function generates the code that acts as a proxy for the UNO function to be called. +// The generated code does the following: +// - Save register parametrs. + +unsigned char * codeSnippet( + unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset) +{ + unsigned char * p = code; + + // mov eax, functionIndex: + *p++ = 0xB8; + *reinterpret_cast< sal_Int32 * >(p) = functionIndex; + p += sizeof (sal_Int32); + + // mov edx, vtableOffset: + *p++ = 0xBA; + *reinterpret_cast< sal_Int32 * >(p) = vtableOffset; + p += sizeof (sal_Int32); + +#if 0 + sub esp, 8 // space for immediate return type + push esp + push edx // vtable offset + push eax // function index + mov eax, esp + add eax, 20 + push eax // original stack ptr + + call cpp_mediate + add esp, 16 + + cmp eax, typelib_TypeClass_FLOAT + je Lfloat + cmp eax, typelib_TypeClass_DOUBLE + je Ldouble + cmp eax, typelib_TypeClass_HYPER + je Lhyper + cmp eax, typelib_TypeClass_UNSIGNED_HYPER + je Lhyper + // rest is eax + pop eax + add esp, 4 + ret +Lhyper: + pop eax + pop edx + ret +Lfloat: + fld dword ptr [esp] + add esp, 8 + ret +Ldouble: + fld qword ptr [esp] + add esp, 8 + ret + +#endif + +#if 0 + // jmp rel64 cpp_vtable_call: + *p++ = 0xE9; + *reinterpret_cast< sal_Int64 * >(p) + = ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int64); + p += sizeof (sal_Int64); +#endif + OSL_ASSERT(p - code <= codeSnippetSize); + return code + codeSnippetSize; +} + +} + +struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; }; + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) +{ + return static_cast< Slot * >(block) + 1; +} + +sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize( + sal_Int32 slotCount) +{ + return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize; +} + +bridges::cpp_uno::shared::VtableFactory::Slot * +bridges::cpp_uno::shared::VtableFactory::initializeBlock( + void * block, sal_Int32 slotCount) +{ + struct Rtti { + sal_Int32 n0, n1, n2; + type_info * rtti; + Rtti(): + n0(0), n1(0), n2(0), + rtti(CPPU_CURRENT_NAMESPACE::mscx_getRTTI( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.uno.XInterface")))) + {} + }; + static Rtti rtti; + + Slot * slots = mapBlockToVtable(block); + slots[-1].fn = &rtti; + return slots + slotCount; +} + +#if 0 + +#else + +static void whatthefuck(sal_Int64 i, ...) +{ + MessageBoxA (NULL, "Shit!", "whatthefuck in cpp2uno.cxx", MB_OK); +} + +#endif + +unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions( + Slot ** slots, unsigned char * code, + typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset, + sal_Int32 functionCount, sal_Int32 vtableOffset) +{ + (*slots) -= functionCount; + Slot * s = *slots; + + for (int i = 0; i < functionCount; ++i) { + typelib_TypeDescription * pTD = 0; + + TYPELIB_DANGER_GET( &pTD, type->ppMembers[ i ] ); + OSL_ASSERT( pTD ); + + CPPU_CURRENT_NAMESPACE::RegParamKind param_kind[4]; + int nr = 0; + + if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE ) + { + typelib_InterfaceAttributeTypeDescription *pAttrTD = + reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD ); + + // get method +#if 0 + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset); +#else + (s++)->fn = whatthefuck; +#endif + + if ( ! pAttrTD->bReadOnly ) + { + // set method +#if 0 + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset); +#else + (s++)->fn = whatthefuck; +#endif + } + } + else if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_METHOD ) + { + typelib_InterfaceMethodTypeDescription *pMethodTD = + reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD ); + + typelib_TypeDescription *pReturnTD = 0; + TYPELIB_DANGER_GET( &pReturnTD, pMethodTD->pReturnTypeRef ); + OSL_ASSERT( pReturnTD ); + + if ( pReturnTD->nSize > 8 ) { + // Hidden return value + param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT; + } + TYPELIB_DANGER_RELEASE( pReturnTD ); + + // 'this' + param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT; + + for (int j = 0; nr < 4 && j < pMethodTD->nParams; ++j) + { + typelib_TypeDescription *pParamTD = 0; + + TYPELIB_DANGER_GET( &pParamTD, pMethodTD->pParams[j].pTypeRef ); + OSL_ASSERT( pParamTD ); + + if ( pParamTD->eTypeClass == typelib_TypeClass_FLOAT || + pParamTD->eTypeClass == typelib_TypeClass_DOUBLE ) + param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT; + else + param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT; + + TYPELIB_DANGER_RELEASE( pParamTD ); + +#if 0 + (s++)->fn = code; + code = codeSnippet(code, functionOffset++, vtableOffset); +#else + (s++)->fn = whatthefuck; +#endif + } + } + else + OSL_ASSERT( false ); + } + return code; +} + +void bridges::cpp_uno::shared::VtableFactory::flushCode( + unsigned char const *, unsigned char const *) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/dllinit.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/dllinit.cxx new file mode 100644 index 000000000000..cfbc58650f0d --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/dllinit.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + + +#pragma warning(push,1) // disable warnings within system headers +#include <windows.h> +#pragma warning(pop) + + +void dso_init(void); +void dso_exit(void); + + +extern "C" BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpvReserved) +{ + switch(dwReason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hModule); + + dso_init(); + break; + + case DLL_PROCESS_DETACH: + if (!lpvReserved) + dso_exit(); + break; + } + + return TRUE; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx new file mode 100644 index 000000000000..bb5c5b1922b8 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx @@ -0,0 +1,623 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#pragma warning( disable : 4237 ) +#include <hash_map> +#include <sal/config.h> +#include <malloc.h> +#include <new.h> +#include <typeinfo.h> +#include <signal.h> + +#include "rtl/alloc.h" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" + +#include "com/sun/star/uno/Any.hxx" + +#include "mscx.hxx" + + +#pragma pack(push, 8) + +using namespace ::com::sun::star::uno; +using namespace ::std; +using namespace ::osl; +using namespace ::rtl; + +namespace CPPU_CURRENT_NAMESPACE +{ + +//================================================================================================== +static inline OUString toUNOname( OUString const & rRTTIname ) throw () +{ + OUStringBuffer aRet( 64 ); + OUString aStr( rRTTIname.copy( 4, rRTTIname.getLength()-4-2 ) ); // filter .?AUzzz@yyy@xxx@@ + sal_Int32 nPos = aStr.getLength(); + while (nPos > 0) + { + sal_Int32 n = aStr.lastIndexOf( '@', nPos ); + aRet.append( aStr.copy( n +1, nPos -n -1 ) ); + if (n >= 0) + { + aRet.append( (sal_Unicode)'.' ); + } + nPos = n; + } + return aRet.makeStringAndClear(); +} +//================================================================================================== +static inline OUString toRTTIname( OUString const & rUNOname ) throw () +{ + OUStringBuffer aRet( 64 ); + aRet.appendAscii( RTL_CONSTASCII_STRINGPARAM(".?AV") ); // class ".?AV"; struct ".?AU" + sal_Int32 nPos = rUNOname.getLength(); + while (nPos > 0) + { + sal_Int32 n = rUNOname.lastIndexOf( '.', nPos ); + aRet.append( rUNOname.copy( n +1, nPos -n -1 ) ); + aRet.append( (sal_Unicode)'@' ); + nPos = n; + } + aRet.append( (sal_Unicode)'@' ); + return aRet.makeStringAndClear(); +} + + +//################################################################################################## +//#### RTTI simulation ############################################################################# +//################################################################################################## + + +typedef hash_map< OUString, void *, OUStringHash, equal_to< OUString > > t_string2PtrMap; + +//================================================================================================== +class RTTInfos +{ + Mutex _aMutex; + t_string2PtrMap _allRTTI; + + static OUString toRawName( OUString const & rUNOname ) throw (); +public: + type_info * getRTTI( OUString const & rUNOname ) throw (); + + RTTInfos(); + ~RTTInfos(); +}; + +//================================================================================================== +class __type_info +{ + friend type_info * RTTInfos::getRTTI( OUString const & ) throw (); + friend int mscx_filterCppException( + LPEXCEPTION_POINTERS, uno_Any *, uno_Mapping * ); + +public: + virtual ~__type_info() throw (); + + inline __type_info( void * m_data, const char * m_d_name ) throw () + : _m_data( m_data ) + { ::strcpy( _m_d_name, m_d_name ); } // #100211# - checked + +private: + void * _m_data; + char _m_d_name[1]; +}; +//__________________________________________________________________________________________________ +__type_info::~__type_info() throw () +{ +} +//__________________________________________________________________________________________________ +type_info * RTTInfos::getRTTI( OUString const & rUNOname ) throw () +{ + // a must be + OSL_ENSURE( sizeof(__type_info) == sizeof(type_info), "### type info structure size differ!" ); + + MutexGuard aGuard( _aMutex ); + t_string2PtrMap::const_iterator const iFind( _allRTTI.find( rUNOname ) ); + + // check if type is already available + if (iFind == _allRTTI.end()) + { + // insert new type_info + OString aRawName( OUStringToOString( toRTTIname( rUNOname ), RTL_TEXTENCODING_ASCII_US ) ); + __type_info * pRTTI = new( ::rtl_allocateMemory( sizeof(__type_info) + aRawName.getLength() ) ) + __type_info( NULL, aRawName.getStr() ); + + // put into map + pair< t_string2PtrMap::iterator, bool > insertion( + _allRTTI.insert( t_string2PtrMap::value_type( rUNOname, pRTTI ) ) ); + OSL_ENSURE( insertion.second, "### rtti insertion failed?!" ); + + return (type_info *)pRTTI; + } + else + { + return (type_info *)iFind->second; + } +} +//__________________________________________________________________________________________________ +RTTInfos::RTTInfos() throw () +{ +} +//__________________________________________________________________________________________________ +RTTInfos::~RTTInfos() throw () +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "> freeing generated RTTI infos... <\n" ); +#endif + + MutexGuard aGuard( _aMutex ); + for ( t_string2PtrMap::const_iterator iPos( _allRTTI.begin() ); + iPos != _allRTTI.end(); ++iPos ) + { + __type_info * pType = (__type_info *)iPos->second; + pType->~__type_info(); // obsolete, but good style... + ::rtl_freeMemory( pType ); + } +} + + +//################################################################################################## +//#### Exception raising ########################################################################### +//################################################################################################## + + +//================================================================================================== +struct ObjectFunction +{ + char somecode[12]; + typelib_TypeDescription * _pTypeDescr; // type of object + + inline static void * operator new ( size_t nSize ); + inline static void operator delete ( void * pMem ); + + ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) throw (); + ~ObjectFunction() throw (); +}; + +inline void * ObjectFunction::operator new ( size_t nSize ) +{ + void * pMem = rtl_allocateMemory( nSize ); + if (pMem != 0) + { + DWORD old_protect; +#if OSL_DEBUG_LEVEL > 0 + BOOL success = +#endif + VirtualProtect( pMem, nSize, PAGE_EXECUTE_READWRITE, &old_protect ); + OSL_ENSURE( success, "VirtualProtect() failed!" ); + } + return pMem; +} + +inline void ObjectFunction::operator delete ( void * pMem ) +{ + rtl_freeMemory( pMem ); +} + +//__________________________________________________________________________________________________ +ObjectFunction::ObjectFunction( typelib_TypeDescription * pTypeDescr, void * fpFunc ) throw () + : _pTypeDescr( pTypeDescr ) +{ + ::typelib_typedescription_acquire( _pTypeDescr ); + + unsigned char * pCode = (unsigned char *)somecode; + // a must be! + OSL_ENSURE( (void *)this == (void *)pCode, "### unexpected!" ); + + // push ObjectFunction this + *pCode++ = 0x68; + *(void **)pCode = this; + pCode += sizeof(void *); + // jmp rel64 fpFunc + *pCode++ = 0xe9; + *(sal_Int64 *)pCode = ((unsigned char *)fpFunc) - pCode - sizeof(sal_Int64); +} +//__________________________________________________________________________________________________ +ObjectFunction::~ObjectFunction() throw () +{ + ::typelib_typedescription_release( _pTypeDescr ); +} + +//================================================================================================== +void * __cdecl __copyConstruct( void * pExcThis, void * pSource, ObjectFunction * pThis ) + throw () +{ + ::uno_copyData( pExcThis, pSource, pThis->_pTypeDescr, cpp_acquire ); + return pExcThis; +} +//================================================================================================== +void * __cdecl __destruct( void * pExcThis, ObjectFunction * pThis ) + throw () +{ + ::uno_destructData( pExcThis, pThis->_pTypeDescr, cpp_release ); + return pExcThis; +} + + +#if 0 + +// These are machine code snippets in asmbits.asm + +extern void *copyConstruct; +extern void *destruct; + +#else + +static void whatthefuck_copyctor(sal_Int64 i, ...) +{ + MessageBoxA (NULL, "Shit!", "whatthefuck_copyctor in except.cxx", MB_OK); +} + +static void whatthefuck_dtor(sal_Int64 i, ...) +{ + MessageBoxA (NULL, "Shit!", "whatthefuck_dtor in except.cxx", MB_OK); +} + +#endif + +//================================================================================================== +struct ExceptionType +{ + sal_Int32 _n0; + type_info * _pTypeInfo; + sal_Int32 _n1, _n2, _n3, _n4; + ObjectFunction * _pCopyCtor; + sal_Int32 _n5; + + inline ExceptionType( typelib_TypeDescription * pTypeDescr ) throw () + : _n0( 0 ) + , _n1( 0 ) + , _n2( -1 ) + , _n3( 0 ) + , _n4( pTypeDescr->nSize ) +#if 0 + , _pCopyCtor( new ObjectFunction( pTypeDescr, copyConstruct ) ) +#else + , _pCopyCtor( (ObjectFunction*) whatthefuck_copyctor ) +#endif + , _n5( 0 ) + { _pTypeInfo = mscx_getRTTI( pTypeDescr->pTypeName ); } + inline ~ExceptionType() throw () + { delete _pCopyCtor; } +}; +//================================================================================================== +struct RaiseInfo +{ + sal_Int32 _n0; + ObjectFunction * _pDtor; + sal_Int32 _n2; + void * _types; + sal_Int32 _n3, _n4; + + RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw (); + ~RaiseInfo() throw (); +}; +//__________________________________________________________________________________________________ +RaiseInfo::RaiseInfo( typelib_TypeDescription * pTypeDescr ) throw () + : _n0( 0 ) +#if 0 + , _pDtor( new ObjectFunction( pTypeDescr, destruct ) ) +#else + , _pDtor( (ObjectFunction*) whatthefuck_dtor ) +#endif + , _n2( 0 ) + , _n3( 0 ) + , _n4( 0 ) +{ + typelib_CompoundTypeDescription * pCompTypeDescr; + + // info count + sal_Int32 nLen = 0; + for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr; + pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + ++nLen; + } + + // info count accompanied by type info ptrs: type, base type, base base type, ... + _types = ::rtl_allocateMemory( sizeof(sal_Int64) + (sizeof(ExceptionType *) * nLen) ); + *(sal_Int64 *)_types = nLen; + + ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1); + + sal_Int32 nPos = 0; + for ( pCompTypeDescr = (typelib_CompoundTypeDescription*)pTypeDescr; + pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + ppTypes[nPos++] = new ExceptionType( (typelib_TypeDescription *)pCompTypeDescr ); + } +} +//__________________________________________________________________________________________________ +RaiseInfo::~RaiseInfo() throw () +{ + ExceptionType ** ppTypes = (ExceptionType **)((sal_Int64 *)_types + 1); + for ( sal_Int32 nTypes = *(sal_Int64 *)_types; nTypes--; ) + { + delete ppTypes[nTypes]; + } + ::rtl_freeMemory( _types ); + + delete _pDtor; +} + +//================================================================================================== +class ExceptionInfos +{ + Mutex _aMutex; + t_string2PtrMap _allRaiseInfos; + +public: + static void * getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw (); + + ExceptionInfos() throw (); + ~ExceptionInfos() throw (); +}; +//__________________________________________________________________________________________________ +ExceptionInfos::ExceptionInfos() throw () +{ +} +//__________________________________________________________________________________________________ +ExceptionInfos::~ExceptionInfos() throw () +{ +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "> freeing exception infos... <\n" ); +#endif + + MutexGuard aGuard( _aMutex ); + for ( t_string2PtrMap::const_iterator iPos( _allRaiseInfos.begin() ); + iPos != _allRaiseInfos.end(); ++iPos ) + { + delete (RaiseInfo *)iPos->second; + } +} +//__________________________________________________________________________________________________ +void * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTypeDescr ) throw () +{ + static ExceptionInfos * s_pInfos = 0; + if (! s_pInfos) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pInfos) + { +#ifdef LEAK_STATIC_DATA + s_pInfos = new ExceptionInfos(); +#else + static ExceptionInfos s_allExceptionInfos; + s_pInfos = &s_allExceptionInfos; +#endif + } + } + + OSL_ASSERT( pTypeDescr && + (pTypeDescr->eTypeClass == typelib_TypeClass_STRUCT || + pTypeDescr->eTypeClass == typelib_TypeClass_EXCEPTION) ); + + void * pRaiseInfo; + + OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTypeDescr->pTypeName ); + MutexGuard aGuard( s_pInfos->_aMutex ); + t_string2PtrMap::const_iterator const iFind( + s_pInfos->_allRaiseInfos.find( rTypeName ) ); + if (iFind == s_pInfos->_allRaiseInfos.end()) + { + pRaiseInfo = new RaiseInfo( pTypeDescr ); + // put into map + pair< t_string2PtrMap::iterator, bool > insertion( + s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, pRaiseInfo ) ) ); + OSL_ENSURE( insertion.second, "### raise info insertion failed?!" ); + } + else + { + // reuse existing info + pRaiseInfo = iFind->second; + } + + return pRaiseInfo; +} + + +//################################################################################################## +//#### exported #################################################################################### +//################################################################################################## + + +//################################################################################################## +type_info * mscx_getRTTI( OUString const & rUNOname ) +{ + static RTTInfos * s_pRTTIs = 0; + if (! s_pRTTIs) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pRTTIs) + { +#ifdef LEAK_STATIC_DATA + s_pRTTIs = new RTTInfos(); +#else + static RTTInfos s_aRTTIs; + s_pRTTIs = &s_aRTTIs; +#endif + } + } + return s_pRTTIs->getRTTI( rUNOname ); +} + +//################################################################################################## +void mscx_raiseException( uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ) +{ + // no ctor/dtor in here: this leads to dtors called twice upon RaiseException()! + // thus this obj file will be compiled without opt, so no inling of + // ExceptionInfos::getRaiseInfo() + + // construct cpp exception object + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, pUnoExc->pType ); + + void * pCppExc = alloca( pTypeDescr->nSize ); + ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTypeDescr, pUno2Cpp ); + + ULONG_PTR arFilterArgs[3]; + arFilterArgs[0] = MSVC_magic_number; + arFilterArgs[1] = (ULONG_PTR)pCppExc; + arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTypeDescr ); + + // destruct uno exception + ::uno_any_destruct( pUnoExc, 0 ); + TYPELIB_DANGER_RELEASE( pTypeDescr ); + + // last point to release anything not affected by stack unwinding + RaiseException( MSVC_ExceptionCode, EXCEPTION_NONCONTINUABLE, 3, arFilterArgs ); +} + +//############################################################################## +int mscx_filterCppException( + EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ) +{ + if (pPointers == 0) + return EXCEPTION_CONTINUE_SEARCH; + EXCEPTION_RECORD * pRecord = pPointers->ExceptionRecord; + // handle only C++ exceptions: + if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) + return EXCEPTION_CONTINUE_SEARCH; + + bool rethrow = __CxxDetectRethrow( &pRecord ); + OSL_ASSERT( pRecord == pPointers->ExceptionRecord ); + + if (rethrow && pRecord == pPointers->ExceptionRecord) + { + // hack to get msvcrt internal _curexception field: + pRecord = *reinterpret_cast< EXCEPTION_RECORD ** >( + reinterpret_cast< char * >( __pxcptinfoptrs() ) + + // as long as we don't demand msvcr source as build prerequisite + // (->platform sdk), we have to code those offsets here. + // + // crt\src\mtdll.h: + // offsetof (_tiddata, _curexception) - + // offsetof (_tiddata, _tpxcptinfoptrs): +#if _MSC_VER < 1500 + error, this compiler version is not supported +#elif _MSC_VER < 1600 + 0x48 // msvcr90.dll +#else + error, please find value for this compiler version +#endif + ); + } + // rethrow: handle only C++ exceptions: + if (pRecord == 0 || pRecord->ExceptionCode != MSVC_ExceptionCode) + return EXCEPTION_CONTINUE_SEARCH; + + if (pRecord->NumberParameters == 3 && +// pRecord->ExceptionInformation[ 0 ] == MSVC_magic_number && + pRecord->ExceptionInformation[ 1 ] != 0 && + pRecord->ExceptionInformation[ 2 ] != 0) + { + void * types = reinterpret_cast< RaiseInfo * >( + pRecord->ExceptionInformation[ 2 ] )->_types; + if (types != 0 && *reinterpret_cast< DWORD * >( types ) > 0) // count + { + ExceptionType * pType = *reinterpret_cast< ExceptionType ** >( + reinterpret_cast< DWORD * >( types ) + 1 ); + if (pType != 0 && pType->_pTypeInfo != 0) + { + OUString aRTTIname( + OStringToOUString( + reinterpret_cast< __type_info * >( + pType->_pTypeInfo )->_m_d_name, + RTL_TEXTENCODING_ASCII_US ) ); + OUString aUNOname( toUNOname( aRTTIname ) ); + + typelib_TypeDescription * pExcTypeDescr = 0; + typelib_typedescription_getByName( + &pExcTypeDescr, aUNOname.pData ); + if (pExcTypeDescr == 0) + { + OUStringBuffer buf; + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM( + "[mscx_uno bridge error] UNO type of " + "C++ exception unknown: \"") ); + buf.append( aUNOname ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\", RTTI-name=\"") ); + buf.append( aRTTIname ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") ); + RuntimeException exc( + buf.makeStringAndClear(), Reference< XInterface >() ); + uno_type_any_constructAndConvert( + pUnoExc, &exc, + ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno ); +#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs + // if (! rethrow): + // though this unknown exception leaks now, no user-defined + // exception is ever thrown thru the binary C-UNO dispatcher + // call stack. +#endif + } + else + { + // construct uno exception any + uno_any_constructAndConvert( + pUnoExc, (void *) pRecord->ExceptionInformation[1], + pExcTypeDescr, pCpp2Uno ); +#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs + if (! rethrow) + { + uno_destructData( + (void *) pRecord->ExceptionInformation[1], + pExcTypeDescr, cpp_release ); + } +#endif + typelib_typedescription_release( pExcTypeDescr ); + } + + return EXCEPTION_EXECUTE_HANDLER; + } + } + } + // though this unknown exception leaks now, no user-defined exception + // is ever thrown thru the binary C-UNO dispatcher call stack. + RuntimeException exc( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "[mscx_uno bridge error] unexpected " + "C++ exception occurred!") ), + Reference< XInterface >() ); + uno_type_any_constructAndConvert( + pUnoExc, &exc, ::getCppuType( &exc ).getTypeLibType(), pCpp2Uno ); + return EXCEPTION_EXECUTE_HANDLER; +} + +} + +#pragma pack(pop) + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk new file mode 100644 index 000000000000..604799a18e5a --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=bridges +TARGET=mscx_uno +LIBTARGET=no +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +.IF "$(COM)$(CPU)" == "MSCX" + +.IF "$(debug)" != "" +CFLAGS += -Ob0 +.ENDIF + +.IF "$(cppu_no_leak)" == "" +.IF "$(bndchk)" == "" +CFLAGS += -DLEAK_STATIC_DATA +.ENDIF +.ENDIF + + +SLOFILES= \ + $(SLO)$/cpp2uno.obj \ + $(SLO)$/uno2cpp.obj \ + $(SLO)$/dllinit.obj \ + $(SLO)$/except.obj + +NOOPTFILES= \ + $(SLO)$/except.obj + +SHL1TARGET= $(TARGET) + +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1IMPLIB=i$(TARGET) +SHL1VERSIONMAP=..$/..$/bridge_exports.map +SHL1RPATH=URELIB + +SHL1OBJS = $(SLOFILES) +SHL1LIBS = $(SLB)$/cpp_uno_shared.lib + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALLIB) + +DEF1NAME=$(SHL1TARGET) + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx b/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx new file mode 100644 index 000000000000..044bd4bb1316 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#pragma warning(push, 1) +#include <windows.h> +#pragma warning(pop) + +#include "rtl/ustring.hxx" + + +class type_info; +typedef struct _uno_Any uno_Any; +typedef struct _uno_Mapping uno_Mapping; + +namespace CPPU_CURRENT_NAMESPACE +{ + +const DWORD MSVC_ExceptionCode = 0xe06d7363; +const long MSVC_magic_number = 0x19930520L; + +typedef enum { REGPARAM_INT, REGPARAM_FLT } RegParamKind; + + +//============================================================================== +type_info * mscx_getRTTI( ::rtl::OUString const & rUNOname ); + +//============================================================================== +int mscx_filterCppException( + EXCEPTION_POINTERS * pPointers, uno_Any * pUnoExc, uno_Mapping * pCpp2Uno ); + +//============================================================================== +void mscx_raiseException( + uno_Any * pUnoExc, uno_Mapping * pUno2Cpp ); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx new file mode 100644 index 000000000000..de6f5f212ec4 --- /dev/null +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx @@ -0,0 +1,453 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_bridges.hxx" + +#include <malloc.h> + +#include <com/sun/star/uno/genfunc.hxx> +#include <uno/data.h> + +#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 "mscx.hxx" + +#if OSL_DEBUG_LEVEL > 1 +#include <stdio.h> +#endif + +using namespace ::rtl; +using namespace ::com::sun::star::uno; + +namespace +{ + +// As "long" is 32 bit also in x64 Windows we don't use "longs" in names +// to indicate pointer-sized stack slots etc like in the other x64 archs, +// but "qword" as in ml64. + +//================================================================================================== +// In asmbits.asm +extern void callVirtualMethod( + void * pAdjustedThisPtr, sal_Int32 nVtableIndex, + void * pReturn, typelib_TypeClass eReturnTypeClass, + sal_Int64 * pStack, sal_Int32 nStack, + sal_uInt64 *pGPR, + double *pFPR); + +#if OSL_DEBUG_LEVEL > 1 +inline void callVirtualMethodwrapper( + void * pAdjustedThisPtr, sal_Int32 nVtableIndex, + void * pReturn, typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int64 * pStack, sal_Int32 nStack, + sal_uInt64 *pGPR, sal_uInt32 nGPR, + double *pFPR, sal_uInt32 nFPR) +{ + // Let's figure out what is really going on here + { + fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR ); + for ( unsigned int i = 0; i < nGPR; ++i ) + fprintf( stderr, "0x%lx, ", pGPR[i] ); + fprintf( stderr, "\nFPR's (%d): ", nFPR ); + for ( unsigned int i = 0; i < nFPR; ++i ) + fprintf( stderr, "%f, ", pFPR[i] ); + fprintf( stderr, "\nStack (%d): ", nStack ); + for ( unsigned int i = 0; i < nStack; ++i ) + fprintf( stderr, "0x%lx, ", pStack[i] ); + fprintf( stderr, "\n" ); + } + + callVirtualMethod( pAdjustedThisPtr, nVtableIndex, + pReturn, pReturnTypeRef->eTypeClass, + pStack, nStack, + pGPR, + pFPR); +} + +#define callVirtualMethod callVirtualMethodwrapper + +#endif + +//================================================================================================== +static void cpp_call( + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis, + bridges::cpp_uno::shared::VtableSlot aVtableSlot, + typelib_TypeDescriptionReference * pReturnTypeRef, + sal_Int32 nParams, typelib_MethodParameter * pParams, + void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc ) throw () +{ + const int MAXPARAMS = 20; + + MessageBoxA (NULL, "Whoa!", "cpp_call in uno2cpp.cxx", MB_OK); + + if (nParams > MAXPARAMS) + { + // We have a hard limit on the number of parameters so that we + // don't need any assembler stuff but can call the function + // using normal C++. + + // What is the proper way to abort with at least some + // information given to the user? + abort(); + } + + // table with optional complex return value ptr, this pointer, and the parameters + union { + sal_Int64 i; + void *p; + double d; + } aCppParams[MAXPARAMS+2], uRetVal; + int nCppParamIndex = 0; + + // Return type + typelib_TypeDescription * pReturnTypeDescr = 0; + TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef ); + OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" ); + + bool bSimpleReturn = true; + if (pReturnTypeDescr) + { + if (pReturnTypeDescr->nSize > 8) + { + // complex return via ptr + bSimpleReturn = false; + aCppParams[nCppParamIndex++].p = alloca( pReturnTypeDescr->nSize ); + } + } + + // "this" + sal_Int64 * pCppThis = (sal_Int64 *) (pThis->getCppI()) + aVtableSlot.offset; + aCppParams[nCppParamIndex++].p = pCppThis; + + // Indexes of values this have to be converted (interface conversion cpp<=>uno) + int pTempCppIndexes[MAXPARAMS]; + int pTempIndexes[MAXPARAMS]; + int nTempIndexes = 0; + + // Type descriptions for reconversions + typelib_TypeDescription *pTempParamTypeDescr[MAXPARAMS]; + + for ( int nPos = 0; nPos < nParams; ++nPos ) + { + const typelib_MethodParameter & rParam = pParams[nPos]; + typelib_TypeDescription * pParamTypeDescr = 0; + TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef ); + + if (!rParam.bOut + && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) + { + ::uno_copyAndConvertData( + aCppParams[nCppParamIndex++].p, pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + else // ptr to complex value | ref + { + if (! rParam.bIn) // is pure out + { + // cpp out is constructed mem, uno out is not! + ::uno_constructData( + aCppParams[nCppParamIndex].p = alloca( pParamTypeDescr->nSize ), + pParamTypeDescr ); + + pTempCppIndexes[nTempIndexes] = nCppParamIndex; + pTempIndexes[nTempIndexes] = nPos; + + // will be released at reconversion + pTempParamTypeDescr[nTempIndexes++] = pParamTypeDescr; + + nCppParamIndex++; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType( + pParamTypeDescr )) + { + ::uno_copyAndConvertData( + aCppParams[nCppParamIndex].p = alloca( pParamTypeDescr->nSize ), + pUnoArgs[nPos], pParamTypeDescr, + pThis->getBridge()->getUno2Cpp() ); + + pTempCppIndexes[nTempIndexes] = nCppParamIndex; + pTempIndexes[nTempIndexes] = nPos; + + // will be released at reconversion + pTempParamTypeDescr[nTempIndexes++] = pParamTypeDescr; + + nCppParamIndex++; + } + else // direct way + { + aCppParams[nCppParamIndex++].p = pUnoArgs[nPos]; + // no longer needed + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + } + } + + __try + { + // The first real parameter is always a pointer: either the + // address of where to store a complex return value or "this". + + // The Windows x64 calling convention is very regular and + // elegant (even if perhaps then slightly slower than the + // Linux x64 one): The first four parameters, never more, are + // passed in registers, as long as they are a qword in size + // or less. (If larger, a pointer to a temp copy is passed, so + // it's equivalent anyway.) Floating point values are passed + // in XMM0..3 registers, others in RCX, RDX, R8, R9. + + // Now, the nice thing for us is that when calling varargs + // functions, floating-point parameters among the four first + // ones are always passed *both* in an XMM and integer + // register. So we don't need to bother here calling the + // method different ways depending on what types of parameters + // it actually expects. We just pretend parameters 3..4 are + // doubles, and they will be passed both in XMM and integer + // registers, and the callee will find them where it + // expects. (The callee is not actually varargs, of course.) + + sal_Int64 (*pMethod)(sal_Int64, ...) = + (sal_Int64 (*)(sal_Int64, ...)) + (((sal_Int64 *)pCppThis) + aVtableSlot.index); + + // Pass parameters 2..4 as double so that it gets put in both XMM and integer + // registers per the + uRetVal.i = + pMethod (aCppParams[0].i, aCppParams[1].d, aCppParams[2].d, aCppParams[3].d, + aCppParams[4].i, aCppParams[5].i, aCppParams[6].i, aCppParams[7].i, + aCppParams[8].i, aCppParams[9].i, aCppParams[10].i, aCppParams[11].i, + aCppParams[12].i, aCppParams[13].i, aCppParams[14].i, aCppParams[15].i, + aCppParams[16].i, aCppParams[17].i, aCppParams[18].i, aCppParams[19].i ); + } + __except (CPPU_CURRENT_NAMESPACE::mscx_filterCppException( + GetExceptionInformation(), + *ppUnoExc, pThis->getBridge()->getCpp2Uno() )) + { + // *ppUnoExc was constructed by filter function + // temporary params + while (nTempIndexes--) + { + int nCppIndex = pTempCppIndexes[nTempIndexes]; + // destroy temp cpp param => cpp: every param was constructed + ::uno_destructData( + aCppParams[nCppIndex].p, pTempParamTypeDescr[nTempIndexes], + cpp_release ); + TYPELIB_DANGER_RELEASE( pTempParamTypeDescr[nTempIndexes] ); + } + // return type + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } + // end here + return; + } + + // NO exception occurred + *ppUnoExc = 0; + + // Reconvert temporary params + while (nTempIndexes--) + { + int nCppIndex = pTempCppIndexes[nTempIndexes]; + int nIndex = pTempIndexes[nTempIndexes]; + typelib_TypeDescription * pParamTypeDescr = + pTempParamTypeDescr[nTempIndexes]; + + if (pParams[nIndex].bIn) + { + if (pParams[nIndex].bOut) // inout + { + ::uno_destructData( + pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value + ::uno_copyAndConvertData( + pUnoArgs[nIndex], aCppParams[nCppIndex].p, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + } + else // pure out + { + ::uno_copyAndConvertData( + pUnoArgs[nIndex], aCppParams[nCppIndex].p, pParamTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + } + // destroy temp cpp param => cpp: every param was constructed + ::uno_destructData( + aCppParams[nCppIndex].p, pParamTypeDescr, cpp_release ); + + TYPELIB_DANGER_RELEASE( pParamTypeDescr ); + } + // return value + if (!bSimpleReturn) + { + ::uno_copyAndConvertData( + pUnoReturn, uRetVal.p, pReturnTypeDescr, + pThis->getBridge()->getCpp2Uno() ); + ::uno_destructData( + aCppParams[0].p, pReturnTypeDescr, cpp_release ); + } + // return type + if (pReturnTypeDescr) + { + TYPELIB_DANGER_RELEASE( pReturnTypeDescr ); + } +} + +} + +namespace bridges { namespace cpp_uno { namespace shared { + +void unoInterfaceProxyDispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // is my surrogate + bridges::cpp_uno::shared::UnoInterfaceProxy * pThis + = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI); + + switch (pMemberDescr->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceAttributeTypeDescription const * >( + pMemberDescr))); + if (pReturn) + { + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef, + 0, 0, // no params + pReturn, pArgs, ppException ); + } + else + { + // is SET + typelib_MethodParameter aParam; + aParam.pTypeRef = + ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef; + aParam.bIn = sal_True; + aParam.bOut = sal_False; + + typelib_TypeDescriptionReference * pReturnTypeRef = 0; + OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") ); + typelib_typedescriptionreference_new( + &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData ); + + // dependent dispatch + aVtableSlot.index += 1; // get, then set method + cpp_call( + pThis, aVtableSlot, + pReturnTypeRef, + 1, &aParam, + pReturn, pArgs, ppException ); + + typelib_typedescriptionreference_release( pReturnTypeRef ); + } + + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + VtableSlot aVtableSlot( + getVtableSlot( + reinterpret_cast< + typelib_InterfaceMethodTypeDescription const * >( + pMemberDescr))); + switch (aVtableSlot.index) + { + // standard calls + case 1: // acquire uno interface + (*pUnoI->acquire)( pUnoI ); + *ppException = 0; + break; + case 2: // release uno interface + (*pUnoI->release)( pUnoI ); + *ppException = 0; + break; + case 0: // queryInterface() opt + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() ); + if (pTD) + { + uno_Interface * pInterface = 0; + (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)( + pThis->pBridge->getUnoEnv(), + (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD ); + + if (pInterface) + { + ::uno_any_construct( + reinterpret_cast< uno_Any * >( pReturn ), + &pInterface, pTD, 0 ); + (*pInterface->release)( pInterface ); + TYPELIB_DANGER_RELEASE( pTD ); + *ppException = 0; + break; + } + TYPELIB_DANGER_RELEASE( pTD ); + } + } // else perform queryInterface() + default: + // dependent dispatch + cpp_call( + pThis, aVtableSlot, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams, + ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams, + pReturn, pArgs, ppException ); + } + break; + } + default: + { + ::com::sun::star::uno::RuntimeException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ), + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); + + Type const & rExcType = ::getCppuType( &aExc ); + // binary identical null reference + ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 ); + } + } +} + +} } } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |