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
relatesToInterface(typelib_TypeDescription * pTypeDescr)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
s_Proxy_dispatch(uno_Interface * pUnoI,typelib_TypeDescription const * pMemberType,void * pReturn,void * pArgs[],uno_Any ** ppException)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
Proxy_free(uno_ExtEnvironment *,void * pProxy)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" {
s_Proxy_acquire(uno_Interface * pUnoI)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
s_Proxy_release(uno_Interface * pUnoI)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
s_acquireAndRegister_v(va_list * pParam)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
Proxy(uno::Mapping const & to_from,uno_Environment * pTo,uno_Environment * pFrom,uno_Interface * pUnoI,typelib_InterfaceTypeDescription * pTypeDescr,rtl::OUString const & rOId,cppu::helper::purpenv::ProbeFun * probeFun,void * pProbeContext)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
s_releaseAndRevoke_v(va_list * pParam)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
~Proxy()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
getAcquireMethod(void)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
getReleaseMethod(void)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
acquire(void)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
release(void)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" {
s_type_destructData_v(va_list * pParam)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
s_dispatcher_v(va_list * pParam)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
dispatch(typelib_TypeDescriptionReference * pReturnTypeRef,typelib_MethodParameter * pParams,sal_Int32 nParams,typelib_TypeDescription const * pMemberType,void * pReturn,void * pArgs[],uno_Any ** ppException)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