winex11: Implement cursor clipping using a pointer grab.
[wine] / dlls / rpcrt4 / ndr_stubless.c
1 /*
2  * NDR -Oi,-Oif,-Oicf Interpreter
3  *
4  * Copyright 2001 Ove Kåven, TransGaming Technologies
5  * Copyright 2003-5 Robert Shearman (for CodeWeavers)
6  *
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.
11  *
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.
16  *
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
20  *
21  * TODO:
22  *  - Pipes
23  *  - Some types of binding handles
24  */
25
26 #include "config.h"
27 #include "wine/port.h"
28
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winerror.h"
36
37 #include "objbase.h"
38 #include "rpc.h"
39 #include "rpcproxy.h"
40
41 #include "wine/exception.h"
42 #include "wine/debug.h"
43 #include "wine/rpcfc.h"
44
45 #include "cpsf.h"
46 #include "ndr_misc.h"
47 #include "ndr_stubless.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
50
51 #define NDR_TABLE_MASK 127
52
53 static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
54 {
55     NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK];
56     if (m) m(pStubMsg, pMemory, pFormat);
57     else
58     {
59         FIXME("format type 0x%x not implemented\n", pFormat[0]);
60         RpcRaiseException(RPC_X_BAD_STUB_DATA);
61     }
62 }
63
64 static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
65 {
66     NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK];
67     if (m) return m(pStubMsg, pMemory, pFormat);
68     else
69     {
70         FIXME("format type 0x%x not implemented\n", pFormat[0]);
71         RpcRaiseException(RPC_X_BAD_STUB_DATA);
72         return NULL;
73     }
74 }
75
76 static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc)
77 {
78     NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK];
79     if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc);
80     else
81     {
82         FIXME("format type 0x%x not implemented\n", pFormat[0]);
83         RpcRaiseException(RPC_X_BAD_STUB_DATA);
84         return NULL;
85     }
86 }
87
88 static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
89 {
90     NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK];
91     if (m) m(pStubMsg, pMemory, pFormat);
92 }
93
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
101
102 void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage)
103 {
104 #if 0 /* these functions are not defined yet */
105     pMessage->pfnAllocate = NdrRpcSmClientAllocate;
106     pMessage->pfnFree = NdrRpcSmClientFree;
107 #endif
108 }
109
110 static void dump_RPC_FC_PROC_PF(PARAM_ATTRIBUTES param_attributes)
111 {
112     if (param_attributes.MustSize) TRACE(" MustSize");
113     if (param_attributes.MustFree) TRACE(" MustFree");
114     if (param_attributes.IsPipe) TRACE(" IsPipe");
115     if (param_attributes.IsIn) TRACE(" IsIn");
116     if (param_attributes.IsOut) TRACE(" IsOut");
117     if (param_attributes.IsReturn) TRACE(" IsReturn");
118     if (param_attributes.IsBasetype) TRACE(" IsBasetype");
119     if (param_attributes.IsByValue) TRACE(" IsByValue");
120     if (param_attributes.IsSimpleRef) TRACE(" IsSimpleRef");
121     if (param_attributes.IsDontCallFreeInst) TRACE(" IsDontCallFreeInst");
122     if (param_attributes.SaveForAsyncFinish) TRACE(" SaveForAsyncFinish");
123     if (param_attributes.ServerAllocSize) TRACE(" ServerAllocSize = %d", param_attributes.ServerAllocSize * 8);
124 }
125
126 static void dump_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags)
127 {
128     if (Oi2Flags.ServerMustSize) TRACE(" ServerMustSize");
129     if (Oi2Flags.ClientMustSize) TRACE(" ClientMustSize");
130     if (Oi2Flags.HasReturn) TRACE(" HasReturn");
131     if (Oi2Flags.HasPipes) TRACE(" HasPipes");
132     if (Oi2Flags.Unused) TRACE(" Unused");
133     if (Oi2Flags.HasAsyncUuid) TRACE(" HasAsyncUuid");
134     if (Oi2Flags.HasExtensions) TRACE(" HasExtensions");
135     if (Oi2Flags.HasAsyncHandle) TRACE(" HasAsyncHandle");
136     TRACE("\n");
137 }
138
139 #define ARG_FROM_OFFSET(args, offset) ((args) + (offset))
140
141 static PFORMAT_STRING client_get_handle(
142     PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
143     PFORMAT_STRING pFormat, handle_t *phBinding)
144 {
145     /* binding */
146     switch (pProcHeader->handle_type)
147     {
148     /* explicit binding: parse additional section */
149     case RPC_FC_BIND_EXPLICIT:
150         switch (*pFormat) /* handle_type */
151         {
152         case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
153             {
154                 const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat;
155
156                 TRACE("Explicit primitive handle @ %d\n", pDesc->offset);
157
158                 if (pDesc->flag) /* pointer to binding */
159                     *phBinding = **(handle_t **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
160                 else
161                     *phBinding = *(handle_t *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
162                 return pFormat + sizeof(NDR_EHD_PRIMITIVE);
163             }
164         case RPC_FC_BIND_GENERIC: /* explicit generic */
165             {
166                 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat;
167                 void *pObject = NULL;
168                 void *pArg;
169                 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
170
171                 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
172
173                 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
174                     pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
175                 else
176                     pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
177                 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
178                 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
179                 *phBinding = pGenPair->pfnBind(pObject);
180                 return pFormat + sizeof(NDR_EHD_GENERIC);
181             }
182         case RPC_FC_BIND_CONTEXT: /* explicit context */
183             {
184                 const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat;
185                 NDR_CCONTEXT context_handle;
186                 TRACE("Explicit bind context\n");
187                 if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR)
188                 {
189                     TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n");
190                     context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
191                 }
192                 else
193                     context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
194                 if ((pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) &&
195                     !context_handle)
196                 {
197                     ERR("null context handle isn't allowed\n");
198                     RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT);
199                     return NULL;
200                 }
201                 *phBinding = NDRCContextBinding(context_handle);
202                 /* FIXME: should we store this structure in stubMsg.pContext? */
203                 return pFormat + sizeof(NDR_EHD_CONTEXT);
204             }
205         default:
206             ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
207             RpcRaiseException(RPC_X_BAD_STUB_DATA);
208         }
209         break;
210     case RPC_FC_BIND_GENERIC: /* implicit generic */
211         FIXME("RPC_FC_BIND_GENERIC\n");
212         RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
213         break;
214     case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
215         TRACE("Implicit primitive handle\n");
216         *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle;
217         break;
218     case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
219         FIXME("RPC_FC_CALLBACK_HANDLE\n");
220         break;
221     case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
222         /* strictly speaking, it isn't necessary to set hBinding here
223          * since it isn't actually used (hence the automatic in its name),
224          * but then why does MIDL generate a valid entry in the
225          * MIDL_STUB_DESC for it? */
226         TRACE("Implicit auto handle\n");
227         *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle;
228         break;
229     default:
230         ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
231         RpcRaiseException(RPC_X_BAD_STUB_DATA);
232     }
233     return pFormat;
234 }
235
236 static void client_free_handle(
237     PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
238     PFORMAT_STRING pFormat, handle_t hBinding)
239 {
240     /* binding */
241     switch (pProcHeader->handle_type)
242     {
243     /* explicit binding: parse additional section */
244     case RPC_FC_BIND_EXPLICIT:
245         switch (*pFormat) /* handle_type */
246         {
247         case RPC_FC_BIND_GENERIC: /* explicit generic */
248             {
249                 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat;
250                 void *pObject = NULL;
251                 void *pArg;
252                 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
253
254                 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
255
256                 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
257                     pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
258                 else
259                     pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
260                 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
261                 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
262                 pGenPair->pfnUnbind(pObject, hBinding);
263                 break;
264             }
265         case RPC_FC_BIND_CONTEXT: /* explicit context */
266         case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
267             break;
268         default:
269             ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
270             RpcRaiseException(RPC_X_BAD_STUB_DATA);
271         }
272         break;
273     case RPC_FC_BIND_GENERIC: /* implicit generic */
274         FIXME("RPC_FC_BIND_GENERIC\n");
275         RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
276         break;
277     case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
278     case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
279     case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
280         break;
281     default:
282         ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
283         RpcRaiseException(RPC_X_BAD_STUB_DATA);
284     }
285 }
286
287 static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
288     int phase, unsigned char *args, unsigned short number_of_params,
289     unsigned char *pRetVal)
290 {
291     /* current format string offset */
292     int current_offset = 0;
293     /* current stack offset */
294     unsigned short current_stack_offset = 0;
295     /* counter */
296     unsigned short i;
297
298     for (i = 0; i < number_of_params; i++)
299     {
300         const NDR_PARAM_OIF_BASETYPE *pParam =
301             (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
302         unsigned char * pArg;
303
304         current_stack_offset = pParam->stack_offset;
305         pArg = ARG_FROM_OFFSET(args, current_stack_offset);
306
307         TRACE("param[%d]: new format\n", i);
308         TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
309         TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
310         TRACE("\tmemory addr (before): %p\n", pArg);
311
312         if (pParam->param_attributes.IsBasetype)
313         {
314             const unsigned char * pTypeFormat =
315                 &pParam->type_format_char;
316
317             if (pParam->param_attributes.IsSimpleRef)
318                 pArg = *(unsigned char **)pArg;
319
320             TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
321
322             switch (phase)
323             {
324             case PROXY_CALCSIZE:
325                 if (pParam->param_attributes.IsIn)
326                     call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
327                 break;
328             case PROXY_MARSHAL:
329                 if (pParam->param_attributes.IsIn)
330                     call_marshaller(pStubMsg, pArg, pTypeFormat);
331                 break;
332             case PROXY_UNMARSHAL:
333                 if (pParam->param_attributes.IsOut)
334                 {
335                     if (pParam->param_attributes.IsReturn)
336                         call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0);
337                     else
338                         call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
339                     TRACE("pRetVal = %p\n", pRetVal);
340                 }
341                 break;
342             default:
343                 RpcRaiseException(RPC_S_INTERNAL_ERROR);
344             }
345
346             current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
347         }
348         else
349         {
350             const NDR_PARAM_OIF_OTHER *pParamOther =
351                 (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
352
353             const unsigned char * pTypeFormat =
354                 &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]);
355
356             /* if a simple ref pointer then we have to do the
357              * check for the pointer being non-NULL. */
358             if (pParam->param_attributes.IsSimpleRef)
359             {
360                 if (!*(unsigned char **)pArg)
361                     RpcRaiseException(RPC_X_NULL_REF_POINTER);
362             }
363
364             TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat);
365
366             switch (phase)
367             {
368             case PROXY_CALCSIZE:
369                 if (pParam->param_attributes.IsIn)
370                 {
371                     if (pParam->param_attributes.IsByValue)
372                         call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
373                     else
374                         call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
375                 }
376                 break;
377             case PROXY_MARSHAL:
378                 if (pParam->param_attributes.IsIn)
379                 {
380                     if (pParam->param_attributes.IsByValue)
381                         call_marshaller(pStubMsg, pArg, pTypeFormat);
382                     else
383                         call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
384                 }
385                 break;
386             case PROXY_UNMARSHAL:
387                 if (pParam->param_attributes.IsOut)
388                 {
389                     if (pParam->param_attributes.IsReturn)
390                         call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0);
391                     else if (pParam->param_attributes.IsByValue)
392                         call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
393                     else
394                         call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
395                 }
396                 break;
397             default:
398                 RpcRaiseException(RPC_S_INTERNAL_ERROR);
399             }
400
401             current_offset += sizeof(NDR_PARAM_OIF_OTHER);
402         }
403         TRACE("\tmemory addr (after): %p\n", pArg);
404     }
405 }
406
407 static unsigned int type_stack_size(unsigned char fc)
408 {
409     switch (fc)
410     {
411     case RPC_FC_BYTE:
412     case RPC_FC_CHAR:
413     case RPC_FC_SMALL:
414     case RPC_FC_USMALL:
415         return sizeof(char);
416     case RPC_FC_WCHAR:
417     case RPC_FC_SHORT:
418     case RPC_FC_USHORT:
419         return sizeof(short);
420     case RPC_FC_LONG:
421     case RPC_FC_ULONG:
422     case RPC_FC_ENUM16:
423     case RPC_FC_ENUM32:
424         return sizeof(int);
425     case RPC_FC_FLOAT:
426         return sizeof(float);
427     case RPC_FC_DOUBLE:
428         return sizeof(double);
429     case RPC_FC_HYPER:
430         return sizeof(ULONGLONG);
431     case RPC_FC_ERROR_STATUS_T:
432         return sizeof(error_status_t);
433     case RPC_FC_IGNORE:
434         return sizeof(void *);
435     default:
436         ERR("invalid base type 0x%x\n", fc);
437         RpcRaiseException(RPC_S_INTERNAL_ERROR);
438     }
439 }
440
441 void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
442     PFORMAT_STRING pFormat, int phase, unsigned char *args,
443     unsigned short stack_size,
444     unsigned char *pRetVal, BOOL object_proc, BOOL ignore_retval)
445 {
446     /* current format string offset */
447     int current_offset = 0;
448     /* current stack offset */
449     unsigned short current_stack_offset = 0;
450     /* counter */
451     unsigned short i;
452
453     /* NOTE: V1 style format doesn't terminate on the number_of_params
454      * condition as it doesn't have this attribute. Instead it
455      * terminates when the stack size given in the header is exceeded.
456      */
457     for (i = 0; TRUE; i++)
458     {
459         const NDR_PARAM_OI_BASETYPE *pParam =
460             (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
461         /* note: current_stack_offset starts after the This pointer
462          * if present, so adjust this */
463         unsigned short current_stack_offset_adjusted = current_stack_offset +
464             (object_proc ? sizeof(void *) : 0);
465         unsigned char * pArg = ARG_FROM_OFFSET(args, current_stack_offset_adjusted);
466
467         /* no more parameters; exit loop */
468         if (current_stack_offset_adjusted >= stack_size)
469             break;
470
471         TRACE("param[%d]: old format\n", i);
472         TRACE("\tparam_direction: 0x%x\n", pParam->param_direction);
473         TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted);
474         TRACE("\tmemory addr (before): %p\n", pArg);
475
476         if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
477             pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
478         {
479             const unsigned char * pTypeFormat =
480                 &pParam->type_format_char;
481
482             TRACE("\tbase type 0x%02x\n", *pTypeFormat);
483
484             switch (phase)
485             {
486             case PROXY_CALCSIZE:
487                 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
488                     call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
489                 break;
490             case PROXY_MARSHAL:
491                 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
492                     call_marshaller(pStubMsg, pArg, pTypeFormat);
493                 break;
494             case PROXY_UNMARSHAL:
495                 if (!ignore_retval &&
496                     pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
497                 {
498                     if (pParam->param_direction & RPC_FC_RETURN_PARAM)
499                         call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0);
500                     else
501                         call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
502                 }
503                 break;
504             default:
505                 RpcRaiseException(RPC_S_INTERNAL_ERROR);
506             }
507
508             current_stack_offset += type_stack_size(*pTypeFormat);
509             current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
510         }
511         else
512         {
513             const NDR_PARAM_OI_OTHER *pParamOther = 
514                 (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
515
516             const unsigned char *pTypeFormat =
517                 &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset];
518
519             TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
520
521             switch (phase)
522             {
523             case PROXY_CALCSIZE:
524                 if (pParam->param_direction == RPC_FC_IN_PARAM ||
525                     pParam->param_direction & RPC_FC_IN_OUT_PARAM)
526                     call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
527                 break;
528             case PROXY_MARSHAL:
529                 if (pParam->param_direction == RPC_FC_IN_PARAM ||
530                     pParam->param_direction & RPC_FC_IN_OUT_PARAM)
531                     call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
532                 break;
533             case PROXY_UNMARSHAL:
534                 if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
535                     pParam->param_direction == RPC_FC_OUT_PARAM)
536                     call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
537                 else if (pParam->param_direction == RPC_FC_RETURN_PARAM)
538                     call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0);
539                 break;
540             default:
541                 RpcRaiseException(RPC_S_INTERNAL_ERROR);
542             }
543
544             current_stack_offset += pParamOther->stack_size * sizeof(INT);
545             current_offset += sizeof(NDR_PARAM_OI_OTHER);
546         }
547         TRACE("\tmemory addr (after): %p\n", pArg);
548     }
549 }
550
551 /* the return type should be CLIENT_CALL_RETURN, but this is incompatible
552  * with the way gcc returns structures. "void *" should be the largest type
553  * that MIDL should allow you to return anyway */
554 LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, ...)
555 {
556     /* pointer to start of stack where arguments start */
557     RPC_MESSAGE rpcMsg;
558     MIDL_STUB_MESSAGE stubMsg;
559     handle_t hBinding = NULL;
560     /* procedure number */
561     unsigned short procedure_number;
562     /* size of stack */
563     unsigned short stack_size;
564     /* number of parameters. optional for client to give it to us */
565     unsigned char number_of_params = ~0;
566     /* cache of Oif_flags from v2 procedure header */
567     INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
568     /* cache of extension flags from NDR_PROC_HEADER_EXTS */
569     INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
570     /* the type of pass we are currently doing */
571     int phase;
572     /* header for procedure string */
573     const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
574     /* -Oif or -Oicf generated format */
575     BOOL bV2Format = FALSE;
576     /* the value to return to the client from the remote procedure */
577     LONG_PTR RetVal = 0;
578     /* the pointer to the object when in OLE mode */
579     void * This = NULL;
580     PFORMAT_STRING pHandleFormat;
581     /* correlation cache */
582     ULONG_PTR NdrCorrCache[256];
583     __ms_va_list args;
584
585     TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
586
587     TRACE("NDR Version: 0x%x\n", pStubDesc->Version);
588
589     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
590     {
591         const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
592         stack_size = pProcHeader->stack_size;
593         procedure_number = pProcHeader->proc_num;
594         pFormat += sizeof(NDR_PROC_HEADER_RPC);
595     }
596     else
597     {
598         stack_size = pProcHeader->stack_size;
599         procedure_number = pProcHeader->proc_num;
600         pFormat += sizeof(NDR_PROC_HEADER);
601     }
602     TRACE("stack size: 0x%x\n", stack_size);
603     TRACE("proc num: %d\n", procedure_number);
604
605     /* create the full pointer translation tables, if requested */
606     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
607         stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
608
609     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
610     {
611         /* object is always the first argument */
612         This = **(void *const **)(&pFormat+1);
613         NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number);
614     }
615     else
616         NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number);
617
618     TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
619     TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
620
621     /* needed for conformance of top-level objects */
622     __ms_va_start( args, pFormat );
623     stubMsg.StackTop = va_arg( args, unsigned char * );
624     __ms_va_end( args );
625
626     pHandleFormat = pFormat;
627
628     /* we only need a handle if this isn't an object method */
629     if (!(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT))
630     {
631         pFormat = client_get_handle(&stubMsg, pProcHeader, pHandleFormat, &hBinding);
632         if (!pFormat) return 0;
633     }
634
635     bV2Format = (pStubDesc->Version >= 0x20000);
636
637     if (bV2Format)
638     {
639         const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
640             (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
641
642         Oif_flags = pOIFHeader->Oi2Flags;
643         number_of_params = pOIFHeader->number_of_params;
644
645         pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
646     }
647
648     TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
649
650     if (Oif_flags.HasExtensions)
651     {
652         const NDR_PROC_HEADER_EXTS *pExtensions =
653             (const NDR_PROC_HEADER_EXTS *)pFormat;
654         ext_flags = pExtensions->Flags2;
655         pFormat += pExtensions->Size;
656     }
657
658     stubMsg.BufferLength = 0;
659
660     /* store the RPC flags away */
661     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
662         rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
663
664     /* use alternate memory allocation routines */
665     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
666         NdrRpcSmSetClientToOsf(&stubMsg);
667
668     if (Oif_flags.HasPipes)
669     {
670         FIXME("pipes not supported yet\n");
671         RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
672         /* init pipes package */
673         /* NdrPipesInitialize(...) */
674     }
675     if (ext_flags.HasNewCorrDesc)
676     {
677         /* initialize extra correlation package */
678         NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0);
679     }
680
681     /* order of phases:
682      * 1. PROXY_CALCSIZE - calculate the buffer size
683      * 2. PROXY_GETBUFFER - allocate the buffer
684      * 3. PROXY_MARHSAL - marshal [in] params into the buffer
685      * 4. PROXY_SENDRECEIVE - send/receive buffer
686      * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer
687      */
688     if ((pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) ||
689         (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_HAS_COMM_OR_FAULT))
690     {
691         __TRY
692         {
693             for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++)
694             {
695                 TRACE("phase = %d\n", phase);
696                 switch (phase)
697                 {
698                 case PROXY_GETBUFFER:
699                     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
700                     {
701                         /* allocate the buffer */
702                         NdrProxyGetBuffer(This, &stubMsg);
703                     }
704                     else
705                     {
706                         /* allocate the buffer */
707                         if (Oif_flags.HasPipes)
708                             /* NdrGetPipeBuffer(...) */
709                             FIXME("pipes not supported yet\n");
710                         else
711                         {
712                             if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
713 #if 0
714                                 NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
715 #else
716                                 FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
717 #endif
718                             else
719                                 NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
720                         }
721                     }
722                     break;
723                 case PROXY_SENDRECEIVE:
724                     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
725                     {
726                         /* send the [in] params and receive the [out] and [retval]
727                          * params */
728                         NdrProxySendReceive(This, &stubMsg);
729                     }
730                     else
731                     {
732                         /* send the [in] params and receive the [out] and [retval]
733                          * params */
734                         if (Oif_flags.HasPipes)
735                             /* NdrPipesSendReceive(...) */
736                             FIXME("pipes not supported yet\n");
737                         else
738                         {
739                             if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
740 #if 0
741                                 NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
742 #else
743                                 FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
744 #endif
745                             else
746                                 NdrSendReceive(&stubMsg, stubMsg.Buffer);
747                         }
748                     }
749
750                     /* convert strings, floating point values and endianess into our
751                      * preferred format */
752                     if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
753                         NdrConvert(&stubMsg, pFormat);
754
755                     break;
756                 case PROXY_CALCSIZE:
757                 case PROXY_MARSHAL:
758                 case PROXY_UNMARSHAL:
759                     if (bV2Format)
760                         client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop,
761                             number_of_params, (unsigned char *)&RetVal);
762                     else
763                         client_do_args_old_format(&stubMsg, pFormat, phase,
764                             stubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
765                             (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT), FALSE);
766                     break;
767                 default:
768                     ERR("shouldn't reach here. phase %d\n", phase);
769                     break;
770                 }
771             }
772         }
773         __EXCEPT_ALL
774         {
775             if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
776                 RetVal = NdrProxyErrorHandler(GetExceptionCode());
777             else
778             {
779                 const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number];
780                 ULONG *comm_status;
781                 ULONG *fault_status;
782
783                 TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset);
784
785                 if (comm_fault_offsets->CommOffset == -1)
786                     comm_status = (ULONG *)&RetVal;
787                 else if (comm_fault_offsets->CommOffset >= 0)
788                     comm_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset);
789                 else
790                     comm_status = NULL;
791
792                 if (comm_fault_offsets->FaultOffset == -1)
793                     fault_status = (ULONG *)&RetVal;
794                 else if (comm_fault_offsets->FaultOffset >= 0)
795                     fault_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset);
796                 else
797                     fault_status = NULL;
798
799                 NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status,
800                                          GetExceptionCode());
801             }
802         }
803         __ENDTRY
804     }
805     else
806     {
807         /* order of phases:
808          * 1. PROXY_CALCSIZE - calculate the buffer size
809          * 2. PROXY_GETBUFFER - allocate the buffer
810          * 3. PROXY_MARHSAL - marshal [in] params into the buffer
811          * 4. PROXY_SENDRECEIVE - send/receive buffer
812          * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer
813          */
814         for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++)
815         {
816             TRACE("phase = %d\n", phase);
817             switch (phase)
818             {
819             case PROXY_GETBUFFER:
820                 /* allocate the buffer */
821                 if (Oif_flags.HasPipes)
822                     /* NdrGetPipeBuffer(...) */
823                     FIXME("pipes not supported yet\n");
824                 else
825                 {
826                     if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
827 #if 0
828                         NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
829 #else
830                         FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
831 #endif
832                     else
833                         NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
834                 }
835                 break;
836             case PROXY_SENDRECEIVE:
837                 /* send the [in] params and receive the [out] and [retval]
838                  * params */
839                 if (Oif_flags.HasPipes)
840                     /* NdrPipesSendReceive(...) */
841                     FIXME("pipes not supported yet\n");
842                 else
843                 {
844                     if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
845 #if 0
846                         NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
847 #else
848                         FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
849 #endif
850                     else
851                         NdrSendReceive(&stubMsg, stubMsg.Buffer);
852                 }
853
854                 /* convert strings, floating point values and endianess into our
855                  * preferred format */
856                 if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
857                     NdrConvert(&stubMsg, pFormat);
858
859                 break;
860             case PROXY_CALCSIZE:
861             case PROXY_MARSHAL:
862             case PROXY_UNMARSHAL:
863                 if (bV2Format)
864                     client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop,
865                         number_of_params, (unsigned char *)&RetVal);
866                 else
867                     client_do_args_old_format(&stubMsg, pFormat, phase,
868                         stubMsg.StackTop, stack_size, (unsigned char *)&RetVal,
869                         (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT), FALSE);
870                 break;
871             default:
872                 ERR("shouldn't reach here. phase %d\n", phase);
873                 break;
874             }
875         }
876     }
877
878     if (ext_flags.HasNewCorrDesc)
879     {
880         /* free extra correlation package */
881         NdrCorrelationFree(&stubMsg);
882     }
883
884     if (Oif_flags.HasPipes)
885     {
886         /* NdrPipesDone(...) */
887     }
888
889     /* free the full pointer translation tables */
890     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
891         NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
892
893     /* free marshalling buffer */
894     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
895         NdrProxyFreeBuffer(This, &stubMsg);
896     else
897     {
898         NdrFreeBuffer(&stubMsg);
899         client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding);
900     }
901
902     TRACE("RetVal = 0x%lx\n", RetVal);
903
904     return RetVal;
905 }
906
907 /* Calls a function with the specified arguments, restoring the stack
908  * properly afterwards as we don't know the calling convention of the
909  * function */
910 #if defined __i386__ && defined _MSC_VER
911 __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size)
912 {
913     __asm
914     {
915         push ebp
916         push edi            ; Save registers
917         push esi
918         mov ebp, esp
919         mov eax, [ebp+16]   ; Get stack size
920         sub esp, eax        ; Make room in stack for arguments
921         mov edi, esp
922         mov ecx, eax
923         mov esi, [ebp+12]
924         shr ecx, 2
925         cld
926         rep movsd           ; Copy dword blocks
927         call [ebp+8]        ; Call function
928         lea esp, [ebp-8]    ; Restore stack
929         pop esi             ; Restore registers
930         pop edi
931         pop ebp
932         ret
933     }
934 }
935 #elif defined __i386__ && defined __GNUC__
936 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
937 __ASM_GLOBAL_FUNC(call_server_func,
938     "pushl %ebp\n\t"
939     __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
940     __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
941     "movl %esp,%ebp\n\t"
942     __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
943     "pushl %edi\n\t"            /* Save registers */
944     __ASM_CFI(".cfi_rel_offset %edi,-4\n\t")
945     "pushl %esi\n\t"
946     __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
947     "movl 16(%ebp), %eax\n\t"   /* Get stack size */
948     "subl %eax, %esp\n\t"       /* Make room in stack for arguments */
949     "andl $~15, %esp\n\t"       /* Make sure stack has 16-byte alignment for Mac OS X */
950     "movl %esp, %edi\n\t"
951     "movl %eax, %ecx\n\t"
952     "movl 12(%ebp), %esi\n\t"
953     "shrl $2, %ecx\n\t"         /* divide by 4 */
954     "cld\n\t"
955     "rep; movsl\n\t"            /* Copy dword blocks */
956     "call *8(%ebp)\n\t"         /* Call function */
957     "leal -8(%ebp), %esp\n\t"   /* Restore stack */
958     "popl %esi\n\t"             /* Restore registers */
959     __ASM_CFI(".cfi_same_value %esi\n\t")
960     "popl %edi\n\t"
961     __ASM_CFI(".cfi_same_value %edi\n\t")
962     "popl %ebp\n\t"
963     __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
964     __ASM_CFI(".cfi_same_value %ebp\n\t")
965     "ret" )
966 #else
967 #warning call_server_func not implemented for your architecture
968 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
969 {
970     FIXME("Not implemented for your architecture\n");
971     return 0;
972 }
973 #endif
974
975 static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
976 {
977     DWORD size;
978     switch(*pFormat)
979     {
980     case RPC_FC_STRUCT:
981         size = *(const WORD*)(pFormat + 2);
982         break;
983     case RPC_FC_CARRAY:
984         size = *(const WORD*)(pFormat + 2);
985         ComputeConformance(pStubMsg, NULL, pFormat + 4, 0);
986         size *= pStubMsg->MaxCount;
987         break;
988     case RPC_FC_SMFARRAY:
989         size = *(const WORD*)(pFormat + 2);
990         break;
991     case RPC_FC_LGFARRAY:
992         size = *(const DWORD*)(pFormat + 2);
993         break;
994     case RPC_FC_BOGUS_ARRAY:
995         pFormat = ComputeConformance(pStubMsg, NULL, pFormat + 4, *(const WORD*)&pFormat[2]);
996         TRACE("conformance = %ld\n", pStubMsg->MaxCount);
997         pFormat = ComputeVariance(pStubMsg, NULL, pFormat, pStubMsg->MaxCount);
998         size = ComplexStructSize(pStubMsg, pFormat);
999         size *= pStubMsg->MaxCount;
1000         break;
1001     case RPC_FC_C_CSTRING:
1002     case RPC_FC_C_WSTRING:
1003         if (*pFormat == RPC_FC_C_CSTRING)
1004             size = sizeof(CHAR);
1005         else
1006             size = sizeof(WCHAR);
1007         if (pFormat[1] == RPC_FC_STRING_SIZED)
1008             ComputeConformance(pStubMsg, NULL, pFormat + 2, 0);
1009         else
1010             pStubMsg->MaxCount = 0;
1011         size *= pStubMsg->MaxCount;
1012         break;
1013     default:
1014         FIXME("Unhandled type %02x\n", *pFormat);
1015         /* fallthrough */
1016     case RPC_FC_RP:
1017         size = sizeof(void *);
1018         break;
1019     }
1020     return size;
1021 }
1022
1023 static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg,
1024                               PFORMAT_STRING pFormat, int phase,
1025                               unsigned char *args,
1026                               unsigned short number_of_params)
1027 {
1028     /* counter */
1029     unsigned short i;
1030     /* current format string offset */
1031     int current_offset = 0;
1032     /* current stack offset */
1033     unsigned short current_stack_offset = 0;
1034     /* location to put retval into */
1035     LONG_PTR *retval_ptr = NULL;
1036
1037     for (i = 0; i < number_of_params; i++)
1038     {
1039         const NDR_PARAM_OIF_BASETYPE *pParam =
1040         (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
1041         unsigned char *pArg;
1042
1043         current_stack_offset = pParam->stack_offset;
1044         pArg = args + current_stack_offset;
1045
1046         TRACE("param[%d]: new format\n", i);
1047         TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
1048         TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
1049         TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg);
1050
1051         if (pParam->param_attributes.IsBasetype)
1052         {
1053             const unsigned char *pTypeFormat =
1054             &pParam->type_format_char;
1055
1056             TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
1057
1058             /* make a note of the address of the return value parameter for later */
1059             if (pParam->param_attributes.IsReturn)
1060                 retval_ptr = (LONG_PTR *)pArg;
1061
1062             switch (phase)
1063             {
1064                 case STUBLESS_MARSHAL:
1065                     if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
1066                     {
1067                         if (pParam->param_attributes.IsSimpleRef)
1068                             call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1069                         else
1070                             call_marshaller(pStubMsg, pArg, pTypeFormat);
1071                     }
1072                     break;
1073                 case STUBLESS_FREE:
1074                     if (pParam->param_attributes.ServerAllocSize)
1075                         HeapFree(GetProcessHeap(), 0, *(void **)pArg);
1076                     break;
1077                 case STUBLESS_INITOUT:
1078                     break;
1079                 case STUBLESS_UNMARSHAL:
1080                     if (pParam->param_attributes.ServerAllocSize)
1081                         *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1082                                                    pParam->param_attributes.ServerAllocSize * 8);
1083
1084                     if (pParam->param_attributes.IsIn)
1085                     {
1086                         if (pParam->param_attributes.IsSimpleRef)
1087                             call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
1088                         else
1089                             call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
1090                     }
1091                     break;
1092                 case STUBLESS_CALCSIZE:
1093                     if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
1094                     {
1095                         if (pParam->param_attributes.IsSimpleRef)
1096                             call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1097                         else
1098                             call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
1099                     }
1100                     break;
1101                 default:
1102                     RpcRaiseException(RPC_S_INTERNAL_ERROR);
1103             }
1104
1105             current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
1106         }
1107         else
1108         {
1109             const NDR_PARAM_OIF_OTHER *pParamOther =
1110             (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
1111
1112             const unsigned char * pTypeFormat =
1113                 &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]);
1114
1115             TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
1116
1117             switch (phase)
1118             {
1119                 case STUBLESS_MARSHAL:
1120                     if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
1121                     {
1122                         if (pParam->param_attributes.IsByValue)
1123                             call_marshaller(pStubMsg, pArg, pTypeFormat);
1124                         else
1125                             call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1126                     }
1127                     break;
1128                 case STUBLESS_FREE:
1129                     if (pParam->param_attributes.MustFree)
1130                     {
1131                         if (pParam->param_attributes.IsByValue)
1132                             call_freer(pStubMsg, pArg, pTypeFormat);
1133                         else
1134                             call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1135                     }
1136
1137                     if (pParam->param_attributes.IsOut &&
1138                         !pParam->param_attributes.IsIn &&
1139                         !pParam->param_attributes.IsByValue &&
1140                         !pParam->param_attributes.ServerAllocSize)
1141                     {
1142                         if (*pTypeFormat != RPC_FC_BIND_CONTEXT)
1143                             pStubMsg->pfnFree(*(void **)pArg);
1144                     }
1145
1146                     if (pParam->param_attributes.ServerAllocSize)
1147                         HeapFree(GetProcessHeap(), 0, *(void **)pArg);
1148                     break;
1149                 case STUBLESS_INITOUT:
1150                     if (!pParam->param_attributes.IsIn &&
1151                              pParam->param_attributes.IsOut &&
1152                              !pParam->param_attributes.ServerAllocSize &&
1153                              !pParam->param_attributes.IsByValue)
1154                     {
1155                         if (*pTypeFormat == RPC_FC_BIND_CONTEXT)
1156                         {
1157                             NDR_SCONTEXT ctxt = NdrContextHandleInitialize(
1158                                 pStubMsg, pTypeFormat);
1159                             *(void **)pArg = NDRSContextValue(ctxt);
1160                         }
1161                         else
1162                         {
1163                             DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
1164
1165                             if(size)
1166                             {
1167                                 *(void **)pArg = NdrAllocate(pStubMsg, size);
1168                                 memset(*(void **)pArg, 0, size);
1169                             }
1170                         }
1171                     }
1172                     break;
1173                 case STUBLESS_UNMARSHAL:
1174                     if (pParam->param_attributes.ServerAllocSize)
1175                         *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1176                                                    pParam->param_attributes.ServerAllocSize * 8);
1177
1178                     if (pParam->param_attributes.IsIn)
1179                     {
1180                         if (pParam->param_attributes.IsByValue)
1181                             call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
1182                         else
1183                             call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
1184                     }
1185                     break;
1186                 case STUBLESS_CALCSIZE:
1187                     if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
1188                     {
1189                         if (pParam->param_attributes.IsByValue)
1190                             call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
1191                         else
1192                             call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1193                     }
1194                     break;
1195                 default:
1196                     RpcRaiseException(RPC_S_INTERNAL_ERROR);
1197             }
1198
1199             current_offset += sizeof(NDR_PARAM_OIF_OTHER);
1200         }
1201         TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
1202     }
1203
1204     return retval_ptr;
1205 }
1206
1207 static LONG_PTR *stub_do_old_args(MIDL_STUB_MESSAGE *pStubMsg,
1208                                   PFORMAT_STRING pFormat, int phase,
1209                                   unsigned char *args,
1210                                   unsigned short stack_size, BOOL object)
1211 {
1212     /* counter */
1213     unsigned short i;
1214     /* current format string offset */
1215     int current_offset = 0;
1216     /* current stack offset */
1217     unsigned short current_stack_offset = 0;
1218     /* location to put retval into */
1219     LONG_PTR *retval_ptr = NULL;
1220
1221     for (i = 0; TRUE; i++)
1222     {
1223         const NDR_PARAM_OI_BASETYPE *pParam =
1224         (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
1225         /* note: current_stack_offset starts after the This pointer
1226          * if present, so adjust this */
1227         unsigned short current_stack_offset_adjusted = current_stack_offset +
1228             (object ? sizeof(void *) : 0);
1229         unsigned char *pArg = args + current_stack_offset_adjusted;
1230
1231         /* no more parameters; exit loop */
1232         if (current_stack_offset_adjusted >= stack_size)
1233             break;
1234
1235         TRACE("param[%d]: old format\n", i);
1236         TRACE("\tparam_direction: 0x%x\n", pParam->param_direction);
1237         TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted);
1238
1239         if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
1240             pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1241         {
1242             const unsigned char *pTypeFormat =
1243             &pParam->type_format_char;
1244
1245             TRACE("\tbase type 0x%02x\n", *pTypeFormat);
1246
1247             if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1248                 retval_ptr = (LONG_PTR *)pArg;
1249
1250             switch (phase)
1251             {
1252                 case STUBLESS_MARSHAL:
1253                     if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1254                         call_marshaller(pStubMsg, pArg, pTypeFormat);
1255                     break;
1256                 case STUBLESS_FREE:
1257                     if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
1258                         call_freer(pStubMsg, pArg, pTypeFormat);
1259                     break;
1260                 case STUBLESS_INITOUT:
1261                     break;
1262                 case STUBLESS_UNMARSHAL:
1263                     if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
1264                         call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
1265                     break;
1266                 case STUBLESS_CALCSIZE:
1267                     if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1268                         call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
1269                     break;
1270                 default:
1271                     RpcRaiseException(RPC_S_INTERNAL_ERROR);
1272             }
1273
1274             current_stack_offset += type_stack_size(*pTypeFormat);
1275             current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
1276         }
1277         else
1278         {
1279             const NDR_PARAM_OI_OTHER *pParamOther =
1280             (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
1281
1282             const unsigned char * pTypeFormat =
1283                 &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset];
1284
1285             TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
1286
1287             if (pParam->param_direction == RPC_FC_RETURN_PARAM)
1288                 retval_ptr = (LONG_PTR *)pArg;
1289
1290             switch (phase)
1291             {
1292                 case STUBLESS_MARSHAL:
1293                     if (pParam->param_direction == RPC_FC_OUT_PARAM ||
1294                         pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1295                         pParam->param_direction == RPC_FC_RETURN_PARAM)
1296                         call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1297                     break;
1298                 case STUBLESS_FREE:
1299                     if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1300                         pParam->param_direction == RPC_FC_IN_PARAM)
1301                         call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1302                     else if (pParam->param_direction == RPC_FC_OUT_PARAM)
1303                         pStubMsg->pfnFree(*(void **)pArg);
1304                     break;
1305                 case STUBLESS_INITOUT:
1306                     if (pParam->param_direction == RPC_FC_OUT_PARAM)
1307                     {
1308                         DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
1309
1310                         if(size)
1311                         {
1312                             *(void **)pArg = NdrAllocate(pStubMsg, size);
1313                             memset(*(void **)pArg, 0, size);
1314                         }
1315                     }
1316                     break;
1317                 case STUBLESS_UNMARSHAL:
1318                     if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1319                         pParam->param_direction == RPC_FC_IN_PARAM)
1320                         call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
1321                     break;
1322                 case STUBLESS_CALCSIZE:
1323                     if (pParam->param_direction == RPC_FC_OUT_PARAM ||
1324                         pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1325                         pParam->param_direction == RPC_FC_RETURN_PARAM)
1326                         call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1327                     break;
1328                 default:
1329                     RpcRaiseException(RPC_S_INTERNAL_ERROR);
1330             }
1331
1332             current_stack_offset += pParamOther->stack_size * sizeof(INT);
1333             current_offset += sizeof(NDR_PARAM_OI_OTHER);
1334         }
1335     }
1336
1337     return retval_ptr;
1338 }
1339
1340 /***********************************************************************
1341  *            NdrStubCall2 [RPCRT4.@]
1342  *
1343  * Unmarshals [in] parameters, calls either a method in an object or a server
1344  * function, marshals any [out] parameters and frees any allocated data.
1345  *
1346  * NOTES
1347  *  Used by stubless MIDL-generated code.
1348  */
1349 LONG WINAPI NdrStubCall2(
1350     struct IRpcStubBuffer * pThis,
1351     struct IRpcChannelBuffer * pChannel,
1352     PRPC_MESSAGE pRpcMsg,
1353     DWORD * pdwStubPhase)
1354 {
1355     const MIDL_SERVER_INFO *pServerInfo;
1356     const MIDL_STUB_DESC *pStubDesc;
1357     PFORMAT_STRING pFormat;
1358     MIDL_STUB_MESSAGE stubMsg;
1359     /* pointer to start of stack to pass into stub implementation */
1360     unsigned char * args;
1361     /* size of stack */
1362     unsigned short stack_size;
1363     /* number of parameters. optional for client to give it to us */
1364     unsigned char number_of_params = ~0;
1365     /* cache of Oif_flags from v2 procedure header */
1366     INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1367     /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1368     INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1369     /* the type of pass we are currently doing */
1370     int phase;
1371     /* header for procedure string */
1372     const NDR_PROC_HEADER *pProcHeader;
1373     /* offset in format string for start of params */
1374     int parameter_start_offset;
1375     /* current format string offset */
1376     int current_offset;
1377     /* -Oif or -Oicf generated format */
1378     BOOL bV2Format = FALSE;
1379     /* location to put retval into */
1380     LONG_PTR *retval_ptr = NULL;
1381
1382     TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase);
1383
1384     if (pThis)
1385         pServerInfo = CStdStubBuffer_GetServerInfo(pThis);
1386     else
1387         pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1388
1389     pStubDesc = pServerInfo->pStubDesc;
1390     pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1391     pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1392
1393     TRACE("NDR Version: 0x%x\n", pStubDesc->Version);
1394
1395     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1396     {
1397         const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1398         stack_size = pProcHeader->stack_size;
1399         current_offset = sizeof(NDR_PROC_HEADER_RPC);
1400
1401     }
1402     else
1403     {
1404         stack_size = pProcHeader->stack_size;
1405         current_offset = sizeof(NDR_PROC_HEADER);
1406     }
1407
1408     TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1409
1410     /* binding */
1411     switch (pProcHeader->handle_type)
1412     {
1413     /* explicit binding: parse additional section */
1414     case RPC_FC_BIND_EXPLICIT:
1415         switch (pFormat[current_offset]) /* handle_type */
1416         {
1417         case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
1418             current_offset += sizeof(NDR_EHD_PRIMITIVE);
1419             break;
1420         case RPC_FC_BIND_GENERIC: /* explicit generic */
1421             current_offset += sizeof(NDR_EHD_GENERIC);
1422             break;
1423         case RPC_FC_BIND_CONTEXT: /* explicit context */
1424             current_offset += sizeof(NDR_EHD_CONTEXT);
1425             break;
1426         default:
1427             ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1428             RpcRaiseException(RPC_X_BAD_STUB_DATA);
1429         }
1430         break;
1431     case RPC_FC_BIND_GENERIC: /* implicit generic */
1432     case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
1433     case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
1434     case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
1435         break;
1436     default:
1437         ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1438         RpcRaiseException(RPC_X_BAD_STUB_DATA);
1439     }
1440
1441     bV2Format = (pStubDesc->Version >= 0x20000);
1442
1443     if (bV2Format)
1444     {
1445         const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
1446             (const NDR_PROC_PARTIAL_OIF_HEADER *)&pFormat[current_offset];
1447
1448         Oif_flags = pOIFHeader->Oi2Flags;
1449         number_of_params = pOIFHeader->number_of_params;
1450
1451         current_offset += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1452     }
1453
1454     TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
1455
1456     if (Oif_flags.HasExtensions)
1457     {
1458         const NDR_PROC_HEADER_EXTS *pExtensions =
1459             (const NDR_PROC_HEADER_EXTS *)&pFormat[current_offset];
1460         ext_flags = pExtensions->Flags2;
1461         current_offset += pExtensions->Size;
1462     }
1463
1464     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1465         NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel);
1466     else
1467         NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc);
1468
1469     /* create the full pointer translation tables, if requested */
1470     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1471         stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
1472
1473     /* store the RPC flags away */
1474     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1475         pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1476
1477     /* use alternate memory allocation routines */
1478     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
1479 #if 0
1480           NdrRpcSsEnableAllocate(&stubMsg);
1481 #else
1482           FIXME("Set RPCSS memory allocation routines\n");
1483 #endif
1484
1485     if (Oif_flags.HasPipes)
1486     {
1487         FIXME("pipes not supported yet\n");
1488         RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1489         /* init pipes package */
1490         /* NdrPipesInitialize(...) */
1491     }
1492     if (ext_flags.HasNewCorrDesc)
1493     {
1494         /* initialize extra correlation package */
1495         FIXME("new correlation description not implemented\n");
1496         stubMsg.fHasNewCorrDesc = TRUE;
1497     }
1498
1499     /* convert strings, floating point values and endianess into our
1500      * preferred format */
1501     if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1502         NdrConvert(&stubMsg, pFormat);
1503
1504     parameter_start_offset = current_offset;
1505
1506     TRACE("allocating memory for stack of size %x\n", stack_size);
1507
1508     args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size);
1509     stubMsg.StackTop = args; /* used by conformance of top-level objects */
1510
1511     /* add the implicit This pointer as the first arg to the function if we
1512      * are calling an object method */
1513     if (pThis)
1514         *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject;
1515
1516     for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++)
1517     {
1518         TRACE("phase = %d\n", phase);
1519         switch (phase)
1520         {
1521         case STUBLESS_CALLSERVER:
1522             /* call the server function */
1523             if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
1524                 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg);
1525             else
1526             {
1527                 SERVER_ROUTINE func;
1528                 LONG_PTR retval;
1529
1530                 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1531                 {
1532                     SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject;
1533                     func = vtbl[pRpcMsg->ProcNum];
1534                 }
1535                 else
1536                     func = pServerInfo->DispatchTable[pRpcMsg->ProcNum];
1537
1538                 /* FIXME: what happens with return values that don't fit into a single register on x86? */
1539                 retval = call_server_func(func, args, stack_size);
1540
1541                 if (retval_ptr)
1542                 {
1543                     TRACE("stub implementation returned 0x%lx\n", retval);
1544                     *retval_ptr = retval;
1545                 }
1546                 else
1547                     TRACE("void stub implementation\n");
1548             }
1549
1550             stubMsg.Buffer = NULL;
1551             stubMsg.BufferLength = 0;
1552
1553             break;
1554         case STUBLESS_GETBUFFER:
1555             if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1556                 NdrStubGetBuffer(pThis, pChannel, &stubMsg);
1557             else
1558             {
1559                 RPC_STATUS Status;
1560
1561                 pRpcMsg->BufferLength = stubMsg.BufferLength;
1562                 /* allocate buffer for [out] and [ret] params */
1563                 Status = I_RpcGetBuffer(pRpcMsg); 
1564                 if (Status)
1565                     RpcRaiseException(Status);
1566                 stubMsg.Buffer = pRpcMsg->Buffer;
1567             }
1568             break;
1569         case STUBLESS_UNMARSHAL:
1570         case STUBLESS_INITOUT:
1571         case STUBLESS_CALCSIZE:
1572         case STUBLESS_MARSHAL:
1573         case STUBLESS_FREE:
1574             if (bV2Format)
1575                 retval_ptr = stub_do_args(&stubMsg, &pFormat[parameter_start_offset],
1576                                           phase, args, number_of_params);
1577             else
1578                 retval_ptr = stub_do_old_args(&stubMsg, &pFormat[parameter_start_offset],
1579                                               phase, args, stack_size,
1580                                               (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT));
1581
1582             break;
1583         default:
1584             ERR("shouldn't reach here. phase %d\n", phase);
1585             break;
1586         }
1587     }
1588
1589     pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer);
1590
1591     if (ext_flags.HasNewCorrDesc)
1592     {
1593         /* free extra correlation package */
1594         /* NdrCorrelationFree(&stubMsg); */
1595     }
1596
1597     if (Oif_flags.HasPipes)
1598     {
1599         /* NdrPipesDone(...) */
1600     }
1601
1602     /* free the full pointer translation tables */
1603     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1604         NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
1605
1606     /* free server function stack */
1607     HeapFree(GetProcessHeap(), 0, args);
1608
1609     return S_OK;
1610 }
1611
1612 /***********************************************************************
1613  *            NdrServerCall2 [RPCRT4.@]
1614  */
1615 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
1616 {
1617     DWORD dwPhase;
1618     NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
1619 }
1620
1621 struct async_call_data
1622 {
1623     MIDL_STUB_MESSAGE *pStubMsg;
1624     const NDR_PROC_HEADER *pProcHeader;
1625     PFORMAT_STRING pHandleFormat;
1626     PFORMAT_STRING pParamFormat;
1627     RPC_BINDING_HANDLE hBinding;
1628     /* size of stack */
1629     unsigned short stack_size;
1630     /* number of parameters. optional for client to give it to us */
1631     unsigned char number_of_params;
1632     /* correlation cache */
1633     ULONG_PTR NdrCorrCache[256];
1634 };
1635
1636 LONG_PTR WINAPIV NdrAsyncClientCall(PMIDL_STUB_DESC pStubDesc,
1637   PFORMAT_STRING pFormat, ...)
1638 {
1639     /* pointer to start of stack where arguments start */
1640     PRPC_MESSAGE pRpcMsg;
1641     PMIDL_STUB_MESSAGE pStubMsg;
1642     RPC_ASYNC_STATE *pAsync;
1643     struct async_call_data *async_call_data;
1644     /* procedure number */
1645     unsigned short procedure_number;
1646     /* cache of Oif_flags from v2 procedure header */
1647     INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1648     /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1649     INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1650     /* the type of pass we are currently doing */
1651     int phase;
1652     /* header for procedure string */
1653     const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1654     /* -Oif or -Oicf generated format */
1655     BOOL bV2Format = FALSE;
1656     __ms_va_list args;
1657
1658     TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
1659
1660     /* Later NDR language versions probably won't be backwards compatible */
1661     if (pStubDesc->Version > 0x50002)
1662     {
1663         FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
1664         RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
1665     }
1666
1667     async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
1668     if (!async_call_data) RpcRaiseException(ERROR_OUTOFMEMORY);
1669     async_call_data->number_of_params = ~0;
1670     async_call_data->pProcHeader = pProcHeader;
1671
1672     async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
1673     pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1);
1674
1675     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1676     {
1677         const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1678         async_call_data->stack_size = pProcHeader->stack_size;
1679         procedure_number = pProcHeader->proc_num;
1680         pFormat += sizeof(NDR_PROC_HEADER_RPC);
1681     }
1682     else
1683     {
1684         async_call_data->stack_size = pProcHeader->stack_size;
1685         procedure_number = pProcHeader->proc_num;
1686         pFormat += sizeof(NDR_PROC_HEADER);
1687     }
1688     TRACE("stack size: 0x%x\n", async_call_data->stack_size);
1689     TRACE("proc num: %d\n", procedure_number);
1690
1691     /* create the full pointer translation tables, if requested */
1692     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1693         pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
1694
1695     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1696     {
1697         ERR("objects not supported\n");
1698         I_RpcFree(async_call_data);
1699         RpcRaiseException(RPC_X_BAD_STUB_DATA);
1700     }
1701
1702     NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number);
1703
1704     TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1705     TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
1706
1707     /* needed for conformance of top-level objects */
1708     pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size);
1709     __ms_va_start( args, pFormat );
1710     memcpy(pStubMsg->StackTop, va_arg( args, unsigned char * ), async_call_data->stack_size);
1711     __ms_va_end( args );
1712
1713     pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop;
1714     pAsync->StubInfo = async_call_data;
1715     async_call_data->pHandleFormat = pFormat;
1716
1717     pFormat = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, &async_call_data->hBinding);
1718     if (!pFormat) return 0;
1719
1720     bV2Format = (pStubDesc->Version >= 0x20000);
1721
1722     if (bV2Format)
1723     {
1724         const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
1725             (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
1726
1727         Oif_flags = pOIFHeader->Oi2Flags;
1728         async_call_data->number_of_params = pOIFHeader->number_of_params;
1729
1730         pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1731     }
1732
1733     TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
1734
1735     if (Oif_flags.HasExtensions)
1736     {
1737         const NDR_PROC_HEADER_EXTS *pExtensions =
1738             (const NDR_PROC_HEADER_EXTS *)pFormat;
1739         ext_flags = pExtensions->Flags2;
1740         pFormat += pExtensions->Size;
1741     }
1742
1743     async_call_data->pParamFormat = pFormat;
1744
1745     pStubMsg->BufferLength = 0;
1746
1747     /* store the RPC flags away */
1748     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1749         pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1750
1751     /* use alternate memory allocation routines */
1752     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
1753         NdrRpcSmSetClientToOsf(pStubMsg);
1754
1755     if (Oif_flags.HasPipes)
1756     {
1757         FIXME("pipes not supported yet\n");
1758         RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1759         /* init pipes package */
1760         /* NdrPipesInitialize(...) */
1761     }
1762     if (ext_flags.HasNewCorrDesc)
1763     {
1764         /* initialize extra correlation package */
1765         NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
1766     }
1767
1768     /* order of phases:
1769      * 1. PROXY_CALCSIZE - calculate the buffer size
1770      * 2. PROXY_GETBUFFER - allocate the buffer
1771      * 3. PROXY_MARHSAL - marshal [in] params into the buffer
1772      * 4. PROXY_SENDRECEIVE - send buffer
1773      * Then in NdrpCompleteAsyncClientCall:
1774      * 1. PROXY_SENDRECEIVE - receive buffer
1775      * 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
1776      */
1777     for (phase = PROXY_CALCSIZE; phase <= PROXY_SENDRECEIVE; phase++)
1778     {
1779         RPC_STATUS status;
1780         TRACE("phase = %d\n", phase);
1781         switch (phase)
1782         {
1783         case PROXY_GETBUFFER:
1784             /* allocate the buffer */
1785             if (Oif_flags.HasPipes)
1786                 /* NdrGetPipeBuffer(...) */
1787                 FIXME("pipes not supported yet\n");
1788             else
1789             {
1790                 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
1791 #if 0
1792                     NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1793 #else
1794                     FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
1795 #endif
1796                 else
1797                     NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
1798             }
1799             pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1800             status = I_RpcAsyncSetHandle(pRpcMsg, pAsync);
1801             if (status != RPC_S_OK)
1802                 RpcRaiseException(status);
1803             break;
1804         case PROXY_SENDRECEIVE:
1805             pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1806             /* send the [in] params only */
1807             if (Oif_flags.HasPipes)
1808                 /* NdrPipesSend(...) */
1809                 FIXME("pipes not supported yet\n");
1810             else
1811             {
1812                 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
1813 #if 0
1814                     NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
1815 #else
1816                     FIXME("using auto handle - call NdrNsSend when it gets implemented\n");
1817 #endif
1818                 else
1819                 {
1820                     pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
1821                     status = I_RpcSend(pStubMsg->RpcMsg);
1822                     if (status != RPC_S_OK)
1823                         RpcRaiseException(status);
1824                 }
1825             }
1826
1827             break;
1828         case PROXY_CALCSIZE:
1829         case PROXY_MARSHAL:
1830             if (bV2Format)
1831                 client_do_args(pStubMsg, pFormat, phase, pStubMsg->StackTop,
1832                     async_call_data->number_of_params, NULL);
1833             else
1834                 client_do_args_old_format(pStubMsg, pFormat, phase,
1835                     pStubMsg->StackTop, async_call_data->stack_size, NULL,
1836                     (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT), FALSE);
1837             break;
1838         default:
1839             ERR("shouldn't reach here. phase %d\n", phase);
1840             break;
1841         }
1842     }
1843
1844     TRACE("returning 0\n");
1845     return 0;
1846 }
1847
1848 RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
1849 {
1850     /* pointer to start of stack where arguments start */
1851     PMIDL_STUB_MESSAGE pStubMsg;
1852     struct async_call_data *async_call_data;
1853     /* the type of pass we are currently doing */
1854     int phase;
1855     /* header for procedure string */
1856     const NDR_PROC_HEADER * pProcHeader;
1857     /* -Oif or -Oicf generated format */
1858     BOOL bV2Format;
1859     RPC_STATUS status = RPC_S_OK;
1860
1861     if (!pAsync->StubInfo)
1862         return RPC_S_INVALID_ASYNC_HANDLE;
1863
1864     async_call_data = pAsync->StubInfo;
1865     pStubMsg = async_call_data->pStubMsg;
1866     pProcHeader = async_call_data->pProcHeader;
1867
1868     bV2Format = (pStubMsg->StubDesc->Version >= 0x20000);
1869
1870     /* order of phases:
1871      * 1. PROXY_CALCSIZE - calculate the buffer size
1872      * 2. PROXY_GETBUFFER - allocate the buffer
1873      * 3. PROXY_MARHSAL - marshal [in] params into the buffer
1874      * 4. PROXY_SENDRECEIVE - send buffer
1875      * Then in NdrpCompleteAsyncClientCall:
1876      * 1. PROXY_SENDRECEIVE - receive buffer
1877      * 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
1878      */
1879     for (phase = PROXY_SENDRECEIVE; phase <= PROXY_UNMARSHAL; phase++)
1880     {
1881         switch (phase)
1882         {
1883         case PROXY_SENDRECEIVE:
1884             pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
1885             /* receive the [out] params */
1886             if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
1887 #if 0
1888                 NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
1889 #else
1890                 FIXME("using auto handle - call NdrNsReceive when it gets implemented\n");
1891 #endif
1892             else
1893             {
1894                 status = I_RpcReceive(pStubMsg->RpcMsg);
1895                 if (status != RPC_S_OK)
1896                     goto cleanup;
1897                 pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;
1898                 pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
1899                 pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
1900                 pStubMsg->Buffer = pStubMsg->BufferStart;
1901             }
1902
1903             /* convert strings, floating point values and endianess into our
1904              * preferred format */
1905 #if 0
1906             if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1907                 NdrConvert(pStubMsg, pFormat);
1908 #endif
1909
1910             break;
1911         case PROXY_UNMARSHAL:
1912             if (bV2Format)
1913                 client_do_args(pStubMsg, async_call_data->pParamFormat, phase, pStubMsg->StackTop,
1914                     async_call_data->number_of_params, Reply);
1915             else
1916                 client_do_args_old_format(pStubMsg, async_call_data->pParamFormat, phase,
1917                     pStubMsg->StackTop, async_call_data->stack_size, Reply, FALSE, FALSE);
1918             break;
1919         default:
1920             ERR("shouldn't reach here. phase %d\n", phase);
1921             break;
1922         }
1923     }
1924
1925 cleanup:
1926     if (pStubMsg->fHasNewCorrDesc)
1927     {
1928         /* free extra correlation package */
1929         NdrCorrelationFree(pStubMsg);
1930     }
1931
1932     /* free the full pointer translation tables */
1933     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1934         NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
1935
1936     /* free marshalling buffer */
1937     NdrFreeBuffer(pStubMsg);
1938     client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding);
1939
1940     I_RpcFree(pStubMsg->StackTop);
1941     I_RpcFree(async_call_data);
1942
1943     TRACE("-- 0x%x\n", status);
1944     return status;
1945 }
1946
1947 RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis,
1948     struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg,
1949     DWORD * pdwStubPhase)
1950 {
1951     FIXME("unimplemented, expect crash!\n");
1952     return 0;
1953 }