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