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_bridges.hxx"
26
27 #include <malloc.h>
28
29 #include <com/sun/star/uno/genfunc.hxx>
30 #include <uno/data.h>
31 #include <typelib/typedescription.hxx>
32
33 #include "bridges/cpp_uno/shared/bridge.hxx"
34 #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
35 #include "bridges/cpp_uno/shared/types.hxx"
36 #include "bridges/cpp_uno/shared/vtablefactory.hxx"
37
38 #include "abi.hxx"
39 #include "mscx.hxx"
40
41 using namespace ::rtl;
42 using namespace ::com::sun::star::uno;
43
44 namespace
45 {
46
47 //==================================================================================================
48
49 // Perform the UNO call
50 //
51 // We must convert the parameters stored in pCallStack to UNO
52 // arguments and call pThis->getUnoI()->pDispatcher.
53 //
54 // pCallStack: ret addr, this, [ret *], [params]
55 //
56 // [ret *] is present when we are returning a structure bigger than 8 bytes
57 // Simple types are returned in rax, or xmm0 (fp).
58 // Similarly structures <= 8 bytes are in rax, xmm0 as necessary.
cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy * pThis,const typelib_TypeDescription * pMemberTypeDescr,typelib_TypeDescriptionReference * pReturnTypeRef,sal_Int32 nParams,typelib_MethodParameter * pParams,void ** pCallStack,sal_uInt64 * pRegisterReturn)59 static inline typelib_TypeClass cpp2uno_call(
60 bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
61 const typelib_TypeDescription * pMemberTypeDescr,
62 typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
63 sal_Int32 nParams, typelib_MethodParameter * pParams,
64 void ** pCallStack,
65 sal_uInt64 * pRegisterReturn /* space for register return */ )
66 {
67 // return
68 typelib_TypeDescription * pReturnTypeDescr = 0;
69 if (pReturnTypeRef)
70 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
71
72 void * pUnoReturn = 0;
73 void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
74
75 if ( pReturnTypeDescr )
76 {
77 if ( x86_64::return_in_hidden_param( pReturnTypeRef ) )
78 {
79 // complex return via ptr (pCppReturn)
80 pCppReturn = pCallStack[2];
81 ++pCallStack;
82
83 pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
84 ? alloca( pReturnTypeDescr->nSize )
85 : pCppReturn ); // direct way
86 }
87 else
88 pUnoReturn = pRegisterReturn; // direct way for simple types
89 }
90
91 // skip to first argument
92 pCallStack += 2;
93
94 // stack space
95 // parameters
96 void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
97 void ** pCppArgs = pUnoArgs + nParams;
98 // indices of values this have to be converted (interface conversion cpp<=>uno)
99 sal_Int32 * pTempIndizes = (sal_Int32 *)(pUnoArgs + (2 * nParams));
100 // type descriptions for reconversions
101 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
102
103 sal_Int32 nTempIndizes = 0;
104
105 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
106 {
107 const typelib_MethodParameter & rParam = pParams[nPos];
108 typelib_TypeDescription * pParamTypeDescr = 0;
109 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
110
111 if ( !rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr )) // value
112 {
113 pCppArgs[nPos] = pUnoArgs[nPos] = pCallStack++;
114 // no longer needed
115 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
116 }
117 else // ptr to complex value || ref
118 {
119 void *pCppStack;
120 pCppArgs[nPos] = pCppStack = *pCallStack++;
121
122 if (! rParam.bIn) // is pure out
123 {
124 // uno out is unconstructed mem!
125 pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
126 pTempIndizes[nTempIndizes] = nPos;
127 // will be released at reconversion
128 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
129 }
130 else if ( bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ) ) // is in/inout
131 {
132 uno_copyAndConvertData( pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
133 pCppStack, pParamTypeDescr,
134 pThis->getBridge()->getCpp2Uno() );
135 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
136 // will be released at reconversion
137 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
138 }
139 else // direct way
140 {
141 pUnoArgs[nPos] = pCppStack;
142 // no longer needed
143 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
144 }
145 }
146 }
147
148 // ExceptionHolder
149 uno_Any aUnoExc; // Any will be constructed by callee
150 uno_Any * pUnoExc = &aUnoExc;
151
152 // invoke uno dispatch call
153 (*pThis->getUnoI()->pDispatcher)( pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
154
155 // in case an exception occurred...
156 if ( pUnoExc )
157 {
158 // destruct temporary in/inout params
159 for ( ; nTempIndizes--; )
160 {
161 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
162
163 if (pParams[nIndex].bIn) // is in/inout => was constructed
164 uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], 0 );
165 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
166 }
167 if (pReturnTypeDescr)
168 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
169
170 CPPU_CURRENT_NAMESPACE::mscx_raiseException( &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
171 // is here for dummy
172 return typelib_TypeClass_VOID;
173 }
174 else // else no exception occurred...
175 {
176 // temporary params
177 for ( ; nTempIndizes--; )
178 {
179 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
180 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
181
182 if ( pParams[nIndex].bOut ) // inout/out
183 {
184 // convert and assign
185 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
186 uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
187 pThis->getBridge()->getUno2Cpp() );
188 }
189 // destroy temp uno param
190 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
191
192 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
193 }
194 // return
195 if ( pCppReturn ) // has complex return
196 {
197 if ( pUnoReturn != pCppReturn ) // needs reconversion
198 {
199 uno_copyAndConvertData( pCppReturn, pUnoReturn, pReturnTypeDescr,
200 pThis->getBridge()->getUno2Cpp() );
201 // destroy temp uno return
202 uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
203 }
204 // complex return ptr is set to rax
205 *(void **)pRegisterReturn = pCppReturn;
206 }
207 if ( pReturnTypeDescr )
208 {
209 typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
210 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
211 return eRet;
212 }
213 else
214 return typelib_TypeClass_VOID;
215 }
216 }
217
218
219 //==================================================================================================
cpp_vtable_call(void ** pCallStack,sal_Int32 nFunctionIndex,sal_Int32 nVtableOffset,sal_uInt64 * pRegisterReturn)220 extern "C" typelib_TypeClass cpp_vtable_call(
221 void ** pCallStack, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
222 sal_uInt64 * pRegisterReturn /* space for register return */ )
223 {
224 // pCallStack: ret adr, this, [ret *], params
225 void * pThis = static_cast< char * >(pCallStack[1]) - nVtableOffset;
226
227 bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
228 bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
229
230 typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
231
232 OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!" );
233 if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
234 {
235 throw RuntimeException( OUString::createFromAscii("illegal vtable index!"),
236 reinterpret_cast<XInterface *>( pCppI ) );
237 }
238
239 // determine called method
240 sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
241 OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
242
243 TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
244
245 typelib_TypeClass eRet;
246 switch ( aMemberDescr.get()->eTypeClass )
247 {
248 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
249 {
250 typelib_TypeDescriptionReference *pAttrTypeRef =
251 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
252
253 if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
254 {
255 // is GET method
256 eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
257 0, 0, // no params
258 pCallStack, pRegisterReturn );
259 }
260 else
261 {
262 // is SET method
263 typelib_MethodParameter aParam;
264 aParam.pTypeRef = pAttrTypeRef;
265 aParam.bIn = sal_True;
266 aParam.bOut = sal_False;
267
268 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
269 0, // indicates void return
270 1, &aParam,
271 pCallStack, pRegisterReturn );
272 }
273 break;
274 }
275 case typelib_TypeClass_INTERFACE_METHOD:
276 {
277 // is METHOD
278 switch ( nFunctionIndex )
279 {
280 // standard XInterface vtable calls
281 case 1: // acquire()
282 pCppI->acquireProxy(); // non virtual call!
283 eRet = typelib_TypeClass_VOID;
284 break;
285 case 2: // release()
286 pCppI->releaseProxy(); // non virtual call!
287 eRet = typelib_TypeClass_VOID;
288 break;
289 case 0: // queryInterface() opt
290 {
291 typelib_TypeDescription * pTD = 0;
292 TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( pCallStack[3] )->getTypeLibType() );
293 if ( pTD )
294 {
295 XInterface * pInterface = 0;
296 (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
297 ( pCppI->getBridge()->getCppEnv(),
298 (void **)&pInterface,
299 pCppI->getOid().pData,
300 reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
301
302 if ( pInterface )
303 {
304 // pCallStack is "ret addr, this, [ret *], params", so the
305 // hidden return buffer is [2]; [1] is `this`. Writing the
306 // Any to [1] overwrote the proxy object and left the
307 // caller's return buffer untouched, so the caller then
308 // destructed an uninitialised Any.
309 ::uno_any_construct( reinterpret_cast<uno_Any *>( pCallStack[2] ),
310 &pInterface, pTD, cpp_acquire );
311
312 pInterface->release();
313 TYPELIB_DANGER_RELEASE( pTD );
314
315 reinterpret_cast<void **>( pRegisterReturn )[0] = pCallStack[2];
316 eRet = typelib_TypeClass_ANY;
317 break;
318 }
319 TYPELIB_DANGER_RELEASE( pTD );
320 }
321 } // else perform queryInterface()
322 default:
323 {
324 typelib_InterfaceMethodTypeDescription *pMethodTD =
325 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
326
327 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
328 pMethodTD->pReturnTypeRef,
329 pMethodTD->nParams,
330 pMethodTD->pParams,
331 pCallStack, pRegisterReturn );
332 }
333 }
334 break;
335 }
336 default:
337 {
338 throw RuntimeException( OUString::createFromAscii("no member description found!"),
339 reinterpret_cast<XInterface *>( pCppI ) );
340 // is here for dummy
341 eRet = typelib_TypeClass_VOID;
342 }
343 }
344
345 return eRet;
346 }
347
348 //==================================================================================================
349 extern "C" void privateSnippetExecutor( ... );
350
351 int const codeSnippetSize = 48;
352
codeSnippet(unsigned char * code,sal_Int32 functionIndex,sal_Int32 vtableOffset,bool isArgFloat[4])353 unsigned char * codeSnippet(
354 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, bool isArgFloat[4])
355 {
356 unsigned char * p = code;
357
358
359 //
360 // | ... |
361 // +----------------------------+
362 // | argument 4 |
363 // rsp+40 +----------------------------+ -------
364 // | argument 3, r9/xmm3 home | ^ shadow
365 // rsp+32 +----------------------------+ | space,
366 // | argument 2, r8/xmm2 home | | guaranteed to be present but uninitialized,
367 // rsp+24 +----------------------------+ | we have to copy
368 // | argument 1, rdx/xmm1 home | | the first 4 parameters there from the registers,
369 // rsp+16 +----------------------------+ | to form the continuous array of arguments.
370 // | argument 0, rcx/xmm0 home | v
371 // rsp+08 +----------------------------+ -------
372 // | return address |
373 // rsp--> +----------------------------+
374 //
375 //
376
377 // When it doubt about correctness,
378 // uncomment this and disassemble at runtime:
379 // INT 0x3
380 //*p++ = 0xcc;
381
382 if (isArgFloat[0])
383 {
384 // movsd QWORD[rsp+8], XMM0
385 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08;
386 }
387 else
388 {
389 // mov QWORD[rsp+8], rcx
390 *p++ = 0x48; *p++ = 0x89; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x08;
391 }
392
393 if (isArgFloat[1])
394 {
395 // movsd QWORD[rsp+16], XMM1
396 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x10;
397 }
398 else
399 {
400 // mov QWORD[rsp+16], rdx
401 *p++ = 0x48; *p++ = 0x89; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10;
402 }
403
404 if (isArgFloat[2])
405 {
406 // movsd QWORD[rsp+24], XMM2
407 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18;
408 }
409 else
410 {
411 // mov QWORD[rsp+24], r8
412 *p++ = 0x4c; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18;
413 }
414
415 if (isArgFloat[3])
416 {
417 // movsd QWORD[rsp+32], XMM3
418 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x5c; *p++ = 0x24; *p++ = 0x20;
419 }
420 else
421 {
422 // mov QWORD[rsp+32], r9
423 *p++ = 0x4c; *p++ = 0x89; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x20;
424 }
425
426 // mov rax, functionIndex
427 *p++ = 0xb8;
428 *p++ = functionIndex & 0xff;
429 *p++ = (functionIndex >> 8) & 0xff;
430 *p++ = (functionIndex >> 16) & 0xff;
431 *p++ = (functionIndex >> 24) & 0xff;
432
433 // mov r10, vtableOffset
434 *p++ = 0x41;
435 *p++ = 0xba;
436 *p++ = vtableOffset & 0xff;
437 *p++ = (vtableOffset >> 8) & 0xff;
438 *p++ = (vtableOffset >> 16) & 0xff;
439 *p++ = (vtableOffset >> 24) & 0xff;
440
441 // mov r11, privateSnippetExecutor
442 *p++ = 0x49;
443 *p++ = 0xbb;
444 *p++ = ((sal_uIntPtr)(&privateSnippetExecutor)) & 0xff;
445 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 8) & 0xff;
446 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 16) & 0xff;
447 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 24) & 0xff;
448 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 32) & 0xff;
449 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 40) & 0xff;
450 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 48) & 0xff;
451 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 56) & 0xff;
452
453 // jmp r11
454 *p++ = 0x41;
455 *p++ = 0xff;
456 *p++ = 0xe3;
457
458 OSL_ASSERT(p - code <= codeSnippetSize);
459 return code + codeSnippetSize;
460 }
461
462 }
463
464 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
465
466 bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)467 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
468 {
469 return static_cast< Slot * >(block) + 1;
470 }
471
getBlockSize(sal_Int32 slotCount)472 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
473 sal_Int32 slotCount)
474 {
475 return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
476 }
477
478 bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)479 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
480 void * block, sal_Int32 slotCount)
481 {
482 struct RttiCompleteObjectLocator {
483 sal_uInt32 signature;
484 sal_uInt32 offset; // offset of vtable in objects of the class
485 sal_uInt32 cdOffset; // constructor displacement offset
486 // On AMD64, these 2 are offsets from the module's base address (when signature == 0):
487 sal_uInt32 typeDescriptorAddress;
488 sal_uInt32 classDescriptorAddress;
489 sal_uInt32 objectBase; // ignored when signature == 0
490
491 RttiCompleteObjectLocator(): signature(0), offset(0), cdOffset(0)
492 {
493 type_info *typeInfo = CPPU_CURRENT_NAMESPACE::mscx_getRTTI(
494 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
495 "com.sun.star.uno.XInterface")));
496 HMODULE thisDLLBase;
497 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)&bridges::cpp_uno::shared::VtableFactory::initializeBlock, &thisDLLBase);
498 typeDescriptorAddress = (sal_uInt32) (((char*)typeInfo) - (char*)thisDLLBase);
499 classDescriptorAddress = 0;
500 objectBase = 0;
501 }
502 };
503 static RttiCompleteObjectLocator rtti;
504
505 Slot * slots = mapBlockToVtable(block);
506 slots[-1].fn = &rtti;
507 return slots + slotCount;
508 }
509
findFirst4Win64ArgumentTypes(typelib_MethodParameter * pParams,sal_Int32 nParams,typelib_TypeDescriptionReference * pReturnType,bool isArgFloat[4])510 static void findFirst4Win64ArgumentTypes(
511 typelib_MethodParameter *pParams, sal_Int32 nParams,
512 typelib_TypeDescriptionReference *pReturnType, bool isArgFloat[4])
513 {
514 sal_uInt32 index = 0;
515
516 isArgFloat[0] = isArgFloat[1] = isArgFloat[2] = isArgFloat[3] = false;
517
518 // C++ "this" pointer:
519 ++index;
520
521 // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017
522 // "Otherwise the caller assumes the responsibility of allocating memory
523 // and passing a pointer for the return value as the first argument.
524 // Subsequent arguments are then shifted one argument to the right.
525 // The same pointer must be returned by the callee in RAX."
526 if ( pReturnType && x86_64::return_in_hidden_param( pReturnType ) )
527 ++index;
528
529 for (int param = 0; param < nParams; param++)
530 {
531 if (index >= 4)
532 break;
533
534 typelib_TypeDescription *pParamTypeDescr = 0;
535
536 TYPELIB_DANGER_GET( &pParamTypeDescr, pParams[param].pTypeRef );
537 OSL_ASSERT( pParamTypeDescr );
538
539 isArgFloat[index++] = !pParams[param].bOut &&
540 (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT ||
541 pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE);
542
543 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
544 }
545 }
546
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 functionOffset,sal_Int32 functionCount,sal_Int32 vtableOffset)547 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
548 Slot ** slots, unsigned char * code,
549 typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset,
550 sal_Int32 functionCount, sal_Int32 vtableOffset)
551 {
552 (*slots) -= functionCount;
553 Slot * s = *slots;
554 for (sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos) {
555 typelib_TypeDescription * pTD = 0;
556
557 TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
558 OSL_ASSERT( pTD );
559
560 bool isArgFloat[4];
561 if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
562 {
563 typelib_InterfaceAttributeTypeDescription *pAttrTD =
564 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
565
566 // get method
567 findFirst4Win64ArgumentTypes(0, 0, pAttrTD->pAttributeTypeRef, isArgFloat);
568 (s++)->fn = code;
569 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
570
571 if ( ! pAttrTD->bReadOnly )
572 {
573 // set method
574 typelib_MethodParameter aParam;
575 aParam.pTypeRef = pAttrTD->pAttributeTypeRef;
576 aParam.bIn = sal_True;
577 aParam.bOut = sal_False;
578 findFirst4Win64ArgumentTypes(&aParam, 1, 0, isArgFloat);
579 (s++)->fn = code;
580 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
581 }
582 }
583 else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
584 {
585 typelib_InterfaceMethodTypeDescription *pMethodTD =
586 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
587 findFirst4Win64ArgumentTypes(pMethodTD->pParams, pMethodTD->nParams,
588 pMethodTD->pReturnTypeRef, isArgFloat);
589 (s++)->fn = code;
590 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
591 }
592 else
593 OSL_ASSERT( false );
594
595 TYPELIB_DANGER_RELEASE( pTD );
596 }
597 return code;
598 }
599
flushCode(unsigned char const *,unsigned char const *)600 void bridges::cpp_uno::shared::VtableFactory::flushCode(
601 unsigned char const *, unsigned char const *)
602 {}
603