154c06456SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 354c06456SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 454c06456SAndrew Rist * or more contributor license agreements. See the NOTICE file 554c06456SAndrew Rist * distributed with this work for additional information 654c06456SAndrew Rist * regarding copyright ownership. The ASF licenses this file 754c06456SAndrew Rist * to you under the Apache License, Version 2.0 (the 854c06456SAndrew Rist * "License"); you may not use this file except in compliance 954c06456SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 1154c06456SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 1354c06456SAndrew Rist * Unless required by applicable law or agreed to in writing, 1454c06456SAndrew Rist * software distributed under the License is distributed on an 1554c06456SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1654c06456SAndrew Rist * KIND, either express or implied. See the License for the 1754c06456SAndrew Rist * specific language governing permissions and limitations 1854c06456SAndrew Rist * under the License. 19cdf0e10cSrcweir * 2054c06456SAndrew Rist *************************************************************/ 2154c06456SAndrew Rist 2254c06456SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_cli_ure.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <sal/alloca.h> 28cdf0e10cSrcweir #include "rtl/ustrbuf.hxx" 29cdf0e10cSrcweir #include "cli_base.h" 30cdf0e10cSrcweir #include "cli_bridge.h" 31cdf0e10cSrcweir 32cdf0e10cSrcweir namespace sr=System::Reflection; 33cdf0e10cSrcweir namespace css=com::sun::star; 34cdf0e10cSrcweir using namespace rtl; 35cdf0e10cSrcweir 36cdf0e10cSrcweir namespace cli_uno 37cdf0e10cSrcweir { 38cdf0e10cSrcweir 39cdf0e10cSrcweir union largest 40cdf0e10cSrcweir { 41cdf0e10cSrcweir sal_Int64 n; 42cdf0e10cSrcweir double d; 43cdf0e10cSrcweir void * p; 44cdf0e10cSrcweir uno_Any a; 45cdf0e10cSrcweir }; 46cdf0e10cSrcweir 47cdf0e10cSrcweir System::Object* Bridge::call_uno(uno_Interface * pUnoI, 48cdf0e10cSrcweir typelib_TypeDescription* member_td, 49cdf0e10cSrcweir typelib_TypeDescriptionReference * return_type, 50cdf0e10cSrcweir sal_Int32 nParams, typelib_MethodParameter const * pParams, 51cdf0e10cSrcweir System::Object * args[], System::Type* argTypes[], 52cdf0e10cSrcweir System::Object** ppExc) const 53cdf0e10cSrcweir { 54cdf0e10cSrcweir // return mem 55cdf0e10cSrcweir sal_Int32 return_size = sizeof (largest); 56cdf0e10cSrcweir if ((0 != return_type) && 57cdf0e10cSrcweir (typelib_TypeClass_STRUCT == return_type->eTypeClass || 58cdf0e10cSrcweir typelib_TypeClass_EXCEPTION == return_type->eTypeClass)) 59cdf0e10cSrcweir { 60cdf0e10cSrcweir TypeDescr return_td( return_type ); 61cdf0e10cSrcweir if (return_td.get()->nSize > sizeof (largest)) 62cdf0e10cSrcweir return_size = return_td.get()->nSize; 63cdf0e10cSrcweir } 64cdf0e10cSrcweir //Prepare memory that contains all converted arguments and return valuse 65cdf0e10cSrcweir //The memory block contains first pointers to the arguments which are in the same block 66cdf0e10cSrcweir // For example, 2 arguments, 1 ret. 67cdf0e10cSrcweir // 68cdf0e10cSrcweir // | Pointer 69cdf0e10cSrcweir // | Pointer 70cdf0e10cSrcweir // | Return value 71cdf0e10cSrcweir // | Arg 1 72cdf0e10cSrcweir // | Arg 2 73cdf0e10cSrcweir // 74cdf0e10cSrcweir // If an argument is larger then union largest, such as some structures, then the pointer 75cdf0e10cSrcweir // points to an extra block of memory. The same goes for a big return value. 76cdf0e10cSrcweir 77cdf0e10cSrcweir char * mem = (char *)alloca( 78cdf0e10cSrcweir (nParams * sizeof (void *)) + return_size + (nParams * sizeof (largest)) ); 79cdf0e10cSrcweir //array of pointers to args 80cdf0e10cSrcweir void ** uno_args = (void **)mem; 81cdf0e10cSrcweir //If an attribute is set, then uno_ret must be null, e.g void setAttribute(int ) 82cdf0e10cSrcweir void * uno_ret= NULL; 83cdf0e10cSrcweir if ( !(member_td->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE && nParams == 1)) 84cdf0e10cSrcweir uno_ret = (mem + (nParams * sizeof (void *))); 85cdf0e10cSrcweir largest * uno_args_mem = (largest *)(mem + (nParams * sizeof (void *)) + return_size); 86cdf0e10cSrcweir 87cdf0e10cSrcweir OSL_ASSERT( (0 == nParams) || (nParams == args->get_Length()) ); 88cdf0e10cSrcweir for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 89cdf0e10cSrcweir { 90cdf0e10cSrcweir typelib_MethodParameter const & param = pParams[ nPos ]; 91cdf0e10cSrcweir typelib_TypeDescriptionReference * type = param.pTypeRef; 92cdf0e10cSrcweir 93cdf0e10cSrcweir uno_args[ nPos ] = &uno_args_mem[ nPos ]; 94cdf0e10cSrcweir if (typelib_TypeClass_STRUCT == type->eTypeClass || 95cdf0e10cSrcweir typelib_TypeClass_EXCEPTION == type->eTypeClass) 96cdf0e10cSrcweir { 97cdf0e10cSrcweir TypeDescr td( type ); 98cdf0e10cSrcweir if (td.get()->nSize > sizeof (largest)) 99cdf0e10cSrcweir uno_args[ nPos ] = alloca( td.get()->nSize ); 100cdf0e10cSrcweir } 101cdf0e10cSrcweir 102cdf0e10cSrcweir if (param.bIn) 103cdf0e10cSrcweir { 104cdf0e10cSrcweir try 105cdf0e10cSrcweir { 106cdf0e10cSrcweir // in, in/out params 107cdf0e10cSrcweir map_to_uno( 108cdf0e10cSrcweir uno_args[ nPos ],args[nPos] , type, false /* no assign */); 109cdf0e10cSrcweir } 110cdf0e10cSrcweir catch (...) 111cdf0e10cSrcweir { 112cdf0e10cSrcweir // cleanup uno in args 113cdf0e10cSrcweir for (sal_Int32 n = 0; n < nPos; ++n) 114cdf0e10cSrcweir { 115cdf0e10cSrcweir typelib_MethodParameter const & param = pParams[n]; 116cdf0e10cSrcweir if (param.bIn) 117cdf0e10cSrcweir { 118cdf0e10cSrcweir uno_type_destructData(uno_args[n], param.pTypeRef, 0); 119cdf0e10cSrcweir } 120cdf0e10cSrcweir } 121cdf0e10cSrcweir throw; 122cdf0e10cSrcweir } 123cdf0e10cSrcweir } 124cdf0e10cSrcweir } 125cdf0e10cSrcweir uno_Any uno_exc_holder; 126cdf0e10cSrcweir uno_Any * uno_exc = &uno_exc_holder; 127cdf0e10cSrcweir // call binary uno 128cdf0e10cSrcweir 129cdf0e10cSrcweir (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc ); 130cdf0e10cSrcweir 131cdf0e10cSrcweir if (0 == uno_exc) 132cdf0e10cSrcweir { 133cdf0e10cSrcweir // convert out args; destruct uno args 134cdf0e10cSrcweir for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 135cdf0e10cSrcweir { 136cdf0e10cSrcweir typelib_MethodParameter const & param = pParams[ nPos ]; 137cdf0e10cSrcweir typelib_TypeDescriptionReference * type = param.pTypeRef; 138cdf0e10cSrcweir if (param.bOut) 139cdf0e10cSrcweir { 140cdf0e10cSrcweir try 141cdf0e10cSrcweir { 142cdf0e10cSrcweir map_to_cli( 143cdf0e10cSrcweir &args[nPos], uno_args[nPos], param.pTypeRef, 144cdf0e10cSrcweir argTypes != NULL ? argTypes[nPos] : NULL, false ); 145cdf0e10cSrcweir } 146cdf0e10cSrcweir catch (...) 147cdf0e10cSrcweir { 148cdf0e10cSrcweir // cleanup further uno args 149cdf0e10cSrcweir for ( sal_Int32 n = nPos; n < nParams; ++n ) 150cdf0e10cSrcweir { 151cdf0e10cSrcweir uno_type_destructData( uno_args[n], pParams[n].pTypeRef, 0 ); 152cdf0e10cSrcweir } 153cdf0e10cSrcweir // cleanup uno return value 154cdf0e10cSrcweir uno_type_destructData( uno_ret, return_type, 0 ); 155cdf0e10cSrcweir throw; 156cdf0e10cSrcweir } 157cdf0e10cSrcweir } 158cdf0e10cSrcweir //cleanup args 159cdf0e10cSrcweir if (typelib_TypeClass_DOUBLE < type->eTypeClass && 160cdf0e10cSrcweir typelib_TypeClass_ENUM != type->eTypeClass) // opt 161cdf0e10cSrcweir { 162cdf0e10cSrcweir uno_type_destructData(uno_args[nPos], type, 0); 163cdf0e10cSrcweir } 164cdf0e10cSrcweir } 165cdf0e10cSrcweir 166cdf0e10cSrcweir if ((0 != return_type) && 167cdf0e10cSrcweir (typelib_TypeClass_VOID != return_type->eTypeClass)) 168cdf0e10cSrcweir { 169cdf0e10cSrcweir // convert uno return value 170cdf0e10cSrcweir try 171cdf0e10cSrcweir { 172cdf0e10cSrcweir System::Object* cli_ret; 173cdf0e10cSrcweir map_to_cli( 174cdf0e10cSrcweir &cli_ret, uno_ret, return_type, 0, false); 175cdf0e10cSrcweir uno_type_destructData(uno_ret, return_type, 0); 176cdf0e10cSrcweir return cli_ret; 177cdf0e10cSrcweir } 178cdf0e10cSrcweir catch (...) 179cdf0e10cSrcweir { 180cdf0e10cSrcweir uno_type_destructData(uno_ret, return_type, 0); 181cdf0e10cSrcweir throw; 182cdf0e10cSrcweir } 183cdf0e10cSrcweir } 184cdf0e10cSrcweir return 0; // void return 185cdf0e10cSrcweir } 186*07a3d7f1SPedro Giffuni else // exception occurred 187cdf0e10cSrcweir { 188cdf0e10cSrcweir // destruct uno in args 189cdf0e10cSrcweir for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 190cdf0e10cSrcweir { 191cdf0e10cSrcweir typelib_MethodParameter const & param = pParams[ nPos ]; 192cdf0e10cSrcweir if (param.bIn) 193cdf0e10cSrcweir { 194cdf0e10cSrcweir uno_type_destructData( uno_args[ nPos ], param.pTypeRef, 0 ); 195cdf0e10cSrcweir } 196cdf0e10cSrcweir } 197cdf0e10cSrcweir map_to_cli(ppExc, uno_exc_holder.pData, 198cdf0e10cSrcweir uno_exc_holder.pType, NULL, false); 199cdf0e10cSrcweir return 0; 200cdf0e10cSrcweir } 201cdf0e10cSrcweir } 202cdf0e10cSrcweir 203cdf0e10cSrcweir void Bridge::call_cli( 204cdf0e10cSrcweir System::Object* cliI, 205cdf0e10cSrcweir sr::MethodInfo* method, 206cdf0e10cSrcweir typelib_TypeDescriptionReference * return_type, 207cdf0e10cSrcweir typelib_MethodParameter * params, int nParams, 208cdf0e10cSrcweir void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const 209cdf0e10cSrcweir { 210cdf0e10cSrcweir System::Object *args[]= new System::Object*[nParams]; 211cdf0e10cSrcweir for (int nPos= 0; nPos < nParams; nPos++) 212cdf0e10cSrcweir { 213cdf0e10cSrcweir typelib_MethodParameter const & param= params[nPos]; 214cdf0e10cSrcweir if (param.bIn) 215cdf0e10cSrcweir { 216cdf0e10cSrcweir map_to_cli( &args[nPos], 217cdf0e10cSrcweir uno_args[nPos], param.pTypeRef, 0, false); 218cdf0e10cSrcweir } 219cdf0e10cSrcweir } 220cdf0e10cSrcweir System::Object* retInvoke= NULL; 221cdf0e10cSrcweir try 222cdf0e10cSrcweir { 223cdf0e10cSrcweir retInvoke= method->Invoke(cliI, args); 224cdf0e10cSrcweir } 225cdf0e10cSrcweir catch (sr::TargetInvocationException* e) 226cdf0e10cSrcweir { 227cdf0e10cSrcweir System::Exception* exc= e->get_InnerException(); 228cdf0e10cSrcweir css::uno::TypeDescription td(mapCliType(exc->GetType())); 229cdf0e10cSrcweir // memory for exception 230cdf0e10cSrcweir std::auto_ptr< rtl_mem > memExc(rtl_mem::allocate(td.get()->nSize)); 231cdf0e10cSrcweir map_to_uno(memExc.get(), exc, td.get()->pWeakRef, false); 232cdf0e10cSrcweir (*uno_exc)->pType= td.get()->pWeakRef; 233cdf0e10cSrcweir (*uno_exc)->pData= memExc.release(); 234cdf0e10cSrcweir return; 235cdf0e10cSrcweir } 236cdf0e10cSrcweir catch (System::Exception* e) 237cdf0e10cSrcweir { 238cdf0e10cSrcweir OUStringBuffer buf( 128 ); 239cdf0e10cSrcweir buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 240cdf0e10cSrcweir "Unexspected exception during invocation of cli object. " 241cdf0e10cSrcweir "Original message is: \n") ); 242cdf0e10cSrcweir buf.append(mapCliString(e->get_Message())); 243cdf0e10cSrcweir throw BridgeRuntimeError( buf.makeStringAndClear() ); 244cdf0e10cSrcweir } 245cdf0e10cSrcweir 246cdf0e10cSrcweir //convert out, in/out params 247cdf0e10cSrcweir for (int nPos = 0; nPos < nParams; ++nPos ) 248cdf0e10cSrcweir { 249cdf0e10cSrcweir typelib_MethodParameter const & param = params[ nPos ]; 250cdf0e10cSrcweir 251cdf0e10cSrcweir if (param.bOut) 252cdf0e10cSrcweir { 253cdf0e10cSrcweir try 254cdf0e10cSrcweir { 255cdf0e10cSrcweir map_to_uno( 256cdf0e10cSrcweir uno_args[ nPos ], args[ nPos ], param.pTypeRef, 257cdf0e10cSrcweir sal_True == param.bIn /* assign if inout */); 258cdf0e10cSrcweir // out array 259cdf0e10cSrcweir } 260cdf0e10cSrcweir catch (...) 261cdf0e10cSrcweir { 262cdf0e10cSrcweir // cleanup uno pure out 263cdf0e10cSrcweir for ( sal_Int32 n = 0; n < nPos; ++n ) 264cdf0e10cSrcweir { 265cdf0e10cSrcweir typelib_MethodParameter const & param = params[ n ]; 266cdf0e10cSrcweir if (! param.bIn) 267cdf0e10cSrcweir uno_type_destructData( uno_args[ n ], param.pTypeRef, 0 ); 268cdf0e10cSrcweir } 269cdf0e10cSrcweir throw; 270cdf0e10cSrcweir } 271cdf0e10cSrcweir } 272cdf0e10cSrcweir } 273cdf0e10cSrcweir // return value 274cdf0e10cSrcweir if (0 != return_type) 275cdf0e10cSrcweir { 276cdf0e10cSrcweir map_to_uno( 277cdf0e10cSrcweir uno_ret, retInvoke, return_type, false /* no assign */); 278cdf0e10cSrcweir } 279*07a3d7f1SPedro Giffuni // no exception occurred 280cdf0e10cSrcweir *uno_exc = 0; 281cdf0e10cSrcweir } 282cdf0e10cSrcweir 283cdf0e10cSrcweir 284cdf0e10cSrcweir 285cdf0e10cSrcweir 286cdf0e10cSrcweir } 287