1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_cppu.hxx" 26 27 #include "Proxy.hxx" 28 29 #include "sal/alloca.h" 30 #include "uno/dispatcher.h" 31 #include "typelib/typedescription.hxx" 32 #include "cppu/EnvDcp.hxx" 33 34 35 //#define LOG_LIFECYCLE_Proxy 36 #ifdef LOG_LIFECYCLE_Proxy 37 # include <iostream> 38 # define LOG_LIFECYCLE_Proxy_emit(x) x 39 40 #else 41 # define LOG_LIFECYCLE_Proxy_emit(x) 42 43 #endif 44 45 46 using namespace com::sun::star; 47 48 49 static bool relatesToInterface(typelib_TypeDescription * pTypeDescr) 50 SAL_THROW( () ) 51 { 52 switch (pTypeDescr->eTypeClass) 53 { 54 // case typelib_TypeClass_TYPEDEF: 55 case typelib_TypeClass_SEQUENCE: 56 { 57 switch (((typelib_IndirectTypeDescription *)pTypeDescr)->pType->eTypeClass) 58 { 59 case typelib_TypeClass_INTERFACE: 60 case typelib_TypeClass_UNION: // might relate to interface 61 case typelib_TypeClass_ANY: // might relate to interface 62 return true; 63 case typelib_TypeClass_SEQUENCE: 64 case typelib_TypeClass_STRUCT: 65 case typelib_TypeClass_EXCEPTION: 66 { 67 typelib_TypeDescription * pTD = 0; 68 TYPELIB_DANGER_GET( &pTD, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType ); 69 bool bRel = relatesToInterface( pTD ); 70 TYPELIB_DANGER_RELEASE( pTD ); 71 return bRel; 72 } 73 default: 74 ; 75 } 76 return false; 77 } 78 case typelib_TypeClass_STRUCT: 79 case typelib_TypeClass_EXCEPTION: 80 { 81 // ...optimized... to avoid getDescription() calls! 82 typelib_CompoundTypeDescription * pComp = (typelib_CompoundTypeDescription *)pTypeDescr; 83 typelib_TypeDescriptionReference ** pTypes = pComp->ppTypeRefs; 84 for ( sal_Int32 nPos = pComp->nMembers; nPos--; ) 85 { 86 switch (pTypes[nPos]->eTypeClass) 87 { 88 case typelib_TypeClass_INTERFACE: 89 case typelib_TypeClass_UNION: // might relate to interface 90 case typelib_TypeClass_ANY: // might relate to interface 91 return true; 92 // case typelib_TypeClass_TYPEDEF: 93 case typelib_TypeClass_SEQUENCE: 94 case typelib_TypeClass_STRUCT: 95 case typelib_TypeClass_EXCEPTION: 96 { 97 typelib_TypeDescription * pTD = 0; 98 TYPELIB_DANGER_GET( &pTD, pTypes[nPos] ); 99 bool bRel = relatesToInterface( pTD ); 100 TYPELIB_DANGER_RELEASE( pTD ); 101 if (bRel) 102 return true; 103 } 104 default: 105 ; 106 } 107 } 108 if (pComp->pBaseTypeDescription) 109 return relatesToInterface( (typelib_TypeDescription *)pComp->pBaseTypeDescription ); 110 break; 111 } 112 case typelib_TypeClass_UNION: // might relate to interface 113 case typelib_TypeClass_ANY: // might relate to interface 114 case typelib_TypeClass_INTERFACE: 115 return true; 116 117 default: 118 ; 119 } 120 return false; 121 } 122 123 extern "C" { static void SAL_CALL s_Proxy_dispatch( 124 uno_Interface * pUnoI, 125 typelib_TypeDescription const * pMemberType, 126 void * pReturn, 127 void * pArgs[], 128 uno_Any ** ppException) 129 SAL_THROW_EXTERN_C() 130 { 131 Proxy * pThis = static_cast<Proxy *>(pUnoI); 132 133 typelib_MethodParameter param; 134 sal_Int32 nParams = 0; 135 typelib_MethodParameter * pParams = 0; 136 typelib_TypeDescriptionReference * pReturnTypeRef = 0; 137 // sal_Int32 nOutParams = 0; 138 139 switch (pMemberType->eTypeClass) 140 { 141 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 142 if (pReturn) 143 { 144 pReturnTypeRef = 145 ((typelib_InterfaceAttributeTypeDescription *) 146 pMemberType)->pAttributeTypeRef; 147 nParams = 0; 148 pParams = NULL; 149 } 150 else 151 { 152 param.pTypeRef = ((typelib_InterfaceAttributeTypeDescription *) 153 pMemberType)->pAttributeTypeRef; 154 param.bIn = sal_True; 155 param.bOut = sal_False; 156 nParams = 1; 157 pParams = ¶m; 158 } 159 break; 160 case typelib_TypeClass_INTERFACE_METHOD: 161 { 162 typelib_InterfaceMethodTypeDescription * method_td = 163 (typelib_InterfaceMethodTypeDescription *) pMemberType; 164 pReturnTypeRef = method_td->pReturnTypeRef; 165 nParams = method_td->nParams; 166 pParams = method_td->pParams; 167 break; 168 } 169 default: 170 OSL_ENSURE( sal_False, "### illegal member typeclass!" ); 171 abort(); 172 } 173 174 pThis->dispatch( pReturnTypeRef, 175 pParams, 176 nParams, 177 pMemberType, 178 pReturn, 179 pArgs, 180 ppException ); 181 }} 182 183 extern "C" void SAL_CALL Proxy_free(uno_ExtEnvironment * /*pEnv*/, void * pProxy) SAL_THROW_EXTERN_C() 184 { 185 Proxy * pThis = static_cast<Proxy * >(reinterpret_cast<uno_Interface *>(pProxy)); 186 delete pThis; 187 } 188 189 extern "C" { 190 static void SAL_CALL s_Proxy_acquire(uno_Interface * pUnoI) SAL_THROW_EXTERN_C() 191 { 192 Proxy * pProxy = static_cast<Proxy *>(pUnoI); 193 pProxy->acquire(); 194 } 195 196 static void SAL_CALL s_Proxy_release(uno_Interface * pUnoI) SAL_THROW_EXTERN_C() 197 { 198 Proxy * pProxy = static_cast<Proxy *>(pUnoI); 199 pProxy->release(); 200 } 201 202 static void s_acquireAndRegister_v(va_list * pParam) 203 { 204 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); 205 rtl_uString * pOid = va_arg(*pParam, rtl_uString *); 206 typelib_InterfaceTypeDescription * pTypeDescr = va_arg(*pParam, typelib_InterfaceTypeDescription *); 207 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); 208 209 pUnoI->acquire(pUnoI); 210 pEnv->registerInterface(pEnv, reinterpret_cast<void **>(&pUnoI), pOid, pTypeDescr); 211 } 212 } 213 214 Proxy::Proxy(uno::Mapping const & to_from, 215 uno_Environment * pTo, 216 uno_Environment * pFrom, 217 uno_Interface * pUnoI, 218 typelib_InterfaceTypeDescription * pTypeDescr, 219 rtl::OUString const & rOId, 220 cppu::helper::purpenv::ProbeFun * probeFun, 221 void * pProbeContext 222 ) 223 SAL_THROW(()) 224 : m_nRef (1), 225 m_from (pFrom), 226 m_to (pTo), 227 m_from_to (pFrom, pTo), 228 m_to_from (to_from), 229 m_pUnoI (pUnoI), 230 m_pTypeDescr (pTypeDescr), 231 m_aOId (rOId), 232 m_probeFun (probeFun), 233 m_pProbeContext(pProbeContext) 234 { 235 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::Proxy(<>)", this)); 236 237 typelib_typedescription_acquire((typelib_TypeDescription *)m_pTypeDescr); 238 if (!((typelib_TypeDescription *)m_pTypeDescr)->bComplete) 239 typelib_typedescription_complete((typelib_TypeDescription **)&m_pTypeDescr); 240 241 OSL_ENSURE(((typelib_TypeDescription *)m_pTypeDescr)->bComplete, "### type is incomplete!"); 242 243 uno_Environment_invoke(m_to.get(), s_acquireAndRegister_v, m_pUnoI, rOId.pData, pTypeDescr, m_to.get()); 244 245 // uno_Interface 246 uno_Interface::acquire = s_Proxy_acquire; 247 uno_Interface::release = s_Proxy_release; 248 uno_Interface::pDispatcher = s_Proxy_dispatch; 249 } 250 251 extern "C" { static void s_releaseAndRevoke_v(va_list * pParam) 252 { 253 uno_ExtEnvironment * pEnv = va_arg(*pParam, uno_ExtEnvironment *); 254 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); 255 256 pEnv->revokeInterface(pEnv, reinterpret_cast<void *>(pUnoI)); 257 pUnoI->release(pUnoI); 258 }} 259 260 Proxy::~Proxy() 261 { 262 LOG_LIFECYCLE_Proxy_emit(fprintf(stderr, "LIFE: %s -> %p\n", "Proxy::~Proxy()", this)); 263 264 uno_Environment_invoke(m_to.get(), s_releaseAndRevoke_v, m_to.get(), m_pUnoI); 265 266 typelib_typedescription_release((typelib_TypeDescription *)m_pTypeDescr); 267 } 268 269 static uno::TypeDescription getAcquireMethod(void) 270 { 271 typelib_TypeDescriptionReference * type_XInterface = 272 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE); 273 274 typelib_TypeDescription * pTXInterfaceDescr = 0; 275 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface); 276 uno::TypeDescription acquire( 277 reinterpret_cast< typelib_InterfaceTypeDescription * >( 278 pTXInterfaceDescr)->ppAllMembers[1]); 279 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr); 280 281 return acquire; 282 } 283 284 static uno::TypeDescription getReleaseMethod(void) 285 { 286 typelib_TypeDescriptionReference * type_XInterface = 287 * typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE); 288 289 typelib_TypeDescription * pTXInterfaceDescr = 0; 290 TYPELIB_DANGER_GET (&pTXInterfaceDescr, type_XInterface); 291 uno::TypeDescription release( 292 reinterpret_cast< typelib_InterfaceTypeDescription * >( 293 pTXInterfaceDescr)->ppAllMembers[2]); 294 TYPELIB_DANGER_RELEASE(pTXInterfaceDescr); 295 296 return release; 297 } 298 299 static uno::TypeDescription s_acquireMethod(getAcquireMethod()); 300 static uno::TypeDescription s_releaseMethod(getReleaseMethod()); 301 302 void Proxy::acquire(void) 303 { 304 if (m_probeFun) 305 m_probeFun(true, 306 this, 307 m_pProbeContext, 308 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), 309 NULL, 310 0, 311 s_acquireMethod.get(), 312 NULL, 313 NULL, 314 NULL); 315 316 if (osl_incrementInterlockedCount(&m_nRef) == 1) 317 { 318 // rebirth of proxy zombie 319 void * pThis = this; 320 m_from.get()->pExtEnv->registerProxyInterface(m_from.get()->pExtEnv, 321 &pThis, 322 Proxy_free, 323 m_aOId.pData, 324 m_pTypeDescr); 325 OSL_ASSERT(pThis == this); 326 } 327 328 if (m_probeFun) 329 m_probeFun(false, 330 this, 331 m_pProbeContext, 332 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), 333 NULL, 334 0, 335 s_acquireMethod.get(), 336 NULL, 337 NULL, 338 NULL); 339 340 } 341 342 void Proxy::release(void) 343 { 344 cppu::helper::purpenv::ProbeFun * probeFun = m_probeFun; 345 void * pProbeContext = m_pProbeContext; 346 347 if (m_probeFun) 348 m_probeFun(true, 349 this, 350 m_pProbeContext, 351 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), 352 NULL, 353 0, 354 s_releaseMethod.get(), 355 NULL, 356 NULL, 357 NULL); 358 359 if (osl_decrementInterlockedCount(&m_nRef) == 0) 360 m_from.get()->pExtEnv->revokeInterface(m_from.get()->pExtEnv, this); 361 362 if (probeFun) 363 probeFun(false, 364 this, 365 pProbeContext, 366 *typelib_static_type_getByTypeClass(typelib_TypeClass_VOID), 367 NULL, 368 0, 369 s_releaseMethod.get(), 370 NULL, 371 NULL, 372 NULL); 373 374 } 375 376 377 extern "C" { 378 static void s_type_destructData_v(va_list * pParam) 379 { 380 void * ret = va_arg(*pParam, void *); 381 typelib_TypeDescriptionReference * pReturnTypeRef = va_arg(*pParam, typelib_TypeDescriptionReference *); 382 383 uno_type_destructData(ret, pReturnTypeRef, 0); 384 } 385 386 static void s_dispatcher_v(va_list * pParam) 387 { 388 uno_Interface * pUnoI = va_arg(*pParam, uno_Interface *); 389 typelib_TypeDescription const * pMemberType = va_arg(*pParam, typelib_TypeDescription const *); 390 void * pReturn = va_arg(*pParam, void *); 391 void ** pArgs = va_arg(*pParam, void **); 392 uno_Any ** ppException = va_arg(*pParam, uno_Any **); 393 394 pUnoI->pDispatcher(pUnoI, pMemberType, pReturn, pArgs, ppException); 395 } 396 } 397 398 void Proxy::dispatch(typelib_TypeDescriptionReference * pReturnTypeRef, 399 typelib_MethodParameter * pParams, 400 sal_Int32 nParams, 401 typelib_TypeDescription const * pMemberType, 402 void * pReturn, 403 void * pArgs[], 404 uno_Any ** ppException) 405 { 406 if (m_probeFun) 407 m_probeFun(true, 408 this, 409 m_pProbeContext, 410 pReturnTypeRef, 411 pParams, 412 nParams, 413 pMemberType, 414 pReturn, 415 pArgs, 416 ppException); 417 418 void ** args = (void **) alloca( sizeof (void *) * nParams ); 419 420 typelib_TypeDescription * return_td = 0; 421 void * ret = pReturn; 422 if (pReturnTypeRef) 423 { 424 TYPELIB_DANGER_GET(&return_td, pReturnTypeRef); 425 426 if (relatesToInterface(return_td)) 427 ret = alloca(return_td->nSize); 428 429 TYPELIB_DANGER_RELEASE(return_td); 430 } 431 432 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos) 433 { 434 typelib_MethodParameter const & param = pParams[nPos]; 435 typelib_TypeDescription * td = 0; 436 TYPELIB_DANGER_GET( &td, param.pTypeRef ); 437 if (relatesToInterface(td)) 438 { 439 args[nPos] = alloca(td->nSize); 440 if (param.bIn) 441 { 442 uno_copyAndConvertData(args[nPos], pArgs[nPos], td, m_from_to.get()); 443 } 444 } 445 else 446 { 447 args[nPos] = pArgs[nPos]; 448 } 449 TYPELIB_DANGER_RELEASE( td ); 450 } 451 452 uno_Any exc_data; 453 uno_Any * exc = &exc_data; 454 455 // do the UNO call... 456 uno_Environment_invoke(m_to.get(), s_dispatcher_v, m_pUnoI, pMemberType, ret, args, &exc); 457 458 if (exc == 0) 459 { 460 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos) 461 { 462 if (args[nPos] != pArgs[nPos]) 463 { 464 typelib_MethodParameter const & param = pParams[nPos]; 465 if (param.bOut) 466 { 467 if (param.bIn) // is inout 468 { 469 uno_type_destructData(pArgs[nPos], param.pTypeRef, 0); 470 } 471 uno_type_copyAndConvertData(pArgs[ nPos ], 472 args[ nPos ], 473 param.pTypeRef, 474 m_to_from.get()); 475 } 476 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0); 477 } 478 } 479 if (ret != pReturn) 480 { 481 uno_type_copyAndConvertData(pReturn, 482 ret, 483 pReturnTypeRef, 484 m_to_from.get()); 485 486 uno_Environment_invoke(m_to.get(), s_type_destructData_v, ret, pReturnTypeRef, 0); 487 } 488 489 *ppException = 0; 490 } 491 else // exception occured 492 { 493 for (sal_Int32 nPos = 0; nPos < nParams; ++ nPos) 494 { 495 if (args[nPos] != pArgs[nPos]) 496 { 497 typelib_MethodParameter const & param = pParams[nPos]; 498 if (param.bIn) 499 { 500 uno_Environment_invoke(m_to.get(), s_type_destructData_v, args[nPos], param.pTypeRef, 0); 501 } 502 } 503 } 504 505 uno_type_any_constructAndConvert(*ppException, 506 exc->pData, 507 exc->pType, 508 m_to_from.get()); 509 510 // FIXME: need to destruct in m_to 511 uno_any_destruct(exc, 0); 512 } 513 514 if (m_probeFun) 515 m_probeFun(false, 516 this, 517 m_pProbeContext, 518 pReturnTypeRef, 519 pParams, 520 nParams, 521 pMemberType, 522 pReturn, 523 pArgs, 524 ppException); 525 } 526 527