windows.applicationmodel/tests: Use PathRemoveFileSpecW() instead of PathCchRemoveFil...
[wine.git] / dlls / rpcrt4 / ndr_stubless.c
blob2e84d64bba5dc62921b6ed448c81996afa8a29c8
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 __ASM_SEH(".seh_save_fplr_x 16\n\t")
1185 "mov x29, sp\n\t"
1186 __ASM_SEH(".seh_set_fp\n\t")
1187 __ASM_SEH(".seh_endprologue\n\t")
1188 "add x9, x2, #15\n\t"
1189 "lsr x9, x9, #4\n\t"
1190 "sub sp, sp, x9, lsl #4\n\t"
1191 "cbz x2, 2f\n"
1192 "1:\tsub x2, x2, #8\n\t"
1193 "ldr x4, [x1, x2]\n\t"
1194 "str x4, [sp, x2]\n\t"
1195 "cbnz x2, 1b\n"
1196 "2:\tmov x8, x0\n\t"
1197 "cbz x9, 3f\n\t"
1198 "ldp x0, x1, [sp], #16\n\t"
1199 "cmp x9, #1\n\t"
1200 "b.le 3f\n\t"
1201 "ldp x2, x3, [sp], #16\n\t"
1202 "cmp x9, #2\n\t"
1203 "b.le 3f\n\t"
1204 "ldp x4, x5, [sp], #16\n\t"
1205 "cmp x9, #3\n\t"
1206 "b.le 3f\n\t"
1207 "ldp x6, x7, [sp], #16\n"
1208 "3:\tblr x8\n\t"
1209 "mov sp, x29\n\t"
1210 "ldp x29, x30, [sp], #16\n\t"
1211 "ret" )
1212 #else
1213 #warning call_server_func not implemented for your architecture
1214 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
1216 FIXME("Not implemented for your architecture\n");
1217 return 0;
1219 #endif
1221 static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg,
1222 PFORMAT_STRING pFormat, enum stubless_phase phase,
1223 unsigned short number_of_params)
1225 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat;
1226 unsigned int i;
1227 LONG_PTR *retval_ptr = NULL;
1229 for (i = 0; i < number_of_params; i++)
1231 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset;
1232 const unsigned char *pTypeFormat = &pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset];
1234 TRACE("param[%d]: %p -> %p type %02x %s\n", i,
1235 pArg, *(unsigned char **)pArg,
1236 params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat,
1237 debugstr_PROC_PF( params[i].attr ));
1239 switch (phase)
1241 case STUBLESS_MARSHAL:
1242 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1243 call_marshaller(pStubMsg, pArg, &params[i]);
1244 break;
1245 case STUBLESS_MUSTFREE:
1246 if (params[i].attr.MustFree)
1248 call_freer(pStubMsg, pArg, &params[i]);
1250 break;
1251 case STUBLESS_FREE:
1252 if (params[i].attr.ServerAllocSize)
1254 free(*(void **)pArg);
1256 else if (param_needs_alloc(params[i].attr) &&
1257 (!params[i].attr.MustFree || params[i].attr.IsSimpleRef))
1259 if (*pTypeFormat != FC_BIND_CONTEXT) pStubMsg->pfnFree(*(void **)pArg);
1261 break;
1262 case STUBLESS_INITOUT:
1263 if (param_needs_alloc(params[i].attr) && !params[i].attr.ServerAllocSize)
1265 if (*pTypeFormat == FC_BIND_CONTEXT)
1267 NDR_SCONTEXT ctxt = NdrContextHandleInitialize(pStubMsg, pTypeFormat);
1268 *(void **)pArg = NDRSContextValue(ctxt);
1269 if (params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)NDRSContextValue(ctxt);
1271 else
1273 DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
1274 if (size)
1276 *(void **)pArg = NdrAllocate(pStubMsg, size);
1277 memset(*(void **)pArg, 0, size);
1281 if (!retval_ptr && params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)pArg;
1282 break;
1283 case STUBLESS_UNMARSHAL:
1284 if (params[i].attr.ServerAllocSize)
1285 *(void **)pArg = calloc(params[i].attr.ServerAllocSize, 8);
1287 if (params[i].attr.IsIn)
1288 call_unmarshaller(pStubMsg, &pArg, &params[i], 0);
1289 break;
1290 case STUBLESS_CALCSIZE:
1291 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1292 call_buffer_sizer(pStubMsg, pArg, &params[i]);
1293 break;
1294 default:
1295 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1297 TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
1299 return retval_ptr;
1302 /***********************************************************************
1303 * NdrStubCall2 [RPCRT4.@]
1305 * Unmarshals [in] parameters, calls either a method in an object or a server
1306 * function, marshals any [out] parameters and frees any allocated data.
1308 * NOTES
1309 * Used by stubless MIDL-generated code.
1311 LONG WINAPI NdrStubCall2(
1312 struct IRpcStubBuffer * pThis,
1313 struct IRpcChannelBuffer * pChannel,
1314 PRPC_MESSAGE pRpcMsg,
1315 DWORD * pdwStubPhase)
1317 const MIDL_SERVER_INFO *pServerInfo;
1318 const MIDL_STUB_DESC *pStubDesc;
1319 PFORMAT_STRING pFormat;
1320 MIDL_STUB_MESSAGE stubMsg;
1321 /* pointer to start of stack to pass into stub implementation */
1322 unsigned char * args;
1323 /* size of stack */
1324 unsigned short stack_size;
1325 /* number of parameters. optional for client to give it to us */
1326 unsigned int number_of_params;
1327 /* cache of Oif_flags from v2 procedure header */
1328 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1329 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1330 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1331 /* the type of pass we are currently doing */
1332 enum stubless_phase phase;
1333 /* header for procedure string */
1334 const NDR_PROC_HEADER *pProcHeader;
1335 /* location to put retval into */
1336 LONG_PTR *retval_ptr = NULL;
1337 /* correlation cache */
1338 ULONG_PTR NdrCorrCache[256];
1340 TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase);
1342 if (pThis)
1343 pServerInfo = CStdStubBuffer_GetServerInfo(pThis);
1344 else
1345 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1347 pStubDesc = pServerInfo->pStubDesc;
1348 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1349 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1351 TRACE("NDR Version: 0x%lx\n", pStubDesc->Version);
1353 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1355 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1356 stack_size = header_rpc->stack_size;
1357 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1360 else
1362 stack_size = pProcHeader->stack_size;
1363 pFormat += sizeof(NDR_PROC_HEADER);
1366 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1368 /* binding */
1369 switch (pProcHeader->handle_type)
1371 /* explicit binding: parse additional section */
1372 case 0:
1373 switch (*pFormat) /* handle_type */
1375 case FC_BIND_PRIMITIVE: /* explicit primitive */
1376 pFormat += sizeof(NDR_EHD_PRIMITIVE);
1377 break;
1378 case FC_BIND_GENERIC: /* explicit generic */
1379 pFormat += sizeof(NDR_EHD_GENERIC);
1380 break;
1381 case FC_BIND_CONTEXT: /* explicit context */
1382 pFormat += sizeof(NDR_EHD_CONTEXT);
1383 break;
1384 default:
1385 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1386 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1388 break;
1389 case FC_BIND_GENERIC: /* implicit generic */
1390 case FC_BIND_PRIMITIVE: /* implicit primitive */
1391 case FC_CALLBACK_HANDLE: /* implicit callback */
1392 case FC_AUTO_HANDLE: /* implicit auto handle */
1393 break;
1394 default:
1395 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1396 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1399 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1400 NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel);
1401 else
1402 NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc);
1404 /* create the full pointer translation tables, if requested */
1405 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1406 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
1408 /* store the RPC flags away */
1409 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1410 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1412 /* use alternate memory allocation routines */
1413 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
1414 #if 0
1415 NdrRpcSsEnableAllocate(&stubMsg);
1416 #else
1417 FIXME("Set RPCSS memory allocation routines\n");
1418 #endif
1420 TRACE("allocating memory for stack of size %x\n", stack_size);
1422 args = calloc(1, stack_size);
1423 stubMsg.StackTop = args; /* used by conformance of top-level objects */
1425 /* add the implicit This pointer as the first arg to the function if we
1426 * are calling an object method */
1427 if (pThis)
1428 *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject;
1430 if (is_oicf_stubdesc(pStubDesc))
1432 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
1434 Oif_flags = pOIFHeader->Oi2Flags;
1435 number_of_params = pOIFHeader->number_of_params;
1437 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1439 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
1441 if (Oif_flags.HasExtensions)
1443 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
1444 ext_flags = pExtensions->Flags2;
1445 pFormat += pExtensions->Size;
1448 if (Oif_flags.HasPipes)
1450 FIXME("pipes not supported yet\n");
1451 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1452 /* init pipes package */
1453 /* NdrPipesInitialize(...) */
1455 if (ext_flags.HasNewCorrDesc)
1457 /* initialize extra correlation package */
1458 NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0);
1459 if (ext_flags.Unused & 0x2) /* has range on conformance */
1460 stubMsg.CorrDespIncrement = 12;
1463 else
1465 pFormat = convert_old_args( &stubMsg, pFormat, stack_size,
1466 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
1467 /* reuse the correlation cache, it's not needed for v1 format */
1468 NdrCorrCache, sizeof(NdrCorrCache), &number_of_params );
1471 /* convert strings, floating point values and endianness into our
1472 * preferred format */
1473 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1474 NdrConvert(&stubMsg, pFormat);
1476 for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++)
1478 TRACE("phase = %d\n", phase);
1479 switch (phase)
1481 case STUBLESS_CALLSERVER:
1482 /* call the server function */
1483 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
1484 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg);
1485 else
1487 SERVER_ROUTINE func;
1488 LONG_PTR retval;
1490 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1492 SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject;
1493 func = vtbl[pRpcMsg->ProcNum];
1495 else
1496 func = pServerInfo->DispatchTable[pRpcMsg->ProcNum];
1498 /* FIXME: what happens with return values that don't fit into a single register on x86? */
1499 retval = call_server_func(func, args, stack_size);
1501 if (retval_ptr)
1503 TRACE("stub implementation returned 0x%Ix\n", retval);
1504 *retval_ptr = retval;
1506 else
1507 TRACE("void stub implementation\n");
1510 stubMsg.Buffer = NULL;
1511 stubMsg.BufferLength = 0;
1513 break;
1514 case STUBLESS_GETBUFFER:
1515 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1516 NdrStubGetBuffer(pThis, pChannel, &stubMsg);
1517 else
1519 RPC_STATUS Status;
1521 pRpcMsg->BufferLength = stubMsg.BufferLength;
1522 /* allocate buffer for [out] and [ret] params */
1523 Status = I_RpcGetBuffer(pRpcMsg);
1524 if (Status)
1525 RpcRaiseException(Status);
1526 stubMsg.Buffer = pRpcMsg->Buffer;
1528 break;
1529 case STUBLESS_UNMARSHAL:
1530 case STUBLESS_INITOUT:
1531 case STUBLESS_CALCSIZE:
1532 case STUBLESS_MARSHAL:
1533 case STUBLESS_MUSTFREE:
1534 case STUBLESS_FREE:
1535 retval_ptr = stub_do_args(&stubMsg, pFormat, phase, number_of_params);
1536 break;
1537 default:
1538 ERR("shouldn't reach here. phase %d\n", phase);
1539 break;
1543 pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer);
1545 if (ext_flags.HasNewCorrDesc)
1547 /* free extra correlation package */
1548 NdrCorrelationFree(&stubMsg);
1551 if (Oif_flags.HasPipes)
1553 /* NdrPipesDone(...) */
1556 /* free the full pointer translation tables */
1557 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1558 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
1560 /* free server function stack */
1561 free(args);
1563 return S_OK;
1566 /***********************************************************************
1567 * NdrServerCall2 [RPCRT4.@]
1569 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
1571 DWORD dwPhase;
1572 NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
1575 /***********************************************************************
1576 * NdrStubCall [RPCRT4.@]
1578 LONG WINAPI NdrStubCall( struct IRpcStubBuffer *This, struct IRpcChannelBuffer *channel,
1579 PRPC_MESSAGE msg, DWORD *phase )
1581 return NdrStubCall2( This, channel, msg, phase );
1584 /***********************************************************************
1585 * NdrServerCall [RPCRT4.@]
1587 void WINAPI NdrServerCall( PRPC_MESSAGE msg )
1589 DWORD phase;
1590 NdrStubCall( NULL, NULL, msg, &phase );
1593 /***********************************************************************
1594 * NdrServerCallAll [RPCRT4.@]
1596 void WINAPI NdrServerCallAll( PRPC_MESSAGE msg )
1598 FIXME("%p stub\n", msg);
1601 /* Helper for ndr_async_client_call, to factor out the part that may or may not be
1602 * guarded by a try/except block. */
1603 static void do_ndr_async_client_call( const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormat, void **stack_top )
1605 /* pointer to start of stack where arguments start */
1606 PRPC_MESSAGE pRpcMsg;
1607 PMIDL_STUB_MESSAGE pStubMsg;
1608 RPC_ASYNC_STATE *pAsync;
1609 struct async_call_data *async_call_data;
1610 /* procedure number */
1611 unsigned short procedure_number;
1612 /* cache of Oif_flags from v2 procedure header */
1613 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1614 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1615 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1616 /* header for procedure string */
1617 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1618 RPC_STATUS status;
1620 /* Later NDR language versions probably won't be backwards compatible */
1621 if (pStubDesc->Version > 0x60001)
1623 FIXME("Incompatible stub description version: 0x%lx\n", pStubDesc->Version);
1624 RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
1627 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
1628 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY);
1629 async_call_data->pProcHeader = pProcHeader;
1631 async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
1632 pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1);
1634 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1636 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1637 async_call_data->stack_size = header_rpc->stack_size;
1638 procedure_number = header_rpc->proc_num;
1639 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1641 else
1643 async_call_data->stack_size = pProcHeader->stack_size;
1644 procedure_number = pProcHeader->proc_num;
1645 pFormat += sizeof(NDR_PROC_HEADER);
1647 TRACE("stack size: 0x%x\n", async_call_data->stack_size);
1648 TRACE("proc num: %d\n", procedure_number);
1650 /* create the full pointer translation tables, if requested */
1651 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1652 pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
1654 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
1656 ERR("objects not supported\n");
1657 I_RpcFree(async_call_data);
1658 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1661 NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number);
1663 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1664 TRACE("MIDL stub version = 0x%lx\n", pStubDesc->MIDLVersion);
1666 /* needed for conformance of top-level objects */
1667 pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size);
1668 memcpy(pStubMsg->StackTop, stack_top, async_call_data->stack_size);
1670 pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop;
1671 pAsync->StubInfo = async_call_data;
1672 async_call_data->pHandleFormat = pFormat;
1674 TRACE("pAsync %p, pAsync->StubInfo %p, NotificationType %d\n", pAsync, pAsync->StubInfo, pAsync->NotificationType);
1676 pFormat += get_handle_desc_size(pProcHeader, pFormat);
1677 async_call_data->hBinding = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat);
1678 if (!async_call_data->hBinding) return;
1680 if (is_oicf_stubdesc(pStubDesc))
1682 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
1683 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
1685 Oif_flags = pOIFHeader->Oi2Flags;
1686 async_call_data->number_of_params = pOIFHeader->number_of_params;
1688 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1690 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
1692 if (Oif_flags.HasExtensions)
1694 const NDR_PROC_HEADER_EXTS *pExtensions =
1695 (const NDR_PROC_HEADER_EXTS *)pFormat;
1696 ext_flags = pExtensions->Flags2;
1697 pFormat += pExtensions->Size;
1700 else
1702 pFormat = convert_old_args( pStubMsg, pFormat, async_call_data->stack_size,
1703 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
1704 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache),
1705 &async_call_data->number_of_params );
1708 async_call_data->pParamFormat = pFormat;
1710 pStubMsg->BufferLength = 0;
1712 /* store the RPC flags away */
1713 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1714 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1716 /* use alternate memory allocation routines */
1717 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
1718 NdrRpcSmSetClientToOsf(pStubMsg);
1720 if (Oif_flags.HasPipes)
1722 FIXME("pipes not supported yet\n");
1723 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1724 /* init pipes package */
1725 /* NdrPipesInitialize(...) */
1727 if (ext_flags.HasNewCorrDesc)
1729 /* initialize extra correlation package */
1730 NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
1731 if (ext_flags.Unused & 0x2) /* has range on conformance */
1732 pStubMsg->CorrDespIncrement = 12;
1735 /* order of phases:
1736 * 1. CALCSIZE - calculate the buffer size
1737 * 2. GETBUFFER - allocate the buffer
1738 * 3. MARSHAL - marshal [in] params into the buffer
1739 * 4. SENDRECEIVE - send buffer
1740 * Then in NdrpCompleteAsyncClientCall:
1741 * 1. SENDRECEIVE - receive buffer
1742 * 2. UNMARSHAL - unmarshal [out] params from buffer
1745 /* 1. CALCSIZE */
1746 TRACE( "CALCSIZE\n" );
1747 client_do_args(pStubMsg, pFormat, STUBLESS_CALCSIZE, NULL, async_call_data->number_of_params, NULL);
1749 /* 2. GETBUFFER */
1750 TRACE( "GETBUFFER\n" );
1751 if (Oif_flags.HasPipes)
1752 /* NdrGetPipeBuffer(...) */
1753 FIXME("pipes not supported yet\n");
1754 else
1756 if (pProcHeader->handle_type == FC_AUTO_HANDLE)
1757 #if 0
1758 NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1759 #else
1760 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
1761 #endif
1762 else
1763 NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1765 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1766 status = I_RpcAsyncSetHandle(pRpcMsg, pAsync);
1767 if (status != RPC_S_OK)
1768 RpcRaiseException(status);
1770 /* 3. MARSHAL */
1771 TRACE( "MARSHAL\n" );
1772 client_do_args(pStubMsg, pFormat, STUBLESS_MARSHAL, NULL, async_call_data->number_of_params, NULL);
1774 /* 4. SENDRECEIVE */
1775 TRACE( "SEND\n" );
1776 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1777 /* send the [in] params only */
1778 if (Oif_flags.HasPipes)
1779 /* NdrPipesSend(...) */
1780 FIXME("pipes not supported yet\n");
1781 else
1783 if (pProcHeader->handle_type == FC_AUTO_HANDLE)
1784 #if 0
1785 NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
1786 #else
1787 FIXME("using auto handle - call NdrNsSend when it gets implemented\n");
1788 #endif
1789 else
1791 pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
1792 status = I_RpcSend(pStubMsg->RpcMsg);
1793 if (status != RPC_S_OK)
1794 RpcRaiseException(status);
1799 LONG_PTR CDECL DECLSPEC_HIDDEN ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat,
1800 void **stack_top )
1802 LONG_PTR ret = 0;
1803 const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1805 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
1807 if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT)
1809 __TRY
1811 do_ndr_async_client_call( pStubDesc, pFormat, stack_top );
1813 __EXCEPT_ALL
1815 FIXME("exception %lx during ndr_async_client_call()\n", GetExceptionCode());
1816 ret = GetExceptionCode();
1818 __ENDTRY
1820 else
1821 do_ndr_async_client_call( pStubDesc, pFormat, stack_top);
1823 TRACE("returning %Id\n", ret);
1824 return ret;
1827 RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
1829 /* pointer to start of stack where arguments start */
1830 PMIDL_STUB_MESSAGE pStubMsg;
1831 struct async_call_data *async_call_data;
1832 /* header for procedure string */
1833 const NDR_PROC_HEADER * pProcHeader;
1834 RPC_STATUS status = RPC_S_OK;
1836 if (!pAsync->StubInfo)
1837 return RPC_S_INVALID_ASYNC_HANDLE;
1839 async_call_data = pAsync->StubInfo;
1840 pStubMsg = async_call_data->pStubMsg;
1841 pProcHeader = async_call_data->pProcHeader;
1843 /* order of phases:
1844 * 1. CALCSIZE - calculate the buffer size
1845 * 2. GETBUFFER - allocate the buffer
1846 * 3. MARSHAL - marshal [in] params into the buffer
1847 * 4. SENDRECEIVE - send buffer
1848 * Then in NdrpCompleteAsyncClientCall:
1849 * 1. SENDRECEIVE - receive buffer
1850 * 2. UNMARSHAL - unmarshal [out] params from buffer
1853 /* 1. SENDRECEIVE */
1854 TRACE( "RECEIVE\n" );
1855 pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1856 /* receive the [out] params */
1857 if (pProcHeader->handle_type == FC_AUTO_HANDLE)
1858 #if 0
1859 NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
1860 #else
1861 FIXME("using auto handle - call NdrNsReceive when it gets implemented\n");
1862 #endif
1863 else
1865 status = I_RpcReceive(pStubMsg->RpcMsg);
1866 if (status != RPC_S_OK)
1867 goto cleanup;
1868 pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;
1869 pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
1870 pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
1871 pStubMsg->Buffer = pStubMsg->BufferStart;
1874 /* convert strings, floating point values and endianness into our
1875 * preferred format */
1876 #if 0
1877 if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1878 NdrConvert(pStubMsg, pFormat);
1879 #endif
1881 /* 2. UNMARSHAL */
1882 TRACE( "UNMARSHAL\n" );
1883 client_do_args(pStubMsg, async_call_data->pParamFormat, STUBLESS_UNMARSHAL,
1884 NULL, async_call_data->number_of_params, Reply);
1886 cleanup:
1887 if (pStubMsg->fHasNewCorrDesc)
1889 /* free extra correlation package */
1890 NdrCorrelationFree(pStubMsg);
1893 /* free the full pointer translation tables */
1894 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
1895 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
1897 /* free marshalling buffer */
1898 NdrFreeBuffer(pStubMsg);
1899 client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding);
1901 I_RpcFree(pStubMsg->StackTop);
1902 I_RpcFree(async_call_data);
1904 TRACE("-- 0x%lx\n", status);
1905 return status;
1908 #ifdef __x86_64__
1910 __ASM_GLOBAL_FUNC( NdrAsyncClientCall,
1911 "subq $0x28,%rsp\n\t"
1912 __ASM_SEH(".seh_stackalloc 0x28\n\t")
1913 __ASM_SEH(".seh_endprologue\n\t")
1914 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
1915 "movq %r8,0x40(%rsp)\n\t"
1916 "movq %r9,0x48(%rsp)\n\t"
1917 "leaq 0x40(%rsp),%r8\n\t"
1918 "call " __ASM_NAME("ndr_async_client_call") "\n\t"
1919 "addq $0x28,%rsp\n\t"
1920 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
1921 "ret" );
1923 #else /* __x86_64__ */
1925 /***********************************************************************
1926 * NdrAsyncClientCall [RPCRT4.@]
1928 CLIENT_CALL_RETURN WINAPIV NdrAsyncClientCall( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... )
1930 va_list args;
1931 LONG_PTR ret;
1933 va_start( args, format );
1934 ret = ndr_async_client_call( desc, format, va_arg( args, void ** ));
1935 va_end( args );
1936 return *(CLIENT_CALL_RETURN *)&ret;
1939 #endif /* __x86_64__ */
1941 RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis,
1942 struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg,
1943 DWORD * pdwStubPhase)
1945 FIXME("unimplemented, expect crash!\n");
1946 return 0;
1949 void RPC_ENTRY NdrAsyncServerCall(PRPC_MESSAGE pRpcMsg)
1951 const MIDL_SERVER_INFO *pServerInfo;
1952 const MIDL_STUB_DESC *pStubDesc;
1953 PFORMAT_STRING pFormat;
1954 /* pointer to start of stack to pass into stub implementation */
1955 unsigned char *args;
1956 /* header for procedure string */
1957 const NDR_PROC_HEADER *pProcHeader;
1958 struct async_call_data *async_call_data;
1959 PRPC_ASYNC_STATE pAsync;
1960 RPC_STATUS status;
1962 TRACE("%p\n", pRpcMsg);
1964 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1966 pStubDesc = pServerInfo->pStubDesc;
1967 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1968 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1970 TRACE("NDR Version: 0x%lx\n", pStubDesc->Version);
1972 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
1973 if (!async_call_data) RpcRaiseException(RPC_X_NO_MEMORY);
1974 async_call_data->pProcHeader = pProcHeader;
1976 async_call_data->pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
1977 *(PRPC_MESSAGE)(async_call_data->pStubMsg + 1) = *pRpcMsg;
1979 if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
1981 const NDR_PROC_HEADER_RPC *header_rpc = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1982 async_call_data->stack_size = header_rpc->stack_size;
1983 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1985 else
1987 async_call_data->stack_size = pProcHeader->stack_size;
1988 pFormat += sizeof(NDR_PROC_HEADER);
1991 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1993 /* binding */
1994 switch (pProcHeader->handle_type)
1996 /* explicit binding: parse additional section */
1997 case 0:
1998 switch (*pFormat) /* handle_type */
2000 case FC_BIND_PRIMITIVE: /* explicit primitive */
2001 pFormat += sizeof(NDR_EHD_PRIMITIVE);
2002 break;
2003 case FC_BIND_GENERIC: /* explicit generic */
2004 pFormat += sizeof(NDR_EHD_GENERIC);
2005 break;
2006 case FC_BIND_CONTEXT: /* explicit context */
2007 pFormat += sizeof(NDR_EHD_CONTEXT);
2008 break;
2009 default:
2010 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
2011 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2013 break;
2014 case FC_BIND_GENERIC: /* implicit generic */
2015 case FC_BIND_PRIMITIVE: /* implicit primitive */
2016 case FC_CALLBACK_HANDLE: /* implicit callback */
2017 case FC_AUTO_HANDLE: /* implicit auto handle */
2018 break;
2019 default:
2020 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
2021 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2024 if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
2026 ERR("objects not supported\n");
2027 I_RpcFree(async_call_data);
2028 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2031 NdrServerInitializeNew(pRpcMsg, async_call_data->pStubMsg, pStubDesc);
2033 /* create the full pointer translation tables, if requested */
2034 if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
2035 async_call_data->pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0, XLAT_SERVER);
2037 /* use alternate memory allocation routines */
2038 if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
2039 #if 0
2040 NdrRpcSsEnableAllocate(&stubMsg);
2041 #else
2042 FIXME("Set RPCSS memory allocation routines\n");
2043 #endif
2045 TRACE("allocating memory for stack of size %x\n", async_call_data->stack_size);
2047 args = calloc(1, async_call_data->stack_size);
2048 async_call_data->pStubMsg->StackTop = args; /* used by conformance of top-level objects */
2050 pAsync = I_RpcAllocate(sizeof(*pAsync));
2051 if (!pAsync) RpcRaiseException(RPC_X_NO_MEMORY);
2053 status = RpcAsyncInitializeHandle(pAsync, sizeof(*pAsync));
2054 if (status != RPC_S_OK)
2055 RpcRaiseException(status);
2057 pAsync->StubInfo = async_call_data;
2058 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat);
2060 /* add the implicit pAsync pointer as the first arg to the function */
2061 *(void **)args = pAsync;
2063 if (is_oicf_stubdesc(pStubDesc))
2065 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
2066 /* cache of Oif_flags from v2 procedure header */
2067 INTERPRETER_OPT_FLAGS Oif_flags;
2068 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
2069 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
2071 Oif_flags = pOIFHeader->Oi2Flags;
2072 async_call_data->number_of_params = pOIFHeader->number_of_params;
2074 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
2076 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
2078 if (Oif_flags.HasExtensions)
2080 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
2081 ext_flags = pExtensions->Flags2;
2082 pFormat += pExtensions->Size;
2085 if (Oif_flags.HasPipes)
2087 FIXME("pipes not supported yet\n");
2088 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
2089 /* init pipes package */
2090 /* NdrPipesInitialize(...) */
2092 if (ext_flags.HasNewCorrDesc)
2094 /* initialize extra correlation package */
2095 NdrCorrelationInitialize(async_call_data->pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
2096 if (ext_flags.Unused & 0x2) /* has range on conformance */
2097 async_call_data->pStubMsg->CorrDespIncrement = 12;
2100 else
2102 pFormat = convert_old_args( async_call_data->pStubMsg, pFormat, async_call_data->stack_size,
2103 pProcHeader->Oi_flags & Oi_OBJECT_PROC,
2104 /* reuse the correlation cache, it's not needed for v1 format */
2105 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), &async_call_data->number_of_params );
2108 /* convert strings, floating point values and endianness into our
2109 * preferred format */
2110 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
2111 NdrConvert(async_call_data->pStubMsg, pFormat);
2113 async_call_data->pHandleFormat = pFormat;
2115 /* 1. UNMARSHAL */
2116 TRACE("UNMARSHAL\n");
2117 stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_UNMARSHAL, async_call_data->number_of_params);
2119 /* 2. INITOUT */
2120 TRACE("INITOUT\n");
2121 async_call_data->retval_ptr = stub_do_args(async_call_data->pStubMsg, pFormat, STUBLESS_INITOUT, async_call_data->number_of_params);
2123 /* 3. CALLSERVER */
2124 TRACE("CALLSERVER\n");
2125 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
2126 pServerInfo->ThunkTable[pRpcMsg->ProcNum](async_call_data->pStubMsg);
2127 else
2128 call_server_func(pServerInfo->DispatchTable[pRpcMsg->ProcNum], args, async_call_data->stack_size);
2131 RPC_STATUS NdrpCompleteAsyncServerCall(RPC_ASYNC_STATE *pAsync, void *Reply)
2133 /* pointer to start of stack where arguments start */
2134 PMIDL_STUB_MESSAGE pStubMsg;
2135 struct async_call_data *async_call_data;
2136 /* the type of pass we are currently doing */
2137 enum stubless_phase phase;
2138 RPC_STATUS status = RPC_S_OK;
2140 if (!pAsync->StubInfo)
2141 return RPC_S_INVALID_ASYNC_HANDLE;
2143 async_call_data = pAsync->StubInfo;
2144 pStubMsg = async_call_data->pStubMsg;
2146 TRACE("pAsync %p, pAsync->StubInfo %p, pFormat %p\n", pAsync, pAsync->StubInfo, async_call_data->pHandleFormat);
2148 if (async_call_data->retval_ptr)
2150 TRACE("stub implementation returned 0x%Ix\n", *(LONG_PTR *)Reply);
2151 *async_call_data->retval_ptr = *(LONG_PTR *)Reply;
2153 else
2154 TRACE("void stub implementation\n");
2156 for (phase = STUBLESS_CALCSIZE; phase <= STUBLESS_FREE; phase++)
2158 TRACE("phase = %d\n", phase);
2159 switch (phase)
2161 case STUBLESS_GETBUFFER:
2162 if (async_call_data->pProcHeader->Oi_flags & Oi_OBJECT_PROC)
2164 ERR("objects not supported\n");
2165 free(async_call_data->pStubMsg->StackTop);
2166 I_RpcFree(async_call_data);
2167 I_RpcFree(pAsync);
2168 RpcRaiseException(RPC_X_BAD_STUB_DATA);
2170 else
2172 pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength;
2173 /* allocate buffer for [out] and [ret] params */
2174 status = I_RpcGetBuffer(pStubMsg->RpcMsg);
2175 if (status)
2176 RpcRaiseException(status);
2177 pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer;
2179 break;
2181 case STUBLESS_CALCSIZE:
2182 case STUBLESS_MARSHAL:
2183 case STUBLESS_MUSTFREE:
2184 case STUBLESS_FREE:
2185 stub_do_args(pStubMsg, async_call_data->pHandleFormat, phase, async_call_data->number_of_params);
2186 break;
2187 default:
2188 ERR("shouldn't reach here. phase %d\n", phase);
2189 break;
2193 #if 0 /* FIXME */
2194 if (ext_flags.HasNewCorrDesc)
2196 /* free extra correlation package */
2197 NdrCorrelationFree(pStubMsg);
2200 if (Oif_flags.HasPipes)
2202 /* NdrPipesDone(...) */
2205 /* free the full pointer translation tables */
2206 if (async_call_data->pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
2207 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
2208 #endif
2210 /* free server function stack */
2211 free(async_call_data->pStubMsg->StackTop);
2212 I_RpcFree(async_call_data);
2213 I_RpcFree(pAsync);
2215 return S_OK;
2218 static const RPC_SYNTAX_IDENTIFIER ndr_syntax_id =
2219 {{0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60}}, {2, 0}};
2221 LONG_PTR CDECL DECLSPEC_HIDDEN ndr64_client_call( MIDL_STUBLESS_PROXY_INFO *info,
2222 ULONG proc, void *retval, void **stack_top, void **fpu_stack )
2224 ULONG_PTR i;
2226 TRACE("info %p, proc %lu, retval %p, stack_top %p, fpu_stack %p\n",
2227 info, proc, retval, stack_top, fpu_stack);
2229 for (i = 0; i < info->nCount; ++i)
2231 const MIDL_SYNTAX_INFO *syntax_info = &info->pSyntaxInfo[i];
2232 const RPC_SYNTAX_IDENTIFIER *id = &syntax_info->TransferSyntax;
2234 TRACE("Found syntax %s, version %u.%u.\n", debugstr_guid(&id->SyntaxGUID),
2235 id->SyntaxVersion.MajorVersion, id->SyntaxVersion.MinorVersion);
2236 if (!memcmp(id, &ndr_syntax_id, sizeof(RPC_SYNTAX_IDENTIFIER)))
2238 if (retval)
2239 FIXME("Complex return types are not supported.\n");
2241 return ndr_client_call( info->pStubDesc,
2242 syntax_info->ProcString + syntax_info->FmtStringOffset[proc], stack_top, fpu_stack );
2246 FIXME("NDR64 syntax is not supported.\n");
2247 return 0;
2250 #ifdef __x86_64__
2252 __ASM_GLOBAL_FUNC( NdrClientCall3,
2253 "subq $0x28,%rsp\n\t"
2254 __ASM_SEH(".seh_stackalloc 0x28\n\t")
2255 __ASM_SEH(".seh_endprologue\n\t")
2256 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
2257 "movq %r9,0x48(%rsp)\n\t"
2258 "leaq 0x48(%rsp),%r9\n\t"
2259 "movq $0,0x20(%rsp)\n\t"
2260 "call " __ASM_NAME("ndr64_client_call") "\n\t"
2261 "addq $0x28,%rsp\n\t"
2262 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
2263 "ret" );
2265 #elif defined(_WIN64)
2267 /***********************************************************************
2268 * NdrClientCall3 [RPCRT4.@]
2270 CLIENT_CALL_RETURN WINAPIV NdrClientCall3( MIDL_STUBLESS_PROXY_INFO *info, ULONG proc, void *retval, ... )
2272 va_list args;
2273 LONG_PTR ret;
2275 va_start( args, retval );
2276 ret = ndr64_client_call( info, proc, retval, va_arg( args, void ** ), NULL );
2277 va_end( args );
2278 return *(CLIENT_CALL_RETURN *)&ret;
2281 #endif
2283 LONG_PTR CDECL DECLSPEC_HIDDEN ndr64_async_client_call( MIDL_STUBLESS_PROXY_INFO *info,
2284 ULONG proc, void *retval, void **stack_top, void **fpu_stack )
2286 ULONG_PTR i;
2288 TRACE("info %p, proc %lu, retval %p, stack_top %p, fpu_stack %p\n",
2289 info, proc, retval, stack_top, fpu_stack);
2291 for (i = 0; i < info->nCount; ++i)
2293 const MIDL_SYNTAX_INFO *syntax_info = &info->pSyntaxInfo[i];
2294 const RPC_SYNTAX_IDENTIFIER *id = &syntax_info->TransferSyntax;
2296 TRACE("Found syntax %s, version %u.%u.\n", debugstr_guid(&id->SyntaxGUID),
2297 id->SyntaxVersion.MajorVersion, id->SyntaxVersion.MinorVersion);
2298 if (!memcmp(id, &ndr_syntax_id, sizeof(RPC_SYNTAX_IDENTIFIER)))
2300 if (retval)
2301 FIXME("Complex return types are not supported.\n");
2303 return ndr_async_client_call( info->pStubDesc,
2304 syntax_info->ProcString + syntax_info->FmtStringOffset[proc], stack_top );
2308 FIXME("NDR64 syntax is not supported.\n");
2309 return 0;
2312 #ifdef __x86_64__
2314 __ASM_GLOBAL_FUNC( Ndr64AsyncClientCall,
2315 "subq $0x28,%rsp\n\t"
2316 __ASM_SEH(".seh_stackalloc 0x28\n\t")
2317 __ASM_SEH(".seh_endprologue\n\t")
2318 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
2319 "movq %r9,0x48(%rsp)\n\t"
2320 "leaq 0x48(%rsp),%r9\n\t"
2321 "movq $0,0x20(%rsp)\n\t"
2322 "call " __ASM_NAME("ndr64_async_client_call") "\n\t"
2323 "addq $0x28,%rsp\n\t"
2324 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
2325 "ret" );
2327 #elif defined(_WIN64)
2329 /***********************************************************************
2330 * Ndr64AsyncClientCall [RPCRT4.@]
2332 CLIENT_CALL_RETURN WINAPIV Ndr64AsyncClientCall( MIDL_STUBLESS_PROXY_INFO *info, ULONG proc, void *retval, ... )
2334 va_list args;
2335 LONG_PTR ret;
2337 va_start( args, retval );
2338 ret = ndr64_async_client_call( info, proc, retval, va_arg( args, void ** ), NULL );
2339 va_end( args );
2340 return *(CLIENT_CALL_RETURN *)&ret;
2343 #endif