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