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
23 * - Some types of binding handles
27 #include "wine/port.h"
41 #include "wine/exception.h"
42 #include "wine/debug.h"
43 #include "wine/rpcfc.h"
47 #include "ndr_stubless.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
51 #define NDR_TABLE_MASK 127
53 static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
55 NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK];
56 if (m) m(pStubMsg, pMemory, pFormat);
59 FIXME("format type 0x%x not implemented\n", pFormat[0]);
60 RpcRaiseException(RPC_X_BAD_STUB_DATA);
64 static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
66 NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK];
67 if (m) return m(pStubMsg, pMemory, pFormat);
70 FIXME("format type 0x%x not implemented\n", pFormat[0]);
71 RpcRaiseException(RPC_X_BAD_STUB_DATA);
76 static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc)
78 NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK];
79 if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc);
82 FIXME("format type 0x%x not implemented\n", pFormat[0]);
83 RpcRaiseException(RPC_X_BAD_STUB_DATA);
88 static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
90 NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK];
91 if (m) m(pStubMsg, pMemory, pFormat);
94 #define STUBLESS_UNMARSHAL 1
95 #define STUBLESS_INITOUT 2
96 #define STUBLESS_CALLSERVER 3
97 #define STUBLESS_CALCSIZE 4
98 #define STUBLESS_GETBUFFER 5
99 #define STUBLESS_MARSHAL 6
100 #define STUBLESS_FREE 7
102 void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage)
104 #if 0 /* these functions are not defined yet */
105 pMessage->pfnAllocate = NdrRpcSmClientAllocate;
106 pMessage->pfnFree = NdrRpcSmClientFree;
110 static const char *debugstr_PROC_PF(PARAM_ATTRIBUTES param_attributes)
115 if (param_attributes.MustSize) strcat(buffer, " MustSize");
116 if (param_attributes.MustFree) strcat(buffer, " MustFree");
117 if (param_attributes.IsPipe) strcat(buffer, " IsPipe");
118 if (param_attributes.IsIn) strcat(buffer, " IsIn");
119 if (param_attributes.IsOut) strcat(buffer, " IsOut");
120 if (param_attributes.IsReturn) strcat(buffer, " IsReturn");
121 if (param_attributes.IsBasetype) strcat(buffer, " IsBasetype");
122 if (param_attributes.IsByValue) strcat(buffer, " IsByValue");
123 if (param_attributes.IsSimpleRef) strcat(buffer, " IsSimpleRef");
124 if (param_attributes.IsDontCallFreeInst) strcat(buffer, " IsDontCallFreeInst");
125 if (param_attributes.SaveForAsyncFinish) strcat(buffer, " SaveForAsyncFinish");
126 if (param_attributes.ServerAllocSize)
127 sprintf( buffer + strlen(buffer), " ServerAllocSize = %d", param_attributes.ServerAllocSize * 8);
128 return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : "";
131 static const char *debugstr_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags)
136 if (Oi2Flags.ServerMustSize) strcat(buffer, " ServerMustSize");
137 if (Oi2Flags.ClientMustSize) strcat(buffer, " ClientMustSize");
138 if (Oi2Flags.HasReturn) strcat(buffer, " HasReturn");
139 if (Oi2Flags.HasPipes) strcat(buffer, " HasPipes");
140 if (Oi2Flags.Unused) strcat(buffer, " Unused");
141 if (Oi2Flags.HasAsyncUuid) strcat(buffer, " HasAsyncUuid");
142 if (Oi2Flags.HasExtensions) strcat(buffer, " HasExtensions");
143 if (Oi2Flags.HasAsyncHandle) strcat(buffer, " HasAsyncHandle");
144 return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : "";
147 #define ARG_FROM_OFFSET(args, offset) ((args) + (offset))
149 static PFORMAT_STRING client_get_handle(
150 PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
151 PFORMAT_STRING pFormat, handle_t *phBinding)
154 switch (pProcHeader->handle_type)
156 /* explicit binding: parse additional section */
157 case RPC_FC_BIND_EXPLICIT:
158 switch (*pFormat) /* handle_type */
160 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
162 const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat;
164 TRACE("Explicit primitive handle @ %d\n", pDesc->offset);
166 if (pDesc->flag) /* pointer to binding */
167 *phBinding = **(handle_t **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
169 *phBinding = *(handle_t *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
170 return pFormat + sizeof(NDR_EHD_PRIMITIVE);
172 case RPC_FC_BIND_GENERIC: /* explicit generic */
174 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat;
175 void *pObject = NULL;
177 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
179 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
181 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
182 pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
184 pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
185 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
186 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
187 *phBinding = pGenPair->pfnBind(pObject);
188 return pFormat + sizeof(NDR_EHD_GENERIC);
190 case RPC_FC_BIND_CONTEXT: /* explicit context */
192 const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat;
193 NDR_CCONTEXT context_handle;
194 TRACE("Explicit bind context\n");
195 if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR)
197 TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n");
198 context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
201 context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
203 if (context_handle) *phBinding = NDRCContextBinding(context_handle);
204 else if (pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL)
206 ERR("null context handle isn't allowed\n");
207 RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT);
210 /* FIXME: should we store this structure in stubMsg.pContext? */
211 return pFormat + sizeof(NDR_EHD_CONTEXT);
214 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
215 RpcRaiseException(RPC_X_BAD_STUB_DATA);
218 case RPC_FC_BIND_GENERIC: /* implicit generic */
219 FIXME("RPC_FC_BIND_GENERIC\n");
220 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
222 case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
223 TRACE("Implicit primitive handle\n");
224 *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle;
226 case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
227 FIXME("RPC_FC_CALLBACK_HANDLE\n");
229 case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
230 /* strictly speaking, it isn't necessary to set hBinding here
231 * since it isn't actually used (hence the automatic in its name),
232 * but then why does MIDL generate a valid entry in the
233 * MIDL_STUB_DESC for it? */
234 TRACE("Implicit auto handle\n");
235 *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle;
238 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
239 RpcRaiseException(RPC_X_BAD_STUB_DATA);
244 static void client_free_handle(
245 PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
246 PFORMAT_STRING pFormat, handle_t hBinding)
249 switch (pProcHeader->handle_type)
251 /* explicit binding: parse additional section */
252 case RPC_FC_BIND_EXPLICIT:
253 switch (*pFormat) /* handle_type */
255 case RPC_FC_BIND_GENERIC: /* explicit generic */
257 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat;
258 void *pObject = NULL;
260 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
262 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
264 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
265 pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
267 pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
268 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
269 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
270 pGenPair->pfnUnbind(pObject, hBinding);
273 case RPC_FC_BIND_CONTEXT: /* explicit context */
274 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
277 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
278 RpcRaiseException(RPC_X_BAD_STUB_DATA);
281 case RPC_FC_BIND_GENERIC: /* implicit generic */
282 FIXME("RPC_FC_BIND_GENERIC\n");
283 RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
285 case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
286 case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
287 case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
290 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
291 RpcRaiseException(RPC_X_BAD_STUB_DATA);
295 static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, int phase, void **fpu_args,
296 unsigned short number_of_params, unsigned char *pRetVal)
298 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat;
301 for (i = 0; i < number_of_params; i++)
303 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset;
305 TRACE("param[%d]: %p %s\n", i, pArg, debugstr_PROC_PF( params[i].attr ));
307 if (params[i].attr.IsBasetype)
309 const unsigned char * pTypeFormat = ¶ms[i].u.type_format_char;
311 #ifdef __x86_64__ /* floats are passed as doubles through varargs functions */
313 if (*pTypeFormat == RPC_FC_FLOAT && !params[i].attr.IsSimpleRef && !fpu_args)
316 pArg = (unsigned char *)&f;
319 if (params[i].attr.IsSimpleRef)
321 pArg = *(unsigned char **)pArg;
322 if (!pArg) RpcRaiseException(RPC_X_NULL_REF_POINTER);
325 TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
330 if (params[i].attr.IsIn)
331 call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
334 if (params[i].attr.IsIn)
335 call_marshaller(pStubMsg, pArg, pTypeFormat);
337 case PROXY_UNMARSHAL:
338 if (params[i].attr.IsOut)
340 if (params[i].attr.IsReturn) pArg = pRetVal;
341 call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
345 RpcRaiseException(RPC_S_INTERNAL_ERROR);
350 const unsigned char * pTypeFormat =
351 &(pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset]);
353 /* if a simple ref pointer then we have to do the
354 * check for the pointer being non-NULL. */
355 if (params[i].attr.IsSimpleRef)
357 if (!*(unsigned char **)pArg)
358 RpcRaiseException(RPC_X_NULL_REF_POINTER);
361 TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat);
366 if (params[i].attr.IsIn)
368 if (params[i].attr.IsByValue)
369 call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
371 call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
375 if (params[i].attr.IsIn)
377 if (params[i].attr.IsByValue)
378 call_marshaller(pStubMsg, pArg, pTypeFormat);
380 call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
383 case PROXY_UNMARSHAL:
384 if (params[i].attr.IsOut)
386 if (params[i].attr.IsReturn) pArg = pRetVal;
387 if (params[i].attr.IsByValue)
388 call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
390 call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
394 RpcRaiseException(RPC_S_INTERNAL_ERROR);
397 TRACE("\tmemory addr (after): %p\n", pArg);
401 static unsigned int type_stack_size(unsigned char fc)
415 case RPC_FC_UINT3264:
419 case RPC_FC_ERROR_STATUS_T:
421 return sizeof(void *);
423 return sizeof(double);
425 return sizeof(ULONGLONG);
427 ERR("invalid base type 0x%x\n", fc);
428 RpcRaiseException(RPC_S_INTERNAL_ERROR);
432 static BOOL is_by_value( PFORMAT_STRING format )
436 case RPC_FC_USER_MARSHAL:
440 case RPC_FC_CPSTRUCT:
441 case RPC_FC_CVSTRUCT:
442 case RPC_FC_BOGUS_STRUCT:
449 static PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
450 unsigned int stack_size, BOOL object_proc,
451 void *buffer, unsigned int size, unsigned int *count )
453 NDR_PARAM_OIF *args = buffer;
454 unsigned int i, stack_offset = object_proc ? sizeof(void *) : 0;
456 for (i = 0; stack_offset < stack_size; i++)
458 const NDR_PARAM_OI_BASETYPE *param = (const NDR_PARAM_OI_BASETYPE *)pFormat;
459 const NDR_PARAM_OI_OTHER *other = (const NDR_PARAM_OI_OTHER *)pFormat;
461 if (i + 1 > size / sizeof(*args))
463 FIXME( "%u args not supported\n", i );
464 RpcRaiseException( RPC_S_INTERNAL_ERROR );
467 args[i].stack_offset = stack_offset;
468 memset( &args[i].attr, 0, sizeof(args[i].attr) );
470 switch (param->param_direction)
472 case RPC_FC_IN_PARAM_BASETYPE:
473 args[i].attr.IsIn = 1;
474 args[i].attr.IsBasetype = 1;
476 case RPC_FC_RETURN_PARAM_BASETYPE:
477 args[i].attr.IsOut = 1;
478 args[i].attr.IsReturn = 1;
479 args[i].attr.IsBasetype = 1;
481 case RPC_FC_IN_PARAM:
482 args[i].attr.IsIn = 1;
484 case RPC_FC_IN_PARAM_NO_FREE_INST:
485 args[i].attr.IsIn = 1;
486 args[i].attr.IsDontCallFreeInst = 1;
488 case RPC_FC_IN_OUT_PARAM:
489 args[i].attr.IsIn = 1;
490 args[i].attr.IsOut = 1;
492 case RPC_FC_OUT_PARAM:
493 args[i].attr.IsOut = 1;
495 case RPC_FC_RETURN_PARAM:
496 args[i].attr.IsOut = 1;
497 args[i].attr.IsReturn = 1;
500 if (args[i].attr.IsBasetype)
502 args[i].u.type_format_char = param->type_format_char;
503 stack_offset += type_stack_size( param->type_format_char );
504 pFormat += sizeof(NDR_PARAM_OI_BASETYPE);
508 args[i].u.type_offset = other->type_offset;
509 args[i].attr.IsByValue = is_by_value( &pStubMsg->StubDesc->pFormatTypes[other->type_offset] );
510 stack_offset += other->stack_size * sizeof(void *);
511 pFormat += sizeof(NDR_PARAM_OI_OTHER);
515 return (PFORMAT_STRING)args;
518 void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
519 PFORMAT_STRING pFormat, int phase, unsigned short stack_size,
520 unsigned char *pRetVal, BOOL object_proc, BOOL ignore_retval)
522 /* current format string offset */
523 int current_offset = 0;
524 /* current stack offset */
525 unsigned short current_stack_offset = object_proc ? sizeof(void *) : 0;
529 /* NOTE: V1 style format doesn't terminate on the number_of_params
530 * condition as it doesn't have this attribute. Instead it
531 * terminates when the stack size given in the header is exceeded.
533 for (i = 0; TRUE; i++)
535 const NDR_PARAM_OI_BASETYPE *pParam =
536 (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
537 unsigned char * pArg = pStubMsg->StackTop + current_stack_offset;
539 /* no more parameters; exit loop */
540 if (current_stack_offset >= stack_size)
543 TRACE("param[%d]: old format\n", i);
544 TRACE("\tparam_direction: 0x%x\n", pParam->param_direction);
545 TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
546 TRACE("\tmemory addr (before): %p\n", pArg);
548 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
549 pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
551 const unsigned char * pTypeFormat =
552 &pParam->type_format_char;
554 TRACE("\tbase type 0x%02x\n", *pTypeFormat);
559 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
560 call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
563 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
564 call_marshaller(pStubMsg, pArg, pTypeFormat);
566 case PROXY_UNMARSHAL:
567 if (!ignore_retval &&
568 pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
570 if (pParam->param_direction & RPC_FC_RETURN_PARAM)
571 call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0);
573 call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
577 RpcRaiseException(RPC_S_INTERNAL_ERROR);
580 current_stack_offset += type_stack_size(*pTypeFormat);
581 current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
585 const NDR_PARAM_OI_OTHER *pParamOther = (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
586 const unsigned char *pTypeFormat = &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset];
587 const BOOL by_value = is_by_value( pTypeFormat );
589 TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
594 if (pParam->param_direction == RPC_FC_IN_PARAM ||
595 pParam->param_direction == RPC_FC_IN_OUT_PARAM)
597 if (!by_value) pArg = *(unsigned char **)pArg;
598 call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
602 if (pParam->param_direction == RPC_FC_IN_PARAM ||
603 pParam->param_direction == RPC_FC_IN_OUT_PARAM)
605 if (!by_value) pArg = *(unsigned char **)pArg;
606 call_marshaller(pStubMsg, pArg, pTypeFormat);
609 case PROXY_UNMARSHAL:
610 if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
611 pParam->param_direction == RPC_FC_OUT_PARAM)
614 call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
616 call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
618 else if (pParam->param_direction == RPC_FC_RETURN_PARAM)
619 call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0);
622 RpcRaiseException(RPC_S_INTERNAL_ERROR);
625 current_stack_offset += pParamOther->stack_size * sizeof(void *);
626 current_offset += sizeof(NDR_PARAM_OI_OTHER);
631 LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat,
632 void **stack_top, void **fpu_stack )
634 /* pointer to start of stack where arguments start */
636 MIDL_STUB_MESSAGE stubMsg;
637 handle_t hBinding = NULL;
638 /* procedure number */
639 unsigned short procedure_number;
641 unsigned short stack_size;
642 /* number of parameters. optional for client to give it to us */
643 unsigned int number_of_params;
644 /* cache of Oif_flags from v2 procedure header */
645 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
646 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
647 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
648 /* the type of pass we are currently doing */
650 /* header for procedure string */
651 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
652 /* the value to return to the client from the remote procedure */
654 /* the pointer to the object when in OLE mode */
656 PFORMAT_STRING pHandleFormat;
657 /* correlation cache */
658 ULONG_PTR NdrCorrCache[256];
660 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
662 TRACE("NDR Version: 0x%x\n", pStubDesc->Version);
664 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
666 const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
667 stack_size = pProcHeader->stack_size;
668 procedure_number = pProcHeader->proc_num;
669 pFormat += sizeof(NDR_PROC_HEADER_RPC);
673 stack_size = pProcHeader->stack_size;
674 procedure_number = pProcHeader->proc_num;
675 pFormat += sizeof(NDR_PROC_HEADER);
677 TRACE("stack size: 0x%x\n", stack_size);
678 TRACE("proc num: %d\n", procedure_number);
680 /* create the full pointer translation tables, if requested */
681 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
682 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
684 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
686 /* object is always the first argument */
688 NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number);
691 NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number);
693 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
694 TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
696 stubMsg.StackTop = (unsigned char *)stack_top;
697 pHandleFormat = pFormat;
699 /* we only need a handle if this isn't an object method */
700 if (!(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT))
702 pFormat = client_get_handle(&stubMsg, pProcHeader, pHandleFormat, &hBinding);
703 if (!pFormat) goto done;
706 if (pStubDesc->Version >= 0x20000) /* -Oicf format */
708 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
709 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
711 Oif_flags = pOIFHeader->Oi2Flags;
712 number_of_params = pOIFHeader->number_of_params;
714 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
716 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
718 if (Oif_flags.HasExtensions)
720 const NDR_PROC_HEADER_EXTS *pExtensions = (const NDR_PROC_HEADER_EXTS *)pFormat;
721 ext_flags = pExtensions->Flags2;
722 pFormat += pExtensions->Size;
724 if (pExtensions->Size > sizeof(*pExtensions) && fpu_stack)
727 unsigned short fpu_mask = *(unsigned short *)(pExtensions + 1);
728 for (i = 0; i < 4; i++, fpu_mask >>= 2)
729 switch (fpu_mask & 3)
731 case 1: *(float *)&stack_top[i] = *(float *)&fpu_stack[i]; break;
732 case 2: *(double *)&stack_top[i] = *(double *)&fpu_stack[i]; break;
740 pFormat = convert_old_args( &stubMsg, pFormat, stack_size,
741 pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT,
742 /* reuse the correlation cache, it's not needed for v1 format */
743 NdrCorrCache, sizeof(NdrCorrCache), &number_of_params );
746 stubMsg.BufferLength = 0;
748 /* store the RPC flags away */
749 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
750 rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
752 /* use alternate memory allocation routines */
753 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
754 NdrRpcSmSetClientToOsf(&stubMsg);
756 if (Oif_flags.HasPipes)
758 FIXME("pipes not supported yet\n");
759 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
760 /* init pipes package */
761 /* NdrPipesInitialize(...) */
763 if (ext_flags.HasNewCorrDesc)
765 /* initialize extra correlation package */
766 NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0);
770 * 1. PROXY_CALCSIZE - calculate the buffer size
771 * 2. PROXY_GETBUFFER - allocate the buffer
772 * 3. PROXY_MARHSAL - marshal [in] params into the buffer
773 * 4. PROXY_SENDRECEIVE - send/receive buffer
774 * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer
776 if ((pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) ||
777 (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_HAS_COMM_OR_FAULT))
781 for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++)
783 TRACE("phase = %d\n", phase);
786 case PROXY_GETBUFFER:
787 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
789 /* allocate the buffer */
790 NdrProxyGetBuffer(This, &stubMsg);
794 /* allocate the buffer */
795 if (Oif_flags.HasPipes)
796 /* NdrGetPipeBuffer(...) */
797 FIXME("pipes not supported yet\n");
800 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
802 NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
804 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
807 NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
811 case PROXY_SENDRECEIVE:
812 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
814 /* send the [in] params and receive the [out] and [retval]
816 NdrProxySendReceive(This, &stubMsg);
820 /* send the [in] params and receive the [out] and [retval]
822 if (Oif_flags.HasPipes)
823 /* NdrPipesSendReceive(...) */
824 FIXME("pipes not supported yet\n");
827 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
829 NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
831 FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
834 NdrSendReceive(&stubMsg, stubMsg.Buffer);
838 /* convert strings, floating point values and endianess into our
839 * preferred format */
840 if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
841 NdrConvert(&stubMsg, pFormat);
846 case PROXY_UNMARSHAL:
847 client_do_args(&stubMsg, pFormat, phase, fpu_stack,
848 number_of_params, (unsigned char *)&RetVal);
851 ERR("shouldn't reach here. phase %d\n", phase);
858 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
859 RetVal = NdrProxyErrorHandler(GetExceptionCode());
862 const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number];
866 TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset);
868 if (comm_fault_offsets->CommOffset == -1)
869 comm_status = (ULONG *)&RetVal;
870 else if (comm_fault_offsets->CommOffset >= 0)
871 comm_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset);
875 if (comm_fault_offsets->FaultOffset == -1)
876 fault_status = (ULONG *)&RetVal;
877 else if (comm_fault_offsets->FaultOffset >= 0)
878 fault_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset);
882 NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status,
891 * 1. PROXY_CALCSIZE - calculate the buffer size
892 * 2. PROXY_GETBUFFER - allocate the buffer
893 * 3. PROXY_MARHSAL - marshal [in] params into the buffer
894 * 4. PROXY_SENDRECEIVE - send/receive buffer
895 * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer
897 for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++)
899 TRACE("phase = %d\n", phase);
902 case PROXY_GETBUFFER:
903 /* allocate the buffer */
904 if (Oif_flags.HasPipes)
905 /* NdrGetPipeBuffer(...) */
906 FIXME("pipes not supported yet\n");
909 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
911 NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
913 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
916 NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
919 case PROXY_SENDRECEIVE:
920 /* send the [in] params and receive the [out] and [retval]
922 if (Oif_flags.HasPipes)
923 /* NdrPipesSendReceive(...) */
924 FIXME("pipes not supported yet\n");
927 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
929 NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
931 FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
934 NdrSendReceive(&stubMsg, stubMsg.Buffer);
937 /* convert strings, floating point values and endianess into our
938 * preferred format */
939 if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
940 NdrConvert(&stubMsg, pFormat);
945 case PROXY_UNMARSHAL:
946 client_do_args(&stubMsg, pFormat, phase, fpu_stack,
947 number_of_params, (unsigned char *)&RetVal);
950 ERR("shouldn't reach here. phase %d\n", phase);
956 if (ext_flags.HasNewCorrDesc)
958 /* free extra correlation package */
959 NdrCorrelationFree(&stubMsg);
962 if (Oif_flags.HasPipes)
964 /* NdrPipesDone(...) */
967 /* free the full pointer translation tables */
968 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
969 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
971 /* free marshalling buffer */
972 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
973 NdrProxyFreeBuffer(This, &stubMsg);
976 NdrFreeBuffer(&stubMsg);
977 client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding);
981 TRACE("RetVal = 0x%lx\n", RetVal);
987 __ASM_GLOBAL_FUNC( NdrClientCall2,
988 "movq %r8,0x18(%rsp)\n\t"
989 "movq %r9,0x20(%rsp)\n\t"
990 "leaq 0x18(%rsp),%r8\n\t"
992 "subq $0x28,%rsp\n\t"
993 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
994 "call " __ASM_NAME("ndr_client_call") "\n\t"
995 "addq $0x28,%rsp\n\t"
996 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
999 #else /* __x86_64__ */
1001 /***********************************************************************
1002 * NdrClientCall2 [RPCRT4.@]
1004 CLIENT_CALL_RETURN WINAPIV NdrClientCall2( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... )
1009 __ms_va_start( args, format );
1010 ret = ndr_client_call( desc, format, va_arg( args, void ** ), NULL );
1011 __ms_va_end( args );
1012 return *(CLIENT_CALL_RETURN *)&ret;
1015 #endif /* __x86_64__ */
1017 /* Calls a function with the specified arguments, restoring the stack
1018 * properly afterwards as we don't know the calling convention of the
1020 #if defined __i386__ && defined _MSC_VER
1021 __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size)
1026 push edi ; Save registers
1029 mov eax, [ebp+16] ; Get stack size
1030 sub esp, eax ; Make room in stack for arguments
1036 rep movsd ; Copy dword blocks
1037 call [ebp+8] ; Call function
1038 lea esp, [ebp-8] ; Restore stack
1039 pop esi ; Restore registers
1045 #elif defined __i386__ && defined __GNUC__
1046 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
1047 __ASM_GLOBAL_FUNC(call_server_func,
1049 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
1050 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
1051 "movl %esp,%ebp\n\t"
1052 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
1053 "pushl %edi\n\t" /* Save registers */
1054 __ASM_CFI(".cfi_rel_offset %edi,-4\n\t")
1056 __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
1057 "movl 16(%ebp), %eax\n\t" /* Get stack size */
1058 "subl %eax, %esp\n\t" /* Make room in stack for arguments */
1059 "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */
1060 "movl %esp, %edi\n\t"
1061 "movl %eax, %ecx\n\t"
1062 "movl 12(%ebp), %esi\n\t"
1063 "shrl $2, %ecx\n\t" /* divide by 4 */
1065 "rep; movsl\n\t" /* Copy dword blocks */
1066 "call *8(%ebp)\n\t" /* Call function */
1067 "leal -8(%ebp), %esp\n\t" /* Restore stack */
1068 "popl %esi\n\t" /* Restore registers */
1069 __ASM_CFI(".cfi_same_value %esi\n\t")
1071 __ASM_CFI(".cfi_same_value %edi\n\t")
1073 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
1074 __ASM_CFI(".cfi_same_value %ebp\n\t")
1076 #elif defined __x86_64__
1077 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
1078 __ASM_GLOBAL_FUNC( call_server_func,
1080 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
1081 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
1082 "movq %rsp,%rbp\n\t"
1083 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
1085 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
1087 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
1088 "movq %rcx,%rax\n\t" /* function to call */
1089 "movq $32,%rcx\n\t" /* allocate max(32,stack_size) bytes of stack space */
1091 "cmovgq %r8,%rcx\n\t"
1092 "subq %rcx,%rsp\n\t"
1093 "andq $~15,%rsp\n\t"
1096 "movq %rsp,%rdi\n\t"
1097 "movq %rdx,%rsi\n\t"
1098 "rep; movsq\n\t" /* copy arguments */
1099 "movq 0(%rsp),%rcx\n\t"
1100 "movq 8(%rsp),%rdx\n\t"
1101 "movq 16(%rsp),%r8\n\t"
1102 "movq 24(%rsp),%r9\n\t"
1103 "movq %rcx,%xmm0\n\t"
1104 "movq %rdx,%xmm1\n\t"
1105 "movq %r8,%xmm2\n\t"
1106 "movq %r9,%xmm3\n\t"
1108 "leaq -16(%rbp),%rsp\n\t" /* restore stack */
1110 __ASM_CFI(".cfi_same_value %rdi\n\t")
1112 __ASM_CFI(".cfi_same_value %rsi\n\t")
1113 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
1115 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
1116 __ASM_CFI(".cfi_same_value %rbp\n\t")
1119 #warning call_server_func not implemented for your architecture
1120 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
1122 FIXME("Not implemented for your architecture\n");
1127 static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
1133 size = *(const WORD*)(pFormat + 2);
1135 case RPC_FC_BOGUS_STRUCT:
1136 size = *(const WORD*)(pFormat + 2);
1137 if(*(const WORD*)(pFormat + 4))
1138 FIXME("Unhandled conformant description\n");
1141 case RPC_FC_CVARRAY:
1142 size = *(const WORD*)(pFormat + 2);
1143 ComputeConformance(pStubMsg, NULL, pFormat + 4, 0);
1144 size *= pStubMsg->MaxCount;
1146 case RPC_FC_SMFARRAY:
1147 case RPC_FC_SMVARRAY:
1148 size = *(const WORD*)(pFormat + 2);
1150 case RPC_FC_LGFARRAY:
1151 case RPC_FC_LGVARRAY:
1152 size = *(const DWORD*)(pFormat + 2);
1154 case RPC_FC_BOGUS_ARRAY:
1155 pFormat = ComputeConformance(pStubMsg, NULL, pFormat + 4, *(const WORD*)&pFormat[2]);
1156 TRACE("conformance = %ld\n", pStubMsg->MaxCount);
1157 pFormat = ComputeVariance(pStubMsg, NULL, pFormat, pStubMsg->MaxCount);
1158 size = ComplexStructSize(pStubMsg, pFormat);
1159 size *= pStubMsg->MaxCount;
1161 case RPC_FC_C_CSTRING:
1162 case RPC_FC_C_WSTRING:
1163 if (*pFormat == RPC_FC_C_CSTRING)
1164 size = sizeof(CHAR);
1166 size = sizeof(WCHAR);
1167 if (pFormat[1] == RPC_FC_STRING_SIZED)
1168 ComputeConformance(pStubMsg, NULL, pFormat + 2, 0);
1170 pStubMsg->MaxCount = 0;
1171 size *= pStubMsg->MaxCount;
1174 FIXME("Unhandled type %02x\n", *pFormat);
1177 size = sizeof(void *);
1183 static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg,
1184 PFORMAT_STRING pFormat, int phase,
1185 unsigned short number_of_params)
1187 const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat;
1189 LONG_PTR *retval_ptr = NULL;
1191 for (i = 0; i < number_of_params; i++)
1193 unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset;
1195 TRACE("param[%d]: %p -> %p %s\n", i,
1196 pArg, *(unsigned char **)pArg, debugstr_PROC_PF( params[i].attr ));
1198 if (params[i].attr.IsBasetype)
1200 const unsigned char *pTypeFormat = ¶ms[i].u.type_format_char;
1202 TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
1206 case STUBLESS_MARSHAL:
1207 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1209 if (params[i].attr.IsSimpleRef)
1210 call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1212 call_marshaller(pStubMsg, pArg, pTypeFormat);
1216 if (params[i].attr.ServerAllocSize)
1217 HeapFree(GetProcessHeap(), 0, *(void **)pArg);
1219 case STUBLESS_INITOUT:
1221 case STUBLESS_UNMARSHAL:
1222 if (params[i].attr.ServerAllocSize)
1223 *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1224 params[i].attr.ServerAllocSize * 8);
1226 if (params[i].attr.IsIn)
1228 if (params[i].attr.IsSimpleRef)
1229 call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
1231 call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
1234 case STUBLESS_CALCSIZE:
1235 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1237 if (params[i].attr.IsSimpleRef)
1238 call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1240 call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
1244 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1249 const unsigned char * pTypeFormat =
1250 &(pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset]);
1252 TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
1256 case STUBLESS_MARSHAL:
1257 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1259 if (params[i].attr.IsByValue)
1260 call_marshaller(pStubMsg, pArg, pTypeFormat);
1262 call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1266 if (params[i].attr.MustFree)
1268 if (params[i].attr.IsByValue)
1269 call_freer(pStubMsg, pArg, pTypeFormat);
1271 call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1273 else if (params[i].attr.ServerAllocSize)
1275 HeapFree(GetProcessHeap(), 0, *(void **)pArg);
1277 else if (params[i].attr.IsOut &&
1278 !params[i].attr.IsIn &&
1279 !params[i].attr.IsByValue)
1281 if (*pTypeFormat != RPC_FC_BIND_CONTEXT)
1282 pStubMsg->pfnFree(*(void **)pArg);
1286 case STUBLESS_INITOUT:
1287 if (!params[i].attr.IsIn &&
1288 params[i].attr.IsOut &&
1289 !params[i].attr.ServerAllocSize &&
1290 !params[i].attr.IsByValue)
1292 if (*pTypeFormat == RPC_FC_BIND_CONTEXT)
1294 NDR_SCONTEXT ctxt = NdrContextHandleInitialize(
1295 pStubMsg, pTypeFormat);
1296 *(void **)pArg = NDRSContextValue(ctxt);
1300 DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
1304 *(void **)pArg = NdrAllocate(pStubMsg, size);
1305 memset(*(void **)pArg, 0, size);
1310 case STUBLESS_UNMARSHAL:
1311 if (params[i].attr.ServerAllocSize)
1312 *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1313 params[i].attr.ServerAllocSize * 8);
1315 if (params[i].attr.IsIn)
1317 if (params[i].attr.IsByValue)
1318 call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
1320 call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
1323 case STUBLESS_CALCSIZE:
1324 if (params[i].attr.IsOut || params[i].attr.IsReturn)
1326 if (params[i].attr.IsByValue)
1327 call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
1329 call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1333 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1336 TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
1338 /* make a note of the address of the return value parameter for later */
1339 if (params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)pArg;
1345 static LONG_PTR *stub_do_old_args(MIDL_STUB_MESSAGE *pStubMsg,
1346 PFORMAT_STRING pFormat, int phase,
1347 unsigned short stack_size, BOOL object)
1351 /* current format string offset */
1352 int current_offset = 0;
1353 /* current stack offset */
1354 unsigned short current_stack_offset = object ? sizeof(void *) : 0;
1355 /* location to put retval into */
1356 LONG_PTR *retval_ptr = NULL;
1358 for (i = 0; TRUE; i++)
1360 const NDR_PARAM_OI_BASETYPE *pParam =
1361 (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
1362 unsigned char *pArg = pStubMsg->StackTop + current_stack_offset;
1364 /* no more parameters; exit loop */
1365 if (current_stack_offset >= stack_size)
1368 TRACE("param[%d]: old format\n", i);
1369 TRACE("\tparam_direction: 0x%x\n", pParam->param_direction);
1370 TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
1372 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
1373 pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1375 const unsigned char *pTypeFormat =
1376 &pParam->type_format_char;
1378 TRACE("\tbase type 0x%02x\n", *pTypeFormat);
1380 if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1381 retval_ptr = (LONG_PTR *)pArg;
1385 case STUBLESS_MARSHAL:
1386 if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1387 call_marshaller(pStubMsg, pArg, pTypeFormat);
1390 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
1391 call_freer(pStubMsg, pArg, pTypeFormat);
1393 case STUBLESS_INITOUT:
1395 case STUBLESS_UNMARSHAL:
1396 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
1397 call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
1399 case STUBLESS_CALCSIZE:
1400 if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1401 call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
1404 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1407 current_stack_offset += type_stack_size(*pTypeFormat);
1408 current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
1412 const NDR_PARAM_OI_OTHER *pParamOther =
1413 (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
1415 const unsigned char * pTypeFormat =
1416 &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset];
1417 const BOOL by_value = is_by_value( pTypeFormat );
1419 TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
1421 if (pParam->param_direction == RPC_FC_RETURN_PARAM)
1422 retval_ptr = (LONG_PTR *)pArg;
1426 case STUBLESS_MARSHAL:
1427 if (pParam->param_direction == RPC_FC_OUT_PARAM ||
1428 pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1429 pParam->param_direction == RPC_FC_RETURN_PARAM)
1431 if (!by_value) pArg = *(unsigned char **)pArg;
1432 call_marshaller(pStubMsg, pArg, pTypeFormat);
1436 if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1437 pParam->param_direction == RPC_FC_IN_PARAM)
1439 if (!by_value) pArg = *(unsigned char **)pArg;
1440 call_freer(pStubMsg, pArg, pTypeFormat);
1442 else if (pParam->param_direction == RPC_FC_OUT_PARAM && !by_value)
1443 pStubMsg->pfnFree(*(void **)pArg);
1445 case STUBLESS_INITOUT:
1446 if (pParam->param_direction == RPC_FC_OUT_PARAM && !by_value)
1448 DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
1452 *(void **)pArg = NdrAllocate(pStubMsg, size);
1453 memset(*(void **)pArg, 0, size);
1457 case STUBLESS_UNMARSHAL:
1458 if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1459 pParam->param_direction == RPC_FC_IN_PARAM)
1462 call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
1464 call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
1467 case STUBLESS_CALCSIZE:
1468 if (pParam->param_direction == RPC_FC_OUT_PARAM ||
1469 pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1470 pParam->param_direction == RPC_FC_RETURN_PARAM)
1472 if (!by_value) pArg = *(unsigned char **)pArg;
1473 call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
1477 RpcRaiseException(RPC_S_INTERNAL_ERROR);
1480 current_stack_offset += pParamOther->stack_size * sizeof(void *);
1481 current_offset += sizeof(NDR_PARAM_OI_OTHER);
1488 /***********************************************************************
1489 * NdrStubCall2 [RPCRT4.@]
1491 * Unmarshals [in] parameters, calls either a method in an object or a server
1492 * function, marshals any [out] parameters and frees any allocated data.
1495 * Used by stubless MIDL-generated code.
1497 LONG WINAPI NdrStubCall2(
1498 struct IRpcStubBuffer * pThis,
1499 struct IRpcChannelBuffer * pChannel,
1500 PRPC_MESSAGE pRpcMsg,
1501 DWORD * pdwStubPhase)
1503 const MIDL_SERVER_INFO *pServerInfo;
1504 const MIDL_STUB_DESC *pStubDesc;
1505 PFORMAT_STRING pFormat;
1506 MIDL_STUB_MESSAGE stubMsg;
1507 /* pointer to start of stack to pass into stub implementation */
1508 unsigned char * args;
1510 unsigned short stack_size;
1511 /* number of parameters. optional for client to give it to us */
1512 unsigned char number_of_params = ~0;
1513 /* cache of Oif_flags from v2 procedure header */
1514 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1515 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1516 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1517 /* the type of pass we are currently doing */
1519 /* header for procedure string */
1520 const NDR_PROC_HEADER *pProcHeader;
1521 /* offset in format string for start of params */
1522 int parameter_start_offset;
1523 /* current format string offset */
1525 /* -Oif or -Oicf generated format */
1526 BOOL bV2Format = FALSE;
1527 /* location to put retval into */
1528 LONG_PTR *retval_ptr = NULL;
1530 TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase);
1533 pServerInfo = CStdStubBuffer_GetServerInfo(pThis);
1535 pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1537 pStubDesc = pServerInfo->pStubDesc;
1538 pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1539 pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1541 TRACE("NDR Version: 0x%x\n", pStubDesc->Version);
1543 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1545 const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1546 stack_size = pProcHeader->stack_size;
1547 current_offset = sizeof(NDR_PROC_HEADER_RPC);
1552 stack_size = pProcHeader->stack_size;
1553 current_offset = sizeof(NDR_PROC_HEADER);
1556 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1559 switch (pProcHeader->handle_type)
1561 /* explicit binding: parse additional section */
1562 case RPC_FC_BIND_EXPLICIT:
1563 switch (pFormat[current_offset]) /* handle_type */
1565 case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
1566 current_offset += sizeof(NDR_EHD_PRIMITIVE);
1568 case RPC_FC_BIND_GENERIC: /* explicit generic */
1569 current_offset += sizeof(NDR_EHD_GENERIC);
1571 case RPC_FC_BIND_CONTEXT: /* explicit context */
1572 current_offset += sizeof(NDR_EHD_CONTEXT);
1575 ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1576 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1579 case RPC_FC_BIND_GENERIC: /* implicit generic */
1580 case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
1581 case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
1582 case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
1585 ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1586 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1589 bV2Format = (pStubDesc->Version >= 0x20000);
1593 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
1594 (const NDR_PROC_PARTIAL_OIF_HEADER *)&pFormat[current_offset];
1596 Oif_flags = pOIFHeader->Oi2Flags;
1597 number_of_params = pOIFHeader->number_of_params;
1599 current_offset += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1601 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
1603 if (Oif_flags.HasExtensions)
1605 const NDR_PROC_HEADER_EXTS *pExtensions =
1606 (const NDR_PROC_HEADER_EXTS *)&pFormat[current_offset];
1607 ext_flags = pExtensions->Flags2;
1608 current_offset += pExtensions->Size;
1612 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1613 NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel);
1615 NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc);
1617 /* create the full pointer translation tables, if requested */
1618 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1619 stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
1621 /* store the RPC flags away */
1622 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1623 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1625 /* use alternate memory allocation routines */
1626 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
1628 NdrRpcSsEnableAllocate(&stubMsg);
1630 FIXME("Set RPCSS memory allocation routines\n");
1633 if (Oif_flags.HasPipes)
1635 FIXME("pipes not supported yet\n");
1636 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1637 /* init pipes package */
1638 /* NdrPipesInitialize(...) */
1640 if (ext_flags.HasNewCorrDesc)
1642 /* initialize extra correlation package */
1643 FIXME("new correlation description not implemented\n");
1644 stubMsg.fHasNewCorrDesc = TRUE;
1647 /* convert strings, floating point values and endianess into our
1648 * preferred format */
1649 if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1650 NdrConvert(&stubMsg, pFormat);
1652 parameter_start_offset = current_offset;
1654 TRACE("allocating memory for stack of size %x\n", stack_size);
1656 args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size);
1657 stubMsg.StackTop = args; /* used by conformance of top-level objects */
1659 /* add the implicit This pointer as the first arg to the function if we
1660 * are calling an object method */
1662 *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject;
1664 for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++)
1666 TRACE("phase = %d\n", phase);
1669 case STUBLESS_CALLSERVER:
1670 /* call the server function */
1671 if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
1672 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg);
1675 SERVER_ROUTINE func;
1678 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1680 SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject;
1681 func = vtbl[pRpcMsg->ProcNum];
1684 func = pServerInfo->DispatchTable[pRpcMsg->ProcNum];
1686 /* FIXME: what happens with return values that don't fit into a single register on x86? */
1687 retval = call_server_func(func, args, stack_size);
1691 TRACE("stub implementation returned 0x%lx\n", retval);
1692 *retval_ptr = retval;
1695 TRACE("void stub implementation\n");
1698 stubMsg.Buffer = NULL;
1699 stubMsg.BufferLength = 0;
1702 case STUBLESS_GETBUFFER:
1703 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1704 NdrStubGetBuffer(pThis, pChannel, &stubMsg);
1709 pRpcMsg->BufferLength = stubMsg.BufferLength;
1710 /* allocate buffer for [out] and [ret] params */
1711 Status = I_RpcGetBuffer(pRpcMsg);
1713 RpcRaiseException(Status);
1714 stubMsg.Buffer = pRpcMsg->Buffer;
1717 case STUBLESS_UNMARSHAL:
1718 case STUBLESS_INITOUT:
1719 case STUBLESS_CALCSIZE:
1720 case STUBLESS_MARSHAL:
1723 retval_ptr = stub_do_args(&stubMsg, &pFormat[parameter_start_offset],
1724 phase, number_of_params);
1726 retval_ptr = stub_do_old_args(&stubMsg, &pFormat[parameter_start_offset],
1728 (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT));
1732 ERR("shouldn't reach here. phase %d\n", phase);
1737 pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer);
1739 if (ext_flags.HasNewCorrDesc)
1741 /* free extra correlation package */
1742 /* NdrCorrelationFree(&stubMsg); */
1745 if (Oif_flags.HasPipes)
1747 /* NdrPipesDone(...) */
1750 /* free the full pointer translation tables */
1751 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1752 NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
1754 /* free server function stack */
1755 HeapFree(GetProcessHeap(), 0, args);
1760 /***********************************************************************
1761 * NdrServerCall2 [RPCRT4.@]
1763 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
1766 NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
1769 /***********************************************************************
1770 * NdrStubCall [RPCRT4.@]
1772 LONG WINAPI NdrStubCall( struct IRpcStubBuffer *This, struct IRpcChannelBuffer *channel,
1773 PRPC_MESSAGE msg, DWORD *phase )
1775 return NdrStubCall2( This, channel, msg, phase );
1778 /***********************************************************************
1779 * NdrServerCall [RPCRT4.@]
1781 void WINAPI NdrServerCall( PRPC_MESSAGE msg )
1784 NdrStubCall( NULL, NULL, msg, &phase );
1787 struct async_call_data
1789 MIDL_STUB_MESSAGE *pStubMsg;
1790 const NDR_PROC_HEADER *pProcHeader;
1791 PFORMAT_STRING pHandleFormat;
1792 PFORMAT_STRING pParamFormat;
1793 RPC_BINDING_HANDLE hBinding;
1795 unsigned short stack_size;
1796 /* number of parameters. optional for client to give it to us */
1797 unsigned int number_of_params;
1798 /* correlation cache */
1799 ULONG_PTR NdrCorrCache[256];
1802 LONG_PTR CDECL ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, void **stack_top )
1804 /* pointer to start of stack where arguments start */
1805 PRPC_MESSAGE pRpcMsg;
1806 PMIDL_STUB_MESSAGE pStubMsg;
1807 RPC_ASYNC_STATE *pAsync;
1808 struct async_call_data *async_call_data;
1809 /* procedure number */
1810 unsigned short procedure_number;
1811 /* cache of Oif_flags from v2 procedure header */
1812 INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1813 /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1814 INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1815 /* the type of pass we are currently doing */
1817 /* header for procedure string */
1818 const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1819 /* -Oif or -Oicf generated format */
1820 BOOL bV2Format = FALSE;
1822 TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
1824 /* Later NDR language versions probably won't be backwards compatible */
1825 if (pStubDesc->Version > 0x50002)
1827 FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
1828 RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
1831 async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
1832 if (!async_call_data) RpcRaiseException(ERROR_OUTOFMEMORY);
1833 async_call_data->pProcHeader = pProcHeader;
1835 async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
1836 pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1);
1838 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1840 const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1841 async_call_data->stack_size = pProcHeader->stack_size;
1842 procedure_number = pProcHeader->proc_num;
1843 pFormat += sizeof(NDR_PROC_HEADER_RPC);
1847 async_call_data->stack_size = pProcHeader->stack_size;
1848 procedure_number = pProcHeader->proc_num;
1849 pFormat += sizeof(NDR_PROC_HEADER);
1851 TRACE("stack size: 0x%x\n", async_call_data->stack_size);
1852 TRACE("proc num: %d\n", procedure_number);
1854 /* create the full pointer translation tables, if requested */
1855 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1856 pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
1858 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1860 ERR("objects not supported\n");
1861 I_RpcFree(async_call_data);
1862 RpcRaiseException(RPC_X_BAD_STUB_DATA);
1865 NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number);
1867 TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1868 TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
1870 /* needed for conformance of top-level objects */
1871 pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size);
1872 memcpy(pStubMsg->StackTop, stack_top, async_call_data->stack_size);
1874 pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop;
1875 pAsync->StubInfo = async_call_data;
1876 async_call_data->pHandleFormat = pFormat;
1878 pFormat = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, &async_call_data->hBinding);
1879 if (!pFormat) goto done;
1881 bV2Format = (pStubDesc->Version >= 0x20000);
1885 const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
1886 (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
1888 Oif_flags = pOIFHeader->Oi2Flags;
1889 async_call_data->number_of_params = pOIFHeader->number_of_params;
1891 pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1893 TRACE("Oif_flags = %s\n", debugstr_INTERPRETER_OPT_FLAGS(Oif_flags) );
1895 if (Oif_flags.HasExtensions)
1897 const NDR_PROC_HEADER_EXTS *pExtensions =
1898 (const NDR_PROC_HEADER_EXTS *)pFormat;
1899 ext_flags = pExtensions->Flags2;
1900 pFormat += pExtensions->Size;
1905 pFormat = convert_old_args( pStubMsg, pFormat, async_call_data->stack_size,
1906 pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT,
1907 async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache),
1908 &async_call_data->number_of_params );
1911 async_call_data->pParamFormat = pFormat;
1913 pStubMsg->BufferLength = 0;
1915 /* store the RPC flags away */
1916 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1917 pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1919 /* use alternate memory allocation routines */
1920 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
1921 NdrRpcSmSetClientToOsf(pStubMsg);
1923 if (Oif_flags.HasPipes)
1925 FIXME("pipes not supported yet\n");
1926 RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1927 /* init pipes package */
1928 /* NdrPipesInitialize(...) */
1930 if (ext_flags.HasNewCorrDesc)
1932 /* initialize extra correlation package */
1933 NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
1937 * 1. PROXY_CALCSIZE - calculate the buffer size
1938 * 2. PROXY_GETBUFFER - allocate the buffer
1939 * 3. PROXY_MARHSAL - marshal [in] params into the buffer
1940 * 4. PROXY_SENDRECEIVE - send buffer
1941 * Then in NdrpCompleteAsyncClientCall:
1942 * 1. PROXY_SENDRECEIVE - receive buffer
1943 * 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
1945 for (phase = PROXY_CALCSIZE; phase <= PROXY_SENDRECEIVE; phase++)
1948 TRACE("phase = %d\n", phase);
1951 case PROXY_GETBUFFER:
1952 /* allocate the buffer */
1953 if (Oif_flags.HasPipes)
1954 /* NdrGetPipeBuffer(...) */
1955 FIXME("pipes not supported yet\n");
1958 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
1960 NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1962 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
1965 NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1967 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1968 status = I_RpcAsyncSetHandle(pRpcMsg, pAsync);
1969 if (status != RPC_S_OK)
1970 RpcRaiseException(status);
1972 case PROXY_SENDRECEIVE:
1973 pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1974 /* send the [in] params only */
1975 if (Oif_flags.HasPipes)
1976 /* NdrPipesSend(...) */
1977 FIXME("pipes not supported yet\n");
1980 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
1982 NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
1984 FIXME("using auto handle - call NdrNsSend when it gets implemented\n");
1988 pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
1989 status = I_RpcSend(pStubMsg->RpcMsg);
1990 if (status != RPC_S_OK)
1991 RpcRaiseException(status);
1996 case PROXY_CALCSIZE:
1998 client_do_args(pStubMsg, pFormat, phase, NULL, async_call_data->number_of_params, NULL);
2001 ERR("shouldn't reach here. phase %d\n", phase);
2007 TRACE("returning 0\n");
2011 RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
2013 /* pointer to start of stack where arguments start */
2014 PMIDL_STUB_MESSAGE pStubMsg;
2015 struct async_call_data *async_call_data;
2016 /* the type of pass we are currently doing */
2018 /* header for procedure string */
2019 const NDR_PROC_HEADER * pProcHeader;
2020 RPC_STATUS status = RPC_S_OK;
2022 if (!pAsync->StubInfo)
2023 return RPC_S_INVALID_ASYNC_HANDLE;
2025 async_call_data = pAsync->StubInfo;
2026 pStubMsg = async_call_data->pStubMsg;
2027 pProcHeader = async_call_data->pProcHeader;
2030 * 1. PROXY_CALCSIZE - calculate the buffer size
2031 * 2. PROXY_GETBUFFER - allocate the buffer
2032 * 3. PROXY_MARHSAL - marshal [in] params into the buffer
2033 * 4. PROXY_SENDRECEIVE - send buffer
2034 * Then in NdrpCompleteAsyncClientCall:
2035 * 1. PROXY_SENDRECEIVE - receive buffer
2036 * 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
2038 for (phase = PROXY_SENDRECEIVE; phase <= PROXY_UNMARSHAL; phase++)
2042 case PROXY_SENDRECEIVE:
2043 pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
2044 /* receive the [out] params */
2045 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
2047 NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
2049 FIXME("using auto handle - call NdrNsReceive when it gets implemented\n");
2053 status = I_RpcReceive(pStubMsg->RpcMsg);
2054 if (status != RPC_S_OK)
2056 pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;
2057 pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
2058 pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
2059 pStubMsg->Buffer = pStubMsg->BufferStart;
2062 /* convert strings, floating point values and endianess into our
2063 * preferred format */
2065 if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
2066 NdrConvert(pStubMsg, pFormat);
2070 case PROXY_UNMARSHAL:
2071 client_do_args(pStubMsg, async_call_data->pParamFormat, phase,
2072 NULL, async_call_data->number_of_params, Reply);
2075 ERR("shouldn't reach here. phase %d\n", phase);
2081 if (pStubMsg->fHasNewCorrDesc)
2083 /* free extra correlation package */
2084 NdrCorrelationFree(pStubMsg);
2087 /* free the full pointer translation tables */
2088 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
2089 NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
2091 /* free marshalling buffer */
2092 NdrFreeBuffer(pStubMsg);
2093 client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding);
2095 I_RpcFree(pStubMsg->StackTop);
2096 I_RpcFree(async_call_data);
2098 TRACE("-- 0x%x\n", status);
2104 __ASM_GLOBAL_FUNC( NdrAsyncClientCall,
2105 "movq %r8,0x18(%rsp)\n\t"
2106 "movq %r9,0x20(%rsp)\n\t"
2107 "leaq 0x18(%rsp),%r8\n\t"
2108 "subq $0x28,%rsp\n\t"
2109 __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t")
2110 "call " __ASM_NAME("ndr_async_client_call") "\n\t"
2111 "addq $0x28,%rsp\n\t"
2112 __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t")
2115 #else /* __x86_64__ */
2117 /***********************************************************************
2118 * NdrAsyncClientCall [RPCRT4.@]
2120 CLIENT_CALL_RETURN WINAPIV NdrAsyncClientCall( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... )
2125 __ms_va_start( args, format );
2126 ret = ndr_async_client_call( desc, format, va_arg( args, void ** ));
2127 __ms_va_end( args );
2128 return *(CLIENT_CALL_RETURN *)&ret;
2131 #endif /* __x86_64__ */
2133 RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis,
2134 struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg,
2135 DWORD * pdwStubPhase)
2137 FIXME("unimplemented, expect crash!\n");