1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_cli_ure.hxx" 30 31 #include <sal/alloca.h> 32 #include "rtl/ustrbuf.hxx" 33 #include "cli_base.h" 34 #include "cli_bridge.h" 35 36 namespace sr=System::Reflection; 37 namespace css=com::sun::star; 38 using namespace rtl; 39 40 namespace cli_uno 41 { 42 43 union largest 44 { 45 sal_Int64 n; 46 double d; 47 void * p; 48 uno_Any a; 49 }; 50 51 System::Object* Bridge::call_uno(uno_Interface * pUnoI, 52 typelib_TypeDescription* member_td, 53 typelib_TypeDescriptionReference * return_type, 54 sal_Int32 nParams, typelib_MethodParameter const * pParams, 55 System::Object * args[], System::Type* argTypes[], 56 System::Object** ppExc) const 57 { 58 // return mem 59 sal_Int32 return_size = sizeof (largest); 60 if ((0 != return_type) && 61 (typelib_TypeClass_STRUCT == return_type->eTypeClass || 62 typelib_TypeClass_EXCEPTION == return_type->eTypeClass)) 63 { 64 TypeDescr return_td( return_type ); 65 if (return_td.get()->nSize > sizeof (largest)) 66 return_size = return_td.get()->nSize; 67 } 68 //Prepare memory that contains all converted arguments and return valuse 69 //The memory block contains first pointers to the arguments which are in the same block 70 // For example, 2 arguments, 1 ret. 71 // 72 // | Pointer 73 // | Pointer 74 // | Return value 75 // | Arg 1 76 // | Arg 2 77 // 78 // If an argument is larger then union largest, such as some structures, then the pointer 79 // points to an extra block of memory. The same goes for a big return value. 80 81 char * mem = (char *)alloca( 82 (nParams * sizeof (void *)) + return_size + (nParams * sizeof (largest)) ); 83 //array of pointers to args 84 void ** uno_args = (void **)mem; 85 //If an attribute is set, then uno_ret must be null, e.g void setAttribute(int ) 86 void * uno_ret= NULL; 87 if ( !(member_td->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE && nParams == 1)) 88 uno_ret = (mem + (nParams * sizeof (void *))); 89 largest * uno_args_mem = (largest *)(mem + (nParams * sizeof (void *)) + return_size); 90 91 OSL_ASSERT( (0 == nParams) || (nParams == args->get_Length()) ); 92 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 93 { 94 typelib_MethodParameter const & param = pParams[ nPos ]; 95 typelib_TypeDescriptionReference * type = param.pTypeRef; 96 97 uno_args[ nPos ] = &uno_args_mem[ nPos ]; 98 if (typelib_TypeClass_STRUCT == type->eTypeClass || 99 typelib_TypeClass_EXCEPTION == type->eTypeClass) 100 { 101 TypeDescr td( type ); 102 if (td.get()->nSize > sizeof (largest)) 103 uno_args[ nPos ] = alloca( td.get()->nSize ); 104 } 105 106 if (param.bIn) 107 { 108 try 109 { 110 // in, in/out params 111 map_to_uno( 112 uno_args[ nPos ],args[nPos] , type, false /* no assign */); 113 } 114 catch (...) 115 { 116 // cleanup uno in args 117 for (sal_Int32 n = 0; n < nPos; ++n) 118 { 119 typelib_MethodParameter const & param = pParams[n]; 120 if (param.bIn) 121 { 122 uno_type_destructData(uno_args[n], param.pTypeRef, 0); 123 } 124 } 125 throw; 126 } 127 } 128 } 129 uno_Any uno_exc_holder; 130 uno_Any * uno_exc = &uno_exc_holder; 131 // call binary uno 132 133 (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc ); 134 135 if (0 == uno_exc) 136 { 137 // convert out args; destruct uno args 138 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 139 { 140 typelib_MethodParameter const & param = pParams[ nPos ]; 141 typelib_TypeDescriptionReference * type = param.pTypeRef; 142 if (param.bOut) 143 { 144 try 145 { 146 map_to_cli( 147 &args[nPos], uno_args[nPos], param.pTypeRef, 148 argTypes != NULL ? argTypes[nPos] : NULL, false ); 149 } 150 catch (...) 151 { 152 // cleanup further uno args 153 for ( sal_Int32 n = nPos; n < nParams; ++n ) 154 { 155 uno_type_destructData( uno_args[n], pParams[n].pTypeRef, 0 ); 156 } 157 // cleanup uno return value 158 uno_type_destructData( uno_ret, return_type, 0 ); 159 throw; 160 } 161 } 162 //cleanup args 163 if (typelib_TypeClass_DOUBLE < type->eTypeClass && 164 typelib_TypeClass_ENUM != type->eTypeClass) // opt 165 { 166 uno_type_destructData(uno_args[nPos], type, 0); 167 } 168 } 169 170 if ((0 != return_type) && 171 (typelib_TypeClass_VOID != return_type->eTypeClass)) 172 { 173 // convert uno return value 174 try 175 { 176 System::Object* cli_ret; 177 map_to_cli( 178 &cli_ret, uno_ret, return_type, 0, false); 179 uno_type_destructData(uno_ret, return_type, 0); 180 return cli_ret; 181 } 182 catch (...) 183 { 184 uno_type_destructData(uno_ret, return_type, 0); 185 throw; 186 } 187 } 188 return 0; // void return 189 } 190 else // exception occured 191 { 192 // destruct uno in args 193 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) 194 { 195 typelib_MethodParameter const & param = pParams[ nPos ]; 196 if (param.bIn) 197 { 198 uno_type_destructData( uno_args[ nPos ], param.pTypeRef, 0 ); 199 } 200 } 201 map_to_cli(ppExc, uno_exc_holder.pData, 202 uno_exc_holder.pType, NULL, false); 203 return 0; 204 } 205 } 206 207 void Bridge::call_cli( 208 System::Object* cliI, 209 sr::MethodInfo* method, 210 typelib_TypeDescriptionReference * return_type, 211 typelib_MethodParameter * params, int nParams, 212 void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const 213 { 214 System::Object *args[]= new System::Object*[nParams]; 215 for (int nPos= 0; nPos < nParams; nPos++) 216 { 217 typelib_MethodParameter const & param= params[nPos]; 218 if (param.bIn) 219 { 220 map_to_cli( &args[nPos], 221 uno_args[nPos], param.pTypeRef, 0, false); 222 } 223 } 224 System::Object* retInvoke= NULL; 225 try 226 { 227 retInvoke= method->Invoke(cliI, args); 228 } 229 catch (sr::TargetInvocationException* e) 230 { 231 System::Exception* exc= e->get_InnerException(); 232 css::uno::TypeDescription td(mapCliType(exc->GetType())); 233 // memory for exception 234 std::auto_ptr< rtl_mem > memExc(rtl_mem::allocate(td.get()->nSize)); 235 map_to_uno(memExc.get(), exc, td.get()->pWeakRef, false); 236 (*uno_exc)->pType= td.get()->pWeakRef; 237 (*uno_exc)->pData= memExc.release(); 238 return; 239 } 240 catch (System::Exception* e) 241 { 242 OUStringBuffer buf( 128 ); 243 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( 244 "Unexspected exception during invocation of cli object. " 245 "Original message is: \n") ); 246 buf.append(mapCliString(e->get_Message())); 247 throw BridgeRuntimeError( buf.makeStringAndClear() ); 248 } 249 250 //convert out, in/out params 251 for (int nPos = 0; nPos < nParams; ++nPos ) 252 { 253 typelib_MethodParameter const & param = params[ nPos ]; 254 255 if (param.bOut) 256 { 257 try 258 { 259 map_to_uno( 260 uno_args[ nPos ], args[ nPos ], param.pTypeRef, 261 sal_True == param.bIn /* assign if inout */); 262 // out array 263 } 264 catch (...) 265 { 266 // cleanup uno pure out 267 for ( sal_Int32 n = 0; n < nPos; ++n ) 268 { 269 typelib_MethodParameter const & param = params[ n ]; 270 if (! param.bIn) 271 uno_type_destructData( uno_args[ n ], param.pTypeRef, 0 ); 272 } 273 throw; 274 } 275 } 276 } 277 // return value 278 if (0 != return_type) 279 { 280 map_to_uno( 281 uno_ret, retInvoke, return_type, false /* no assign */); 282 } 283 // no exception occured 284 *uno_exc = 0; 285 } 286 287 288 289 290 } 291