summaryrefslogtreecommitdiff
path: root/bridges/source/cpp_uno/msvc_win32_x86-64
diff options
context:
space:
mode:
Diffstat (limited to 'bridges/source/cpp_uno/msvc_win32_x86-64')
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/call.asm133
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx582
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/dllinit.cxx61
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx850
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk83
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/mscx.hxx62
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx450
7 files changed, 2221 insertions, 0 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/call.asm b/bridges/source/cpp_uno/msvc_win32_x86-64/call.asm
new file mode 100644
index 000000000000..406e78d397a1
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/call.asm
@@ -0,0 +1,133 @@
+; -*- Mode: text; tab-width: 8; indent-tabs-mode: nil comment-column: 44; comment-start: ";; " comment-start-skip: ";; *" -*-
+
+;; Version: MPL 1.1 / GPLv3+ / LGPLv3+
+;;
+;; The contents of this file are subject to the Mozilla Public License Version
+;; 1.1 (the "License"); you may not use this file except in compliance with
+;; the License or as specified alternatively below. You may obtain a copy of
+;; the License at http://www.mozilla.org/MPL/
+;;
+;; Software distributed under the License is distributed on an "AS IS" basis,
+;; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+;; for the specific language governing rights and limitations under the
+;; License.
+;;
+;; The Initial Developer of the Original Code is
+;; Novell, Inc.
+;; Portions created by the Initial Developer are Copyright (C) 2011
+;; Novell, Inc. All Rights Reserved.
+;;
+;; Major Contributor(s):
+;; Tor Lillqvist <tml@iki.fi>
+;; Portions created by Tor Lillqvist are Copyright (C) 2011 Tor Lillqvist. All Rights Reserved.
+;;
+;; For minor contributions see the git repository.
+;;
+;; Alternatively, the contents of this file may be used under the terms of
+;; either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+;; the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+;; in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+;; instead of those above.
+
+;; This is the function jumped to from the trampoline generated by
+;; codeSnippet() in cpp2uno.cxx. Here we call cpp_vtable_call() which
+;; then calls the actual UNO function.
+
+;; The code snippet generated is called from "normal" C++ code which
+;; has no idea that it is calling dynamically generated code.
+
+;; The generated short code snippet is not covered by any function
+;; table and unwind info, but that doesn't matter, as the instructions
+;; in it are not really going to cause any exception. Once it jumps
+;; here it is covered by a function table, and the calls further down
+;; through cpp_vtable_call() can be unwound cleanly.
+
+;; This is in a separate file for x86-64 as MSVC doesn't have in-line
+;; assembly for x64.
+
+;; 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
+
+;; This one has a mass of information about different architectures
+;; and compilers, and contains some details about the x64 Windows
+;; calling convention in particular that Microsoft doesn't mention
+;; above:
+;; http://www.agner.org/optimize/calling_conventions.pdf
+
+;; 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
+
+typelib_TypeClass_FLOAT equ 10
+typelib_TypeClass_DOUBLE equ 11
+
+extern cpp_vtable_call: proc
+
+.code
+
+privateSnippetExecutor proc frame
+
+ ;; Make stack frame. Re-align RSP at 16 bytes. We need just one
+ ;; qword of stack for our own purposes: Where cpp_vtable_call()
+ ;; will store the return value of the UNO callee. But we of course
+ ;; must also allocate space for the functions we call (i.e., just
+ ;; cpp_vtable_call()) to spill their register parameters.
+
+ sub rsp, 40
+ .allocstack (40)
+ .endprolog
+
+ ;; Call cpp_vtable_call() with 2 parameters:
+
+ ;; 1 (rcx): nOffsetAndIndex (already put there in code generated by codeSnippet)
+ ;; 2 (rdx): pointer to where to store return value, followed by our
+ ;; return address (uninteresting to cpp_vtable_call()), followed
+ ;; by our spilled register parameters, as stored above, followed
+ ;; by the rest of our parameters, if any.
+
+ lea rdx, 32[rsp]
+
+ call cpp_vtable_call
+
+ ;; cpp_vtable_call() returns the typelib_TypeClass type of the
+ ;; return value of the called UNO function
+
+ cmp rax, typelib_TypeClass_FLOAT
+ je Lfloat
+
+ cmp rax, typelib_TypeClass_DOUBLE
+ je Lfloat
+
+ mov rax, qword ptr 32[rsp]
+ jmp Lepilogue
+
+Lfloat:
+ movsd xmm0, qword ptr 32[rsp]
+
+Lepilogue:
+ add rsp, 40
+ ret
+privateSnippetExecutor 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..ecfd957947c4
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
@@ -0,0 +1,582 @@
+/* -*- 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;
+
+static inline typelib_TypeClass cpp2uno_call(
+ bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
+ const typelib_TypeDescription * pMemberTD,
+ typelib_TypeDescriptionReference * pReturnTypeRef, // NULL indicates void return
+ sal_Int32 nParams,
+ typelib_MethodParameter * pParams,
+ void ** pStack )
+{
+ // Return type
+ typelib_TypeDescription * pReturnTD = NULL;
+ if ( pReturnTypeRef )
+ TYPELIB_DANGER_GET( &pReturnTD, pReturnTypeRef );
+
+ int nFirstRealParam = 3; // Index into pStack, past return
+ // value, return address and 'this'
+ // pointer.
+
+ void * pUnoReturn = NULL;
+ void * pCppReturn = NULL; // Complex return ptr: if != NULL && != pUnoReturn, reconversion need
+
+ if ( pReturnTD )
+ {
+ if ( bridges::cpp_uno::shared::isSimpleType( pReturnTD ) )
+ {
+ pUnoReturn = pStack;
+ }
+ else
+ {
+ pCppReturn = pStack[nFirstRealParam++];
+
+ pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTD )
+ ? alloca( pReturnTD->nSize )
+ : pCppReturn ); // direct way
+ }
+ }
+
+ void ** pCppIncomingParams = pStack + nFirstRealParam;
+
+ // Unlike this method for other archs, prefer clarity to
+ // micro-optimization, and allocate these array separately
+
+ // Parameters passed to the UNO function
+ void ** pUnoArgs = (void **)alloca( sizeof(void *) * nParams );
+
+ // Parameters received from C++
+ void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams );
+
+ // Indexes of values this have to be converted (interface conversion C++<=>UNO)
+ int * pTempIndexes =
+ (int *)alloca( sizeof(int) * nParams );
+
+ // Type descriptions for reconversions
+ typelib_TypeDescription ** ppTempParamTD =
+ (typelib_TypeDescription **)alloca( sizeof(void *) * nParams );
+
+ int nTempIndexes = 0;
+
+ for ( int nPos = 0; nPos < nParams; ++nPos )
+ {
+ const typelib_MethodParameter & rParam = pParams[nPos];
+
+ typelib_TypeDescription * pParamTD = NULL;
+ TYPELIB_DANGER_GET( &pParamTD, rParam.pTypeRef );
+
+ if ( !rParam.bOut &&
+ bridges::cpp_uno::shared::isSimpleType( pParamTD ) )
+ {
+ pCppArgs[nPos] = pUnoArgs[nPos] = pCppIncomingParams++;
+
+ TYPELIB_DANGER_RELEASE( pParamTD );
+ }
+ else // ptr to complex value | ref
+ {
+ void * pCppStack;
+
+ pCppArgs[nPos] = pCppStack = *pCppIncomingParams++;
+
+ if ( !rParam.bIn ) // Pure out
+ {
+ // UNO out is unconstructed mem
+ pUnoArgs[nPos] = alloca( pParamTD->nSize );
+ pTempIndexes[nTempIndexes] = nPos;
+ // pParamTD will be released at reconversion
+ ppTempParamTD[nTempIndexes++] = pParamTD;
+ }
+ //
+ else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTD ) )
+ {
+ ::uno_copyAndConvertData(
+ pUnoArgs[nPos] = alloca( pParamTD->nSize ),
+ pCppStack, pParamTD,
+ pThis->getBridge()->getCpp2Uno() );
+ pTempIndexes[nTempIndexes] = nPos; // Has to be reconverted
+ // pParamTD will be released at reconversion
+ ppTempParamTD[nTempIndexes++] = pParamTD;
+ }
+ else // direct way
+ {
+ pUnoArgs[nPos] = pCppStack;
+ // No longer needed
+ TYPELIB_DANGER_RELEASE( pParamTD );
+ }
+ }
+ }
+
+ // ExceptionHolder
+ uno_Any aUnoExc; // Any will be constructed by callee
+ uno_Any * pUnoExc = &aUnoExc;
+
+ // invoke UNO dispatch call
+ (*pThis->getUnoI()->pDispatcher)(
+ pThis->getUnoI(), pMemberTD, pUnoReturn, pUnoArgs, &pUnoExc );
+
+ // in case an exception occurred...
+ if ( pUnoExc )
+ {
+ // Destruct temporary in/inout params
+ while ( nTempIndexes-- )
+ {
+ int nIndex = pTempIndexes[nTempIndexes];
+
+ if ( pParams[nIndex].bIn ) // Is in/inout => was constructed
+ {
+ ::uno_destructData( pUnoArgs[nIndex], ppTempParamTD[nTempIndexes], 0 );
+ }
+ TYPELIB_DANGER_RELEASE( ppTempParamTD[nTempIndexes] );
+ }
+ if ( pReturnTD )
+ TYPELIB_DANGER_RELEASE( pReturnTD );
+
+ 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--)
+ {
+ int nIndex = pTempIndexes[nTempIndexes];
+ typelib_TypeDescription * pParamTD = ppTempParamTD[nTempIndexes];
+
+ if ( pParams[nIndex].bOut ) // inout/out
+ {
+ // Convert and assign
+ ::uno_destructData(
+ pCppArgs[nIndex], pParamTD, cpp_release );
+ ::uno_copyAndConvertData(
+ pCppArgs[nIndex], pUnoArgs[nIndex], pParamTD,
+ pThis->getBridge()->getUno2Cpp() );
+ }
+ // Destroy temp UNO param
+ ::uno_destructData( pUnoArgs[nIndex], pParamTD, 0 );
+
+ TYPELIB_DANGER_RELEASE( pParamTD );
+ }
+ // Return
+ if ( pCppReturn ) // Has complex return
+ {
+ if ( pUnoReturn != pCppReturn ) // Needs reconversion
+ {
+ ::uno_copyAndConvertData(
+ pCppReturn, pUnoReturn, pReturnTD,
+ pThis->getBridge()->getUno2Cpp() );
+ // Destroy temp UNO return
+ ::uno_destructData( pUnoReturn, pReturnTD, 0 );
+ }
+ // Complex return ptr is set to eax
+ pStack[0] = pCppReturn;
+ }
+ if ( pReturnTD )
+ {
+ typelib_TypeClass eRet = (typelib_TypeClass)pReturnTD->eTypeClass;
+ TYPELIB_DANGER_RELEASE( pReturnTD );
+ return eRet;
+ }
+ else
+ return typelib_TypeClass_VOID;
+ }
+}
+
+extern "C" typelib_TypeClass cpp_vtable_call(
+ sal_Int64 nOffsetAndIndex,
+ void ** pStack )
+{
+ sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF);
+ sal_Int32 nVtableOffset = ((nOffsetAndIndex >> 32) & 0xFFFFFFFF);
+
+ // pStack points to space for return value allocated by
+ // privateSnippetExecutor() in call.asm, after which follows our
+ // return address (uninteresting), then the integer or
+ // floating-point register parameters (spilled by
+ // privateSnippetExecutor()) from the call to the trampoline,
+ // followed by stacked parameters. The first parameter is the
+ // 'this' pointer. If the callee returns a large value, the
+ // parameter after that is actually a pointer to where the callee
+ // should store its return value.
+
+ void * pThis = static_cast<char *>( pStack[2] ) - nVtableOffset;
+
+ bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
+ bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
+
+ typelib_InterfaceTypeDescription * pTD = pCppI->getTypeDescr();
+
+ OSL_ENSURE( nFunctionIndex < pTD->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
+ if ( nFunctionIndex >= pTD->nMapFunctionIndexToMemberIndex )
+ throw RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Illegal vtable index!")),
+ reinterpret_cast<XInterface *>( pCppI ) );
+
+ // Determine called method
+ int nMemberPos = pTD->pMapFunctionIndexToMemberIndex[nFunctionIndex];
+ OSL_ENSURE( nMemberPos < pTD->nAllMembers, "### illegal member index!\n" );
+
+ TypeDescription aMemberDescr( pTD->ppAllMembers[nMemberPos] );
+
+ typelib_TypeClass eRet;
+ switch ( aMemberDescr.get()->eTypeClass )
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+ typelib_TypeDescriptionReference *pAttrTypeRef =
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
+
+ if ( pTD->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
+ {
+ // is GET method
+ eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
+ 0, NULL, // No params
+ pStack );
+ }
+ else
+ {
+ // is SET method
+ typelib_MethodParameter aParam;
+ aParam.pTypeRef = pAttrTypeRef;
+ aParam.bIn = sal_True;
+ aParam.bOut = sal_False;
+
+ eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
+ NULL, // Indicates void return
+ 1, &aParam,
+ pStack );
+ }
+ break;
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
+ {
+ // is METHOD
+ switch ( nFunctionIndex )
+ {
+ 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 = NULL;
+
+ // the incoming C++ parameters are: The this
+ // pointer, the hidden return value pointer, and
+ // then the actual queryInterface() only
+ // parameter. Thus pStack[4]..
+
+ TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( pStack[4] )->getTypeLibType() );
+
+ if ( pTD )
+ {
+ XInterface * pInterface = NULL;
+ (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
+ ( pCppI->getBridge()->getCppEnv(),
+ (void **)&pInterface,
+ pCppI->getOid().pData,
+ reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
+
+ if ( pInterface )
+ {
+ // pStack[3] = hidden return value pointer
+ ::uno_any_construct( reinterpret_cast<uno_Any *>( pStack[3] ),
+ &pInterface, pTD, cpp_acquire );
+
+ pInterface->release();
+ TYPELIB_DANGER_RELEASE( pTD );
+
+ eRet = typelib_TypeClass_ANY;
+ break;
+ }
+ TYPELIB_DANGER_RELEASE( pTD );
+ }
+ } // Fall through!
+ default:
+ {
+ typelib_InterfaceMethodTypeDescription * pMethodTD =
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
+
+ eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
+ pMethodTD->pReturnTypeRef,
+ pMethodTD->nParams,
+ pMethodTD->pParams,
+ pStack );
+ }
+ }
+ break;
+ }
+ default:
+ {
+ throw RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No member description found!")),
+ reinterpret_cast<XInterface *>( pCppI ) );
+ // is here for dummy
+ eRet = typelib_TypeClass_VOID;
+ }
+ }
+
+ return eRet;
+}
+
+int const codeSnippetSize = 48;
+
+extern "C" char privateSnippetExecutor;
+
+// This function generates the code that acts as a proxy for the UNO function to be called.
+// The generated code does the following:
+// - Spills register parameters on stack
+// - Loads functionIndex and vtableOffset into scratch registers
+// - Jumps to privateSnippetExecutor
+
+unsigned char * codeSnippet(
+ unsigned char * code,
+ char param_kind[4],
+ sal_Int32 nFunctionIndex,
+ sal_Int32 nVtableOffset )
+{
+ sal_uInt64 nOffsetAndIndex = ( ( (sal_uInt64) nVtableOffset ) << 32 ) | ( (sal_uInt64) nFunctionIndex );
+ unsigned char *p = code;
+
+ // Spill parameters
+ if ( param_kind[0] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT )
+ {
+ // mov qword ptr 8[rsp], rcx
+ *p++ = 0x48; *p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x08;
+ }
+ else
+ {
+ // movsd qword ptr 8[rsp], xmm0
+ *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08;
+ }
+ if ( param_kind[1] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT )
+ {
+ // mov qword ptr 16[rsp], rdx
+ *p++ = 0x48; *p++ = 0x89; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10;
+ }
+ else
+ {
+ // movsd qword ptr 16[rsp], xmm1
+ *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x10;
+ }
+ if ( param_kind[2] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT )
+ {
+ // mov qword ptr 24[rsp], r8
+ *p++ = 0x4C; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18;
+ }
+ else
+ {
+ // movsd qword ptr 24[rsp], xmm2
+ *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18;
+ }
+ if ( param_kind[3] == CPPU_CURRENT_NAMESPACE::REGPARAM_INT )
+ {
+ // mov qword ptr 32[rsp], r9
+ *p++ = 0x4C;*p++ = 0x89; *p++ = 0x4C; *p++ = 0x24; *p++ = 0x20;
+ }
+ else
+ {
+ // movsd qword ptr 32[rsp], xmm3
+ *p++ = 0xF2; *p++ = 0x0F; *p++ = 0x11; *p++ = 0x5C; *p++ = 0x24; *p++ = 0x20;
+ }
+
+ // mov rcx, nOffsetAndIndex
+ *p++ = 0x48; *p++ = 0xB9;
+ *((sal_uInt64 *)p) = nOffsetAndIndex; p += 8;
+
+ // mov r11, privateSnippetExecutor
+ *p++ = 0x49; *p++ = 0xBB;
+ *((void **)p) = &privateSnippetExecutor; p += 8;
+
+ // jmp r11
+ *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
+
+ 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;
+}
+
+unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
+ Slot ** slots,
+ unsigned char * code,
+ typelib_InterfaceTypeDescription const * type,
+ sal_Int32 nFunctionOffset,
+ sal_Int32 functionCount,
+ sal_Int32 nVtableOffset )
+{
+ (*slots) -= functionCount;
+ Slot * s = *slots;
+
+ for (int member = 0; member < type->nMembers; ++member) {
+ typelib_TypeDescription * pTD = NULL;
+
+ TYPELIB_DANGER_GET( &pTD, type->ppMembers[ member ] );
+ OSL_ASSERT( pTD );
+
+ char param_kind[4];
+ int nr = 0;
+
+ for (int i = 0; i < 4; ++i)
+ param_kind[i] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT;
+
+ // 'this'
+ ++nr;
+
+ if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE )
+ {
+ typelib_InterfaceAttributeTypeDescription * pIfaceAttrTD =
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
+
+ // Getter
+
+ (s++)->fn = code;
+ code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset );
+ if ( ! pIfaceAttrTD->bReadOnly )
+ {
+ typelib_TypeDescription * pAttrTD = NULL;
+ TYPELIB_DANGER_GET( &pAttrTD, pIfaceAttrTD->pAttributeTypeRef );
+ OSL_ASSERT( pAttrTD );
+
+ // Setter
+ if ( pAttrTD->eTypeClass == typelib_TypeClass_FLOAT ||
+ pAttrTD->eTypeClass == typelib_TypeClass_DOUBLE )
+ param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT;
+
+ TYPELIB_DANGER_RELEASE( pAttrTD );
+
+ (s++)->fn = code;
+ code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset );
+ }
+ }
+ else if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_METHOD )
+ {
+ typelib_InterfaceMethodTypeDescription * pMethodTD =
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
+
+ typelib_TypeDescription * pReturnTD = NULL;
+ TYPELIB_DANGER_GET( &pReturnTD, pMethodTD->pReturnTypeRef );
+ OSL_ASSERT( pReturnTD );
+
+ if ( !bridges::cpp_uno::shared::isSimpleType( pReturnTD ) )
+ {
+ // Return value
+ ++nr;
+ }
+
+ for (int param = 0; nr < 4 && param < pMethodTD->nParams; ++param, ++nr)
+ {
+ typelib_TypeDescription * pParamTD = NULL;
+
+ TYPELIB_DANGER_GET( &pParamTD, pMethodTD->pParams[param].pTypeRef );
+ OSL_ASSERT( pParamTD );
+
+ if ( pParamTD->eTypeClass == typelib_TypeClass_FLOAT ||
+ pParamTD->eTypeClass == typelib_TypeClass_DOUBLE )
+ param_kind[nr] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT;
+
+ TYPELIB_DANGER_RELEASE( pParamTD );
+ }
+ (s++)->fn = code;
+ code = codeSnippet( code, param_kind, nFunctionOffset++, nVtableOffset );
+
+ TYPELIB_DANGER_RELEASE( pReturnTD );
+ }
+ else
+ OSL_ASSERT( false );
+
+ TYPELIB_DANGER_RELEASE( pTD );
+ }
+ 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..2157568ad915
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/except.cxx
@@ -0,0 +1,850 @@
+/* -*- 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.
+ *
+ ************************************************************************/
+
+// Interesting info can be found in:
+
+// MSDN, obviously
+
+// http://www.osronline.com/article.cfm?article=469
+
+// ONTL, "Open NT Native Template Library", a C++ STL-like library
+// that can be used even when writing Windows drivers. This is some
+// quite badass code. The author has done impressive heavy spelunking
+// of MSVCR structures. http://code.google.com/p/ontl/
+
+// Geoff Chappell's pages:
+// http://members.ozemail.com.au/~geoffch/samples/programming/msvc/language/index.html
+
+// The below is from ONTL's ntl/nt/exception.hxx, cleaned up to keep just the _M_X64 parts:
+
+#if 0
+
+/* This information until the corresponding '#endif // 0' is covered
+ * by ONTL's license, which is said to be the "zlib/libgng license"
+ * below, which as far as I see is permissive enough to allow this
+ * information to be included here in this source file. Note that no
+ * actual code from ONTL below gets compiled into the object file.
+ */
+
+/*
+ * Copyright (c) 2011 <copyright holders> (The ONTL main
+ * developer(s) don't tell their real name(s) on the ONTL site.)
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ */
+
+typedef uint32_t rva_t;
+
+///\note the calling convention should not matter since this has no arguments
+typedef void generic_function_t();
+
+struct ptrtomember // _PMD
+{
+ typedef __w64 int32_t mdiff_t;
+ mdiff_t member_offset;
+ mdiff_t vbtable_offset; // -1 if not a virtual base
+ mdiff_t vdisp_offset; // offset to the displacement value inside the vbtable
+
+ template<typename T>
+ T * operator()(T * const thisptr) const
+ {
+ uintptr_t tp = reinterpret_cast<uintptr_t>(thisptr);
+ uintptr_t ptr = tp + member_offset;
+ if ( vbtable_offset != -1 ) // !(vbtable_offset < 0)
+ {
+ ptr += *reinterpret_cast<mdiff_t*>( static_cast<intptr_t>(vdisp_offset + *reinterpret_cast<mdiff_t*>(tp + vbtable_offset)) )
+ + vbtable_offset;
+ }
+ return reinterpret_cast<T*>(ptr);
+ }
+};
+
+struct eobject
+{
+ typedef void (* dtor_ptr )(eobject*);
+ typedef void (* ctor_ptr )(eobject*, eobject*);
+ typedef void (* ctor_ptr2)(eobject*, eobject*, int);
+};
+
+struct catchabletype
+{
+ /** is simple type */
+ uint32_t memmoveable : 1;
+ /** catchable as reference only */
+ uint32_t refonly : 1;
+ /** class with virtual base */
+ uint32_t hasvirtbase : 1;
+ /** offset to the type descriptor */
+ rva_t typeinfo;
+
+ /** catch type instance location within a thrown object */
+ ptrtomember thiscast;
+ /** size of the simple type or offset into buffer of \c this pointer for catch object */
+ uint32_t object_size;
+
+ union
+ {
+ rva_t copyctor;
+ rva_t copyctor2;
+ };
+};
+
+#pragma pack(push, 4)
+struct catchabletypearray
+{
+ uint32_t size;
+ rva_t type[1];
+};
+#pragma pack(pop)
+
+#pragma pack(push, 4)
+struct throwinfo
+{
+ typedef exception_disposition __cdecl forwardcompathandler_t(...);
+
+ /* 0x00 */ uint32_t econst : 1;
+ /* 0x00 */ uint32_t evolatile : 1;
+ /* 0x00 */ uint32_t : 1;
+ /* 0x00 */ uint32_t e8 : 1;
+ /* 0x04 */ rva_t exception_dtor;
+ /* 0x08 */ rva_t forwardcompathandler;
+ /* 0x0C */ rva_t catchabletypearray; ///< types able to catch the exception.
+};
+#pragma pack(pop)
+
+/// This type represents the catch clause
+struct ehandler
+{
+ // union { uint32_t adjectives; void * ptr; };
+ uint32_t isconst : 1;
+ uint32_t isvolatile : 1;
+ uint32_t isunaligned : 1;// guess it is not used on x86
+ uint32_t isreference : 1;
+
+ uint32_t :27;
+ uint32_t ishz : 1;
+
+ /** offset to the type descriptor of this catch object */
+ /*0x04*/ rva_t typeinfo; // dispType
+ /*0x08*/ int eobject_bpoffset; // dispCatchObj
+ /** offset to the catch clause funclet */
+ /*0x0C*/ rva_t handler; // dispOfHandler
+ /*0x10*/ uint32_t frame; // dispFrame
+}
+
+// ___BuildCatchObject
+/// 15.3/16 When the exception-declaration specifies a class type, a copy
+/// constructor is used to initialize either the object declared
+/// in the exception-declaration or,
+/// if the exception-declaration does not specify a name,
+/// a temporary object of that type.
+///\note This is the question may we optimize out the last case.
+///\warning If the copy constructor throws an exception, std::unexpected would be called
+void
+ constructcatchobject(
+ cxxregistration * cxxreg,
+ const ehandler * const catchblock,
+ catchabletype * const convertable,
+ const dispatcher_context* const dispatch
+ )
+ const
+{
+ _EH_TRACE_ENTER();
+ // build helper
+ __try {
+ struct typeinfo_t { void* vtbl; void* spare; char name[1]; };
+ enum catchable_info { cidefault, cicomplex, civirtual } cinfo = cidefault;
+
+ const typeinfo_t* ti = catchblock->typeinfo ? dispatch->va<typeinfo_t*>(catchblock->typeinfo) : NULL;
+ if(ti && *ti->name && (catchblock->eobject_bpoffset || catchblock->ishz)){
+ eobject** objplace = catchblock->ishz
+ ? reinterpret_cast<eobject**>(cxxreg)
+ : reinterpret_cast<eobject**>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers);
+ if(catchblock->isreference){
+ // just ref/pointer
+ *objplace = adjust_pointer(get_object(), convertable);
+ }else if(convertable->memmoveable){
+ // POD
+ std::memcpy(objplace, get_object(), convertable->object_size);
+ if(convertable->object_size == sizeof(void*) && *objplace)
+ *objplace = adjust_pointer((void*)*objplace, convertable);
+ }else{
+ // if copy ctor exists, call it; binary copy otherwise
+ if(convertable->copyctor){
+ cinfo = convertable->hasvirtbase ? civirtual : cicomplex;
+ }else{
+ std::memcpy(objplace, (const void*)adjust_pointer(get_object(), convertable), convertable->object_size);
+ }
+ }
+ }
+ // end of build helper
+ if(cinfo != cidefault){
+ eobject* objthis = catchblock->ishz
+ ? reinterpret_cast<eobject*>(cxxreg)
+ : reinterpret_cast<eobject*>(catchblock->eobject_bpoffset + cxxreg->fp.FramePointers);
+ void* copyctor = thrown_va(convertable->copyctor);
+ eobject* copyarg = adjust_pointer(get_object(), convertable);
+ if(cinfo == cicomplex)
+ (eobject::ctor_ptr (copyctor))(objthis, copyarg);
+ else
+ (eobject::ctor_ptr2(copyctor))(objthis, copyarg, 1);
+ }
+ }
+ __except(cxxregistration::unwindfilter(static_cast<nt::ntstatus>(_exception_code())))
+ {
+ nt::exception::inconsistency();
+ }
+ _EH_TRACE_LEAVE();
+}
+
+#endif // 0
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_bridges.hxx"
+
+#pragma warning( disable : 4237 )
+#include <boost/unordered_map.hpp>
+#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 boost::unordered_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 );
+ }
+}
+
+void * __cdecl copyConstruct(
+ void * pExcThis,
+ void * pSource,
+ typelib_TypeDescription * pTD ) throw ()
+{
+ ::uno_copyData( pExcThis, pSource, pTD, cpp_acquire );
+ return pExcThis;
+}
+
+void * __cdecl destruct(
+ void * pExcThis,
+ typelib_TypeDescription * pTD ) throw ()
+{
+ ::uno_destructData( pExcThis, pTD, cpp_release );
+ return pExcThis;
+}
+
+const int codeSnippetSize = 40;
+
+void GenerateConstructorTrampoline(
+ unsigned char * code,
+ typelib_TypeDescription * pTD ) throw ()
+{
+ unsigned char *p = code;
+
+ // mov r8, pTD
+ *p++ = 0x49; *p++ = 0xB8;
+ *((void **)p) = pTD; p += 8;
+
+ // mov r11, copyConstruct
+ *p++ = 0x49; *p++ = 0xBB;
+ *((void **)p) = &copyConstruct; p += 8;
+
+ // jmp r11
+ *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
+
+ OSL_ASSERT( p < code + codeSnippetSize );
+}
+
+void GenerateDestructorTrampoline(
+ unsigned char * code,
+ typelib_TypeDescription * pTD ) throw ()
+{
+ unsigned char *p = code;
+
+ // mov rdx, pTD
+ *p++ = 0x48; *p++ = 0xBA;
+ *((void **)p) = pTD; p += 8;
+
+ // mov r11, destruct
+ *p++ = 0x49; *p++ = 0xBB;
+ *((void **)p) = &destruct; p += 8;
+
+ // jmp r11
+ *p++ = 0x41; *p++ = 0xFF; *p++ = 0xE3;
+
+ OSL_ASSERT( p < code + codeSnippetSize );
+}
+
+// This looks like it is the struct catchabletype above
+
+struct ExceptionType
+{
+ sal_Int32 _n0; // flags
+ sal_uInt32 _pTypeInfo; // typeinfo
+ sal_Int32 _n1, _n2, _n3; // thiscast
+ sal_Int32 _n4; // object_size
+ sal_uInt32 _pCopyCtor; // copyctor
+
+ inline ExceptionType(
+ sal_uChar * pCode,
+ sal_uInt64 pCodeBase,
+ typelib_TypeDescription * pTD ) throw ()
+ : _n0( 0 )
+ , _n1( 0 )
+ , _n2( -1 )
+ , _n3( 0 )
+ , _n4( pTD->nSize )
+ {
+ // As _n0 is always initialized to zero, that means the
+ // hasvirtbase flag (see the ONTL catchabletype struct) is
+ // off, and thus the copyctor is of the ctor_ptr kind.
+ _pTypeInfo = (sal_uInt32) ((sal_uInt64) mscx_getRTTI( pTD->pTypeName ) - pCodeBase);
+ GenerateConstructorTrampoline( pCode, pTD );
+ _pCopyCtor = (sal_uInt32) ((sal_uInt64) pCode - pCodeBase);
+ }
+ inline ~ExceptionType() throw ()
+ {
+ }
+};
+
+struct RaiseInfo;
+
+class ExceptionInfos
+{
+ Mutex _aMutex;
+ t_string2PtrMap _allRaiseInfos;
+
+public:
+ static RaiseInfo * getRaiseInfo( typelib_TypeDescription * pTD ) throw ();
+
+ static DWORD allocationGranularity;
+
+ ExceptionInfos() throw ();
+ ~ExceptionInfos() throw ();
+};
+
+DWORD ExceptionInfos::allocationGranularity = 0;
+
+// This corresponds to the struct throwinfo described above.
+
+struct RaiseInfo
+{
+ sal_Int32 _n0;
+ sal_uInt32 _pDtor;
+ sal_Int32 _n2;
+ sal_uInt32 _types;
+
+ // Additional fields
+ typelib_TypeDescription * _pTD;
+ sal_uChar * _code;
+ sal_uInt64 _codeBase;
+
+ RaiseInfo( typelib_TypeDescription * pTD ) throw ();
+
+ ~RaiseInfo() throw ();
+};
+
+RaiseInfo::RaiseInfo( typelib_TypeDescription * pTD )throw ()
+ : _n0( 0 )
+ , _n2( 0 )
+ , _pTD( pTD )
+{
+ typelib_CompoundTypeDescription * pCompTD;
+
+ // Count how many trampolines we need
+ int codeSize = codeSnippetSize;
+
+ // Info count
+ int nLen = 0;
+ for ( pCompTD = (typelib_CompoundTypeDescription*)pTD;
+ pCompTD; pCompTD = pCompTD->pBaseTypeDescription )
+ {
+ ++nLen;
+ codeSize += codeSnippetSize;
+ }
+
+ sal_uChar * pCode = _code = (sal_uChar *)::rtl_allocateMemory( codeSize );
+
+ _codeBase = (sal_uInt64)pCode & ~(ExceptionInfos::allocationGranularity-1);
+
+ DWORD old_protect;
+#if OSL_DEBUG_LEVEL > 0
+ BOOL success =
+#endif
+ VirtualProtect( pCode, codeSize, PAGE_EXECUTE_READWRITE, &old_protect );
+ OSL_ENSURE( success, "VirtualProtect() failed!" );
+
+ ::typelib_typedescription_acquire( pTD );
+
+ GenerateDestructorTrampoline( pCode, pTD );
+ _pDtor = (sal_Int32)((sal_uInt64)pCode - _codeBase);
+ pCode += codeSnippetSize;
+
+ // Info count accompanied by type info ptrs: type, base type, base base type, ...
+ _types = (sal_Int32)((sal_uInt64)::rtl_allocateMemory( 4 + 4* nLen) - _codeBase);
+ *(sal_Int32 *)_types = nLen;
+
+ ExceptionType ** ppTypes = (ExceptionType **)((sal_Int32 *)_types + 1);
+
+ int nPos = 0;
+ for ( pCompTD = (typelib_CompoundTypeDescription*)pTD;
+ pCompTD; pCompTD = pCompTD->pBaseTypeDescription )
+ {
+ ppTypes[nPos++] =
+ new ExceptionType( pCode, _codeBase,
+ (typelib_TypeDescription *)pCompTD );
+ pCode += codeSnippetSize;
+ }
+}
+
+RaiseInfo::~RaiseInfo() throw ()
+{
+ sal_uInt32 * pTypes =
+ (sal_uInt32 *)(_codeBase + _types) + 1;
+
+ for ( int nTypes = *(sal_uInt32 *)(_codeBase + _types); nTypes--; )
+ {
+ delete (ExceptionType *) (_codeBase + pTypes[nTypes]);
+ }
+ ::rtl_freeMemory( (void*)(_codeBase +_types) );
+ ::rtl_freeMemory( _code );
+
+ ::typelib_typedescription_release( _pTD );
+}
+
+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;
+ }
+}
+
+RaiseInfo * ExceptionInfos::getRaiseInfo( typelib_TypeDescription * pTD ) throw ()
+{
+ static ExceptionInfos * s_pInfos = 0;
+ if (! s_pInfos)
+ {
+ MutexGuard aGuard( Mutex::getGlobalMutex() );
+ if (! s_pInfos)
+ {
+ SYSTEM_INFO systemInfo;
+ GetSystemInfo( &systemInfo );
+ allocationGranularity = systemInfo.dwAllocationGranularity;
+
+#ifdef LEAK_STATIC_DATA
+ s_pInfos = new ExceptionInfos();
+#else
+ static ExceptionInfos s_allExceptionInfos;
+ s_pInfos = &s_allExceptionInfos;
+#endif
+ }
+ }
+
+ OSL_ASSERT( pTD &&
+ (pTD->eTypeClass == typelib_TypeClass_STRUCT ||
+ pTD->eTypeClass == typelib_TypeClass_EXCEPTION) );
+
+ RaiseInfo * pRaiseInfo;
+
+ OUString const & rTypeName = *reinterpret_cast< OUString * >( &pTD->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( pTD );
+
+ // Put into map
+ pair< t_string2PtrMap::iterator, bool > insertion(
+ s_pInfos->_allRaiseInfos.insert( t_string2PtrMap::value_type( rTypeName, (void *)pRaiseInfo ) ) );
+ OSL_ENSURE( insertion.second, "### raise info insertion failed?!" );
+ }
+ else
+ {
+ // Reuse existing info
+ pRaiseInfo = (RaiseInfo *)iFind->second;
+ }
+
+ return pRaiseInfo;
+}
+
+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 inlining of
+ // ExceptionInfos::getRaiseInfo()
+
+ // construct cpp exception object
+ typelib_TypeDescription * pTD = NULL;
+ TYPELIB_DANGER_GET( &pTD, pUnoExc->pType );
+
+ void * pCppExc = alloca( pTD->nSize );
+ ::uno_copyAndConvertData( pCppExc, pUnoExc->pData, pTD, pUno2Cpp );
+
+ ULONG_PTR arFilterArgs[4];
+ arFilterArgs[0] = MSVC_magic_number;
+ arFilterArgs[1] = (ULONG_PTR)pCppExc;
+ arFilterArgs[2] = (ULONG_PTR)ExceptionInfos::getRaiseInfo( pTD );
+ arFilterArgs[3] = ((RaiseInfo *)arFilterArgs[2])->_codeBase;
+
+ // Destruct uno exception
+ ::uno_any_destruct( pUnoExc, 0 );
+ TYPELIB_DANGER_RELEASE( pTD );
+
+ // 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,
+ // we have to code those offsets here.
+ //
+ // MSVS9/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 == 4 &&
+ pRecord->ExceptionInformation[0] == MSVC_magic_number &&
+ pRecord->ExceptionInformation[1] != 0 &&
+ pRecord->ExceptionInformation[2] != 0 &&
+ pRecord->ExceptionInformation[3] != 0)
+ {
+ // ExceptionInformation[1] is the address of the thrown object
+ // (or the address of a pointer to it, in most cases when it
+ // is a C++ class, obviously).
+
+ // [2] is the throwinfo pointer
+
+ // [3] is the image base address which is added the 32-bit
+ // rva_t fields in throwinfo to get actual 64-bit addresses
+
+ void * types =
+ (void *) (pRecord->ExceptionInformation[3] +
+ ((RaiseInfo *)pRecord->ExceptionInformation[2])->_types);
+
+ if (types != 0 && *(DWORD *)types > 0)
+ {
+ DWORD pType = *((DWORD *)types + 1);
+ if (pType != 0 &&
+ ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo != 0)
+ {
+ OUString aRTTIname(
+ OStringToOUString(
+ reinterpret_cast< __type_info * >(
+ ((ExceptionType *)(pRecord->ExceptionInformation[3]+pType))->_pTypeInfo )->_m_d_name,
+ RTL_TEXTENCODING_ASCII_US ) );
+ OUString aUNOname( toUNOname( aRTTIname ) );
+
+ typelib_TypeDescription * pExcTD = 0;
+ typelib_typedescription_getByName(
+ &pExcTD, aUNOname.pData );
+ if (pExcTD == NULL)
+ {
+ 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],
+ pExcTD, pCpp2Uno );
+#if _MSC_VER < 1400 // msvcr80.dll cleans up, different from former msvcrs
+ if (! rethrow)
+ {
+ uno_destructData(
+ (void *) pRecord->ExceptionInformation[1],
+ pExcTD, cpp_release );
+ }
+#endif
+ typelib_typedescription_release( pExcTD );
+ }
+
+ 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..7f73ebe4bba2
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
@@ -0,0 +1,83 @@
+#*************************************************************************
+#
+# 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 \
+ $(SLO)$/call.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..7271aa510847
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/uno2cpp.cxx
@@ -0,0 +1,450 @@
+/* -*- 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
+{
+
+static bool 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;
+
+ if ( nParams > MAXPARAMS )
+ {
+ // We have a hard limit on the number of parameters so that we
+ // don't need any assembler code here but can call the
+ // function using normal C++.
+
+ return false;
+ }
+
+ // Table with this pointer, optional complex return value ptr, and the parameters
+ union {
+ sal_Int64 i;
+ void *p;
+ double d;
+ } aCppParams[MAXPARAMS+2], uRetVal;
+ int nCppParamIndex = 0;
+
+ // Return type
+ typelib_TypeDescription * pReturnTD = NULL;
+ TYPELIB_DANGER_GET( &pReturnTD, pReturnTypeRef );
+ OSL_ENSURE( pReturnTD, "### expected return type description!" );
+
+ // 'this'
+ void * pAdjustedThisPtr = (void **)( pThis->getCppI() ) + aVtableSlot.offset;
+ aCppParams[nCppParamIndex++].p = pAdjustedThisPtr;
+
+ bool bSimpleReturn = true;
+ if ( pReturnTD )
+ {
+ if ( !bridges::cpp_uno::shared::isSimpleType( pReturnTD ) )
+ {
+ // Complex return via ptr
+ bSimpleReturn = false;
+ aCppParams[nCppParamIndex++].p =
+ bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTD )?
+ alloca( pReturnTD->nSize ) : pUnoReturn;
+ }
+ }
+
+ // Indexes of values this have to be converted (interface conversion C++<=>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, ++nCppParamIndex )
+ {
+ const typelib_MethodParameter & rParam = pParams[nPos];
+
+ typelib_TypeDescription * pParamTD = NULL;
+ TYPELIB_DANGER_GET( &pParamTD, rParam.pTypeRef );
+
+ if ( !rParam.bOut &&
+ bridges::cpp_uno::shared::isSimpleType( pParamTD ) )
+ {
+ ::uno_copyAndConvertData(
+ &aCppParams[nCppParamIndex], pUnoArgs[nPos], pParamTD,
+ pThis->getBridge()->getUno2Cpp() );
+
+ // No longer needed
+ TYPELIB_DANGER_RELEASE( pParamTD );
+ }
+ else // Ptr to complex value | ref
+ {
+ if ( !rParam.bIn ) // Is pure out
+ {
+ // C++ out is constructed mem, UNO out is not!
+ ::uno_constructData(
+ aCppParams[nCppParamIndex].p = alloca( pParamTD->nSize ),
+ pParamTD );
+
+ pTempCppIndexes[nTempIndexes] = nCppParamIndex;
+ pTempIndexes[nTempIndexes] = nPos;
+
+ // Will be released at reconversion
+ pTempParamTypeDescr[nTempIndexes++] = pParamTD;
+
+ }
+ // Is in/inout
+ else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTD ) )
+ {
+ ::uno_copyAndConvertData(
+ aCppParams[nCppParamIndex].p = alloca( pParamTD->nSize ),
+ pUnoArgs[nPos], pParamTD,
+ pThis->getBridge()->getUno2Cpp() );
+
+ pTempCppIndexes[nTempIndexes] = nCppParamIndex;
+ pTempIndexes[nTempIndexes] = nPos;
+
+ // Will be released at reconversion
+ pTempParamTypeDescr[nTempIndexes++] = pParamTD;
+ }
+ else // direct way
+ {
+ aCppParams[nCppParamIndex].p = pUnoArgs[nPos];
+
+ // No longer needed
+ TYPELIB_DANGER_RELEASE( pParamTD );
+ }
+ }
+ }
+
+ __try
+ {
+ // The first real parameter is always '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 (*pIMethod)(sal_Int64, ...) =
+ (sal_Int64 (*)(sal_Int64, ...))
+ (*((sal_uInt64 **)pAdjustedThisPtr))[aVtableSlot.index];
+
+ double (*pFMethod)(sal_Int64, ...) =
+ (double (*)(sal_Int64, ...))
+ (*((sal_uInt64 **)pAdjustedThisPtr))[aVtableSlot.index];
+
+ // Pass parameters 2..4 as if it was a floating-point value so
+ // that it gets put in both XMM and integer registers per the
+ // calling convention. It doesn't matter if it actually is a
+ // fp or not.
+
+ if ( pReturnTD &&
+ (pReturnTD->eTypeClass == typelib_TypeClass_FLOAT ||
+ pReturnTD->eTypeClass == typelib_TypeClass_DOUBLE) )
+ uRetVal.d =
+ pFMethod (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 );
+ else
+ uRetVal.i =
+ pIMethod (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 C++ param => C++: every param was constructed
+ ::uno_destructData(
+ aCppParams[nCppIndex].p, pTempParamTypeDescr[nTempIndexes],
+ cpp_release );
+ TYPELIB_DANGER_RELEASE( pTempParamTypeDescr[nTempIndexes] );
+ }
+ // Return type
+ if ( pReturnTD )
+ TYPELIB_DANGER_RELEASE( pReturnTD );
+
+ // End here
+ return true;
+ }
+
+ // No exception occurred
+ *ppUnoExc = NULL;
+
+ // Reconvert temporary params
+ while ( nTempIndexes-- )
+ {
+ int nCppIndex = pTempCppIndexes[nTempIndexes];
+ int nIndex = pTempIndexes[nTempIndexes];
+ typelib_TypeDescription * pParamTD =
+ pTempParamTypeDescr[nTempIndexes];
+
+ if ( pParams[nIndex].bIn )
+ {
+ if ( pParams[nIndex].bOut ) // Inout
+ {
+ ::uno_destructData(
+ pUnoArgs[nIndex], pParamTD, 0 ); // Destroy UNO value
+ ::uno_copyAndConvertData(
+ pUnoArgs[nIndex], aCppParams[nCppIndex].p, pParamTD,
+ pThis->getBridge()->getCpp2Uno() );
+ }
+ }
+ else // Pure out
+ {
+ ::uno_copyAndConvertData(
+ pUnoArgs[nIndex], aCppParams[nCppIndex].p, pParamTD,
+ pThis->getBridge()->getCpp2Uno() );
+ }
+
+ // Destroy temp C++ param => C++: every param was constructed
+ ::uno_destructData(
+ aCppParams[nCppIndex].p, pParamTD, cpp_release );
+
+ TYPELIB_DANGER_RELEASE( pParamTD );
+ }
+
+ // Return value
+ if ( !bSimpleReturn )
+ {
+ ::uno_copyAndConvertData(
+ pUnoReturn, uRetVal.p, pReturnTD,
+ pThis->getBridge()->getCpp2Uno() );
+ ::uno_destructData(
+ aCppParams[1].p, pReturnTD, cpp_release );
+ }
+ else if ( pUnoReturn )
+ *(sal_Int64*)pUnoReturn = uRetVal.i;
+
+ if ( pReturnTD )
+ TYPELIB_DANGER_RELEASE( pReturnTD );
+
+ return true;
+}
+
+}
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+void unoInterfaceProxyDispatch(
+ uno_Interface * pUnoI,
+ const typelib_TypeDescription * pMemberTD,
+ void * pReturn,
+ void * pArgs[],
+ uno_Any ** ppException )
+{
+ // is my surrogate
+ bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
+ = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
+#if OSL_DEBUG_LEVEL > 0
+ typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
+#endif
+
+ switch (pMemberTD->eTypeClass)
+ {
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+ {
+#if OSL_DEBUG_LEVEL > 0
+ // determine vtable call index
+ sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberTD)->nPosition;
+ OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
+#endif
+ VtableSlot aVtableSlot(
+ getVtableSlot(
+ reinterpret_cast<
+ typelib_InterfaceAttributeTypeDescription const * >(
+ pMemberTD)));
+ if ( pReturn )
+ {
+ // Is GET
+ cpp_call(
+ pThis, aVtableSlot,
+ ((typelib_InterfaceAttributeTypeDescription *)pMemberTD)->pAttributeTypeRef,
+ 0, NULL, // no params
+ pReturn, pArgs, ppException );
+ }
+ else
+ {
+ // Is SET
+ typelib_MethodParameter aParam;
+ aParam.pTypeRef =
+ ((typelib_InterfaceAttributeTypeDescription *)pMemberTD)->pAttributeTypeRef;
+ aParam.bIn = sal_True;
+ aParam.bOut = sal_False;
+
+ typelib_TypeDescriptionReference * pReturnTypeRef = NULL;
+ OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
+ typelib_typedescriptionreference_new(
+ &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
+
+ 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:
+ {
+#if OSL_DEBUG_LEVEL > 0
+ // determine vtable call index
+ sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberTD)->nPosition;
+ OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
+#endif
+ VtableSlot aVtableSlot(
+ getVtableSlot(
+ reinterpret_cast<
+ typelib_InterfaceMethodTypeDescription const * >(
+ pMemberTD)));
+
+ 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 = NULL;
+ TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
+
+ if ( pTD )
+ {
+ uno_Interface * pInterface = NULL;
+ (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
+ pThis->getBridge()->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:
+ if ( ! cpp_call(
+ pThis, aVtableSlot,
+ ((typelib_InterfaceMethodTypeDescription *)pMemberTD)->pReturnTypeRef,
+ ((typelib_InterfaceMethodTypeDescription *)pMemberTD)->nParams,
+ ((typelib_InterfaceMethodTypeDescription *)pMemberTD)->pParams,
+ pReturn, pArgs, ppException ) )
+ {
+ RuntimeException aExc(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("Too many parameters!") ),
+ Reference< XInterface >() );
+
+ Type const & rExcType = ::getCppuType( &aExc );
+ ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
+ }
+ }
+ break;
+ }
+ default:
+ {
+ RuntimeException aExc(
+ OUString( RTL_CONSTASCII_USTRINGPARAM("Illegal member type description!") ),
+ Reference< XInterface >() );
+
+ Type const & rExcType = ::getCppuType( &aExc );
+ // Binary identical null reference (whatever that comment means...)
+ ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
+ }
+ }
+}
+
+} } }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */