cmd: DIR command outputs free space for the path.
[wine.git] / dlls / rpcrt4 / ndr_stubless.c
blob8fc5fd41ca6779171f2b9d79070e5f5cea9ed606
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 "subq $0x28,%rsp\n\t"
1009 __ASM_SEH(".seh_stackalloc 0x28\n\t")
1010 __ASM_SEH(".seh_endprologue\n\t")
1011 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
1012 "movq %r8,0x40(%rsp)\n\t"
1013 "movq %r9,0x48(%rsp)\n\t"
1014 "leaq 0x40(%rsp),%r8\n\t"
1015 "xorq %r9,%r9\n\t"
1016 "call " __ASM_NAME("ndr_client_call") "\n\t"
1017 "addq $0x28,%rsp\n\t"
1018 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
1019 "ret" );
1021 #else /* __x86_64__ */
1023 /***********************************************************************
1024 * NdrClientCall2 [RPCRT4.@]
1026 CLIENT_CALL_RETURN WINAPIV NdrClientCall2( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... )
1028 va_list args;
1029 LONG_PTR ret;
1031 va_start( args, format );
1032 ret = ndr_client_call( desc, format, va_arg( args, void ** ), NULL );
1033 va_end( args );
1034 return *(CLIENT_CALL_RETURN *)&ret;
1037 #endif /* __x86_64__ */
1039 /* Calls a function with the specified arguments, restoring the stack
1040 * properly afterwards as we don't know the calling convention of the
1041 * function */
1042 #if defined __i386__ && defined _MSC_VER
1043 __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size)
1045 __asm
1047 push ebp
1048 mov ebp, esp
1049 push edi ; Save registers
1050 push esi
1051 mov eax, [ebp+16] ; Get stack size
1052 sub esp, eax ; Make room in stack for arguments
1053 and esp, 0xFFFFFFF0
1054 mov edi, esp
1055 mov ecx, eax
1056 mov esi, [ebp+12]
1057 shr ecx, 2
1059 rep movsd ; Copy dword blocks
1060 call [ebp+8] ; Call function
1061 lea esp, [ebp-8] ; Restore stack
1062 pop esi ; Restore registers
1063 pop edi
1064 pop ebp
1068 #elif defined __i386__ && defined __GNUC__
1069 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
1070 __ASM_GLOBAL_FUNC(call_server_func,
1071 "pushl %ebp\n\t"
1072 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
1073 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
1074 "movl %esp,%ebp\n\t"
1075 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
1076 "pushl %edi\n\t" /* Save registers */
1077 __ASM_CFI(".cfi_rel_offset %edi,-4\n\t")
1078 "pushl %esi\n\t"
1079 __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
1080 "movl 16(%ebp), %eax\n\t" /* Get stack size */
1081 "subl %eax, %esp\n\t" /* Make room in stack for arguments */
1082 "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */
1083 "movl %esp, %edi\n\t"
1084 "movl %eax, %ecx\n\t"
1085 "movl 12(%ebp), %esi\n\t"
1086 "shrl $2, %ecx\n\t" /* divide by 4 */
1087 "cld\n\t"
1088 "rep; movsl\n\t" /* Copy dword blocks */
1089 "call *8(%ebp)\n\t" /* Call function */
1090 "leal -8(%ebp), %esp\n\t" /* Restore stack */
1091 "popl %esi\n\t" /* Restore registers */
1092 __ASM_CFI(".cfi_same_value %esi\n\t")
1093 "popl %edi\n\t"
1094 __ASM_CFI(".cfi_same_value %edi\n\t")
1095 "popl %ebp\n\t"
1096 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
1097 __ASM_CFI(".cfi_same_value %ebp\n\t")
1098 "ret" )
1099 #elif defined __x86_64__
1100 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
1101 __ASM_GLOBAL_FUNC( call_server_func,
1102 "pushq %rbp\n\t"
1103 __ASM_SEH(".seh_pushreg %rbp\n\t")
1104 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
1105 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
1106 "movq %rsp,%rbp\n\t"
1107 __ASM_SEH(".seh_setframe %rbp,0\n\t")
1108 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
1109 "pushq %rsi\n\t"
1110 __ASM_SEH(".seh_pushreg %rsi\n\t")
1111 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
1112 "pushq %rdi\n\t"
1113 __ASM_SEH(".seh_pushreg %rdi\n\t")
1114 __ASM_SEH(".seh_endprologue\n\t")
1115 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
1116 "movq %rcx,%rax\n\t" /* function to call */
1117 "movq $32,%rcx\n\t" /* allocate max(32,stack_size) bytes of stack space */
1118 "cmpq %rcx,%r8\n\t"
1119 "cmovgq %r8,%rcx\n\t"
1120 "subq %rcx,%rsp\n\t"
1121 "andq $~15,%rsp\n\t"
1122 "movq %r8,%rcx\n\t"
1123 "shrq $3,%rcx\n\t"
1124 "movq %rsp,%rdi\n\t"
1125 "movq %rdx,%rsi\n\t"
1126 "rep; movsq\n\t" /* copy arguments */
1127 "movq 0(%rsp),%rcx\n\t"
1128 "movq 8(%rsp),%rdx\n\t"
1129 "movq 16(%rsp),%r8\n\t"
1130 "movq 24(%rsp),%r9\n\t"
1131 "movq 0(%rsp),%xmm0\n\t"
1132 "movq 8(%rsp),%xmm1\n\t"
1133 "movq 16(%rsp),%xmm2\n\t"
1134 "movq 24(%rsp),%xmm3\n\t"
1135 "callq *%rax\n\t"
1136 "leaq -16(%rbp),%rsp\n\t" /* restore stack */
1137 "popq %rdi\n\t"
1138 __ASM_CFI(".cfi_same_value %rdi\n\t")
1139 "popq %rsi\n\t"
1140 __ASM_CFI(".cfi_same_value %rsi\n\t")
1141 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
1142 "popq %rbp\n\t"
1143 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
1144 __ASM_CFI(".cfi_same_value %rbp\n\t")
1145 "ret")
1146 #elif defined __arm__
1147 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char *args, unsigned int stack_size);
1148 __ASM_GLOBAL_FUNC( call_server_func,
1149 "push {r4, r5, LR}\n\t"
1150 "mov r4, r0\n\t"
1151 "mov r5, SP\n\t"
1152 "lsr r3, r2, #2\n\t"
1153 "cmp r3, #0\n\t"
1154 "beq 5f\n\t"
1155 "sub SP, SP, r2\n\t"
1156 "tst r3, #1\n\t"
1157 "it eq\n\t"
1158 "subeq SP, SP, #4\n\t"
1159 "1:\tsub r2, r2, #4\n\t"
1160 "ldr r0, [r1, r2]\n\t"
1161 "str r0, [SP, r2]\n\t"
1162 "cmp r2, #0\n\t"
1163 "bgt 1b\n\t"
1164 "cmp r3, #1\n\t"
1165 "bgt 2f\n\t"
1166 "pop {r0}\n\t"
1167 "b 5f\n\t"
1168 "2:\tcmp r3, #2\n\t"
1169 "bgt 3f\n\t"
1170 "pop {r0-r1}\n\t"
1171 "b 5f\n\t"
1172 "3:\tcmp r3, #3\n\t"
1173 "bgt 4f\n\t"
1174 "pop {r0-r2}\n\t"
1175 "b 5f\n\t"
1176 "4:\tpop {r0-r3}\n\t"
1177 "5:\tblx r4\n\t"
1178 "mov SP, r5\n\t"
1179 "pop {r4, r5, PC}" )
1180 #elif defined __aarch64__
1181 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char *args, unsigned int stack_size);
1182 __ASM_GLOBAL_FUNC( call_server_func,
1183 "stp x29, x30, [sp, #-16]!\n\t"
1184 "mov x29, sp\n\t"
1185 "add x9, x2, #15\n\t"
1186 "lsr x9, x9, #4\n\t"
1187 "sub sp, sp, x9, lsl #4\n\t"
1188 "cbz x2, 2f\n"
1189 "1:\tsub x2, x2, #8\n\t"
1190 "ldr x4, [x1, x2]\n\t"
1191 "str x4, [sp, x2]\n\t"
1192 "cbnz x2, 1b\n"
1193 "2:\tmov x8, x0\n\t"
1194 "cbz x9, 3f\n\t"
1195 "ldp x0, x1, [sp], #16\n\t"
1196 "cmp x9, #1\n\t"
1197 "b.le 3f\n\t"
1198 "ldp x2, x3, [sp], #16\n\t"
1199 "cmp x9, #2\n\t"
1200 "b.le 3f\n\t"
1201 "ldp x4, x5, [sp], #16\n\t"
1202 "cmp x9, #3\n\t"
1203 "b.le 3f\n\t"
1204 "ldp x6, x7, [sp], #16\n"
1205 "3:\tblr x8\n\t"
1206 "mov sp, x29\n\t"
1207 "ldp x29, x30, [sp], #16\n\t"
1208 "ret" )
1209 #else
1210 #warning call_server_func not implemented for your architecture
1211 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
1213 FIXME("Not implemented for your architecture\n");
1214 return 0;
1216 #endif
1218 static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg,
1219 PFORMAT_STRING pFormat, enum stubless_phase phase,
1220 unsigned short number_of_params)
1222 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat;
1223 unsigned int i;
1224 LONG_PTR *retval_ptr = NULL;
1226 for (i = 0; i < number_of_params; i++)
1228 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset;
1229 const unsigned char *pTypeFormat = &pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset];
1231 TRACE("param[%d]: %p -> %p type %02x %s\n", i,
1232 pArg, *(unsigned char **)pArg,
1233 params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat,
1234 debugstr_PROC_PF( params[i].attr ));
1236 switch (phase)
1238 case STUBLESS_MARSHAL:
1239 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1240 call_marshaller(pStubMsg, pArg, &params[i]);
1241 break;
1242 case STUBLESS_MUSTFREE:
1243 if (params[i].attr.MustFree)
1245 call_freer(pStubMsg, pArg, &params[i]);
1247 break;
1248 case STUBLESS_FREE:
1249 if (params[i].attr.ServerAllocSize)
1251 free(*(void **)pArg);
1253 else if (param_needs_alloc(params[i].attr) &&
1254 (!params[i].attr.MustFree || params[i].attr.IsSimpleRef))
1256 if (*pTypeFormat != FC_BIND_CONTEXT) pStubMsg->pfnFree(*(void **)pArg);
1258 break;
1259 case STUBLESS_INITOUT:
1260 if (param_needs_alloc(params[i].attr) && !params[i].attr.ServerAllocSize)
1262 if (*pTypeFormat == FC_BIND_CONTEXT)
1264 NDR_SCONTEXT ctxt = NdrContextHandleInitialize(pStubMsg, pTypeFormat);
1265 *(void **)pArg = NDRSContextValue(ctxt);
1266 if (params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)NDRSContextValue(ctxt);
1268 else
1270 DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
1271 if (size)
1273 *(void **)pArg = NdrAllocate(pStubMsg, size);
1274 memset(*(void **)pArg, 0, size);
1278 if (!retval_ptr && params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)pArg;
1279 break;
1280 case STUBLESS_UNMARSHAL:
1281 if (params[i].attr.ServerAllocSize)
1282 *(void **)pArg = calloc(params[i].attr.ServerAllocSize, 8);
1284 if (params[i].attr.IsIn)
1285 call_unmarshaller(pStubMsg, &pArg, &params[i], 0);
1286 break;
1287 case STUBLESS_CALCSIZE:
1288 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1289 call_buffer_sizer(pStubMsg, pArg, &params[i]);
1290 break;
1291 default:
1292 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1294 TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
1296 return retval_ptr;
1299 /***********************************************************************
1300 * NdrStubCall2 [RPCRT4.@]
1302 * Unmarshals [in] parameters, calls either a method in an object or a server
1303 * function, marshals any [out] parameters and frees any allocated data.
1305 * NOTES
1306 * Used by stubless MIDL-generated code.
1308 LONG WINAPI NdrStubCall2(
1309 struct IRpcStubBuffer * pThis,
1310 struct IRpcChannelBuffer * pChannel,
1311 PRPC_MESSAGE pRpcMsg,
1312 DWORD * pdwStubPhase)
1314 const MIDL_SERVER_INFO *pServerInfo;
1315 const MIDL_STUB_DESC *pStubDesc;
1316 PFORMAT_STRING pFormat;
1317 MIDL_STUB_MESSAGE stubMsg;
1318 /* pointer to start of stack to pass into stub implementation */
1319 unsigned char * args;
1320 /* size of stack */
1321 unsigned short stack_size;
1322 /* number of parameters. optional for client to give it to us */
1323 unsigned int number_of_params;
1324 /* cache of Oif_flags from v2 procedure header */
1325 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1326 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1327 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1328 /* the type of pass we are currently doing */
1329 enum stubless_phase phase;
1330 /* header for procedure string */
1331 const NDR_PROC_HEADER *pProcHeader;
1332 /* location to put retval into */
1333 LONG_PTR *retval_ptr = NULL;
1334 /* correlation cache */
1335 ULONG_PTR NdrCorrCache[256];
1337 TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase);
1339 if (pThis)
1340 pServerInfo = CStdStubBuffer_GetServerInfo(pThis);
1341 else
1342 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1344 pStubDesc = pServerInfo->pStubDesc;
1345 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1346 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1348 TRACE("NDR Version: 0x%lx\n", pStubDesc->Version);
1350 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1352 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1353 stack_size = header_rpc->stack_size;
1354 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1357 else
1359 stack_size = pProcHeader->stack_size;
1360 pFormat += sizeof(NDR_PROC_HEADER);
1363 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1365 /* binding */
1366 switch (pProcHeader->handle_type)
1368 /* explicit binding: parse additional section */
1369 case 0:
1370 switch (*pFormat) /* handle_type */
1372 case FC_BIND_PRIMITIVE: /* explicit primitive */
1373 pFormat += sizeof(NDR_EHD_PRIMITIVE);
1374 break;
1375 case FC_BIND_GENERIC: /* explicit generic */
1376 pFormat += sizeof(NDR_EHD_GENERIC);
1377 break;
1378 case FC_BIND_CONTEXT: /* explicit context */
1379 pFormat += sizeof(NDR_EHD_CONTEXT);
1380 break;
1381 default:
1382 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1383 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1385 break;
1386 case FC_BIND_GENERIC: /* implicit generic */
1387 case FC_BIND_PRIMITIVE: /* implicit primitive */
1388 case FC_CALLBACK_HANDLE: /* implicit callback */
1389 case FC_AUTO_HANDLE: /* implicit auto handle */
1390 break;
1391 default:
1392 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1393 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1396 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1397 NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel);
1398 else
1399 NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc);
1401 /* create the full pointer translation tables, if requested */
1402 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1403 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
1405 /* store the RPC flags away */
1406 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1407 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1409 /* use alternate memory allocation routines */
1410 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
1411 #if 0
1412 NdrRpcSsEnableAllocate(&stubMsg);
1413 #else
1414 FIXME("Set RPCSS memory allocation routines\n");
1415 #endif
1417 TRACE("allocating memory for stack of size %x\n", stack_size);
1419 args = calloc(1, stack_size);
1420 stubMsg.StackTop = args; /* used by conformance of top-level objects */
1422 /* add the implicit This pointer as the first arg to the function if we
1423 * are calling an object method */
1424 if (pThis)
1425 *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject;
1427 if (is_oicf_stubdesc(pStubDesc))
1429 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
1431 Oif_flags = pOIFHeader->Oi2Flags;
1432 number_of_params = pOIFHeader->number_of_params;
1434 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1436 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
1438 if (Oif_flags.HasExtensions)
1440 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
1441 ext_flags = pExtensions->Flags2;
1442 pFormat += pExtensions->Size;
1445 if (Oif_flags.HasPipes)
1447 FIXME("pipes not supported yet\n");
1448 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1449 /* init pipes package */
1450 /* NdrPipesInitialize(...) */
1452 if (ext_flags.HasNewCorrDesc)
1454 /* initialize extra correlation package */
1455 NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0);
1456 if (ext_flags.Unused & 0x2) /* has range on conformance */
1457 stubMsg.CorrDespIncrement = 12;
1460 else
1462 pFormat = convert_old_args( &stubMsg, pFormat, stack_size,
1463 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
1464 /* reuse the correlation cache, it's not needed for v1 format */
1465 NdrCorrCache, sizeof(NdrCorrCache), &number_of_params );
1468 /* convert strings, floating point values and endianness into our
1469 * preferred format */
1470 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1471 NdrConvert(&stubMsg, pFormat);
1473 for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++)
1475 TRACE("phase = %d\n", phase);
1476 switch (phase)
1478 case STUBLESS_CALLSERVER:
1479 /* call the server function */
1480 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
1481 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg);
1482 else
1484 SERVER_ROUTINE func;
1485 LONG_PTR retval;
1487 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1489 SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject;
1490 func = vtbl[pRpcMsg->ProcNum];
1492 else
1493 func = pServerInfo->DispatchTable[pRpcMsg->ProcNum];
1495 /* FIXME: what happens with return values that don't fit into a single register on x86? */
1496 retval = call_server_func(func, args, stack_size);
1498 if (retval_ptr)
1500 TRACE("stub implementation returned 0x%Ix\n", retval);
1501 *retval_ptr = retval;
1503 else
1504 TRACE("void stub implementation\n");
1507 stubMsg.Buffer = NULL;
1508 stubMsg.BufferLength = 0;
1510 break;
1511 case STUBLESS_GETBUFFER:
1512 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1513 NdrStubGetBuffer(pThis, pChannel, &stubMsg);
1514 else
1516 RPC_STATUS Status;
1518 pRpcMsg->BufferLength = stubMsg.BufferLength;
1519 /* allocate buffer for [out] and [ret] params */
1520 Status = I_RpcGetBuffer(pRpcMsg);
1521 if (Status)
1522 RpcRaiseException(Status);
1523 stubMsg.Buffer = pRpcMsg->Buffer;
1525 break;
1526 case STUBLESS_UNMARSHAL:
1527 case STUBLESS_INITOUT:
1528 case STUBLESS_CALCSIZE:
1529 case STUBLESS_MARSHAL:
1530 case STUBLESS_MUSTFREE:
1531 case STUBLESS_FREE:
1532 retval_ptr = stub_do_args(&stubMsg, pFormat, phase, number_of_params);
1533 break;
1534 default:
1535 ERR("shouldn't reach here. phase %d\n", phase);
1536 break;
1540 pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer);
1542 if (ext_flags.HasNewCorrDesc)
1544 /* free extra correlation package */
1545 NdrCorrelationFree(&stubMsg);
1548 if (Oif_flags.HasPipes)
1550 /* NdrPipesDone(...) */
1553 /* free the full pointer translation tables */
1554 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1555 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
1557 /* free server function stack */
1558 free(args);
1560 return S_OK;
1563 /***********************************************************************
1564 * NdrServerCall2 [RPCRT4.@]
1566 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
1568 DWORD dwPhase;
1569 NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
1572 /***********************************************************************
1573 * NdrStubCall [RPCRT4.@]
1575 LONG WINAPI NdrStubCall( struct IRpcStubBuffer *This, struct IRpcChannelBuffer *channel,
1576 PRPC_MESSAGE msg, DWORD *phase )
1578 return NdrStubCall2( This, channel, msg, phase );
1581 /***********************************************************************
1582 * NdrServerCall [RPCRT4.@]
1584 void WINAPI NdrServerCall( PRPC_MESSAGE msg )
1586 DWORD phase;
1587 NdrStubCall( NULL, NULL, msg, &phase );
1590 /***********************************************************************
1591 * NdrServerCallAll [RPCRT4.@]
1593 void WINAPI NdrServerCallAll( PRPC_MESSAGE msg )
1595 FIXME("%p stub\n", msg);
1598 /* Helper for ndr_async_client_call, to factor out the part that may or may not be
1599 * guarded by a try/except block. */
1600 static void do_ndr_async_client_call( const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormat, void **stack_top )
1602 /* pointer to start of stack where arguments start */
1603 PRPC_MESSAGE pRpcMsg;
1604 PMIDL_STUB_MESSAGE pStubMsg;
1605 RPC_ASYNC_STATE *pAsync;
1606 struct async_call_data *async_call_data;
1607 /* procedure number */
1608 unsigned short procedure_number;
1609 /* cache of Oif_flags from v2 procedure header */
1610 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1611 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1612 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1613 /* header for procedure string */
1614 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1615 RPC_STATUS status;
1617 /* Later NDR language versions probably won't be backwards compatible */
1618 if (pStubDesc->Version > 0x60001)
1620 FIXME("Incompatible stub description version: 0x%lx\n", pStubDesc->Version);
1621 RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
1624 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
1625 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY);
1626 async_call_data->pProcHeader = pProcHeader;
1628 async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
1629 pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1);
1631 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1633 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1634 async_call_data->stack_size = header_rpc->stack_size;
1635 procedure_number = header_rpc->proc_num;
1636 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1638 else
1640 async_call_data->stack_size = pProcHeader->stack_size;
1641 procedure_number = pProcHeader->proc_num;
1642 pFormat += sizeof(NDR_PROC_HEADER);
1644 TRACE("stack size: 0x%x\n", async_call_data->stack_size);
1645 TRACE("proc num: %d\n", procedure_number);
1647 /* create the full pointer translation tables, if requested */
1648 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1649 pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
1651 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1653 ERR("objects not supported\n");
1654 I_RpcFree(async_call_data);
1655 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1658 NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number);
1660 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1661 TRACE("MIDL stub version = 0x%lx\n", pStubDesc->MIDLVersion);
1663 /* needed for conformance of top-level objects */
1664 pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size);
1665 memcpy(pStubMsg->StackTop, stack_top, async_call_data->stack_size);
1667 pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop;
1668 pAsync->StubInfo = async_call_data;
1669 async_call_data->pHandleFormat = pFormat;
1671 TRACE("pAsync %p, pAsync->StubInfo %p, NotificationType %d\n", pAsync, pAsync->StubInfo, pAsync->NotificationType);
1673 pFormat += get_handle_desc_size(pProcHeader, pFormat);
1674 async_call_data->hBinding = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat);
1675 if (!async_call_data->hBinding) return;
1677 if (is_oicf_stubdesc(pStubDesc))
1679 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
1680 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
1682 Oif_flags = pOIFHeader->Oi2Flags;
1683 async_call_data->number_of_params = pOIFHeader->number_of_params;
1685 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1687 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
1689 if (Oif_flags.HasExtensions)
1691 const NDR_PROC_HEADER_EXTS *pExtensions =
1692 (const NDR_PROC_HEADER_EXTS *)pFormat;
1693 ext_flags = pExtensions->Flags2;
1694 pFormat += pExtensions->Size;
1697 else
1699 pFormat = convert_old_args( pStubMsg, pFormat, async_call_data->stack_size,
1700 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
1701 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache),
1702 &async_call_data->number_of_params );
1705 async_call_data->pParamFormat = pFormat;
1707 pStubMsg->BufferLength = 0;
1709 /* store the RPC flags away */
1710 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1711 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1713 /* use alternate memory allocation routines */
1714 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
1715 NdrRpcSmSetClientToOsf(pStubMsg);
1717 if (Oif_flags.HasPipes)
1719 FIXME("pipes not supported yet\n");
1720 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1721 /* init pipes package */
1722 /* NdrPipesInitialize(...) */
1724 if (ext_flags.HasNewCorrDesc)
1726 /* initialize extra correlation package */
1727 NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
1728 if (ext_flags.Unused & 0x2) /* has range on conformance */
1729 pStubMsg->CorrDespIncrement = 12;
1732 /* order of phases:
1733 * 1. CALCSIZE - calculate the buffer size
1734 * 2. GETBUFFER - allocate the buffer
1735 * 3. MARSHAL - marshal [in] params into the buffer
1736 * 4. SENDRECEIVE - send buffer
1737 * Then in NdrpCompleteAsyncClientCall:
1738 * 1. SENDRECEIVE - receive buffer
1739 * 2. UNMARSHAL - unmarshal [out] params from buffer
1742 /* 1. CALCSIZE */
1743 TRACE( "CALCSIZE\n" );
1744 client_do_args(pStubMsg, pFormat, STUBLESS_CALCSIZE, NULL, async_call_data->number_of_params, NULL);
1746 /* 2. GETBUFFER */
1747 TRACE( "GETBUFFER\n" );
1748 if (Oif_flags.HasPipes)
1749 /* NdrGetPipeBuffer(...) */
1750 FIXME("pipes not supported yet\n");
1751 else
1753 if (pProcHeader->handle_type == FC_AUTO_HANDLE)
1754 #if 0
1755 NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1756 #else
1757 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
1758 #endif
1759 else
1760 NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1762 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1763 status = I_RpcAsyncSetHandle(pRpcMsg, pAsync);
1764 if (status != RPC_S_OK)
1765 RpcRaiseException(status);
1767 /* 3. MARSHAL */
1768 TRACE( "MARSHAL\n" );
1769 client_do_args(pStubMsg, pFormat, STUBLESS_MARSHAL, NULL, async_call_data->number_of_params, NULL);
1771 /* 4. SENDRECEIVE */
1772 TRACE( "SEND\n" );
1773 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1774 /* send the [in] params only */
1775 if (Oif_flags.HasPipes)
1776 /* NdrPipesSend(...) */
1777 FIXME("pipes not supported yet\n");
1778 else
1780 if (pProcHeader->handle_type == FC_AUTO_HANDLE)
1781 #if 0
1782 NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
1783 #else
1784 FIXME("using auto handle - call NdrNsSend when it gets implemented\n");
1785 #endif
1786 else
1788 pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
1789 status = I_RpcSend(pStubMsg->RpcMsg);
1790 if (status != RPC_S_OK)
1791 RpcRaiseException(status);
1796 LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat,
1797 void **stack_top )
1799 LONG_PTR ret = 0;
1800 const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1802 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
1804 if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT)
1806 __TRY
1808 do_ndr_async_client_call( pStubDesc, pFormat, stack_top );
1810 __EXCEPT_ALL
1812 FIXME("exception %lx during ndr_async_client_call()\n", GetExceptionCode());
1813 ret = GetExceptionCode();
1815 __ENDTRY
1817 else
1818 do_ndr_async_client_call( pStubDesc, pFormat, stack_top);
1820 TRACE("returning %Id\n", ret);
1821 return ret;
1824 RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
1826 /* pointer to start of stack where arguments start */
1827 PMIDL_STUB_MESSAGE pStubMsg;
1828 struct async_call_data *async_call_data;
1829 /* header for procedure string */
1830 const NDR_PROC_HEADER * pProcHeader;
1831 RPC_STATUS status = RPC_S_OK;
1833 if (!pAsync->StubInfo)
1834 return RPC_S_INVALID_ASYNC_HANDLE;
1836 async_call_data = pAsync->StubInfo;
1837 pStubMsg = async_call_data->pStubMsg;
1838 pProcHeader = async_call_data->pProcHeader;
1840 /* order of phases:
1841 * 1. CALCSIZE - calculate the buffer size
1842 * 2. GETBUFFER - allocate the buffer
1843 * 3. MARSHAL - marshal [in] params into the buffer
1844 * 4. SENDRECEIVE - send buffer
1845 * Then in NdrpCompleteAsyncClientCall:
1846 * 1. SENDRECEIVE - receive buffer
1847 * 2. UNMARSHAL - unmarshal [out] params from buffer
1850 /* 1. SENDRECEIVE */
1851 TRACE( "RECEIVE\n" );
1852 pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1853 /* receive the [out] params */
1854 if (pProcHeader->handle_type == FC_AUTO_HANDLE)
1855 #if 0
1856 NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
1857 #else
1858 FIXME("using auto handle - call NdrNsReceive when it gets implemented\n");
1859 #endif
1860 else
1862 status = I_RpcReceive(pStubMsg->RpcMsg);
1863 if (status != RPC_S_OK)
1864 goto cleanup;
1865 pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;
1866 pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
1867 pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
1868 pStubMsg->Buffer = pStubMsg->BufferStart;
1871 /* convert strings, floating point values and endianness into our
1872 * preferred format */
1873 #if 0
1874 if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1875 NdrConvert(pStubMsg, pFormat);
1876 #endif
1878 /* 2. UNMARSHAL */
1879 TRACE( "UNMARSHAL\n" );
1880 client_do_args(pStubMsg, async_call_data->pParamFormat, STUBLESS_UNMARSHAL,
1881 NULL, async_call_data->number_of_params, Reply);
1883 cleanup:
1884 if (pStubMsg->fHasNewCorrDesc)
1886 /* free extra correlation package */
1887 NdrCorrelationFree(pStubMsg);
1890 /* free the full pointer translation tables */
1891 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1892 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
1894 /* free marshalling buffer */
1895 NdrFreeBuffer(pStubMsg);
1896 client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding);
1898 I_RpcFree(pStubMsg->StackTop);
1899 I_RpcFree(async_call_data);
1901 TRACE("-- 0x%lx\n", status);
1902 return status;
1905 #ifdef __x86_64__
1907 __ASM_GLOBAL_FUNC( NdrAsyncClientCall,
1908 "subq $0x28,%rsp\n\t"
1909 __ASM_SEH(".seh_stackalloc 0x28\n\t")
1910 __ASM_SEH(".seh_endprologue\n\t")
1911 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
1912 "movq %r8,0x40(%rsp)\n\t"
1913 "movq %r9,0x48(%rsp)\n\t"
1914 "leaq 0x40(%rsp),%r8\n\t"
1915 "call " __ASM_NAME("ndr_async_client_call") "\n\t"
1916 "addq $0x28,%rsp\n\t"
1917 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
1918 "ret" );
1920 #else /* __x86_64__ */
1922 /***********************************************************************
1923 * NdrAsyncClientCall [RPCRT4.@]
1925 CLIENT_CALL_RETURN WINAPIV NdrAsyncClientCall( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... )
1927 va_list args;
1928 LONG_PTR ret;
1930 va_start( args, format );
1931 ret = ndr_async_client_call( desc, format, va_arg( args, void ** ));
1932 va_end( args );
1933 return *(CLIENT_CALL_RETURN *)&ret;
1936 #endif /* __x86_64__ */
1938 RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis,
1939 struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg,
1940 DWORD * pdwStubPhase)
1942 FIXME("unimplemented, expect crash!\n");
1943 return 0;
1946 void RPC_ENTRY NdrAsyncServerCall(PRPC_MESSAGE pRpcMsg)
1948 const MIDL_SERVER_INFO *pServerInfo;
1949 const MIDL_STUB_DESC *pStubDesc;
1950 PFORMAT_STRING pFormat;
1951 /* pointer to start of stack to pass into stub implementation */
1952 unsigned char *args;
1953 /* header for procedure string */
1954 const NDR_PROC_HEADER *pProcHeader;
1955 struct async_call_data *async_call_data;
1956 PRPC_ASYNC_STATE pAsync;
1957 RPC_STATUS status;
1959 TRACE("%p\n", pRpcMsg);
1961 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1963 pStubDesc = pServerInfo->pStubDesc;
1964 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1965 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1967 TRACE("NDR Version: 0x%lx\n", pStubDesc->Version);
1969 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
1970 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY);
1971 async_call_data->pProcHeader = pProcHeader;
1973 async_call_data->pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
1974 *(PRPC_MESSAGE)(async_call_data->pStubMsg + 1) = *pRpcMsg;
1976 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1978 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1979 async_call_data->stack_size = header_rpc->stack_size;
1980 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1982 else
1984 async_call_data->stack_size = pProcHeader->stack_size;
1985 pFormat += sizeof(NDR_PROC_HEADER);
1988 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1990 /* binding */
1991 switch (pProcHeader->handle_type)
1993 /* explicit binding: parse additional section */
1994 case 0:
1995 switch (*pFormat) /* handle_type */
1997 case FC_BIND_PRIMITIVE: /* explicit primitive */
1998 pFormat += sizeof(NDR_EHD_PRIMITIVE);
1999 break;
2000 case FC_BIND_GENERIC: /* explicit generic */
2001 pFormat += sizeof(NDR_EHD_GENERIC);
2002 break;
2003 case FC_BIND_CONTEXT: /* explicit context */
2004 pFormat += sizeof(NDR_EHD_CONTEXT);
2005 break;
2006 default:
2007 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
2008 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2010 break;
2011 case FC_BIND_GENERIC: /* implicit generic */
2012 case FC_BIND_PRIMITIVE: /* implicit primitive */
2013 case FC_CALLBACK_HANDLE: /* implicit callback */
2014 case FC_AUTO_HANDLE: /* implicit auto handle */
2015 break;
2016 default:
2017 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
2018 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2021 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
2023 ERR("objects not supported\n");
2024 I_RpcFree(async_call_data);
2025 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2028 NdrServerInitializeNew(pRpcMsg, async_call_data->pStubMsg, pStubDesc);
2030 /* create the full pointer translation tables, if requested */
2031 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
2032 async_call_data->pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0, XLAT_SERVER);
2034 /* use alternate memory allocation routines */
2035 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
2036 #if 0
2037 NdrRpcSsEnableAllocate(&stubMsg);
2038 #else
2039 FIXME("Set RPCSS memory allocation routines\n");
2040 #endif
2042 TRACE("allocating memory for stack of size %x\n", async_call_data->stack_size);
2044 args = calloc(1, async_call_data->stack_size);
2045 async_call_data->pStubMsg->StackTop = args; /* used by conformance of top-level objects */
2047 pAsync = I_RpcAllocate(sizeof(*pAsync));
2048 if (!pAsync) RpcRaiseException(RPC_X_NO_MEMORY);
2050 status = RpcAsyncInitializeHandle(pAsync, sizeof(*pAsync));
2051 if (status != RPC_S_OK)
2052 RpcRaiseException(status);
2054 pAsync->StubInfo = async_call_data;
2055 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat);
2057 /* add the implicit pAsync pointer as the first arg to the function */
2058 *(void **)args = pAsync;
2060 if (is_oicf_stubdesc(pStubDesc))
2062 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
2063 /* cache of Oif_flags from v2 procedure header */
2064 INTERPRETER_OPT_FLAGS Oif_flags;
2065 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
2066 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
2068 Oif_flags = pOIFHeader->Oi2Flags;
2069 async_call_data->number_of_params = pOIFHeader->number_of_params;
2071 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
2073 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
2075 if (Oif_flags.HasExtensions)
2077 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
2078 ext_flags = pExtensions->Flags2;
2079 pFormat += pExtensions->Size;
2082 if (Oif_flags.HasPipes)
2084 FIXME("pipes not supported yet\n");
2085 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
2086 /* init pipes package */
2087 /* NdrPipesInitialize(...) */
2089 if (ext_flags.HasNewCorrDesc)
2091 /* initialize extra correlation package */
2092 NdrCorrelationInitialize(async_call_data->pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
2093 if (ext_flags.Unused & 0x2) /* has range on conformance */
2094 async_call_data->pStubMsg->CorrDespIncrement = 12;
2097 else
2099 pFormat = convert_old_args( async_call_data->pStubMsg, pFormat, async_call_data->stack_size,
2100 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
2101 /* reuse the correlation cache, it's not needed for v1 format */
2102 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), &async_call_data->number_of_params );
2105 /* convert strings, floating point values and endianness into our
2106 * preferred format */
2107 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
2108 NdrConvert(async_call_data->pStubMsg, pFormat);
2110 async_call_data->pHandleFormat = pFormat;
2112 /* 1. UNMARSHAL */
2113 TRACE("UNMARSHAL\n");
2114 stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_UNMARSHAL, async_call_data->number_of_params);
2116 /* 2. INITOUT */
2117 TRACE("INITOUT\n");
2118 async_call_data->retval_ptr = stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_INITOUT, async_call_data->number_of_params);
2120 /* 3. CALLSERVER */
2121 TRACE("CALLSERVER\n");
2122 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
2123 pServerInfo->ThunkTable[pRpcMsg->ProcNum](async_call_data->pStubMsg);
2124 else
2125 call_server_func(pServerInfo->DispatchTable[pRpcMsg->ProcNum], args, async_call_data->stack_size);
2128 RPC_STATUS NdrpCompleteAsyncServerCall(RPC_ASYNC_STATE *pAsync, void *Reply)
2130 /* pointer to start of stack where arguments start */
2131 PMIDL_STUB_MESSAGE pStubMsg;
2132 struct async_call_data *async_call_data;
2133 /* the type of pass we are currently doing */
2134 enum stubless_phase phase;
2135 RPC_STATUS status = RPC_S_OK;
2137 if (!pAsync->StubInfo)
2138 return RPC_S_INVALID_ASYNC_HANDLE;
2140 async_call_data = pAsync->StubInfo;
2141 pStubMsg = async_call_data->pStubMsg;
2143 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat);
2145 if (async_call_data->retval_ptr)
2147 TRACE("stub implementation returned 0x%Ix\n", *(LONG_PTR *)Reply);
2148 *async_call_data->retval_ptr = *(LONG_PTR *)Reply;
2150 else
2151 TRACE("void stub implementation\n");
2153 for (phase = STUBLESS_CALCSIZE; phase <= STUBLESS_FREE; phase++)
2155 TRACE("phase = %d\n", phase);
2156 switch (phase)
2158 case STUBLESS_GETBUFFER:
2159 if (async_call_data->pProcHeader->Oi_flags & Oi_OBJECT_PROC)
2161 ERR("objects not supported\n");
2162 free(async_call_data->pStubMsg->StackTop);
2163 I_RpcFree(async_call_data);
2164 I_RpcFree(pAsync);
2165 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2167 else
2169 pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength;
2170 /* allocate buffer for [out] and [ret] params */
2171 status = I_RpcGetBuffer(pStubMsg->RpcMsg);
2172 if (status)
2173 RpcRaiseException(status);
2174 pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer;
2176 break;
2178 case STUBLESS_CALCSIZE:
2179 case STUBLESS_MARSHAL:
2180 case STUBLESS_MUSTFREE:
2181 case STUBLESS_FREE:
2182 stub_do_args(pStubMsg, async_call_data->pHandleFormat, phase, async_call_data->number_of_params);
2183 break;
2184 default:
2185 ERR("shouldn't reach here. phase %d\n", phase);
2186 break;
2190 #if 0 /* FIXME */
2191 if (ext_flags.HasNewCorrDesc)
2193 /* free extra correlation package */
2194 NdrCorrelationFree(pStubMsg);
2197 if (Oif_flags.HasPipes)
2199 /* NdrPipesDone(...) */
2202 /* free the full pointer translation tables */
2203 if (async_call_data->pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
2204 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
2205 #endif
2207 /* free server function stack */
2208 free(async_call_data->pStubMsg->StackTop);
2209 I_RpcFree(async_call_data);
2210 I_RpcFree(pAsync);
2212 return S_OK;
2215 static const RPC_SYNTAX_IDENTIFIER ndr_syntax_id =
2216 {{0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60}}, {2, 0}};
2218 LONG_PTR CDECL DECLSPEC_HIDDEN ndr64_client_call( MIDL_STUBLESS_PROXY_INFO *info,
2219 ULONG proc, void *retval, void **stack_top, void **fpu_stack )
2221 ULONG_PTR i;
2223 TRACE("info %p, proc %lu, retval %p, stack_top %p, fpu_stack %p\n",
2224 info, proc, retval, stack_top, fpu_stack);
2226 for (i = 0; i < info->nCount; ++i)
2228 const MIDL_SYNTAX_INFO *syntax_info = &info->pSyntaxInfo[i];
2229 const RPC_SYNTAX_IDENTIFIER *id = &syntax_info->TransferSyntax;
2231 TRACE("Found syntax %s, version %u.%u.\n", debugstr_guid(&id->SyntaxGUID),
2232 id->SyntaxVersion.MajorVersion, id->SyntaxVersion.MinorVersion);
2233 if (!memcmp(id, &ndr_syntax_id, sizeof(RPC_SYNTAX_IDENTIFIER)))
2235 if (retval)
2236 FIXME("Complex return types are not supported.\n");
2238 return ndr_client_call( info->pStubDesc,
2239 syntax_info->ProcString + syntax_info->FmtStringOffset[proc], stack_top, fpu_stack );
2243 FIXME("NDR64 syntax is not supported.\n");
2244 return 0;
2247 #ifdef __x86_64__
2249 __ASM_GLOBAL_FUNC( NdrClientCall3,
2250 "subq $0x28,%rsp\n\t"
2251 __ASM_SEH(".seh_stackalloc 0x28\n\t")
2252 __ASM_SEH(".seh_endprologue\n\t")
2253 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
2254 "movq %r9,0x48(%rsp)\n\t"
2255 "leaq 0x48(%rsp),%r9\n\t"
2256 "movq $0,0x20(%rsp)\n\t"
2257 "call " __ASM_NAME("ndr64_client_call") "\n\t"
2258 "addq $0x28,%rsp\n\t"
2259 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
2260 "ret" );
2262 #elif defined(_WIN64)
2264 /***********************************************************************
2265 * NdrClientCall3 [RPCRT4.@]
2267 CLIENT_CALL_RETURN WINAPIV NdrClientCall3( MIDL_STUBLESS_PROXY_INFO *info, ULONG proc, void *retval, ... )
2269 va_list args;
2270 LONG_PTR ret;
2272 va_start( args, retval );
2273 ret = ndr64_client_call( info, proc, retval, va_arg( args, void ** ), NULL );
2274 va_end( args );
2275 return *(CLIENT_CALL_RETURN *)&ret;
2278 #endif
2280 LONG_PTR CDECL DECLSPEC_HIDDEN ndr64_async_client_call( MIDL_STUBLESS_PROXY_INFO *info,
2281 ULONG proc, void *retval, void **stack_top, void **fpu_stack )
2283 ULONG_PTR i;
2285 TRACE("info %p, proc %lu, retval %p, stack_top %p, fpu_stack %p\n",
2286 info, proc, retval, stack_top, fpu_stack);
2288 for (i = 0; i < info->nCount; ++i)
2290 const MIDL_SYNTAX_INFO *syntax_info = &info->pSyntaxInfo[i];
2291 const RPC_SYNTAX_IDENTIFIER *id = &syntax_info->TransferSyntax;
2293 TRACE("Found syntax %s, version %u.%u.\n", debugstr_guid(&id->SyntaxGUID),
2294 id->SyntaxVersion.MajorVersion, id->SyntaxVersion.MinorVersion);
2295 if (!memcmp(id, &ndr_syntax_id, sizeof(RPC_SYNTAX_IDENTIFIER)))
2297 if (retval)
2298 FIXME("Complex return types are not supported.\n");
2300 return ndr_async_client_call( info->pStubDesc,
2301 syntax_info->ProcString + syntax_info->FmtStringOffset[proc], stack_top );
2305 FIXME("NDR64 syntax is not supported.\n");
2306 return 0;
2309 #ifdef __x86_64__
2311 __ASM_GLOBAL_FUNC( Ndr64AsyncClientCall,
2312 "subq $0x28,%rsp\n\t"
2313 __ASM_SEH(".seh_stackalloc 0x28\n\t")
2314 __ASM_SEH(".seh_endprologue\n\t")
2315 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
2316 "movq %r9,0x48(%rsp)\n\t"
2317 "leaq 0x48(%rsp),%r9\n\t"
2318 "movq $0,0x20(%rsp)\n\t"
2319 "call " __ASM_NAME("ndr64_async_client_call") "\n\t"
2320 "addq $0x28,%rsp\n\t"
2321 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
2322 "ret" );
2324 #elif defined(_WIN64)
2326 /***********************************************************************
2327 * Ndr64AsyncClientCall [RPCRT4.@]
2329 CLIENT_CALL_RETURN WINAPIV Ndr64AsyncClientCall( MIDL_STUBLESS_PROXY_INFO *info, ULONG proc, void *retval, ... )
2331 va_list args;
2332 LONG_PTR ret;
2334 va_start( args, retval );
2335 ret = ndr64_async_client_call( info, proc, retval, va_arg( args, void ** ), NULL );
2336 va_end( args );
2337 return *(CLIENT_CALL_RETURN *)&ret;
2340 #endif