rpcrt4: Remove some unused includes.
[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/debug.h"
42 #include "wine/rpcfc.h"
43
44 #include "cpsf.h"
45 #include "ndr_misc.h"
46 #include "ndr_stubless.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
49
50 #define NDR_TABLE_MASK 127
51
52 static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
53 {
54     NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK];
55     if (m) m(pStubMsg, pMemory, pFormat);
56     else
57     {
58         FIXME("format type 0x%x not implemented\n", pFormat[0]);
59         RpcRaiseException(RPC_X_BAD_STUB_DATA);
60     }
61 }
62
63 static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
64 {
65     NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK];
66     if (m) return m(pStubMsg, pMemory, pFormat);
67     else
68     {
69         FIXME("format type 0x%x not implemented\n", pFormat[0]);
70         RpcRaiseException(RPC_X_BAD_STUB_DATA);
71         return NULL;
72     }
73 }
74
75 static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc)
76 {
77     NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK];
78     if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc);
79     else
80     {
81         FIXME("format type 0x%x not implemented\n", pFormat[0]);
82         RpcRaiseException(RPC_X_BAD_STUB_DATA);
83         return NULL;
84     }
85 }
86
87 static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat)
88 {
89     NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK];
90     if (m) m(pStubMsg, pMemory, pFormat);
91 }
92
93 static inline unsigned long call_memory_sizer(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat)
94 {
95     NDR_MEMORYSIZE m = NdrMemorySizer[pFormat[0] & NDR_TABLE_MASK];
96     if (m)
97     {
98         unsigned char *saved_buffer = pStubMsg->Buffer;
99         unsigned long ret;
100         int saved_ignore_embedded_pointers = pStubMsg->IgnoreEmbeddedPointers;
101         pStubMsg->MemorySize = 0;
102         pStubMsg->IgnoreEmbeddedPointers = 1;
103         ret = m(pStubMsg, pFormat);
104         pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded_pointers;
105         pStubMsg->Buffer = saved_buffer;
106         return ret;
107     }
108     else
109     {
110         FIXME("format type 0x%x not implemented\n", pFormat[0]);
111         RpcRaiseException(RPC_X_BAD_STUB_DATA);
112         return 0;
113     }
114 }
115
116 #define STUBLESS_UNMARSHAL  1
117 #define STUBLESS_CALLSERVER 2
118 #define STUBLESS_CALCSIZE   3
119 #define STUBLESS_GETBUFFER  4
120 #define STUBLESS_MARSHAL    5
121 #define STUBLESS_FREE       6
122
123 void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage)
124 {
125 #if 0 /* these functions are not defined yet */
126     pMessage->pfnAllocate = NdrRpcSmClientAllocate;
127     pMessage->pfnFree = NdrRpcSmClientFree;
128 #endif
129 }
130
131 static void WINAPI dump_RPC_FC_PROC_PF(PARAM_ATTRIBUTES param_attributes)
132 {
133     if (param_attributes.MustSize) TRACE(" MustSize");
134     if (param_attributes.MustFree) TRACE(" MustFree");
135     if (param_attributes.IsPipe) TRACE(" IsPipe");
136     if (param_attributes.IsIn) TRACE(" IsIn");
137     if (param_attributes.IsOut) TRACE(" IsOut");
138     if (param_attributes.IsReturn) TRACE(" IsReturn");
139     if (param_attributes.IsBasetype) TRACE(" IsBasetype");
140     if (param_attributes.IsByValue) TRACE(" IsByValue");
141     if (param_attributes.IsSimpleRef) TRACE(" IsSimpleRef");
142     if (param_attributes.IsDontCallFreeInst) TRACE(" IsDontCallFreeInst");
143     if (param_attributes.SaveForAsyncFinish) TRACE(" SaveForAsyncFinish");
144     if (param_attributes.ServerAllocSize) TRACE(" ServerAllocSize = %d", param_attributes.ServerAllocSize * 8);
145 }
146
147 static void WINAPI dump_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags)
148 {
149     if (Oi2Flags.ServerMustSize) TRACE(" ServerMustSize");
150     if (Oi2Flags.ClientMustSize) TRACE(" ClientMustSize");
151     if (Oi2Flags.HasReturn) TRACE(" HasReturn");
152     if (Oi2Flags.HasPipes) TRACE(" HasPipes");
153     if (Oi2Flags.Unused) TRACE(" Unused");
154     if (Oi2Flags.HasAsyncUuid) TRACE(" HasAsyncUuid");
155     if (Oi2Flags.HasExtensions) TRACE(" HasExtensions");
156     if (Oi2Flags.HasAsyncHandle) TRACE(" HasAsyncHandle");
157     TRACE("\n");
158 }
159
160 #define ARG_FROM_OFFSET(stubMsg, offset) ((stubMsg).StackTop + (offset))
161
162 static PFORMAT_STRING client_get_handle(
163     PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
164     PFORMAT_STRING pFormat, handle_t *phBinding)
165 {
166     /* binding */
167     switch (pProcHeader->handle_type)
168     {
169     /* explicit binding: parse additional section */
170     case RPC_FC_BIND_EXPLICIT:
171         switch (*pFormat) /* handle_type */
172         {
173         case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
174             {
175                 const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat;
176
177                 TRACE("Explicit primitive handle @ %d\n", pDesc->offset);
178
179                 if (pDesc->flag) /* pointer to binding */
180                     *phBinding = **(handle_t **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
181                 else
182                     *phBinding = *(handle_t *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
183                 return pFormat + sizeof(NDR_EHD_PRIMITIVE);
184             }
185         case RPC_FC_BIND_GENERIC: /* explicit generic */
186             {
187                 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat;
188                 void *pObject = NULL;
189                 void *pArg;
190                 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
191
192                 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
193
194                 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
195                     pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
196                 else
197                     pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
198                 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
199                 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
200                 *phBinding = pGenPair->pfnBind(pObject);
201                 return pFormat + sizeof(NDR_EHD_GENERIC);
202             }
203         case RPC_FC_BIND_CONTEXT: /* explicit context */
204             {
205                 const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat;
206                 NDR_CCONTEXT context_handle;
207                 TRACE("Explicit bind context\n");
208                 if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR)
209                 {
210                     TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n");
211                     context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
212                 }
213                 else
214                     context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
215                 if ((pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) &&
216                     !context_handle)
217                 {
218                     ERR("null context handle isn't allowed\n");
219                     RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT);
220                     return NULL;
221                 }
222                 *phBinding = NDRCContextBinding(context_handle);
223                 /* FIXME: should we store this structure in stubMsg.pContext? */
224                 return pFormat + sizeof(NDR_EHD_CONTEXT);
225             }
226         default:
227             ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
228             RpcRaiseException(RPC_X_BAD_STUB_DATA);
229         }
230         break;
231     case RPC_FC_BIND_GENERIC: /* implicit generic */
232         FIXME("RPC_FC_BIND_GENERIC\n");
233         RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
234         break;
235     case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
236         TRACE("Implicit primitive handle\n");
237         *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle;
238         break;
239     case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
240         FIXME("RPC_FC_CALLBACK_HANDLE\n");
241         break;
242     case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
243         /* strictly speaking, it isn't necessary to set hBinding here
244          * since it isn't actually used (hence the automatic in its name),
245          * but then why does MIDL generate a valid entry in the
246          * MIDL_STUB_DESC for it? */
247         TRACE("Implicit auto handle\n");
248         *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle;
249         break;
250     default:
251         ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
252         RpcRaiseException(RPC_X_BAD_STUB_DATA);
253     }
254     return pFormat;
255 }
256
257 static void client_free_handle(
258     PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader,
259     PFORMAT_STRING pFormat, handle_t hBinding)
260 {
261     /* binding */
262     switch (pProcHeader->handle_type)
263     {
264     /* explicit binding: parse additional section */
265     case RPC_FC_BIND_EXPLICIT:
266         switch (*pFormat) /* handle_type */
267         {
268         case RPC_FC_BIND_GENERIC: /* explicit generic */
269             {
270                 const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat;
271                 void *pObject = NULL;
272                 void *pArg;
273                 const GENERIC_BINDING_ROUTINE_PAIR *pGenPair;
274
275                 TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index);
276
277                 if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
278                     pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
279                 else
280                     pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset);
281                 memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
282                 pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
283                 pGenPair->pfnUnbind(pObject, hBinding);
284                 break;
285             }
286         case RPC_FC_BIND_CONTEXT: /* explicit context */
287         case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
288             break;
289         default:
290             ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
291             RpcRaiseException(RPC_X_BAD_STUB_DATA);
292         }
293         break;
294     case RPC_FC_BIND_GENERIC: /* implicit generic */
295         FIXME("RPC_FC_BIND_GENERIC\n");
296         RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */
297         break;
298     case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
299     case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
300     case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
301         break;
302     default:
303         ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
304         RpcRaiseException(RPC_X_BAD_STUB_DATA);
305     }
306 }
307
308 static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat,
309     int phase, unsigned short number_of_params, unsigned char *pRetVal)
310 {
311     /* current format string offset */
312     int current_offset = 0;
313     /* current stack offset */
314     unsigned short current_stack_offset = 0;
315     /* counter */
316     unsigned short i;
317
318     for (i = 0; i < number_of_params; i++)
319     {
320         const NDR_PARAM_OIF_BASETYPE *pParam =
321             (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
322         unsigned char * pArg;
323
324         current_stack_offset = pParam->stack_offset;
325         pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset);
326
327         TRACE("param[%d]: new format\n", i);
328         TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
329         TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
330         TRACE("\tmemory addr (before): %p\n", pArg);
331
332         if (pParam->param_attributes.IsBasetype)
333         {
334             const unsigned char * pTypeFormat =
335                 &pParam->type_format_char;
336
337             if (pParam->param_attributes.IsSimpleRef)
338                 pArg = *(unsigned char **)pArg;
339
340             TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
341
342             switch (phase)
343             {
344             case PROXY_CALCSIZE:
345                 if (pParam->param_attributes.IsIn)
346                     call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
347                 break;
348             case PROXY_MARSHAL:
349                 if (pParam->param_attributes.IsIn)
350                     call_marshaller(pStubMsg, pArg, pTypeFormat);
351                 break;
352             case PROXY_UNMARSHAL:
353                 if (pParam->param_attributes.IsOut)
354                 {
355                     if (pParam->param_attributes.IsReturn)
356                         call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0);
357                     else
358                         call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
359                     TRACE("pRetVal = %p\n", pRetVal);
360                 }
361                 break;
362             default:
363                 RpcRaiseException(RPC_S_INTERNAL_ERROR);
364             }
365
366             current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
367         }
368         else
369         {
370             const NDR_PARAM_OIF_OTHER *pParamOther =
371                 (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
372
373             const unsigned char * pTypeFormat =
374                 &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]);
375
376             /* if a simple ref pointer then we have to do the
377              * check for the pointer being non-NULL. */
378             if (pParam->param_attributes.IsSimpleRef)
379             {
380                 if (!*(unsigned char **)pArg)
381                     RpcRaiseException(RPC_X_NULL_REF_POINTER);
382             }
383
384             TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat);
385
386             switch (phase)
387             {
388             case PROXY_CALCSIZE:
389                 if (pParam->param_attributes.IsIn)
390                 {
391                     if (pParam->param_attributes.IsByValue)
392                         call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
393                     else
394                         call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
395                 }
396                 break;
397             case PROXY_MARSHAL:
398                 if (pParam->param_attributes.IsIn)
399                 {
400                     if (pParam->param_attributes.IsByValue)
401                         call_marshaller(pStubMsg, pArg, pTypeFormat);
402                     else
403                         call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
404                 }
405                 break;
406             case PROXY_UNMARSHAL:
407                 if (pParam->param_attributes.IsOut)
408                 {
409                     if (pParam->param_attributes.IsReturn)
410                         call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0);
411                     else if (pParam->param_attributes.IsByValue)
412                         call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
413                     else
414                         call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
415                 }
416                 break;
417             default:
418                 RpcRaiseException(RPC_S_INTERNAL_ERROR);
419             }
420
421             current_offset += sizeof(NDR_PARAM_OIF_OTHER);
422         }
423         TRACE("\tmemory addr (after): %p\n", pArg);
424     }
425 }
426
427 static void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
428     PFORMAT_STRING pFormat, int phase, unsigned short stack_size,
429     unsigned char *pRetVal, BOOL object_proc)
430 {
431     /* current format string offset */
432     int current_offset = 0;
433     /* current stack offset */
434     unsigned short current_stack_offset = 0;
435     /* counter */
436     unsigned short i;
437
438     /* NOTE: V1 style format does't terminate on the number_of_params
439      * condition as it doesn't have this attribute. Instead it
440      * terminates when the stack size given in the header is exceeded.
441      */
442     for (i = 0; TRUE; i++)
443     {
444         const NDR_PARAM_OI_BASETYPE *pParam =
445             (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
446         /* note: current_stack_offset starts after the This pointer
447          * if present, so adjust this */
448         unsigned short current_stack_offset_adjusted = current_stack_offset +
449             (object_proc ? sizeof(void *) : 0);
450         unsigned char * pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset_adjusted);
451
452         /* no more parameters; exit loop */
453         if (current_stack_offset_adjusted >= stack_size)
454             break;
455
456         TRACE("param[%d]: old format\n", i);
457         TRACE("\tparam_direction: 0x%x\n", pParam->param_direction);
458         TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted);
459         TRACE("\tmemory addr (before): %p\n", pArg);
460
461         if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
462             pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
463         {
464             const unsigned char * pTypeFormat =
465                 &pParam->type_format_char;
466
467             TRACE("\tbase type 0x%02x\n", *pTypeFormat);
468
469             switch (phase)
470             {
471             case PROXY_CALCSIZE:
472                 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
473                     call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
474                 break;
475             case PROXY_MARSHAL:
476                 if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
477                     call_marshaller(pStubMsg, pArg, pTypeFormat);
478                 break;
479             case PROXY_UNMARSHAL:
480                 if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
481                 {
482                     if (pParam->param_direction & RPC_FC_RETURN_PARAM)
483                         call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0);
484                     else
485                         call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
486                 }
487                 break;
488             default:
489                 RpcRaiseException(RPC_S_INTERNAL_ERROR);
490             }
491
492             current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat);
493             current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
494         }
495         else
496         {
497             const NDR_PARAM_OI_OTHER *pParamOther = 
498                 (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
499
500             const unsigned char *pTypeFormat =
501                 &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset];
502
503             TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
504
505             switch (phase)
506             {
507             case PROXY_CALCSIZE:
508                 if (pParam->param_direction == RPC_FC_IN_PARAM ||
509                     pParam->param_direction & RPC_FC_IN_OUT_PARAM)
510                     call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
511                 break;
512             case PROXY_MARSHAL:
513                 if (pParam->param_direction == RPC_FC_IN_PARAM ||
514                     pParam->param_direction & RPC_FC_IN_OUT_PARAM)
515                     call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
516                 break;
517             case PROXY_UNMARSHAL:
518                 if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
519                     pParam->param_direction == RPC_FC_OUT_PARAM)
520                     call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
521                 else if (pParam->param_direction == RPC_FC_RETURN_PARAM)
522                     call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0);
523                 break;
524             default:
525                 RpcRaiseException(RPC_S_INTERNAL_ERROR);
526             }
527
528             current_stack_offset += pParamOther->stack_size * sizeof(INT);
529             current_offset += sizeof(NDR_PARAM_OI_OTHER);
530         }
531         TRACE("\tmemory addr (after): %p\n", pArg);
532     }
533 }
534
535 /* the return type should be CLIENT_CALL_RETURN, but this is incompatible
536  * with the way gcc returns structures. "void *" should be the largest type
537  * that MIDL should allow you to return anyway */
538 LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, ...)
539 {
540     /* pointer to start of stack where arguments start */
541     RPC_MESSAGE rpcMsg;
542     MIDL_STUB_MESSAGE stubMsg;
543     handle_t hBinding = NULL;
544     /* procedure number */
545     unsigned short procedure_number;
546     /* size of stack */
547     unsigned short stack_size;
548     /* number of parameters. optional for client to give it to us */
549     unsigned char number_of_params = ~0;
550     /* cache of Oif_flags from v2 procedure header */
551     INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
552     /* cache of extension flags from NDR_PROC_HEADER_EXTS */
553     INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
554     /* the type of pass we are currently doing */
555     int phase;
556     /* header for procedure string */
557     const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
558     /* -Oif or -Oicf generated format */
559     BOOL bV2Format = FALSE;
560     /* the value to return to the client from the remote procedure */
561     LONG_PTR RetVal = 0;
562     /* the pointer to the object when in OLE mode */
563     void * This = NULL;
564     PFORMAT_STRING pHandleFormat;
565     /* correlation cache */
566     unsigned long NdrCorrCache[256];
567
568     TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
569
570     /* Later NDR language versions probably won't be backwards compatible */
571     if (pStubDesc->Version > 0x50002)
572     {
573         FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
574         RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
575     }
576
577     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
578     {
579         const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
580         stack_size = pProcHeader->stack_size;
581         procedure_number = pProcHeader->proc_num;
582         pFormat += sizeof(NDR_PROC_HEADER_RPC);
583     }
584     else
585     {
586         stack_size = pProcHeader->stack_size;
587         procedure_number = pProcHeader->proc_num;
588         pFormat += sizeof(NDR_PROC_HEADER);
589     }
590     TRACE("stack size: 0x%x\n", stack_size);
591     TRACE("proc num: %d\n", procedure_number);
592
593     /* create the full pointer translation tables, if requested */
594     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
595         stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
596
597     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
598     {
599         /* object is always the first argument */
600         This = **(void *const **)(&pFormat+1);
601         NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number);
602     }
603     else
604         NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number);
605
606     TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
607     TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
608
609     /* needed for conformance of top-level objects */
610 #ifdef __i386__
611     stubMsg.StackTop = *(unsigned char **)(&pFormat+1);
612 #else
613 # warning Stack not retrieved for your CPU architecture
614 #endif
615
616     pHandleFormat = pFormat;
617
618     /* we only need a handle if this isn't an object method */
619     if (!(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT))
620     {
621         pFormat = client_get_handle(&stubMsg, pProcHeader, pHandleFormat, &hBinding);
622         if (!pFormat) return 0;
623     }
624
625     bV2Format = (pStubDesc->Version >= 0x20000);
626
627     if (bV2Format)
628     {
629         const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
630             (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
631
632         Oif_flags = pOIFHeader->Oi2Flags;
633         number_of_params = pOIFHeader->number_of_params;
634
635         pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
636     }
637
638     TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
639
640     if (Oif_flags.HasExtensions)
641     {
642         const NDR_PROC_HEADER_EXTS *pExtensions =
643             (const NDR_PROC_HEADER_EXTS *)pFormat;
644         ext_flags = pExtensions->Flags2;
645         pFormat += pExtensions->Size;
646     }
647
648     stubMsg.BufferLength = 0;
649
650     /* store the RPC flags away */
651     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
652         rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
653
654     /* use alternate memory allocation routines */
655     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
656         NdrRpcSmSetClientToOsf(&stubMsg);
657
658     if (Oif_flags.HasPipes)
659     {
660         FIXME("pipes not supported yet\n");
661         RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
662         /* init pipes package */
663         /* NdrPipesInitialize(...) */
664     }
665     if (ext_flags.HasNewCorrDesc)
666     {
667         /* initialize extra correlation package */
668         NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0);
669     }
670
671     /* order of phases:
672      * 1. PROXY_CALCSIZE - calculate the buffer size
673      * 2. PROXY_GETBUFFER - allocate the buffer
674      * 3. PROXY_MARHSAL - marshal [in] params into the buffer
675      * 4. PROXY_SENDRECEIVE - send/receive buffer
676      * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer
677      */
678     for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++)
679     {
680         TRACE("phase = %d\n", phase);
681         switch (phase)
682         {
683         case PROXY_GETBUFFER:
684             /* allocate the buffer */
685             if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
686                 NdrProxyGetBuffer(This, &stubMsg);
687             else if (Oif_flags.HasPipes)
688                 /* NdrGetPipeBuffer(...) */
689                 FIXME("pipes not supported yet\n");
690             else
691             {
692                 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
693 #if 0
694                     NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
695 #else
696                     FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
697 #endif
698                 else
699                     NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
700             }
701             break;
702         case PROXY_SENDRECEIVE:
703             /* send the [in] params and receive the [out] and [retval]
704              * params */
705             if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
706                 NdrProxySendReceive(This, &stubMsg);
707             else if (Oif_flags.HasPipes)
708                 /* NdrPipesSendReceive(...) */
709                 FIXME("pipes not supported yet\n");
710             else
711             {
712                 if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
713 #if 0
714                     NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
715 #else
716                     FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
717 #endif
718                 else
719                     NdrSendReceive(&stubMsg, stubMsg.Buffer);
720             }
721
722             /* convert strings, floating point values and endianess into our
723              * preferred format */
724             if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
725                 NdrConvert(&stubMsg, pFormat);
726
727             break;
728         case PROXY_CALCSIZE:
729         case PROXY_MARSHAL:
730         case PROXY_UNMARSHAL:
731             if (bV2Format)
732                 client_do_args(&stubMsg, pFormat, phase, number_of_params,
733                     (unsigned char *)&RetVal);
734             else
735                 client_do_args_old_format(&stubMsg, pFormat, phase, stack_size,
736                     (unsigned char *)&RetVal,
737                     (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT));
738             break;
739         default:
740             ERR("shouldn't reach here. phase %d\n", phase);
741             break;
742         }
743     }
744
745     if (ext_flags.HasNewCorrDesc)
746     {
747         /* free extra correlation package */
748         NdrCorrelationFree(&stubMsg);
749     }
750
751     if (Oif_flags.HasPipes)
752     {
753         /* NdrPipesDone(...) */
754     }
755
756     /* free the full pointer translation tables */
757     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
758         NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
759
760     /* free marshalling buffer */
761     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
762         NdrProxyFreeBuffer(This, &stubMsg);
763     else
764     {
765         NdrFreeBuffer(&stubMsg);
766         client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding);
767     }
768
769     TRACE("RetVal = 0x%lx\n", RetVal);
770
771     return RetVal;
772 }
773
774 /* calls a function with the specificed arguments, restoring the stack
775  * properly afterwards as we don't know the calling convention of the
776  * function */
777 #if defined __i386__ && defined _MSC_VER
778 __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size)
779 {
780     __asm
781     {
782         push ebp
783         push edi            ; Save registers
784         push esi
785         mov ebp, esp
786         mov eax, [ebp+16]   ; Get stack size
787         sub esp, eax        ; Make room in stack for arguments
788         mov edi, esp
789         mov ecx, eax
790         mov esi, [ebp+12]
791         shr ecx, 2
792         cld
793         rep movsd           ; Copy dword blocks
794         call [ebp+8]        ; Call function
795         lea esp, [ebp-8]    ; Restore stack
796         pop esi             ; Restore registers
797         pop edi
798         pop ebp
799         ret
800     }
801 }
802 #elif defined __i386__ && defined __GNUC__
803 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
804 __ASM_GLOBAL_FUNC(call_server_func,
805     "pushl %ebp\n\t"
806     "movl %esp, %ebp\n\t"
807     "pushl %edi\n\t"            /* Save registers */
808     "pushl %esi\n\t"
809     "movl 16(%ebp), %eax\n\t"   /* Get stack size */
810     "subl %eax, %esp\n\t"       /* Make room in stack for arguments */
811     "andl $~15, %esp\n\t"       /* Make sure stack has 16-byte alignment for Mac OS X */
812     "movl %esp, %edi\n\t"
813     "movl %eax, %ecx\n\t"
814     "movl 12(%ebp), %esi\n\t"
815     "shrl $2, %ecx\n\t"         /* divide by 4 */
816     "cld\n\t"
817     "rep; movsl\n\t"            /* Copy dword blocks */
818     "call *8(%ebp)\n\t"         /* Call function */
819     "leal -8(%ebp), %esp\n\t"   /* Restore stack */
820     "popl %esi\n\t"             /* Restore registers */
821     "popl %edi\n\t"
822     "popl %ebp\n\t"
823     "ret\n" )
824 #else
825 #warning call_server_func not implemented for your architecture
826 LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
827 {
828     FIXME("Not implemented for your architecture\n");
829     return 0;
830 }
831 #endif
832
833 static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
834 {
835     DWORD size;
836     switch(*pFormat)
837     {
838     case RPC_FC_STRUCT:
839         size = *(const WORD*)(pFormat + 2);
840         break;
841     case RPC_FC_CARRAY:
842         size = *(const WORD*)(pFormat + 2);
843         ComputeConformance(pStubMsg, NULL, pFormat + 4, 0);
844         size *= pStubMsg->MaxCount;
845         break;
846     case RPC_FC_SMFARRAY:
847         size = *(const WORD*)(pFormat + 2);
848         break;
849     case RPC_FC_LGFARRAY:
850         size = *(const DWORD*)(pFormat + 2);
851         break;
852     default:
853         FIXME("Unhandled type %02x\n", *pFormat);
854         /* fallthrough */
855     case RPC_FC_RP:
856         size = sizeof(void *);
857         break;
858     }
859     return size;
860 }
861
862 static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg,
863                               PFORMAT_STRING pFormat, int phase,
864                               unsigned char *args,
865                               unsigned short number_of_params)
866 {
867     /* counter */
868     unsigned short i;
869     /* current format string offset */
870     int current_offset = 0;
871     /* current stack offset */
872     unsigned short current_stack_offset = 0;
873     /* location to put retval into */
874     LONG_PTR *retval_ptr = NULL;
875
876     for (i = 0; i < number_of_params; i++)
877     {
878         const NDR_PARAM_OIF_BASETYPE *pParam =
879         (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
880         unsigned char *pArg;
881
882         current_stack_offset = pParam->stack_offset;
883         pArg = (unsigned char *)(args+current_stack_offset);
884
885         TRACE("param[%d]: new format\n", i);
886         TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
887         TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
888         TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg);
889
890         if (pParam->param_attributes.IsBasetype)
891         {
892             const unsigned char *pTypeFormat =
893             &pParam->type_format_char;
894
895             TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
896
897             switch (phase)
898             {
899                 case STUBLESS_MARSHAL:
900                     if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
901                     {
902                         if (pParam->param_attributes.IsSimpleRef)
903                             call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
904                         else
905                             call_marshaller(pStubMsg, pArg, pTypeFormat);
906                     }
907                     break;
908                 case STUBLESS_FREE:
909                     if (pParam->param_attributes.ServerAllocSize)
910                         HeapFree(GetProcessHeap(), 0, *(void **)pArg);
911                     break;
912                 case STUBLESS_UNMARSHAL:
913                     if (pParam->param_attributes.ServerAllocSize)
914                         *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
915                                                    pParam->param_attributes.ServerAllocSize * 8);
916
917                     if (pParam->param_attributes.IsIn)
918                     {
919                         if (pParam->param_attributes.IsSimpleRef)
920                             call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
921                         else
922                             call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
923                     }
924
925                     /* make a note of the address of the return value parameter for later */
926                     if (pParam->param_attributes.IsReturn)
927                         retval_ptr = (LONG_PTR *)pArg;
928
929                     break;
930                 case STUBLESS_CALCSIZE:
931                     if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
932                     {
933                         if (pParam->param_attributes.IsSimpleRef)
934                             call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
935                         else
936                             call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
937                     }
938                     break;
939                 default:
940                     RpcRaiseException(RPC_S_INTERNAL_ERROR);
941             }
942
943             current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
944         }
945         else
946         {
947             const NDR_PARAM_OIF_OTHER *pParamOther =
948             (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
949
950             const unsigned char * pTypeFormat =
951                 &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]);
952
953             TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
954
955             switch (phase)
956             {
957                 case STUBLESS_MARSHAL:
958                     if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
959                     {
960                         if (pParam->param_attributes.IsByValue)
961                             call_marshaller(pStubMsg, pArg, pTypeFormat);
962                         else
963                             call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
964                     }
965                     break;
966                 case STUBLESS_FREE:
967                     if (pParam->param_attributes.MustFree)
968                     {
969                         if (pParam->param_attributes.IsByValue)
970                             call_freer(pStubMsg, pArg, pTypeFormat);
971                         else
972                             call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
973                     }
974
975                     if (pParam->param_attributes.IsOut &&
976                         !pParam->param_attributes.IsIn &&
977                         !pParam->param_attributes.IsByValue &&
978                         !pParam->param_attributes.ServerAllocSize)
979                     {
980                         pStubMsg->pfnFree(*(void **)pArg);
981                     }
982
983                     if (pParam->param_attributes.ServerAllocSize)
984                         HeapFree(GetProcessHeap(), 0, *(void **)pArg);
985                     /* FIXME: call call_freer here for IN types with MustFree set */
986                     break;
987                 case STUBLESS_UNMARSHAL:
988                     if (pParam->param_attributes.ServerAllocSize)
989                         *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
990                                                    pParam->param_attributes.ServerAllocSize * 8);
991
992                     if (pParam->param_attributes.IsIn)
993                     {
994                         if (pParam->param_attributes.IsByValue)
995                             call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
996                         else
997                             call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
998                     }
999                     else if (pParam->param_attributes.IsOut &&
1000                              !pParam->param_attributes.ServerAllocSize &&
1001                              !pParam->param_attributes.IsByValue)
1002                     {
1003                         DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
1004
1005                         if(size)
1006                         {
1007                             *(void **)pArg = NdrAllocate(pStubMsg, size);
1008                             memset(*(void **)pArg, 0, size);
1009                         }
1010                     }
1011                     break;
1012                 case STUBLESS_CALCSIZE:
1013                     if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
1014                     {
1015                         if (pParam->param_attributes.IsByValue)
1016                             call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
1017                         else
1018                             call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1019                     }
1020                     break;
1021                 default:
1022                     RpcRaiseException(RPC_S_INTERNAL_ERROR);
1023             }
1024
1025             current_offset += sizeof(NDR_PARAM_OIF_OTHER);
1026         }
1027         TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
1028     }
1029
1030     return retval_ptr;
1031 }
1032
1033 static LONG_PTR *stub_do_old_args(MIDL_STUB_MESSAGE *pStubMsg,
1034                                   PFORMAT_STRING pFormat, int phase,
1035                                   unsigned char *args,
1036                                   unsigned short stack_size, BOOL object)
1037 {
1038     /* counter */
1039     unsigned short i;
1040     /* current format string offset */
1041     int current_offset = 0;
1042     /* current stack offset */
1043     unsigned short current_stack_offset = 0;
1044     /* location to put retval into */
1045     LONG_PTR *retval_ptr = NULL;
1046
1047     for (i = 0; TRUE; i++)
1048     {
1049         const NDR_PARAM_OI_BASETYPE *pParam =
1050         (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
1051         /* note: current_stack_offset starts after the This pointer
1052          * if present, so adjust this */
1053         unsigned short current_stack_offset_adjusted = current_stack_offset +
1054             (object ? sizeof(void *) : 0);
1055         unsigned char *pArg = (unsigned char *)(args+current_stack_offset_adjusted);
1056
1057         /* no more parameters; exit loop */
1058         if (current_stack_offset_adjusted >= stack_size)
1059             break;
1060
1061         TRACE("param[%d]: old format\n", i);
1062         TRACE("\tparam_direction: 0x%x\n", pParam->param_direction);
1063         TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted);
1064
1065         if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
1066             pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1067         {
1068             const unsigned char *pTypeFormat =
1069             &pParam->type_format_char;
1070
1071             TRACE("\tbase type 0x%02x\n", *pTypeFormat);
1072
1073             switch (phase)
1074             {
1075                 case STUBLESS_MARSHAL:
1076                     if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1077                         call_marshaller(pStubMsg, pArg, pTypeFormat);
1078                     break;
1079                 case STUBLESS_FREE:
1080                     if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
1081                         call_freer(pStubMsg, pArg, pTypeFormat);
1082                     break;
1083                 case STUBLESS_UNMARSHAL:
1084                     if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
1085                         call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
1086                     else if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1087                         retval_ptr = (LONG_PTR *)pArg;
1088                         break;
1089                 case STUBLESS_CALCSIZE:
1090                     if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
1091                         call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
1092                     break;
1093                 default:
1094                     RpcRaiseException(RPC_S_INTERNAL_ERROR);
1095             }
1096
1097             current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat);
1098             current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
1099         }
1100         else
1101         {
1102             const NDR_PARAM_OI_OTHER *pParamOther =
1103             (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
1104
1105             const unsigned char * pTypeFormat =
1106                 &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset];
1107
1108             TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
1109
1110             switch (phase)
1111             {
1112                 case STUBLESS_MARSHAL:
1113                     if (pParam->param_direction == RPC_FC_OUT_PARAM ||
1114                         pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1115                         pParam->param_direction == RPC_FC_RETURN_PARAM)
1116                         call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1117                     break;
1118                 case STUBLESS_FREE:
1119                     if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1120                         pParam->param_direction == RPC_FC_IN_PARAM)
1121                         call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1122                     else if (pParam->param_direction == RPC_FC_OUT_PARAM)
1123                         pStubMsg->pfnFree(*(void **)pArg);
1124                         break;
1125                 case STUBLESS_UNMARSHAL:
1126                     if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1127                         pParam->param_direction == RPC_FC_IN_PARAM)
1128                         call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
1129                     else if (pParam->param_direction == RPC_FC_RETURN_PARAM)
1130                         retval_ptr = (LONG_PTR *)pArg;
1131                     else if (pParam->param_direction == RPC_FC_OUT_PARAM)
1132                     {
1133                         DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
1134
1135                         if(size)
1136                         {
1137                             *(void **)pArg = NdrAllocate(pStubMsg, size);
1138                             memset(*(void **)pArg, 0, size);
1139                         }
1140                     }
1141                     break;
1142                 case STUBLESS_CALCSIZE:
1143                     if (pParam->param_direction == RPC_FC_OUT_PARAM ||
1144                         pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
1145                         pParam->param_direction == RPC_FC_RETURN_PARAM)
1146                         call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
1147                     break;
1148                 default:
1149                     RpcRaiseException(RPC_S_INTERNAL_ERROR);
1150             }
1151
1152             current_stack_offset += pParamOther->stack_size * sizeof(INT);
1153             current_offset += sizeof(NDR_PARAM_OI_OTHER);
1154         }
1155     }
1156
1157     return retval_ptr;
1158 }
1159
1160 /***********************************************************************
1161  *            NdrStubCall2 [RPCRT4.@]
1162  *
1163  * Unmarshals [in] parameters, calls either a method in an object or a server
1164  * function, marshals any [out] parameters and frees any allocated data.
1165  *
1166  * NOTES
1167  *  Used by stubless MIDL-generated code.
1168  */
1169 LONG WINAPI NdrStubCall2(
1170     struct IRpcStubBuffer * pThis,
1171     struct IRpcChannelBuffer * pChannel,
1172     PRPC_MESSAGE pRpcMsg,
1173     DWORD * pdwStubPhase)
1174 {
1175     const MIDL_SERVER_INFO *pServerInfo;
1176     const MIDL_STUB_DESC *pStubDesc;
1177     PFORMAT_STRING pFormat;
1178     MIDL_STUB_MESSAGE stubMsg;
1179     /* pointer to start of stack to pass into stub implementation */
1180     unsigned char * args;
1181     /* size of stack */
1182     unsigned short stack_size;
1183     /* number of parameters. optional for client to give it to us */
1184     unsigned char number_of_params = ~0;
1185     /* cache of Oif_flags from v2 procedure header */
1186     INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
1187     /* cache of extension flags from NDR_PROC_HEADER_EXTS */
1188     INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
1189     /* the type of pass we are currently doing */
1190     int phase;
1191     /* header for procedure string */
1192     const NDR_PROC_HEADER *pProcHeader;
1193     /* offset in format string for start of params */
1194     int parameter_start_offset;
1195     /* current format string offset */
1196     int current_offset;
1197     /* -Oif or -Oicf generated format */
1198     BOOL bV2Format = FALSE;
1199     /* location to put retval into */
1200     LONG_PTR *retval_ptr = NULL;
1201
1202     TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase);
1203
1204     if (pThis)
1205         pServerInfo = CStdStubBuffer_GetServerInfo(pThis);
1206     else
1207         pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo;
1208
1209     pStubDesc = pServerInfo->pStubDesc;
1210     pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum];
1211     pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
1212
1213     /* Later NDR language versions probably won't be backwards compatible */
1214     if (pStubDesc->Version > 0x50002)
1215     {
1216         FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
1217         RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
1218     }
1219
1220     /* create the full pointer translation tables, if requested */
1221     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1222         stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER);
1223
1224     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1225     {
1226         const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
1227         stack_size = pProcHeader->stack_size;
1228         current_offset = sizeof(NDR_PROC_HEADER_RPC);
1229
1230     }
1231     else
1232     {
1233         stack_size = pProcHeader->stack_size;
1234         current_offset = sizeof(NDR_PROC_HEADER);
1235     }
1236
1237     TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
1238
1239     /* binding */
1240     switch (pProcHeader->handle_type)
1241     {
1242     /* explicit binding: parse additional section */
1243     case RPC_FC_BIND_EXPLICIT:
1244         switch (pFormat[current_offset]) /* handle_type */
1245         {
1246         case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */
1247             current_offset += sizeof(NDR_EHD_PRIMITIVE);
1248             break;
1249         case RPC_FC_BIND_GENERIC: /* explicit generic */
1250             current_offset += sizeof(NDR_EHD_GENERIC);
1251             break;
1252         case RPC_FC_BIND_CONTEXT: /* explicit context */
1253             current_offset += sizeof(NDR_EHD_CONTEXT);
1254             break;
1255         default:
1256             ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1257             RpcRaiseException(RPC_X_BAD_STUB_DATA);
1258         }
1259         break;
1260     case RPC_FC_BIND_GENERIC: /* implicit generic */
1261     case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */
1262     case RPC_FC_CALLBACK_HANDLE: /* implicit callback */
1263     case RPC_FC_AUTO_HANDLE: /* implicit auto handle */
1264         break;
1265     default:
1266         ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type);
1267         RpcRaiseException(RPC_X_BAD_STUB_DATA);
1268     }
1269
1270     bV2Format = (pStubDesc->Version >= 0x20000);
1271
1272     if (bV2Format)
1273     {
1274         const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
1275             (const NDR_PROC_PARTIAL_OIF_HEADER *)&pFormat[current_offset];
1276
1277         Oif_flags = pOIFHeader->Oi2Flags;
1278         number_of_params = pOIFHeader->number_of_params;
1279
1280         current_offset += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
1281     }
1282
1283     TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
1284
1285     if (Oif_flags.HasExtensions)
1286     {
1287         const NDR_PROC_HEADER_EXTS *pExtensions =
1288             (const NDR_PROC_HEADER_EXTS *)&pFormat[current_offset];
1289         ext_flags = pExtensions->Flags2;
1290         current_offset += pExtensions->Size;
1291     }
1292
1293     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1294         NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel);
1295     else
1296         NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc);
1297
1298     /* store the RPC flags away */
1299     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
1300         pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
1301
1302     /* use alternate memory allocation routines */
1303     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
1304 #if 0
1305           NdrRpcSsEnableAllocate(&stubMsg);
1306 #else
1307           FIXME("Set RPCSS memory allocation routines\n");
1308 #endif
1309
1310     if (Oif_flags.HasPipes)
1311     {
1312         FIXME("pipes not supported yet\n");
1313         RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
1314         /* init pipes package */
1315         /* NdrPipesInitialize(...) */
1316     }
1317     if (ext_flags.HasNewCorrDesc)
1318     {
1319         /* initialize extra correlation package */
1320         FIXME("new correlation description not implemented\n");
1321         stubMsg.fHasNewCorrDesc = TRUE;
1322     }
1323
1324     /* convert strings, floating point values and endianess into our
1325      * preferred format */
1326     if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
1327         NdrConvert(&stubMsg, pFormat);
1328
1329     parameter_start_offset = current_offset;
1330
1331     TRACE("allocating memory for stack of size %x\n", stack_size);
1332
1333     args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size);
1334     stubMsg.StackTop = args; /* used by conformance of top-level objects */
1335
1336     /* add the implicit This pointer as the first arg to the function if we
1337      * are calling an object method */
1338     if (pThis)
1339         *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject;
1340
1341     /* order of phases:
1342      * 1. STUBLESS_UNMARHSAL - unmarshal [in] params from buffer
1343      * 2. STUBLESS_CALLSERVER - send/receive buffer
1344      * 3. STUBLESS_CALCSIZE - get [out] buffer size
1345      * 4. STUBLESS_GETBUFFER - allocate [out] buffer
1346      * 5. STUBLESS_MARHSAL - marshal [out] params to buffer
1347      */
1348     for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++)
1349     {
1350         TRACE("phase = %d\n", phase);
1351         switch (phase)
1352         {
1353         case STUBLESS_CALLSERVER:
1354             /* call the server function */
1355             if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum])
1356                 pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg);
1357             else
1358             {
1359                 SERVER_ROUTINE func;
1360                 LONG_PTR retval;
1361
1362                 if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1363                 {
1364                     SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject;
1365                     func = vtbl[pRpcMsg->ProcNum];
1366                 }
1367                 else
1368                     func = pServerInfo->DispatchTable[pRpcMsg->ProcNum];
1369
1370                 /* FIXME: what happens with return values that don't fit into a single register on x86? */
1371                 retval = call_server_func(func, args, stack_size);
1372
1373                 if (retval_ptr)
1374                 {
1375                     TRACE("stub implementation returned 0x%lx\n", retval);
1376                     *retval_ptr = retval;
1377                 }
1378                 else
1379                     TRACE("void stub implementation\n");
1380             }
1381
1382             stubMsg.Buffer = NULL;
1383             stubMsg.BufferLength = 0;
1384
1385             break;
1386         case STUBLESS_GETBUFFER:
1387             if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
1388                 NdrStubGetBuffer(pThis, pChannel, &stubMsg);
1389             else
1390             {
1391                 RPC_STATUS Status;
1392
1393                 pRpcMsg->BufferLength = stubMsg.BufferLength;
1394                 /* allocate buffer for [out] and [ret] params */
1395                 Status = I_RpcGetBuffer(pRpcMsg); 
1396                 if (Status)
1397                     RpcRaiseException(Status);
1398                 stubMsg.BufferStart = pRpcMsg->Buffer;
1399                 stubMsg.BufferEnd = stubMsg.BufferStart + stubMsg.BufferLength;
1400                 stubMsg.Buffer = stubMsg.BufferStart;
1401             }
1402             break;
1403         case STUBLESS_MARSHAL:
1404         case STUBLESS_UNMARSHAL:
1405         case STUBLESS_CALCSIZE:
1406         case STUBLESS_FREE:
1407             if (bV2Format)
1408                 retval_ptr = stub_do_args(&stubMsg, &pFormat[parameter_start_offset],
1409                                           phase, args, number_of_params);
1410             else
1411                 retval_ptr = stub_do_old_args(&stubMsg, &pFormat[parameter_start_offset],
1412                                               phase, args, stack_size,
1413                                               (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT));
1414
1415             break;
1416         default:
1417             ERR("shouldn't reach here. phase %d\n", phase);
1418             break;
1419         }
1420     }
1421
1422     pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer);
1423
1424     if (ext_flags.HasNewCorrDesc)
1425     {
1426         /* free extra correlation package */
1427         /* NdrCorrelationFree(&stubMsg); */
1428     }
1429
1430     if (Oif_flags.HasPipes)
1431     {
1432         /* NdrPipesDone(...) */
1433     }
1434
1435     /* free the full pointer translation tables */
1436     if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
1437         NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
1438
1439     /* free server function stack */
1440     HeapFree(GetProcessHeap(), 0, args);
1441
1442     return S_OK;
1443 }
1444
1445 /***********************************************************************
1446  *            NdrServerCall2 [RPCRT4.@]
1447  */
1448 void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
1449 {
1450     DWORD dwPhase;
1451     NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
1452 }