ia2comproxy: Introduce new proxy stub DLL for IAccessible2.
[wine.git] / dlls / rpcrt4 / ndr_stubless.c
blobe15c93d23107f4cf03d973a0cec3a3dab1b108be
1 /*
2 * NDR -Oi,-Oif,-Oicf Interpreter
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003-5 Robert Shearman (for CodeWeavers)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * TODO:
22 * - Pipes
23 * - Some types of binding handles
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winerror.h"
34 #include "objbase.h"
35 #include "rpc.h"
36 #include "rpcproxy.h"
38 #include "wine/exception.h"
39 #include "wine/asm.h"
40 #include "wine/debug.h"
42 #include "cpsf.h"
43 #include "ndr_misc.h"
44 #include "ndr_stubless.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
48 #define NDR_TABLE_MASK 127
50 static inline BOOL is_oicf_stubdesc(const PMIDL_STUB_DESC pStubDesc)
52 return pStubDesc->Version >= 0x20000;
55 static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
56 const NDR_PARAM_OIF *param)
58 PFORMAT_STRING pFormat;
59 NDR_BUFFERSIZE m;
61 if (param->attr.IsBasetype)
63 pFormat = &param->u.type_format_char;
64 if (param->attr.IsSimpleRef) pMemory = *(unsigned char **)pMemory;
66 else
68 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset];
69 if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory;
72 m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK];
73 if (m) m(pStubMsg, pMemory, pFormat);
74 else
76 FIXME("format type 0x%x not implemented\n", pFormat[0]);
77 RpcRaiseException(RPC_X_BAD_STUB_DATA);
81 static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
82 const NDR_PARAM_OIF *param)
84 PFORMAT_STRING pFormat;
85 NDR_MARSHALL m;
87 if (param->attr.IsBasetype)
89 pFormat = &param->u.type_format_char;
90 if (param->attr.IsSimpleRef) pMemory = *(unsigned char **)pMemory;
92 else
94 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset];
95 if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory;
98 m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK];
99 if (m) return m(pStubMsg, pMemory, pFormat);
100 else
102 FIXME("format type 0x%x not implemented\n", pFormat[0]);
103 RpcRaiseException(RPC_X_BAD_STUB_DATA);
104 return NULL;
108 static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory,
109 const NDR_PARAM_OIF *param, unsigned char fMustAlloc)
111 PFORMAT_STRING pFormat;
112 NDR_UNMARSHALL m;
114 if (param->attr.IsBasetype)
116 pFormat = &param->u.type_format_char;
117 if (param->attr.IsSimpleRef) ppMemory = (unsigned char **)*ppMemory;
119 else
121 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset];
122 if (!param->attr.IsByValue) ppMemory = (unsigned char **)*ppMemory;
125 m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK];
126 if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc);
127 else
129 FIXME("format type 0x%x not implemented\n", pFormat[0]);
130 RpcRaiseException(RPC_X_BAD_STUB_DATA);
131 return NULL;
135 static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory,
136 const NDR_PARAM_OIF *param)
138 PFORMAT_STRING pFormat;
139 NDR_FREE m;
141 if (param->attr.IsBasetype) return; /* nothing to do */
142 pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset];
143 if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory;
145 m = NdrFreer[pFormat[0] & NDR_TABLE_MASK];
146 if (m) m(pStubMsg, pMemory, pFormat);
149 static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
151 DWORD size;
152 switch(*pFormat)
154 case FC_RP:
155 if (pFormat[1] & FC_SIMPLE_POINTER)
157 size = 0;
158 break;
160 size = calc_arg_size(pStubMsg, &pFormat[2] + *(const SHORT*)&pFormat[2]);
161 break;
162 case FC_STRUCT:
163 case FC_PSTRUCT:
164 size = *(const WORD*)(pFormat + 2);
165 break;
166 case FC_BOGUS_STRUCT:
167 size = *(const WORD*)(pFormat + 2);
168 if(*(const WORD*)(pFormat + 4))
169 FIXME("Unhandled conformant description\n");
170 break;
171 case FC_CARRAY:
172 case FC_CVARRAY:
173 size = *(const WORD*)(pFormat + 2);
174 ComputeConformance(pStubMsg, NULL, pFormat + 4, 0);
175 size *= pStubMsg->MaxCount;
176 break;
177 case FC_SMFARRAY:
178 case FC_SMVARRAY:
179 size = *(const WORD*)(pFormat + 2);
180 break;
181 case FC_LGFARRAY:
182 case FC_LGVARRAY:
183 size = *(const DWORD*)(pFormat + 2);
184 break;
185 case FC_BOGUS_ARRAY:
186 pFormat = ComputeConformance(pStubMsg, NULL, pFormat + 4, *(const WORD*)&pFormat[2]);
187 TRACE("conformance = %Id\n", pStubMsg->MaxCount);
188 pFormat = ComputeVariance(pStubMsg, NULL, pFormat, pStubMsg->MaxCount);
189 size = ComplexStructSize(pStubMsg, pFormat);
190 size *= pStubMsg->MaxCount;
191 break;
192 case FC_USER_MARSHAL:
193 size = *(const WORD*)(pFormat + 4);
194 break;
195 case FC_CSTRING:
196 size = *(const WORD*)(pFormat + 2);
197 break;
198 case FC_WSTRING:
199 size = *(const WORD*)(pFormat + 2) * sizeof(WCHAR);
200 break;
201 case FC_C_CSTRING:
202 case FC_C_WSTRING:
203 if (*pFormat == FC_C_CSTRING)
204 size = sizeof(CHAR);
205 else
206 size = sizeof(WCHAR);
207 if (pFormat[1] == FC_STRING_SIZED)
208 ComputeConformance(pStubMsg, NULL, pFormat + 2, 0);
209 else
210 pStubMsg->MaxCount = 0;
211 size *= pStubMsg->MaxCount;
212 break;
213 case FC_NON_ENCAPSULATED_UNION:
215 DWORD offset = *(const WORD *)(pFormat + 6 + pStubMsg->CorrDespIncrement);
216 size = *(const WORD *)(pFormat + 8 + pStubMsg->CorrDespIncrement + offset);
217 break;
219 default:
220 FIXME("Unhandled type %02x\n", *pFormat);
221 /* fallthrough */
222 case FC_UP:
223 case FC_OP:
224 case FC_FP:
225 case FC_IP:
226 size = sizeof(void *);
227 break;
229 return size;
232 void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage)
234 #if 0 /* these functions are not defined yet */
235 pMessage->pfnAllocate = NdrRpcSmClientAllocate;
236 pMessage->pfnFree = NdrRpcSmClientFree;
237 #endif
240 static const char *debugstr_PROC_PF(PARAM_ATTRIBUTES param_attributes)
242 char buffer[160];
244 buffer[0] = 0;
245 if (param_attributes.MustSize) strcat(buffer, " MustSize");
246 if (param_attributes.MustFree) strcat(buffer, " MustFree");
247 if (param_attributes.IsPipe) strcat(buffer, " IsPipe");
248 if (param_attributes.IsIn) strcat(buffer, " IsIn");
249 if (param_attributes.IsOut) strcat(buffer, " IsOut");
250 if (param_attributes.IsReturn) strcat(buffer, " IsReturn");
251 if (param_attributes.IsBasetype) strcat(buffer, " IsBasetype");
252 if (param_attributes.IsByValue) strcat(buffer, " IsByValue");
253 if (param_attributes.IsSimpleRef) strcat(buffer, " IsSimpleRef");
254 if (param_attributes.IsDontCallFreeInst) strcat(buffer, " IsDontCallFreeInst");
255 if (param_attributes.SaveForAsyncFinish) strcat(buffer, " SaveForAsyncFinish");
256 if (param_attributes.ServerAllocSize)
257 sprintf( buffer + strlen(buffer), " ServerAllocSize = %d", param_attributes.ServerAllocSize * 8);
258 return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : "";
261 static const char *debugstr_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags)
263 char buffer[160];
265 buffer[0] = 0;
266 if (Oi2Flags.ServerMustSize) strcat(buffer, " ServerMustSize");
267 if (Oi2Flags.ClientMustSize) strcat(buffer, " ClientMustSize");
268 if (Oi2Flags.HasReturn) strcat(buffer, " HasReturn");
269 if (Oi2Flags.HasPipes) strcat(buffer, " HasPipes");
270 if (Oi2Flags.Unused) strcat(buffer, " Unused");
271 if (Oi2Flags.HasAsyncUuid) strcat(buffer, " HasAsyncUuid");
272 if (Oi2Flags.HasExtensions) strcat(buffer, " HasExtensions");
273 if (Oi2Flags.HasAsyncHandle) strcat(buffer, " HasAsyncHandle");
274 return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : "";
277 #define ARG_FROM_OFFSET(args, offset) ((args) + (offset))
279 static size_t get_handle_desc_size(const NDR_PROC_HEADER *proc_header, PFORMAT_STRING format)
281 if (!proc_header->handle_type)
283 if (*format == FC_BIND_PRIMITIVE)
284 return sizeof(NDR_EHD_PRIMITIVE);
285 else if (*format == FC_BIND_GENERIC)
286 return sizeof(NDR_EHD_GENERIC);
287 else if (*format == FC_BIND_CONTEXT)
288 return sizeof(NDR_EHD_CONTEXT);
290 return 0;
293 static handle_t client_get_handle(const MIDL_STUB_MESSAGE *pStubMsg,
294 const NDR_PROC_HEADER *pProcHeader, const PFORMAT_STRING pFormat)
296 /* binding */
297 switch (pProcHeader->handle_type)
299 /* explicit binding: parse additional section */
300 case 0:
301 switch (*pFormat) /* handle_type */
303 case FC_BIND_PRIMITIVE: /* explicit primitive */
305 const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat;
307 TRACE("Explicit primitive handle @ %d\n", pDesc->offset);
309 if (pDesc->flag) /* pointer to binding */
310 return **(handle_t **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
311 else
312 return *(handle_t *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
314 case FC_BIND_GENERIC: /* explicit generic */
316 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat;
317 void *pObject = NULL;
318 void *pArg;
319 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
321 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
323 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
324 pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
325 else
326 pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
327 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
328 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
329 return pGenPair->pfnBind(pObject);
331 case FC_BIND_CONTEXT: /* explicit context */
333 const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat;
334 NDR_CCONTEXT context_handle;
335 TRACE("Explicit bind context\n");
336 if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR)
338 TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n");
339 context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
341 else
342 context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
344 if (context_handle) return NDRCContextBinding(context_handle);
345 else if (pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL)
347 ERR("null context handle isn't allowed\n");
348 RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT);
349 return NULL;
351 /* FIXME: should we store this structure in stubMsg.pContext? */
353 default:
354 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
355 RpcRaiseException(RPC_X_BAD_STUB_DATA);
357 break;
358 case FC_BIND_GENERIC: /* implicit generic */
359 FIXME("FC_BIND_GENERIC\n");
360 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
361 break;
362 case FC_BIND_PRIMITIVE: /* implicit primitive */
363 TRACE("Implicit primitive handle\n");
364 return *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle;
365 case FC_CALLBACK_HANDLE: /* implicit callback */
366 TRACE("FC_CALLBACK_HANDLE\n");
367 /* server calls callback procedures only in response to remote call, and most recent
368 binding handle is used. Calling back to a client can potentially result in another
369 callback with different current handle. */
370 return I_RpcGetCurrentCallHandle();
371 case FC_AUTO_HANDLE: /* implicit auto handle */
372 /* strictly speaking, it isn't necessary to set hBinding here
373 * since it isn't actually used (hence the automatic in its name),
374 * but then why does MIDL generate a valid entry in the
375 * MIDL_STUB_DESC for it? */
376 TRACE("Implicit auto handle\n");
377 return *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle;
378 default:
379 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
380 RpcRaiseException(RPC_X_BAD_STUB_DATA);
382 return NULL;
385 static void client_free_handle(
386 PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
387 PFORMAT_STRING pFormat, handle_t hBinding)
389 /* binding */
390 switch (pProcHeader->handle_type)
392 /* explicit binding: parse additional section */
393 case 0:
394 switch (*pFormat) /* handle_type */
396 case FC_BIND_GENERIC: /* explicit generic */
398 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat;
399 void *pObject = NULL;
400 void *pArg;
401 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
403 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
405 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
406 pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
407 else
408 pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
409 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
410 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
411 pGenPair->pfnUnbind(pObject, hBinding);
412 break;
414 case FC_BIND_CONTEXT: /* explicit context */
415 case FC_BIND_PRIMITIVE: /* explicit primitive */
416 break;
417 default:
418 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
419 RpcRaiseException(RPC_X_BAD_STUB_DATA);
421 break;
422 case FC_BIND_GENERIC: /* implicit generic */
423 FIXME("FC_BIND_GENERIC\n");
424 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
425 break;
426 case FC_CALLBACK_HANDLE: /* implicit callback */
427 case FC_BIND_PRIMITIVE: /* implicit primitive */
428 case FC_AUTO_HANDLE: /* implicit auto handle */
429 break;
430 default:
431 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
432 RpcRaiseException(RPC_X_BAD_STUB_DATA);
436 static inline BOOL param_needs_alloc( PARAM_ATTRIBUTES attr )
438 return attr.IsOut && !attr.IsIn && !attr.IsBasetype && !attr.IsByValue;
441 static inline BOOL param_is_out_basetype( PARAM_ATTRIBUTES attr )
443 return attr.IsOut && !attr.IsIn && attr.IsBasetype && attr.IsSimpleRef;
446 static size_t basetype_arg_size( unsigned char fc )
448 switch (fc)
450 case FC_BYTE:
451 case FC_CHAR:
452 case FC_SMALL:
453 case FC_USMALL:
454 return sizeof(char);
455 case FC_WCHAR:
456 case FC_SHORT:
457 case FC_USHORT:
458 return sizeof(short);
459 case FC_LONG:
460 case FC_ULONG:
461 case FC_ENUM16:
462 case FC_ENUM32:
463 case FC_ERROR_STATUS_T:
464 return sizeof(int);
465 case FC_FLOAT:
466 return sizeof(float);
467 case FC_HYPER:
468 return sizeof(LONGLONG);
469 case FC_DOUBLE:
470 return sizeof(double);
471 case FC_INT3264:
472 case FC_UINT3264:
473 return sizeof(INT_PTR);
474 default:
475 FIXME("Unhandled basetype %#x.\n", fc);
476 return 0;
480 void client_do_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, enum stubless_phase phase,
481 void **fpu_args, unsigned short number_of_params, unsigned char *pRetVal )
483 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat;
484 unsigned int i;
486 for (i = 0; i < number_of_params; i++)
488 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset;
489 PFORMAT_STRING pTypeFormat = (PFORMAT_STRING)&pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset];
491 #ifdef __x86_64__ /* floats are passed as doubles through varargs functions */
492 float f;
494 if (params[i].attr.IsBasetype &&
495 params[i].u.type_format_char == FC_FLOAT &&
496 !params[i].attr.IsSimpleRef &&
497 !fpu_args)
499 f = *(double *)pArg;
500 pArg = (unsigned char *)&f;
502 #endif
504 TRACE("param[%d]: %p type %02x %s\n", i, pArg,
505 params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat,
506 debugstr_PROC_PF( params[i].attr ));
508 switch (phase)
510 case STUBLESS_INITOUT:
511 if (*(unsigned char **)pArg)
513 if (param_needs_alloc(params[i].attr))
514 memset( *(unsigned char **)pArg, 0, calc_arg_size( pStubMsg, pTypeFormat ));
515 else if (param_is_out_basetype(params[i].attr))
516 memset( *(unsigned char **)pArg, 0, basetype_arg_size( params[i].u.type_format_char ));
518 break;
519 case STUBLESS_CALCSIZE:
520 if (params[i].attr.IsSimpleRef && !*(unsigned char **)pArg)
521 RpcRaiseException(RPC_X_NULL_REF_POINTER);
522 if (params[i].attr.IsIn) call_buffer_sizer(pStubMsg, pArg, &params[i]);
523 break;
524 case STUBLESS_MARSHAL:
525 if (params[i].attr.IsIn) call_marshaller(pStubMsg, pArg, &params[i]);
526 break;
527 case STUBLESS_UNMARSHAL:
528 if (params[i].attr.IsOut)
530 if (params[i].attr.IsReturn && pRetVal) pArg = pRetVal;
531 call_unmarshaller(pStubMsg, &pArg, &params[i], 0);
533 break;
534 case STUBLESS_FREE:
535 if (!params[i].attr.IsBasetype && params[i].attr.IsOut && !params[i].attr.IsByValue)
536 NdrClearOutParameters( pStubMsg, pTypeFormat, *(unsigned char **)pArg );
537 break;
538 default:
539 RpcRaiseException(RPC_S_INTERNAL_ERROR);
544 static unsigned int type_stack_size(unsigned char fc)
546 switch (fc)
548 case FC_BYTE:
549 case FC_CHAR:
550 case FC_SMALL:
551 case FC_USMALL:
552 case FC_WCHAR:
553 case FC_SHORT:
554 case FC_USHORT:
555 case FC_LONG:
556 case FC_ULONG:
557 case FC_INT3264:
558 case FC_UINT3264:
559 case FC_ENUM16:
560 case FC_ENUM32:
561 case FC_FLOAT:
562 case FC_ERROR_STATUS_T:
563 case FC_IGNORE:
564 return sizeof(void *);
565 case FC_DOUBLE:
566 return sizeof(double);
567 case FC_HYPER:
568 return sizeof(ULONGLONG);
569 default:
570 ERR("invalid base type 0x%x\n", fc);
571 RpcRaiseException(RPC_S_INTERNAL_ERROR);
575 static BOOL is_by_value( PFORMAT_STRING format )
577 switch (*format)
579 case FC_USER_MARSHAL:
580 case FC_STRUCT:
581 case FC_PSTRUCT:
582 case FC_CSTRUCT:
583 case FC_CPSTRUCT:
584 case FC_CVSTRUCT:
585 case FC_BOGUS_STRUCT:
586 return TRUE;
587 default:
588 return FALSE;
592 PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
593 unsigned int stack_size, BOOL object_proc,
594 void *buffer, unsigned int size, unsigned int *count )
596 NDR_PARAM_OIF *args = buffer;
597 unsigned int i, stack_offset = object_proc ? sizeof(void *) : 0;
599 for (i = 0; stack_offset < stack_size; i++)
601 const NDR_PARAM_OI_BASETYPE *param = (const NDR_PARAM_OI_BASETYPE *)pFormat;
602 const NDR_PARAM_OI_OTHER *other = (const NDR_PARAM_OI_OTHER *)pFormat;
604 if (i + 1 > size / sizeof(*args))
606 FIXME( "%u args not supported\n", i );
607 RpcRaiseException( RPC_S_INTERNAL_ERROR );
610 args[i].stack_offset = stack_offset;
611 memset( &args[i].attr, 0, sizeof(args[i].attr) );
613 switch (param->param_direction)
615 case FC_IN_PARAM_BASETYPE:
616 args[i].attr.IsIn = 1;
617 args[i].attr.IsBasetype = 1;
618 break;
619 case FC_RETURN_PARAM_BASETYPE:
620 args[i].attr.IsOut = 1;
621 args[i].attr.IsReturn = 1;
622 args[i].attr.IsBasetype = 1;
623 break;
624 case FC_IN_PARAM:
625 args[i].attr.IsIn = 1;
626 args[i].attr.MustFree = 1;
627 break;
628 case FC_IN_PARAM_NO_FREE_INST:
629 args[i].attr.IsIn = 1;
630 args[i].attr.IsDontCallFreeInst = 1;
631 break;
632 case FC_IN_OUT_PARAM:
633 args[i].attr.IsIn = 1;
634 args[i].attr.IsOut = 1;
635 args[i].attr.MustFree = 1;
636 break;
637 case FC_OUT_PARAM:
638 args[i].attr.IsOut = 1;
639 break;
640 case FC_RETURN_PARAM:
641 args[i].attr.IsOut = 1;
642 args[i].attr.IsReturn = 1;
643 break;
645 if (args[i].attr.IsBasetype)
647 args[i].u.type_format_char = param->type_format_char;
648 stack_offset += type_stack_size( param->type_format_char );
649 pFormat += sizeof(NDR_PARAM_OI_BASETYPE);
651 else
653 args[i].u.type_offset = other->type_offset;
654 args[i].attr.IsByValue = is_by_value( &pStubMsg->StubDesc->pFormatTypes[other->type_offset] );
655 stack_offset += other->stack_size * sizeof(void *);
656 pFormat += sizeof(NDR_PARAM_OI_OTHER);
659 *count = i;
660 return (PFORMAT_STRING)args;
663 struct ndr_client_call_ctx
665 MIDL_STUB_MESSAGE *stub_msg;
666 INTERPRETER_OPT_FLAGS Oif_flags;
667 INTERPRETER_OPT_FLAGS2 ext_flags;
668 const NDR_PROC_HEADER *proc_header;
669 void *This;
670 PFORMAT_STRING handle_format;
671 handle_t hbinding;
674 static void CALLBACK ndr_client_call_finally(BOOL normal, void *arg)
676 struct ndr_client_call_ctx *ctx = arg;
678 if (ctx->ext_flags.HasNewCorrDesc)
680 /* free extra correlation package */
681 NdrCorrelationFree(ctx->stub_msg);
684 if (ctx->Oif_flags.HasPipes)
686 /* NdrPipesDone(...) */
689 /* free the full pointer translation tables */
690 if (ctx->proc_header->Oi_flags & Oi_FULL_PTR_USED)
691 NdrFullPointerXlatFree(ctx->stub_msg->FullPtrXlatTables);
693 /* free marshalling buffer */
694 if (ctx->proc_header->Oi_flags & Oi_OBJECT_PROC)
695 NdrProxyFreeBuffer(ctx->This, ctx->stub_msg);
696 else
698 NdrFreeBuffer(ctx->stub_msg);
699 client_free_handle(ctx->stub_msg, ctx->proc_header, ctx->handle_format, ctx->hbinding);
703 /* Helper for ndr_client_call, to factor out the part that may or may not be
704 * guarded by a try/except block. */
705 static LONG_PTR do_ndr_client_call( const MIDL_STUB_DESC *stub_desc, const PFORMAT_STRING format,
706 const PFORMAT_STRING handle_format, void **stack_top, void **fpu_stack, MIDL_STUB_MESSAGE *stub_msg,
707 unsigned short procedure_number, unsigned short stack_size, unsigned int number_of_params,
708 INTERPRETER_OPT_FLAGS Oif_flags, INTERPRETER_OPT_FLAGS2 ext_flags, const NDR_PROC_HEADER *proc_header )
710 struct ndr_client_call_ctx finally_ctx;
711 RPC_MESSAGE rpc_msg;
712 handle_t hbinding = NULL;
713 /* the value to return to the client from the remote procedure */
714 LONG_PTR retval = 0;
715 /* the pointer to the object when in OLE mode */
716 void *This = NULL;
717 /* correlation cache */
718 ULONG_PTR NdrCorrCache[256];
720 /* create the full pointer translation tables, if requested */
721 if (proc_header->Oi_flags & Oi_FULL_PTR_USED)
722 stub_msg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
724 if (proc_header->Oi_flags & Oi_OBJECT_PROC)
726 /* object is always the first argument */
727 This = stack_top[0];
728 NdrProxyInitialize(This, &rpc_msg, stub_msg, stub_desc, procedure_number);
731 finally_ctx.stub_msg = stub_msg;
732 finally_ctx.Oif_flags = Oif_flags;
733 finally_ctx.ext_flags = ext_flags;
734 finally_ctx.proc_header = proc_header;
735 finally_ctx.This = This;
736 finally_ctx.handle_format = handle_format;
737 finally_ctx.hbinding = hbinding;
739 __TRY
741 if (!(proc_header->Oi_flags & Oi_OBJECT_PROC))
742 NdrClientInitializeNew(&rpc_msg, stub_msg, stub_desc, procedure_number);
744 stub_msg->StackTop = (unsigned char *)stack_top;
746 /* we only need a handle if this isn't an object method */
747 if (!(proc_header->Oi_flags & Oi_OBJECT_PROC))
749 hbinding = client_get_handle(stub_msg, proc_header, handle_format);
750 if (!hbinding) return 0;
753 stub_msg->BufferLength = 0;
755 /* store the RPC flags away */
756 if (proc_header->Oi_flags & Oi_HAS_RPCFLAGS)
757 rpc_msg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)proc_header)->rpc_flags;
759 /* use alternate memory allocation routines */
760 if (proc_header->Oi_flags & Oi_RPCSS_ALLOC_USED)
761 NdrRpcSmSetClientToOsf(stub_msg);
763 if (Oif_flags.HasPipes)
765 FIXME("pipes not supported yet\n");
766 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
767 /* init pipes package */
768 /* NdrPipesInitialize(...) */
770 if (ext_flags.HasNewCorrDesc)
772 /* initialize extra correlation package */
773 NdrCorrelationInitialize(stub_msg, NdrCorrCache, sizeof(NdrCorrCache), 0);
774 if (ext_flags.Unused & 0x2) /* has range on conformance */
775 stub_msg->CorrDespIncrement = 12;
778 /* order of phases:
779 * 1. INITOUT - zero [out] parameters (proxies only)
780 * 2. CALCSIZE - calculate the buffer size
781 * 3. GETBUFFER - allocate the buffer
782 * 4. MARSHAL - marshal [in] params into the buffer
783 * 5. SENDRECEIVE - send/receive buffer
784 * 6. UNMARSHAL - unmarshal [out] params from buffer
785 * 7. FREE - clear [out] parameters (for proxies, and only on error)
788 /* 1. INITOUT */
789 if (proc_header->Oi_flags & Oi_OBJECT_PROC)
791 TRACE( "INITOUT\n" );
792 client_do_args(stub_msg, format, STUBLESS_INITOUT, fpu_stack,
793 number_of_params, (unsigned char *)&retval);
796 /* 2. CALCSIZE */
797 TRACE( "CALCSIZE\n" );
798 client_do_args(stub_msg, format, STUBLESS_CALCSIZE, fpu_stack,
799 number_of_params, (unsigned char *)&retval);
801 /* 3. GETBUFFER */
802 TRACE( "GETBUFFER\n" );
803 if (proc_header->Oi_flags & Oi_OBJECT_PROC)
804 NdrProxyGetBuffer(This, stub_msg);
805 else if (Oif_flags.HasPipes)
806 FIXME("pipes not supported yet\n");
807 else if (proc_header->handle_type == FC_AUTO_HANDLE)
808 #if 0
809 NdrNsGetBuffer(stub_msg, stub_msg->BufferLength, hBinding);
810 #else
811 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
812 #endif
813 else
814 NdrGetBuffer(stub_msg, stub_msg->BufferLength, hbinding);
816 /* 4. MARSHAL */
817 TRACE( "MARSHAL\n" );
818 client_do_args(stub_msg, format, STUBLESS_MARSHAL, fpu_stack,
819 number_of_params, (unsigned char *)&retval);
821 /* 5. SENDRECEIVE */
822 TRACE( "SENDRECEIVE\n" );
823 if (proc_header->Oi_flags & Oi_OBJECT_PROC)
824 NdrProxySendReceive(This, stub_msg);
825 else if (Oif_flags.HasPipes)
826 /* NdrPipesSendReceive(...) */
827 FIXME("pipes not supported yet\n");
828 else if (proc_header->handle_type == FC_AUTO_HANDLE)
829 #if 0
830 NdrNsSendReceive(stub_msg, stub_msg->Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
831 #else
832 FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
833 #endif
834 else
835 NdrSendReceive(stub_msg, stub_msg->Buffer);
837 /* convert strings, floating point values and endianness into our
838 * preferred format */
839 if ((rpc_msg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
840 NdrConvert(stub_msg, format);
842 /* 6. UNMARSHAL */
843 TRACE( "UNMARSHAL\n" );
844 client_do_args(stub_msg, format, STUBLESS_UNMARSHAL, fpu_stack,
845 number_of_params, (unsigned char *)&retval);
847 __FINALLY_CTX(ndr_client_call_finally, &finally_ctx)
849 return retval;
852 LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat,
853 void **stack_top, void **fpu_stack )
855 /* pointer to start of stack where arguments start */
856 MIDL_STUB_MESSAGE stubMsg;
857 /* procedure number */
858 unsigned short procedure_number;
859 /* size of stack */
860 unsigned short stack_size;
861 /* number of parameters. optional for client to give it to us */
862 unsigned int number_of_params;
863 /* cache of Oif_flags from v2 procedure header */
864 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
865 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
866 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
867 /* header for procedure string */
868 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
869 /* the value to return to the client from the remote procedure */
870 LONG_PTR RetVal = 0;
871 PFORMAT_STRING pHandleFormat;
872 NDR_PARAM_OIF old_args[256];
874 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
876 TRACE("NDR Version: 0x%lx\n", pStubDesc->Version);
878 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
880 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
881 stack_size = header_rpc->stack_size;
882 procedure_number = header_rpc->proc_num;
883 pFormat += sizeof(NDR_PROC_HEADER_RPC);
885 else
887 stack_size = pProcHeader->stack_size;
888 procedure_number = pProcHeader->proc_num;
889 pFormat += sizeof(NDR_PROC_HEADER);
891 TRACE("stack size: 0x%x\n", stack_size);
892 TRACE("proc num: %d\n", procedure_number);
893 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
894 TRACE("MIDL stub version = 0x%lx\n", pStubDesc->MIDLVersion);
896 pHandleFormat = pFormat;
898 /* we only need a handle if this isn't an object method */
899 if (!(pProcHeader->Oi_flags & Oi_OBJECT_PROC))
900 pFormat += get_handle_desc_size(pProcHeader, pFormat);
902 if (is_oicf_stubdesc(pStubDesc)) /* -Oicf format */
904 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
905 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
907 Oif_flags = pOIFHeader->Oi2Flags;
908 number_of_params = pOIFHeader->number_of_params;
910 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
912 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
914 if (Oif_flags.HasExtensions)
916 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
917 ext_flags = pExtensions->Flags2;
918 pFormat += pExtensions->Size;
919 #ifdef __x86_64__
920 if (pExtensions->Size > sizeof(*pExtensions) && fpu_stack)
922 int i;
923 unsigned short fpu_mask = *(unsigned short *)(pExtensions + 1);
924 for (i = 0; i < 4; i++, fpu_mask >>= 2)
925 switch (fpu_mask & 3)
927 case 1: *(float *)&stack_top[i] = *(float *)&fpu_stack[i]; break;
928 case 2: *(double *)&stack_top[i] = *(double *)&fpu_stack[i]; break;
931 #endif
934 else
936 pFormat = convert_old_args( &stubMsg, pFormat, stack_size,
937 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
938 old_args, sizeof(old_args), &number_of_params );
941 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
943 __TRY
945 RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat,
946 stack_top, fpu_stack, &stubMsg, procedure_number, stack_size,
947 number_of_params, Oif_flags, ext_flags, pProcHeader);
949 __EXCEPT_ALL
951 /* 7. FREE */
952 TRACE( "FREE\n" );
953 client_do_args(&stubMsg, pFormat, STUBLESS_FREE, fpu_stack,
954 number_of_params, (unsigned char *)&RetVal);
955 RetVal = NdrProxyErrorHandler(GetExceptionCode());
957 __ENDTRY
959 else if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT)
961 __TRY
963 RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat,
964 stack_top, fpu_stack, &stubMsg, procedure_number, stack_size,
965 number_of_params, Oif_flags, ext_flags, pProcHeader);
967 __EXCEPT_ALL
969 const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number];
970 ULONG *comm_status;
971 ULONG *fault_status;
973 TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset);
975 if (comm_fault_offsets->CommOffset == -1)
976 comm_status = (ULONG *)&RetVal;
977 else if (comm_fault_offsets->CommOffset >= 0)
978 comm_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset);
979 else
980 comm_status = NULL;
982 if (comm_fault_offsets->FaultOffset == -1)
983 fault_status = (ULONG *)&RetVal;
984 else if (comm_fault_offsets->FaultOffset >= 0)
985 fault_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->FaultOffset);
986 else
987 fault_status = NULL;
989 NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status,
990 GetExceptionCode());
992 __ENDTRY
994 else
996 RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat,
997 stack_top, fpu_stack, &stubMsg, procedure_number, stack_size,
998 number_of_params, Oif_flags, ext_flags, pProcHeader);
1001 TRACE("RetVal = 0x%Ix\n", RetVal);
1002 return RetVal;
1005 #ifdef __x86_64__
1007 __ASM_GLOBAL_FUNC( NdrClientCall2,
1008 "movq %r8,0x18(%rsp)\n\t"
1009 "movq %r9,0x20(%rsp)\n\t"
1010 "leaq 0x18(%rsp),%r8\n\t"
1011 "xorq %r9,%r9\n\t"
1012 "subq $0x28,%rsp\n\t"
1013 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
1014 "call " __ASM_NAME("ndr_client_call") "\n\t"
1015 "addq $0x28,%rsp\n\t"
1016 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
1017 "ret" );
1019 #else /* __x86_64__ */
1021 /***********************************************************************
1022 * NdrClientCall2 [RPCRT4.@]
1024 CLIENT_CALL_RETURN WINAPIV NdrClientCall2( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... )
1026 va_list args;
1027 LONG_PTR ret;
1029 va_start( args, format );
1030 ret = ndr_client_call( desc, format, va_arg( args, void ** ), NULL );
1031 va_end( args );
1032 return *(CLIENT_CALL_RETURN *)&ret;
1035 #endif /* __x86_64__ */
1037 /* Calls a function with the specified arguments, restoring the stack
1038 * properly afterwards as we don't know the calling convention of the
1039 * function */
1040 #if defined __i386__ && defined _MSC_VER
1041 __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size)
1043 __asm
1045 push ebp
1046 mov ebp, esp
1047 push edi ; Save registers
1048 push esi
1049 mov eax, [ebp+16] ; Get stack size
1050 sub esp, eax ; Make room in stack for arguments
1051 and esp, 0xFFFFFFF0
1052 mov edi, esp
1053 mov ecx, eax
1054 mov esi, [ebp+12]
1055 shr ecx, 2
1057 rep movsd ; Copy dword blocks
1058 call [ebp+8] ; Call function
1059 lea esp, [ebp-8] ; Restore stack
1060 pop esi ; Restore registers
1061 pop edi
1062 pop ebp
1066 #elif defined __i386__ && defined __GNUC__
1067 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
1068 __ASM_GLOBAL_FUNC(call_server_func,
1069 "pushl %ebp\n\t"
1070 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
1071 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
1072 "movl %esp,%ebp\n\t"
1073 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
1074 "pushl %edi\n\t" /* Save registers */
1075 __ASM_CFI(".cfi_rel_offset %edi,-4\n\t")
1076 "pushl %esi\n\t"
1077 __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
1078 "movl 16(%ebp), %eax\n\t" /* Get stack size */
1079 "subl %eax, %esp\n\t" /* Make room in stack for arguments */
1080 "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */
1081 "movl %esp, %edi\n\t"
1082 "movl %eax, %ecx\n\t"
1083 "movl 12(%ebp), %esi\n\t"
1084 "shrl $2, %ecx\n\t" /* divide by 4 */
1085 "cld\n\t"
1086 "rep; movsl\n\t" /* Copy dword blocks */
1087 "call *8(%ebp)\n\t" /* Call function */
1088 "leal -8(%ebp), %esp\n\t" /* Restore stack */
1089 "popl %esi\n\t" /* Restore registers */
1090 __ASM_CFI(".cfi_same_value %esi\n\t")
1091 "popl %edi\n\t"
1092 __ASM_CFI(".cfi_same_value %edi\n\t")
1093 "popl %ebp\n\t"
1094 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
1095 __ASM_CFI(".cfi_same_value %ebp\n\t")
1096 "ret" )
1097 #elif defined __x86_64__
1098 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
1099 __ASM_GLOBAL_FUNC( call_server_func,
1100 "pushq %rbp\n\t"
1101 __ASM_SEH(".seh_pushreg %rbp\n\t")
1102 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
1103 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
1104 "movq %rsp,%rbp\n\t"
1105 __ASM_SEH(".seh_setframe %rbp,0\n\t")
1106 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
1107 "pushq %rsi\n\t"
1108 __ASM_SEH(".seh_pushreg %rsi\n\t")
1109 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
1110 "pushq %rdi\n\t"
1111 __ASM_SEH(".seh_pushreg %rdi\n\t")
1112 __ASM_SEH(".seh_endprologue\n\t")
1113 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
1114 "movq %rcx,%rax\n\t" /* function to call */
1115 "movq $32,%rcx\n\t" /* allocate max(32,stack_size) bytes of stack space */
1116 "cmpq %rcx,%r8\n\t"
1117 "cmovgq %r8,%rcx\n\t"
1118 "subq %rcx,%rsp\n\t"
1119 "andq $~15,%rsp\n\t"
1120 "movq %r8,%rcx\n\t"
1121 "shrq $3,%rcx\n\t"
1122 "movq %rsp,%rdi\n\t"
1123 "movq %rdx,%rsi\n\t"
1124 "rep; movsq\n\t" /* copy arguments */
1125 "movq 0(%rsp),%rcx\n\t"
1126 "movq 8(%rsp),%rdx\n\t"
1127 "movq 16(%rsp),%r8\n\t"
1128 "movq 24(%rsp),%r9\n\t"
1129 "movq 0(%rsp),%xmm0\n\t"
1130 "movq 8(%rsp),%xmm1\n\t"
1131 "movq 16(%rsp),%xmm2\n\t"
1132 "movq 24(%rsp),%xmm3\n\t"
1133 "callq *%rax\n\t"
1134 "leaq -16(%rbp),%rsp\n\t" /* restore stack */
1135 "popq %rdi\n\t"
1136 __ASM_CFI(".cfi_same_value %rdi\n\t")
1137 "popq %rsi\n\t"
1138 __ASM_CFI(".cfi_same_value %rsi\n\t")
1139 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
1140 "popq %rbp\n\t"
1141 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
1142 __ASM_CFI(".cfi_same_value %rbp\n\t")
1143 "ret")
1144 #elif defined __arm__
1145 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char *args, unsigned int stack_size);
1146 __ASM_GLOBAL_FUNC( call_server_func,
1147 "push {r4, r5, LR}\n\t"
1148 "mov r4, r0\n\t"
1149 "mov r5, SP\n\t"
1150 "lsr r3, r2, #2\n\t"
1151 "cmp r3, #0\n\t"
1152 "beq 5f\n\t"
1153 "sub SP, SP, r2\n\t"
1154 "tst r3, #1\n\t"
1155 "it eq\n\t"
1156 "subeq SP, SP, #4\n\t"
1157 "1:\tsub r2, r2, #4\n\t"
1158 "ldr r0, [r1, r2]\n\t"
1159 "str r0, [SP, r2]\n\t"
1160 "cmp r2, #0\n\t"
1161 "bgt 1b\n\t"
1162 "cmp r3, #1\n\t"
1163 "bgt 2f\n\t"
1164 "pop {r0}\n\t"
1165 "b 5f\n\t"
1166 "2:\tcmp r3, #2\n\t"
1167 "bgt 3f\n\t"
1168 "pop {r0-r1}\n\t"
1169 "b 5f\n\t"
1170 "3:\tcmp r3, #3\n\t"
1171 "bgt 4f\n\t"
1172 "pop {r0-r2}\n\t"
1173 "b 5f\n\t"
1174 "4:\tpop {r0-r3}\n\t"
1175 "5:\tblx r4\n\t"
1176 "mov SP, r5\n\t"
1177 "pop {r4, r5, PC}" )
1178 #elif defined __aarch64__
1179 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char *args, unsigned int stack_size);
1180 __ASM_GLOBAL_FUNC( call_server_func,
1181 "stp x29, x30, [sp, #-16]!\n\t"
1182 "mov x29, sp\n\t"
1183 "add x9, x2, #15\n\t"
1184 "lsr x9, x9, #4\n\t"
1185 "sub sp, sp, x9, lsl #4\n\t"
1186 "cbz x2, 2f\n"
1187 "1:\tsub x2, x2, #8\n\t"
1188 "ldr x4, [x1, x2]\n\t"
1189 "str x4, [sp, x2]\n\t"
1190 "cbnz x2, 1b\n"
1191 "2:\tmov x8, x0\n\t"
1192 "cbz x9, 3f\n\t"
1193 "ldp x0, x1, [sp], #16\n\t"
1194 "cmp x9, #1\n\t"
1195 "b.le 3f\n\t"
1196 "ldp x2, x3, [sp], #16\n\t"
1197 "cmp x9, #2\n\t"
1198 "b.le 3f\n\t"
1199 "ldp x4, x5, [sp], #16\n\t"
1200 "cmp x9, #3\n\t"
1201 "b.le 3f\n\t"
1202 "ldp x6, x7, [sp], #16\n"
1203 "3:\tblr x8\n\t"
1204 "mov sp, x29\n\t"
1205 "ldp x29, x30, [sp], #16\n\t"
1206 "ret" )
1207 #else
1208 #warning call_server_func not implemented for your architecture
1209 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
1211 FIXME("Not implemented for your architecture\n");
1212 return 0;
1214 #endif
1216 static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg,
1217 PFORMAT_STRING pFormat, enum stubless_phase phase,
1218 unsigned short number_of_params)
1220 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat;
1221 unsigned int i;
1222 LONG_PTR *retval_ptr = NULL;
1224 for (i = 0; i < number_of_params; i++)
1226 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset;
1227 const unsigned char *pTypeFormat = &pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset];
1229 TRACE("param[%d]: %p -> %p type %02x %s\n", i,
1230 pArg, *(unsigned char **)pArg,
1231 params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat,
1232 debugstr_PROC_PF( params[i].attr ));
1234 switch (phase)
1236 case STUBLESS_MARSHAL:
1237 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1238 call_marshaller(pStubMsg, pArg, &params[i]);
1239 break;
1240 case STUBLESS_MUSTFREE:
1241 if (params[i].attr.MustFree)
1243 call_freer(pStubMsg, pArg, &params[i]);
1245 break;
1246 case STUBLESS_FREE:
1247 if (params[i].attr.ServerAllocSize)
1249 HeapFree(GetProcessHeap(), 0, *(void **)pArg);
1251 else if (param_needs_alloc(params[i].attr) &&
1252 (!params[i].attr.MustFree || params[i].attr.IsSimpleRef))
1254 if (*pTypeFormat != FC_BIND_CONTEXT) pStubMsg->pfnFree(*(void **)pArg);
1256 break;
1257 case STUBLESS_INITOUT:
1258 if (param_needs_alloc(params[i].attr) && !params[i].attr.ServerAllocSize)
1260 if (*pTypeFormat == FC_BIND_CONTEXT)
1262 NDR_SCONTEXT ctxt = NdrContextHandleInitialize(pStubMsg, pTypeFormat);
1263 *(void **)pArg = NDRSContextValue(ctxt);
1264 if (params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)NDRSContextValue(ctxt);
1266 else
1268 DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
1269 if (size)
1271 *(void **)pArg = NdrAllocate(pStubMsg, size);
1272 memset(*(void **)pArg, 0, size);
1276 if (!retval_ptr && params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)pArg;
1277 break;
1278 case STUBLESS_UNMARSHAL:
1279 if (params[i].attr.ServerAllocSize)
1280 *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1281 params[i].attr.ServerAllocSize * 8);
1283 if (params[i].attr.IsIn)
1284 call_unmarshaller(pStubMsg, &pArg, &params[i], 0);
1285 break;
1286 case STUBLESS_CALCSIZE:
1287 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1288 call_buffer_sizer(pStubMsg, pArg, &params[i]);
1289 break;
1290 default:
1291 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1293 TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
1295 return retval_ptr;
1298 /***********************************************************************
1299 * NdrStubCall2 [RPCRT4.@]
1301 * Unmarshals [in] parameters, calls either a method in an object or a server
1302 * function, marshals any [out] parameters and frees any allocated data.
1304 * NOTES
1305 * Used by stubless MIDL-generated code.
1307 LONG WINAPI NdrStubCall2(
1308 struct IRpcStubBuffer * pThis,
1309 struct IRpcChannelBuffer * pChannel,
1310 PRPC_MESSAGE pRpcMsg,
1311 DWORD * pdwStubPhase)
1313 const MIDL_SERVER_INFO *pServerInfo;
1314 const MIDL_STUB_DESC *pStubDesc;
1315 PFORMAT_STRING pFormat;
1316 MIDL_STUB_MESSAGE stubMsg;
1317 /* pointer to start of stack to pass into stub implementation */
1318 unsigned char * args;
1319 /* size of stack */
1320 unsigned short stack_size;
1321 /* number of parameters. optional for client to give it to us */
1322 unsigned int number_of_params;
1323 /* cache of Oif_flags from v2 procedure header */
1324 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1325 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1326 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1327 /* the type of pass we are currently doing */
1328 enum stubless_phase phase;
1329 /* header for procedure string */
1330 const NDR_PROC_HEADER *pProcHeader;
1331 /* location to put retval into */
1332 LONG_PTR *retval_ptr = NULL;
1333 /* correlation cache */
1334 ULONG_PTR NdrCorrCache[256];
1336 TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase);
1338 if (pThis)
1339 pServerInfo = CStdStubBuffer_GetServerInfo(pThis);
1340 else
1341 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1343 pStubDesc = pServerInfo->pStubDesc;
1344 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1345 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1347 TRACE("NDR Version: 0x%lx\n", pStubDesc->Version);
1349 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1351 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1352 stack_size = header_rpc->stack_size;
1353 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1356 else
1358 stack_size = pProcHeader->stack_size;
1359 pFormat += sizeof(NDR_PROC_HEADER);
1362 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1364 /* binding */
1365 switch (pProcHeader->handle_type)
1367 /* explicit binding: parse additional section */
1368 case 0:
1369 switch (*pFormat) /* handle_type */
1371 case FC_BIND_PRIMITIVE: /* explicit primitive */
1372 pFormat += sizeof(NDR_EHD_PRIMITIVE);
1373 break;
1374 case FC_BIND_GENERIC: /* explicit generic */
1375 pFormat += sizeof(NDR_EHD_GENERIC);
1376 break;
1377 case FC_BIND_CONTEXT: /* explicit context */
1378 pFormat += sizeof(NDR_EHD_CONTEXT);
1379 break;
1380 default:
1381 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1382 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1384 break;
1385 case FC_BIND_GENERIC: /* implicit generic */
1386 case FC_BIND_PRIMITIVE: /* implicit primitive */
1387 case FC_CALLBACK_HANDLE: /* implicit callback */
1388 case FC_AUTO_HANDLE: /* implicit auto handle */
1389 break;
1390 default:
1391 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1392 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1395 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1396 NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel);
1397 else
1398 NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc);
1400 /* create the full pointer translation tables, if requested */
1401 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1402 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
1404 /* store the RPC flags away */
1405 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1406 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1408 /* use alternate memory allocation routines */
1409 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
1410 #if 0
1411 NdrRpcSsEnableAllocate(&stubMsg);
1412 #else
1413 FIXME("Set RPCSS memory allocation routines\n");
1414 #endif
1416 TRACE("allocating memory for stack of size %x\n", stack_size);
1418 args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size);
1419 stubMsg.StackTop = args; /* used by conformance of top-level objects */
1421 /* add the implicit This pointer as the first arg to the function if we
1422 * are calling an object method */
1423 if (pThis)
1424 *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject;
1426 if (is_oicf_stubdesc(pStubDesc))
1428 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
1430 Oif_flags = pOIFHeader->Oi2Flags;
1431 number_of_params = pOIFHeader->number_of_params;
1433 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1435 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
1437 if (Oif_flags.HasExtensions)
1439 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
1440 ext_flags = pExtensions->Flags2;
1441 pFormat += pExtensions->Size;
1444 if (Oif_flags.HasPipes)
1446 FIXME("pipes not supported yet\n");
1447 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1448 /* init pipes package */
1449 /* NdrPipesInitialize(...) */
1451 if (ext_flags.HasNewCorrDesc)
1453 /* initialize extra correlation package */
1454 NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0);
1455 if (ext_flags.Unused & 0x2) /* has range on conformance */
1456 stubMsg.CorrDespIncrement = 12;
1459 else
1461 pFormat = convert_old_args( &stubMsg, pFormat, stack_size,
1462 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
1463 /* reuse the correlation cache, it's not needed for v1 format */
1464 NdrCorrCache, sizeof(NdrCorrCache), &number_of_params );
1467 /* convert strings, floating point values and endianness into our
1468 * preferred format */
1469 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1470 NdrConvert(&stubMsg, pFormat);
1472 for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++)
1474 TRACE("phase = %d\n", phase);
1475 switch (phase)
1477 case STUBLESS_CALLSERVER:
1478 /* call the server function */
1479 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
1480 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg);
1481 else
1483 SERVER_ROUTINE func;
1484 LONG_PTR retval;
1486 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1488 SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject;
1489 func = vtbl[pRpcMsg->ProcNum];
1491 else
1492 func = pServerInfo->DispatchTable[pRpcMsg->ProcNum];
1494 /* FIXME: what happens with return values that don't fit into a single register on x86? */
1495 retval = call_server_func(func, args, stack_size);
1497 if (retval_ptr)
1499 TRACE("stub implementation returned 0x%Ix\n", retval);
1500 *retval_ptr = retval;
1502 else
1503 TRACE("void stub implementation\n");
1506 stubMsg.Buffer = NULL;
1507 stubMsg.BufferLength = 0;
1509 break;
1510 case STUBLESS_GETBUFFER:
1511 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1512 NdrStubGetBuffer(pThis, pChannel, &stubMsg);
1513 else
1515 RPC_STATUS Status;
1517 pRpcMsg->BufferLength = stubMsg.BufferLength;
1518 /* allocate buffer for [out] and [ret] params */
1519 Status = I_RpcGetBuffer(pRpcMsg);
1520 if (Status)
1521 RpcRaiseException(Status);
1522 stubMsg.Buffer = pRpcMsg->Buffer;
1524 break;
1525 case STUBLESS_UNMARSHAL:
1526 case STUBLESS_INITOUT:
1527 case STUBLESS_CALCSIZE:
1528 case STUBLESS_MARSHAL:
1529 case STUBLESS_MUSTFREE:
1530 case STUBLESS_FREE:
1531 retval_ptr = stub_do_args(&stubMsg, pFormat, phase, number_of_params);
1532 break;
1533 default:
1534 ERR("shouldn't reach here. phase %d\n", phase);
1535 break;
1539 pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer);
1541 if (ext_flags.HasNewCorrDesc)
1543 /* free extra correlation package */
1544 NdrCorrelationFree(&stubMsg);
1547 if (Oif_flags.HasPipes)
1549 /* NdrPipesDone(...) */
1552 /* free the full pointer translation tables */
1553 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1554 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
1556 /* free server function stack */
1557 HeapFree(GetProcessHeap(), 0, args);
1559 return S_OK;
1562 /***********************************************************************
1563 * NdrServerCall2 [RPCRT4.@]
1565 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
1567 DWORD dwPhase;
1568 NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
1571 /***********************************************************************
1572 * NdrStubCall [RPCRT4.@]
1574 LONG WINAPI NdrStubCall( struct IRpcStubBuffer *This, struct IRpcChannelBuffer *channel,
1575 PRPC_MESSAGE msg, DWORD *phase )
1577 return NdrStubCall2( This, channel, msg, phase );
1580 /***********************************************************************
1581 * NdrServerCall [RPCRT4.@]
1583 void WINAPI NdrServerCall( PRPC_MESSAGE msg )
1585 DWORD phase;
1586 NdrStubCall( NULL, NULL, msg, &phase );
1589 /***********************************************************************
1590 * NdrServerCallAll [RPCRT4.@]
1592 void WINAPI NdrServerCallAll( PRPC_MESSAGE msg )
1594 FIXME("%p stub\n", msg);
1597 /* Helper for ndr_async_client_call, to factor out the part that may or may not be
1598 * guarded by a try/except block. */
1599 static void do_ndr_async_client_call( const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormat, void **stack_top )
1601 /* pointer to start of stack where arguments start */
1602 PRPC_MESSAGE pRpcMsg;
1603 PMIDL_STUB_MESSAGE pStubMsg;
1604 RPC_ASYNC_STATE *pAsync;
1605 struct async_call_data *async_call_data;
1606 /* procedure number */
1607 unsigned short procedure_number;
1608 /* cache of Oif_flags from v2 procedure header */
1609 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1610 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1611 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1612 /* header for procedure string */
1613 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1614 RPC_STATUS status;
1616 /* Later NDR language versions probably won't be backwards compatible */
1617 if (pStubDesc->Version > 0x60001)
1619 FIXME("Incompatible stub description version: 0x%lx\n", pStubDesc->Version);
1620 RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
1623 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
1624 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY);
1625 async_call_data->pProcHeader = pProcHeader;
1627 async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
1628 pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1);
1630 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1632 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1633 async_call_data->stack_size = header_rpc->stack_size;
1634 procedure_number = header_rpc->proc_num;
1635 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1637 else
1639 async_call_data->stack_size = pProcHeader->stack_size;
1640 procedure_number = pProcHeader->proc_num;
1641 pFormat += sizeof(NDR_PROC_HEADER);
1643 TRACE("stack size: 0x%x\n", async_call_data->stack_size);
1644 TRACE("proc num: %d\n", procedure_number);
1646 /* create the full pointer translation tables, if requested */
1647 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1648 pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
1650 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1652 ERR("objects not supported\n");
1653 I_RpcFree(async_call_data);
1654 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1657 NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number);
1659 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1660 TRACE("MIDL stub version = 0x%lx\n", pStubDesc->MIDLVersion);
1662 /* needed for conformance of top-level objects */
1663 pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size);
1664 memcpy(pStubMsg->StackTop, stack_top, async_call_data->stack_size);
1666 pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop;
1667 pAsync->StubInfo = async_call_data;
1668 async_call_data->pHandleFormat = pFormat;
1670 TRACE("pAsync %p, pAsync->StubInfo %p, NotificationType %d\n", pAsync, pAsync->StubInfo, pAsync->NotificationType);
1672 pFormat += get_handle_desc_size(pProcHeader, pFormat);
1673 async_call_data->hBinding = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat);
1674 if (!async_call_data->hBinding) return;
1676 if (is_oicf_stubdesc(pStubDesc))
1678 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
1679 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
1681 Oif_flags = pOIFHeader->Oi2Flags;
1682 async_call_data->number_of_params = pOIFHeader->number_of_params;
1684 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1686 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
1688 if (Oif_flags.HasExtensions)
1690 const NDR_PROC_HEADER_EXTS *pExtensions =
1691 (const NDR_PROC_HEADER_EXTS *)pFormat;
1692 ext_flags = pExtensions->Flags2;
1693 pFormat += pExtensions->Size;
1696 else
1698 pFormat = convert_old_args( pStubMsg, pFormat, async_call_data->stack_size,
1699 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
1700 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache),
1701 &async_call_data->number_of_params );
1704 async_call_data->pParamFormat = pFormat;
1706 pStubMsg->BufferLength = 0;
1708 /* store the RPC flags away */
1709 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1710 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1712 /* use alternate memory allocation routines */
1713 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
1714 NdrRpcSmSetClientToOsf(pStubMsg);
1716 if (Oif_flags.HasPipes)
1718 FIXME("pipes not supported yet\n");
1719 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1720 /* init pipes package */
1721 /* NdrPipesInitialize(...) */
1723 if (ext_flags.HasNewCorrDesc)
1725 /* initialize extra correlation package */
1726 NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
1727 if (ext_flags.Unused & 0x2) /* has range on conformance */
1728 pStubMsg->CorrDespIncrement = 12;
1731 /* order of phases:
1732 * 1. CALCSIZE - calculate the buffer size
1733 * 2. GETBUFFER - allocate the buffer
1734 * 3. MARSHAL - marshal [in] params into the buffer
1735 * 4. SENDRECEIVE - send buffer
1736 * Then in NdrpCompleteAsyncClientCall:
1737 * 1. SENDRECEIVE - receive buffer
1738 * 2. UNMARSHAL - unmarshal [out] params from buffer
1741 /* 1. CALCSIZE */
1742 TRACE( "CALCSIZE\n" );
1743 client_do_args(pStubMsg, pFormat, STUBLESS_CALCSIZE, NULL, async_call_data->number_of_params, NULL);
1745 /* 2. GETBUFFER */
1746 TRACE( "GETBUFFER\n" );
1747 if (Oif_flags.HasPipes)
1748 /* NdrGetPipeBuffer(...) */
1749 FIXME("pipes not supported yet\n");
1750 else
1752 if (pProcHeader->handle_type == FC_AUTO_HANDLE)
1753 #if 0
1754 NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1755 #else
1756 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
1757 #endif
1758 else
1759 NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1761 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1762 status = I_RpcAsyncSetHandle(pRpcMsg, pAsync);
1763 if (status != RPC_S_OK)
1764 RpcRaiseException(status);
1766 /* 3. MARSHAL */
1767 TRACE( "MARSHAL\n" );
1768 client_do_args(pStubMsg, pFormat, STUBLESS_MARSHAL, NULL, async_call_data->number_of_params, NULL);
1770 /* 4. SENDRECEIVE */
1771 TRACE( "SEND\n" );
1772 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1773 /* send the [in] params only */
1774 if (Oif_flags.HasPipes)
1775 /* NdrPipesSend(...) */
1776 FIXME("pipes not supported yet\n");
1777 else
1779 if (pProcHeader->handle_type == FC_AUTO_HANDLE)
1780 #if 0
1781 NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
1782 #else
1783 FIXME("using auto handle - call NdrNsSend when it gets implemented\n");
1784 #endif
1785 else
1787 pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
1788 status = I_RpcSend(pStubMsg->RpcMsg);
1789 if (status != RPC_S_OK)
1790 RpcRaiseException(status);
1795 LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat,
1796 void **stack_top )
1798 LONG_PTR ret = 0;
1799 const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1801 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
1803 if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT)
1805 __TRY
1807 do_ndr_async_client_call( pStubDesc, pFormat, stack_top );
1809 __EXCEPT_ALL
1811 FIXME("exception %lx during ndr_async_client_call()\n", GetExceptionCode());
1812 ret = GetExceptionCode();
1814 __ENDTRY
1816 else
1817 do_ndr_async_client_call( pStubDesc, pFormat, stack_top);
1819 TRACE("returning %Id\n", ret);
1820 return ret;
1823 RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
1825 /* pointer to start of stack where arguments start */
1826 PMIDL_STUB_MESSAGE pStubMsg;
1827 struct async_call_data *async_call_data;
1828 /* header for procedure string */
1829 const NDR_PROC_HEADER * pProcHeader;
1830 RPC_STATUS status = RPC_S_OK;
1832 if (!pAsync->StubInfo)
1833 return RPC_S_INVALID_ASYNC_HANDLE;
1835 async_call_data = pAsync->StubInfo;
1836 pStubMsg = async_call_data->pStubMsg;
1837 pProcHeader = async_call_data->pProcHeader;
1839 /* order of phases:
1840 * 1. CALCSIZE - calculate the buffer size
1841 * 2. GETBUFFER - allocate the buffer
1842 * 3. MARSHAL - marshal [in] params into the buffer
1843 * 4. SENDRECEIVE - send buffer
1844 * Then in NdrpCompleteAsyncClientCall:
1845 * 1. SENDRECEIVE - receive buffer
1846 * 2. UNMARSHAL - unmarshal [out] params from buffer
1849 /* 1. SENDRECEIVE */
1850 TRACE( "RECEIVE\n" );
1851 pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1852 /* receive the [out] params */
1853 if (pProcHeader->handle_type == FC_AUTO_HANDLE)
1854 #if 0
1855 NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
1856 #else
1857 FIXME("using auto handle - call NdrNsReceive when it gets implemented\n");
1858 #endif
1859 else
1861 status = I_RpcReceive(pStubMsg->RpcMsg);
1862 if (status != RPC_S_OK)
1863 goto cleanup;
1864 pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;
1865 pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
1866 pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
1867 pStubMsg->Buffer = pStubMsg->BufferStart;
1870 /* convert strings, floating point values and endianness into our
1871 * preferred format */
1872 #if 0
1873 if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1874 NdrConvert(pStubMsg, pFormat);
1875 #endif
1877 /* 2. UNMARSHAL */
1878 TRACE( "UNMARSHAL\n" );
1879 client_do_args(pStubMsg, async_call_data->pParamFormat, STUBLESS_UNMARSHAL,
1880 NULL, async_call_data->number_of_params, Reply);
1882 cleanup:
1883 if (pStubMsg->fHasNewCorrDesc)
1885 /* free extra correlation package */
1886 NdrCorrelationFree(pStubMsg);
1889 /* free the full pointer translation tables */
1890 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1891 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
1893 /* free marshalling buffer */
1894 NdrFreeBuffer(pStubMsg);
1895 client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding);
1897 I_RpcFree(pStubMsg->StackTop);
1898 I_RpcFree(async_call_data);
1900 TRACE("-- 0x%lx\n", status);
1901 return status;
1904 #ifdef __x86_64__
1906 __ASM_GLOBAL_FUNC( NdrAsyncClientCall,
1907 "subq $0x28,%rsp\n\t"
1908 __ASM_SEH(".seh_stackalloc 0x28\n\t")
1909 __ASM_SEH(".seh_endprologue\n\t")
1910 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
1911 "movq %r8,0x40(%rsp)\n\t"
1912 "movq %r9,0x48(%rsp)\n\t"
1913 "leaq 0x40(%rsp),%r8\n\t"
1914 "call " __ASM_NAME("ndr_async_client_call") "\n\t"
1915 "addq $0x28,%rsp\n\t"
1916 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
1917 "ret" );
1919 #else /* __x86_64__ */
1921 /***********************************************************************
1922 * NdrAsyncClientCall [RPCRT4.@]
1924 CLIENT_CALL_RETURN WINAPIV NdrAsyncClientCall( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... )
1926 va_list args;
1927 LONG_PTR ret;
1929 va_start( args, format );
1930 ret = ndr_async_client_call( desc, format, va_arg( args, void ** ));
1931 va_end( args );
1932 return *(CLIENT_CALL_RETURN *)&ret;
1935 #endif /* __x86_64__ */
1937 RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis,
1938 struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg,
1939 DWORD * pdwStubPhase)
1941 FIXME("unimplemented, expect crash!\n");
1942 return 0;
1945 void RPC_ENTRY NdrAsyncServerCall(PRPC_MESSAGE pRpcMsg)
1947 const MIDL_SERVER_INFO *pServerInfo;
1948 const MIDL_STUB_DESC *pStubDesc;
1949 PFORMAT_STRING pFormat;
1950 /* pointer to start of stack to pass into stub implementation */
1951 unsigned char *args;
1952 /* header for procedure string */
1953 const NDR_PROC_HEADER *pProcHeader;
1954 struct async_call_data *async_call_data;
1955 PRPC_ASYNC_STATE pAsync;
1956 RPC_STATUS status;
1958 TRACE("%p\n", pRpcMsg);
1960 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1962 pStubDesc = pServerInfo->pStubDesc;
1963 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1964 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1966 TRACE("NDR Version: 0x%lx\n", pStubDesc->Version);
1968 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
1969 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY);
1970 async_call_data->pProcHeader = pProcHeader;
1972 async_call_data->pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
1973 *(PRPC_MESSAGE)(async_call_data->pStubMsg + 1) = *pRpcMsg;
1975 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1977 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1978 async_call_data->stack_size = header_rpc->stack_size;
1979 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1981 else
1983 async_call_data->stack_size = pProcHeader->stack_size;
1984 pFormat += sizeof(NDR_PROC_HEADER);
1987 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1989 /* binding */
1990 switch (pProcHeader->handle_type)
1992 /* explicit binding: parse additional section */
1993 case 0:
1994 switch (*pFormat) /* handle_type */
1996 case FC_BIND_PRIMITIVE: /* explicit primitive */
1997 pFormat += sizeof(NDR_EHD_PRIMITIVE);
1998 break;
1999 case FC_BIND_GENERIC: /* explicit generic */
2000 pFormat += sizeof(NDR_EHD_GENERIC);
2001 break;
2002 case FC_BIND_CONTEXT: /* explicit context */
2003 pFormat += sizeof(NDR_EHD_CONTEXT);
2004 break;
2005 default:
2006 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
2007 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2009 break;
2010 case FC_BIND_GENERIC: /* implicit generic */
2011 case FC_BIND_PRIMITIVE: /* implicit primitive */
2012 case FC_CALLBACK_HANDLE: /* implicit callback */
2013 case FC_AUTO_HANDLE: /* implicit auto handle */
2014 break;
2015 default:
2016 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
2017 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2020 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
2022 ERR("objects not supported\n");
2023 I_RpcFree(async_call_data);
2024 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2027 NdrServerInitializeNew(pRpcMsg, async_call_data->pStubMsg, pStubDesc);
2029 /* create the full pointer translation tables, if requested */
2030 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
2031 async_call_data->pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0, XLAT_SERVER);
2033 /* use alternate memory allocation routines */
2034 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
2035 #if 0
2036 NdrRpcSsEnableAllocate(&stubMsg);
2037 #else
2038 FIXME("Set RPCSS memory allocation routines\n");
2039 #endif
2041 TRACE("allocating memory for stack of size %x\n", async_call_data->stack_size);
2043 args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, async_call_data->stack_size);
2044 async_call_data->pStubMsg->StackTop = args; /* used by conformance of top-level objects */
2046 pAsync = I_RpcAllocate(sizeof(*pAsync));
2047 if (!pAsync) RpcRaiseException(RPC_X_NO_MEMORY);
2049 status = RpcAsyncInitializeHandle(pAsync, sizeof(*pAsync));
2050 if (status != RPC_S_OK)
2051 RpcRaiseException(status);
2053 pAsync->StubInfo = async_call_data;
2054 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat);
2056 /* add the implicit pAsync pointer as the first arg to the function */
2057 *(void **)args = pAsync;
2059 if (is_oicf_stubdesc(pStubDesc))
2061 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
2062 /* cache of Oif_flags from v2 procedure header */
2063 INTERPRETER_OPT_FLAGS Oif_flags;
2064 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
2065 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
2067 Oif_flags = pOIFHeader->Oi2Flags;
2068 async_call_data->number_of_params = pOIFHeader->number_of_params;
2070 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
2072 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
2074 if (Oif_flags.HasExtensions)
2076 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
2077 ext_flags = pExtensions->Flags2;
2078 pFormat += pExtensions->Size;
2081 if (Oif_flags.HasPipes)
2083 FIXME("pipes not supported yet\n");
2084 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
2085 /* init pipes package */
2086 /* NdrPipesInitialize(...) */
2088 if (ext_flags.HasNewCorrDesc)
2090 /* initialize extra correlation package */
2091 NdrCorrelationInitialize(async_call_data->pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
2092 if (ext_flags.Unused & 0x2) /* has range on conformance */
2093 async_call_data->pStubMsg->CorrDespIncrement = 12;
2096 else
2098 pFormat = convert_old_args( async_call_data->pStubMsg, pFormat, async_call_data->stack_size,
2099 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
2100 /* reuse the correlation cache, it's not needed for v1 format */
2101 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), &async_call_data->number_of_params );
2104 /* convert strings, floating point values and endianness into our
2105 * preferred format */
2106 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
2107 NdrConvert(async_call_data->pStubMsg, pFormat);
2109 async_call_data->pHandleFormat = pFormat;
2111 /* 1. UNMARSHAL */
2112 TRACE("UNMARSHAL\n");
2113 stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_UNMARSHAL, async_call_data->number_of_params);
2115 /* 2. INITOUT */
2116 TRACE("INITOUT\n");
2117 async_call_data->retval_ptr = stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_INITOUT, async_call_data->number_of_params);
2119 /* 3. CALLSERVER */
2120 TRACE("CALLSERVER\n");
2121 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
2122 pServerInfo->ThunkTable[pRpcMsg->ProcNum](async_call_data->pStubMsg);
2123 else
2124 call_server_func(pServerInfo->DispatchTable[pRpcMsg->ProcNum], args, async_call_data->stack_size);
2127 RPC_STATUS NdrpCompleteAsyncServerCall(RPC_ASYNC_STATE *pAsync, void *Reply)
2129 /* pointer to start of stack where arguments start */
2130 PMIDL_STUB_MESSAGE pStubMsg;
2131 struct async_call_data *async_call_data;
2132 /* the type of pass we are currently doing */
2133 enum stubless_phase phase;
2134 RPC_STATUS status = RPC_S_OK;
2136 if (!pAsync->StubInfo)
2137 return RPC_S_INVALID_ASYNC_HANDLE;
2139 async_call_data = pAsync->StubInfo;
2140 pStubMsg = async_call_data->pStubMsg;
2142 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat);
2144 if (async_call_data->retval_ptr)
2146 TRACE("stub implementation returned 0x%Ix\n", *(LONG_PTR *)Reply);
2147 *async_call_data->retval_ptr = *(LONG_PTR *)Reply;
2149 else
2150 TRACE("void stub implementation\n");
2152 for (phase = STUBLESS_CALCSIZE; phase <= STUBLESS_FREE; phase++)
2154 TRACE("phase = %d\n", phase);
2155 switch (phase)
2157 case STUBLESS_GETBUFFER:
2158 if (async_call_data->pProcHeader->Oi_flags & Oi_OBJECT_PROC)
2160 ERR("objects not supported\n");
2161 HeapFree(GetProcessHeap(), 0, async_call_data->pStubMsg->StackTop);
2162 I_RpcFree(async_call_data);
2163 I_RpcFree(pAsync);
2164 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2166 else
2168 pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength;
2169 /* allocate buffer for [out] and [ret] params */
2170 status = I_RpcGetBuffer(pStubMsg->RpcMsg);
2171 if (status)
2172 RpcRaiseException(status);
2173 pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer;
2175 break;
2177 case STUBLESS_CALCSIZE:
2178 case STUBLESS_MARSHAL:
2179 case STUBLESS_MUSTFREE:
2180 case STUBLESS_FREE:
2181 stub_do_args(pStubMsg, async_call_data->pHandleFormat, phase, async_call_data->number_of_params);
2182 break;
2183 default:
2184 ERR("shouldn't reach here. phase %d\n", phase);
2185 break;
2189 #if 0 /* FIXME */
2190 if (ext_flags.HasNewCorrDesc)
2192 /* free extra correlation package */
2193 NdrCorrelationFree(pStubMsg);
2196 if (Oif_flags.HasPipes)
2198 /* NdrPipesDone(...) */
2201 /* free the full pointer translation tables */
2202 if (async_call_data->pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
2203 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
2204 #endif
2206 /* free server function stack */
2207 HeapFree(GetProcessHeap(), 0, async_call_data->pStubMsg->StackTop);
2208 I_RpcFree(async_call_data);
2209 I_RpcFree(pAsync);
2211 return S_OK;
2214 static const RPC_SYNTAX_IDENTIFIER ndr_syntax_id =
2215 {{0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60}}, {2, 0}};
2217 LONG_PTR CDECL DECLSPEC_HIDDEN ndr64_client_call( MIDL_STUBLESS_PROXY_INFO *info,
2218 ULONG proc, void *retval, void **stack_top, void **fpu_stack )
2220 ULONG_PTR i;
2222 TRACE("info %p, proc %lu, retval %p, stack_top %p, fpu_stack %p\n",
2223 info, proc, retval, stack_top, fpu_stack);
2225 for (i = 0; i < info->nCount; ++i)
2227 const MIDL_SYNTAX_INFO *syntax_info = &info->pSyntaxInfo[i];
2228 const RPC_SYNTAX_IDENTIFIER *id = &syntax_info->TransferSyntax;
2230 TRACE("Found syntax %s, version %u.%u.\n", debugstr_guid(&id->SyntaxGUID),
2231 id->SyntaxVersion.MajorVersion, id->SyntaxVersion.MinorVersion);
2232 if (!memcmp(id, &ndr_syntax_id, sizeof(RPC_SYNTAX_IDENTIFIER)))
2234 if (retval)
2235 FIXME("Complex return types are not supported.\n");
2237 return ndr_client_call( info->pStubDesc,
2238 syntax_info->ProcString + syntax_info->FmtStringOffset[proc], stack_top, fpu_stack );
2242 FIXME("NDR64 syntax is not supported.\n");
2243 return 0;
2246 #ifdef __x86_64__
2248 __ASM_GLOBAL_FUNC( NdrClientCall3,
2249 "movq %r9,0x20(%rsp)\n\t"
2250 "leaq 0x20(%rsp),%r9\n\t"
2251 "pushq $0\n\t"
2252 "subq $0x20,%rsp\n\t"
2253 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
2254 "call " __ASM_NAME("ndr64_client_call") "\n\t"
2255 "addq $0x28,%rsp\n\t"
2256 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
2257 "ret" );
2259 #elif defined(_WIN64)
2261 /***********************************************************************
2262 * NdrClientCall3 [RPCRT4.@]
2264 CLIENT_CALL_RETURN WINAPIV NdrClientCall3( MIDL_STUBLESS_PROXY_INFO *info, ULONG proc, void *retval, ... )
2266 va_list args;
2267 LONG_PTR ret;
2269 va_start( args, retval );
2270 ret = ndr64_client_call( info, proc, retval, va_arg( args, void ** ), NULL );
2271 va_end( args );
2272 return *(CLIENT_CALL_RETURN *)&ret;
2275 #endif
2277 LONG_PTR CDECL DECLSPEC_HIDDEN ndr64_async_client_call( MIDL_STUBLESS_PROXY_INFO *info,
2278 ULONG proc, void *retval, void **stack_top, void **fpu_stack )
2280 ULONG_PTR i;
2282 TRACE("info %p, proc %lu, retval %p, stack_top %p, fpu_stack %p\n",
2283 info, proc, retval, stack_top, fpu_stack);
2285 for (i = 0; i < info->nCount; ++i)
2287 const MIDL_SYNTAX_INFO *syntax_info = &info->pSyntaxInfo[i];
2288 const RPC_SYNTAX_IDENTIFIER *id = &syntax_info->TransferSyntax;
2290 TRACE("Found syntax %s, version %u.%u.\n", debugstr_guid(&id->SyntaxGUID),
2291 id->SyntaxVersion.MajorVersion, id->SyntaxVersion.MinorVersion);
2292 if (!memcmp(id, &ndr_syntax_id, sizeof(RPC_SYNTAX_IDENTIFIER)))
2294 if (retval)
2295 FIXME("Complex return types are not supported.\n");
2297 return ndr_async_client_call( info->pStubDesc,
2298 syntax_info->ProcString + syntax_info->FmtStringOffset[proc], stack_top );
2302 FIXME("NDR64 syntax is not supported.\n");
2303 return 0;
2306 #ifdef __x86_64__
2308 __ASM_GLOBAL_FUNC( Ndr64AsyncClientCall,
2309 "movq %r9,0x20(%rsp)\n\t"
2310 "leaq 0x20(%rsp),%r9\n\t"
2311 "pushq $0\n\t"
2312 "subq $0x20,%rsp\n\t"
2313 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
2314 "call " __ASM_NAME("ndr64_async_client_call") "\n\t"
2315 "addq $0x28,%rsp\n\t"
2316 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
2317 "ret" );
2319 #elif defined(_WIN64)
2321 /***********************************************************************
2322 * Ndr64AsyncClientCall [RPCRT4.@]
2324 CLIENT_CALL_RETURN WINAPIV Ndr64AsyncClientCall( MIDL_STUBLESS_PROXY_INFO *info, ULONG proc, void *retval, ... )
2326 va_list args;
2327 LONG_PTR ret;
2329 va_start( args, retval );
2330 ret = ndr64_async_client_call( info, proc, retval, va_arg( args, void ** ), NULL );
2331 va_end( args );
2332 return *(CLIENT_CALL_RETURN *)&ret;
2335 #endif