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