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 ::uno_any_construct( reinterpret_cast<uno_Any *>( pCallStack[1] ),
305 &pInterface, pTD, cpp_acquire );
306
307 pInterface->release();
308 TYPELIB_DANGER_RELEASE( pTD );
309
310 reinterpret_cast<void **>( pRegisterReturn )[0] = pCallStack[1];
311 eRet = typelib_TypeClass_ANY;
312 break;
313 }
314 TYPELIB_DANGER_RELEASE( pTD );
315 }
316 } // else perform queryInterface()
317 default:
318 {
319 typelib_InterfaceMethodTypeDescription *pMethodTD =
320 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
321
322 eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
323 pMethodTD->pReturnTypeRef,
324 pMethodTD->nParams,
325 pMethodTD->pParams,
326 pCallStack, pRegisterReturn );
327 }
328 }
329 break;
330 }
331 default:
332 {
333 throw RuntimeException( OUString::createFromAscii("no member description found!"),
334 reinterpret_cast<XInterface *>( pCppI ) );
335 // is here for dummy
336 eRet = typelib_TypeClass_VOID;
337 }
338 }
339
340 return eRet;
341 }
342
343 //==================================================================================================
344 extern "C" void privateSnippetExecutor( ... );
345
346 int const codeSnippetSize = 44;
347
codeSnippet(unsigned char * code,sal_Int32 functionIndex,sal_Int32 vtableOffset,bool isArgFloat[4])348 unsigned char * codeSnippet(
349 unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset, bool isArgFloat[4])
350 {
351 unsigned char * p = code;
352
353
354 //
355 // | ... |
356 // +----------------------------+
357 // | argument 4 |
358 // rsp+40 +----------------------------+ -------
359 // | argument 3, r9/xmm3 home | ^ shadow
360 // rsp+32 +----------------------------+ | space,
361 // | argument 2, r8/xmm2 home | | guaranteed to be present but uninitialized,
362 // rsp+24 +----------------------------+ | we have to copy
363 // | argument 1, rdx/xmm1 home | | the first 4 parameters there from the registers,
364 // rsp+16 +----------------------------+ | to form the continuous array of arguments.
365 // | argument 0, rcx/xmm0 home | v
366 // rsp+08 +----------------------------+ -------
367 // | return address |
368 // rsp--> +----------------------------+
369 //
370 //
371
372 if (isArgFloat[0])
373 {
374 // movsd QWORD[rsp+8], XMM0
375 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x44; *p++ = 0x24; *p++ = 0x08;
376 }
377 else
378 {
379 // mov QWORD[rsp+8], rcx
380 *p++ = 0x48; *p++ = 0x49; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x08;
381 }
382
383 if (isArgFloat[1])
384 {
385 // movsd QWORD[rsp+16], XMM1
386 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x10;
387 }
388 else
389 {
390 // mov QWORD[rsp+16], rdx
391 *p++ = 0x48; *p++ = 0x49; *p++ = 0x54; *p++ = 0x24; *p++ = 0x10;
392 }
393
394 if (isArgFloat[2])
395 {
396 // movsd QWORD[rsp+24], XMM2
397 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x54; *p++ = 0x24; *p++ = 0x18;
398 }
399 else
400 {
401 // mov QWORD[rsp+24], r8
402 *p++ = 0x4c; *p++ = 0x89; *p++ = 0x44; *p++ = 0x24; *p++ = 0x18;
403 }
404
405 if (isArgFloat[3])
406 {
407 // movsd QWORD[rsp+32], XMM3
408 *p++ = 0xf2; *p++ = 0x0f; *p++ = 0x11; *p++ = 0x5c; *p++ = 0x24; *p++ = 0x20;
409 }
410 else
411 {
412 // mov QWORD[rsp+32], r9
413 *p++ = 0x4c; *p++ = 0x89; *p++ = 0x4c; *p++ = 0x24; *p++ = 0x20;
414 }
415
416 // mov rax, functionIndex
417 *p++ = 0xb8;
418 *p++ = functionIndex & 0xff;
419 *p++ = (functionIndex >> 8) & 0xff;
420 *p++ = (functionIndex >> 16) & 0xff;
421 *p++ = (functionIndex >> 24) & 0xff;
422
423 // mov r10, vtableOffset
424 *p++ = 0x41;
425 *p++ = 0xba;
426 *p++ = vtableOffset & 0xff;
427 *p++ = (vtableOffset >> 8) & 0xff;
428 *p++ = (vtableOffset >> 16) & 0xff;
429 *p++ = (vtableOffset >> 24) & 0xff;
430
431 // mov r11, privateSnippetExecutor
432 *p++ = 0x49;
433 *p++ = 0xbb;
434 *p++ = ((sal_uIntPtr)(&privateSnippetExecutor)) & 0xff;
435 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 8) & 0xff;
436 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 16) & 0xff;
437 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 24) & 0xff;
438 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 32) & 0xff;
439 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 40) & 0xff;
440 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 48) & 0xff;
441 *p++ = (((sal_uIntPtr)(&privateSnippetExecutor)) >> 56) & 0xff;
442
443 // jmp r11
444 *p++ = 0x49;
445 *p++ = 0xff;
446 *p++ = 0xe3;
447
448 OSL_ASSERT(p - code <= codeSnippetSize);
449 return code + codeSnippetSize;
450 }
451
452 }
453
454 struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
455
456 bridges::cpp_uno::shared::VtableFactory::Slot *
mapBlockToVtable(void * block)457 bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
458 {
459 return static_cast< Slot * >(block) + 1;
460 }
461
getBlockSize(sal_Int32 slotCount)462 sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
463 sal_Int32 slotCount)
464 {
465 return (slotCount + 1) * sizeof (Slot) + slotCount * codeSnippetSize;
466 }
467
468 bridges::cpp_uno::shared::VtableFactory::Slot *
initializeBlock(void * block,sal_Int32 slotCount)469 bridges::cpp_uno::shared::VtableFactory::initializeBlock(
470 void * block, sal_Int32 slotCount)
471 {
472 struct RttiCompleteObjectLocator {
473 sal_uInt32 signature;
474 sal_uInt32 offset; // offset of vtable in objects of the class
475 sal_uInt32 cdOffset; // constructor displacement offset
476 // On AMD64, these 2 are offsets from the module's base address (when signature == 0):
477 sal_uInt32 typeDescriptorAddress;
478 sal_uInt32 classDescriptorAddress;
479 sal_uInt32 objectBase; // ignored when signature == 0
480
481 RttiCompleteObjectLocator(): signature(0), offset(0), cdOffset(0)
482 {
483 type_info *typeInfo = CPPU_CURRENT_NAMESPACE::mscx_getRTTI(
484 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
485 "com.sun.star.uno.XInterface")));
486 HMODULE thisDLLBase;
487 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)&bridges::cpp_uno::shared::VtableFactory::initializeBlock, &thisDLLBase);
488 typeDescriptorAddress = (sal_uInt32) (((char*)typeInfo) - (char*)thisDLLBase);
489 classDescriptorAddress = 0;
490 objectBase = 0;
491 }
492 };
493 static RttiCompleteObjectLocator rtti;
494
495 Slot * slots = mapBlockToVtable(block);
496 slots[-1].fn = &rtti;
497 return slots + slotCount;
498 }
499
findFirst4Win64ArgumentTypes(typelib_MethodParameter * pParams,sal_Int32 nParams,typelib_TypeDescriptionReference * pReturnType,bool isArgFloat[4])500 static void findFirst4Win64ArgumentTypes(
501 typelib_MethodParameter *pParams, sal_Int32 nParams,
502 typelib_TypeDescriptionReference *pReturnType, bool isArgFloat[4])
503 {
504 sal_uInt32 index = 0;
505
506 isArgFloat[0] = isArgFloat[1] = isArgFloat[2] = isArgFloat[3] = false;
507
508 // C++ "this" pointer:
509 ++index;
510
511 // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017
512 // "Otherwise the caller assumes the responsibility of allocating memory
513 // and passing a pointer for the return value as the first argument.
514 // Subsequent arguments are then shifted one argument to the right.
515 // The same pointer must be returned by the callee in RAX."
516 if ( pReturnType && x86_64::return_in_hidden_param( pReturnType ) )
517 ++index;
518
519 for (int param = 0; param < nParams; param++)
520 {
521 if (index >= 4)
522 break;
523
524 typelib_TypeDescription *pParamTypeDescr = 0;
525
526 TYPELIB_DANGER_GET( &pParamTypeDescr, pParams[param].pTypeRef );
527 OSL_ASSERT( pParamTypeDescr );
528
529 isArgFloat[index++] = !pParams[param].bOut &&
530 (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT ||
531 pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE);
532
533 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
534 }
535 }
536
addLocalFunctions(Slot ** slots,unsigned char * code,typelib_InterfaceTypeDescription const * type,sal_Int32 functionOffset,sal_Int32 functionCount,sal_Int32 vtableOffset)537 unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
538 Slot ** slots, unsigned char * code,
539 typelib_InterfaceTypeDescription const *type, sal_Int32 functionOffset,
540 sal_Int32 functionCount, sal_Int32 vtableOffset)
541 {
542 (*slots) -= functionCount;
543 Slot * s = *slots;
544 for (sal_Int32 nPos = 0; nPos < type->nMembers; ++nPos) {
545 typelib_TypeDescription * pTD = 0;
546
547 TYPELIB_DANGER_GET( &pTD, type->ppMembers[ nPos ] );
548 OSL_ASSERT( pTD );
549
550 bool isArgFloat[4];
551 if ( typelib_TypeClass_INTERFACE_ATTRIBUTE == pTD->eTypeClass )
552 {
553 typelib_InterfaceAttributeTypeDescription *pAttrTD =
554 reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
555
556 // get method
557 findFirst4Win64ArgumentTypes(0, 0, pAttrTD->pAttributeTypeRef, isArgFloat);
558 (s++)->fn = code;
559 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
560
561 if ( ! pAttrTD->bReadOnly )
562 {
563 // set method
564 typelib_MethodParameter aParam;
565 aParam.pTypeRef = pAttrTD->pAttributeTypeRef;
566 aParam.bIn = sal_True;
567 aParam.bOut = sal_False;
568 findFirst4Win64ArgumentTypes(&aParam, 1, 0, isArgFloat);
569 (s++)->fn = code;
570 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
571 }
572 }
573 else if ( typelib_TypeClass_INTERFACE_METHOD == pTD->eTypeClass )
574 {
575 typelib_InterfaceMethodTypeDescription *pMethodTD =
576 reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( pTD );
577 findFirst4Win64ArgumentTypes(pMethodTD->pParams, pMethodTD->nParams,
578 pMethodTD->pReturnTypeRef, isArgFloat);
579 (s++)->fn = code;
580 code = codeSnippet(code, functionOffset++, vtableOffset, isArgFloat);
581 }
582 else
583 OSL_ASSERT( false );
584
585 TYPELIB_DANGER_RELEASE( pTD );
586 }
587 return code;
588 }
589
flushCode(unsigned char const *,unsigned char const *)590 void bridges::cpp_uno::shared::VtableFactory::flushCode(
591 unsigned char const *, unsigned char const *)
592 {}
593