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