rpcrt4: Handle interface pointers in EmbeddedComplexSize.
[wine] / dlls / rpcrt4 / ndr_marshall.c
1 /*
2  * NDR data marshalling
3  *
4  * Copyright 2002 Greg Turner
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * TODO:
21  *  - figure out whether we *really* got this right
22  *  - check for errors and throw exceptions
23  */
24
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <limits.h>
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winerror.h"
34 #include "winreg.h"
35
36 #include "ndr_misc.h"
37 #include "rpcndr.h"
38
39 #include "wine/unicode.h"
40 #include "wine/rpcfc.h"
41
42 #include "wine/debug.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(ole);
45
46 #if defined(__i386__)
47 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
48     (*((UINT32 *)(pchar)) = (uint32))
49
50 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
51     (*((UINT32 *)(pchar)))
52 #else
53   /* these would work for i386 too, but less efficient */
54 # define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
55     (*(pchar)     = LOBYTE(LOWORD(uint32)), \
56      *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
57      *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
58      *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
59      (uint32)) /* allow as r-value */
60
61 # define LITTLE_ENDIAN_UINT32_READ(pchar) \
62     (MAKELONG( \
63       MAKEWORD(*(pchar), *((pchar)+1)), \
64       MAKEWORD(*((pchar)+2), *((pchar)+3))))
65 #endif
66
67 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
68   (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
69    *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
70    *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
71    *(pchar)     = HIBYTE(HIWORD(uint32)), \
72    (uint32)) /* allow as r-value */
73
74 #define BIG_ENDIAN_UINT32_READ(pchar) \
75   (MAKELONG( \
76     MAKEWORD(*((pchar)+3), *((pchar)+2)), \
77     MAKEWORD(*((pchar)+1), *(pchar))))
78
79 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
80 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
81     BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
82 # define NDR_LOCAL_UINT32_READ(pchar) \
83     BIG_ENDIAN_UINT32_READ(pchar)
84 #else
85 # define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
86     LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
87 # define NDR_LOCAL_UINT32_READ(pchar) \
88     LITTLE_ENDIAN_UINT32_READ(pchar)
89 #endif
90
91 /* _Align must be the desired alignment,
92  * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */
93 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1))
94 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
95 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
96 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
97
98 #define STD_OVERFLOW_CHECK(_Msg) do { \
99     TRACE("buffer=%d/%ld\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \
100     if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \
101         ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \
102   } while (0)
103
104 #define NDR_TABLE_SIZE 128
105 #define NDR_TABLE_MASK 127
106
107 static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
108 static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char);
109 static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
110 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING);
111 static unsigned long WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING);
112
113 const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
114   0,
115   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
116   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
117   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
118   NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall,
119   /* 0x10 */
120   NdrBaseTypeMarshall,
121   /* 0x11 */
122   NdrPointerMarshall, NdrPointerMarshall,
123   NdrPointerMarshall, NdrPointerMarshall,
124   /* 0x15 */
125   NdrSimpleStructMarshall, NdrSimpleStructMarshall,
126   NdrConformantStructMarshall, NdrConformantStructMarshall,
127   NdrConformantVaryingStructMarshall,
128   NdrComplexStructMarshall,
129   /* 0x1b */
130   NdrConformantArrayMarshall, 
131   NdrConformantVaryingArrayMarshall,
132   NdrFixedArrayMarshall, NdrFixedArrayMarshall,
133   NdrVaryingArrayMarshall, NdrVaryingArrayMarshall,
134   NdrComplexArrayMarshall,
135   /* 0x22 */
136   NdrConformantStringMarshall, 0, 0,
137   NdrConformantStringMarshall,
138   NdrNonConformantStringMarshall, 0, 0, 0,
139   /* 0x2a */
140   NdrEncapsulatedUnionMarshall,
141   NdrNonEncapsulatedUnionMarshall,
142   NdrByteCountPointerMarshall,
143   NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall,
144   /* 0x2f */
145   NdrInterfacePointerMarshall,
146   /* 0xb0 */
147   0, 0, 0, 0,
148   NdrUserMarshalMarshall
149 };
150 const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
151   0,
152   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
153   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
154   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
155   NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall,
156   /* 0x10 */
157   NdrBaseTypeUnmarshall,
158   /* 0x11 */
159   NdrPointerUnmarshall, NdrPointerUnmarshall,
160   NdrPointerUnmarshall, NdrPointerUnmarshall,
161   /* 0x15 */
162   NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
163   NdrConformantStructUnmarshall, NdrConformantStructUnmarshall,
164   NdrConformantVaryingStructUnmarshall,
165   NdrComplexStructUnmarshall,
166   /* 0x1b */
167   NdrConformantArrayUnmarshall, 
168   NdrConformantVaryingArrayUnmarshall,
169   NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall,
170   NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall,
171   NdrComplexArrayUnmarshall,
172   /* 0x22 */
173   NdrConformantStringUnmarshall, 0, 0,
174   NdrConformantStringUnmarshall,
175   NdrNonConformantStringUnmarshall, 0, 0, 0,
176   /* 0x2a */
177   NdrEncapsulatedUnionUnmarshall,
178   NdrNonEncapsulatedUnionUnmarshall,
179   NdrByteCountPointerUnmarshall,
180   NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall,
181   /* 0x2f */
182   NdrInterfacePointerUnmarshall,
183   /* 0xb0 */
184   0, 0, 0, 0,
185   NdrUserMarshalUnmarshall
186 };
187 const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
188   0,
189   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
190   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
191   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
192   NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize,
193   /* 0x10 */
194   NdrBaseTypeBufferSize,
195   /* 0x11 */
196   NdrPointerBufferSize, NdrPointerBufferSize,
197   NdrPointerBufferSize, NdrPointerBufferSize,
198   /* 0x15 */
199   NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
200   NdrConformantStructBufferSize, NdrConformantStructBufferSize,
201   NdrConformantVaryingStructBufferSize,
202   NdrComplexStructBufferSize,
203   /* 0x1b */
204   NdrConformantArrayBufferSize, 
205   NdrConformantVaryingArrayBufferSize,
206   NdrFixedArrayBufferSize, NdrFixedArrayBufferSize,
207   NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize,
208   NdrComplexArrayBufferSize,
209   /* 0x22 */
210   NdrConformantStringBufferSize, 0, 0,
211   NdrConformantStringBufferSize,
212   NdrNonConformantStringBufferSize, 0, 0, 0,
213   /* 0x2a */
214   NdrEncapsulatedUnionBufferSize,
215   NdrNonEncapsulatedUnionBufferSize,
216   NdrByteCountPointerBufferSize,
217   NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize,
218   /* 0x2f */
219   NdrInterfacePointerBufferSize,
220   /* 0xb0 */
221   0, 0, 0, 0,
222   NdrUserMarshalBufferSize
223 };
224 const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
225   0,
226   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
227   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
228   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
229   NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize,
230   /* 0x10 */
231   NdrBaseTypeMemorySize,
232   /* 0x11 */
233   NdrPointerMemorySize, NdrPointerMemorySize,
234   NdrPointerMemorySize, NdrPointerMemorySize,
235   /* 0x15 */
236   NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
237   NdrConformantStructMemorySize, NdrConformantStructMemorySize,
238   NdrConformantVaryingStructMemorySize,
239   NdrComplexStructMemorySize,
240   /* 0x1b */
241   NdrConformantArrayMemorySize,
242   NdrConformantVaryingArrayMemorySize,
243   NdrFixedArrayMemorySize, NdrFixedArrayMemorySize,
244   NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize,
245   NdrComplexArrayMemorySize,
246   /* 0x22 */
247   NdrConformantStringMemorySize, 0, 0,
248   NdrConformantStringMemorySize,
249   NdrNonConformantStringMemorySize, 0, 0, 0,
250   /* 0x2a */
251   NdrEncapsulatedUnionMemorySize,
252   NdrNonEncapsulatedUnionMemorySize,
253   NdrByteCountPointerMemorySize,
254   NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize,
255   /* 0x2f */
256   NdrInterfacePointerMemorySize,
257   /* 0xb0 */
258   0, 0, 0, 0,
259   NdrUserMarshalMemorySize
260 };
261 const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
262   0,
263   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
264   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
265   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
266   NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree,
267   /* 0x10 */
268   NdrBaseTypeFree,
269   /* 0x11 */
270   NdrPointerFree, NdrPointerFree,
271   NdrPointerFree, NdrPointerFree,
272   /* 0x15 */
273   NdrSimpleStructFree, NdrSimpleStructFree,
274   NdrConformantStructFree, NdrConformantStructFree,
275   NdrConformantVaryingStructFree,
276   NdrComplexStructFree,
277   /* 0x1b */
278   NdrConformantArrayFree, 
279   NdrConformantVaryingArrayFree,
280   NdrFixedArrayFree, NdrFixedArrayFree,
281   NdrVaryingArrayFree, NdrVaryingArrayFree,
282   NdrComplexArrayFree,
283   /* 0x22 */
284   0, 0, 0,
285   0, 0, 0, 0, 0,
286   /* 0x2a */
287   NdrEncapsulatedUnionFree,
288   NdrNonEncapsulatedUnionFree,
289   0,
290   NdrXmitOrRepAsFree, NdrXmitOrRepAsFree,
291   /* 0x2f */
292   NdrInterfacePointerFree,
293   /* 0xb0 */
294   0, 0, 0, 0,
295   NdrUserMarshalFree
296 };
297
298 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
299 {
300   /* hmm, this is probably supposed to do more? */
301   return pStubMsg->pfnAllocate(len);
302 }
303
304 static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
305 {
306   pStubMsg->pfnFree(Pointer);
307 }
308
309 static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat)
310 {
311     return (*(const ULONG *)pFormat != -1);
312 }
313
314 PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
315 {
316   ALIGN_POINTER(pStubMsg->Buffer, 4);
317   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
318   pStubMsg->Buffer += 4;
319   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
320   if (pStubMsg->fHasNewCorrDesc)
321     return pFormat+6;
322   else
323     return pFormat+4;
324 }
325
326 static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
327 {
328   if (pFormat && !IsConformanceOrVariancePresent(pFormat))
329   {
330     pStubMsg->Offset = 0;
331     pStubMsg->ActualCount = pStubMsg->MaxCount;
332     goto done;
333   }
334
335   ALIGN_POINTER(pStubMsg->Buffer, 4);
336   pStubMsg->Offset      = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
337   pStubMsg->Buffer += 4;
338   TRACE("offset is %ld\n", pStubMsg->Offset);
339   pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
340   pStubMsg->Buffer += 4;
341   TRACE("variance is %ld\n", pStubMsg->ActualCount);
342
343 done:
344   if (pStubMsg->fHasNewCorrDesc)
345     return pFormat+6;
346   else
347     return pFormat+4;
348 }
349
350 /* writes the conformance value to the buffer */
351 static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg)
352 {
353     ALIGN_POINTER(pStubMsg->Buffer, 4);
354     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount);
355     pStubMsg->Buffer += 4;
356 }
357
358 /* writes the variance values to the buffer */
359 static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg)
360 {
361     ALIGN_POINTER(pStubMsg->Buffer, 4);
362     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset);
363     pStubMsg->Buffer += 4;
364     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount);
365     pStubMsg->Buffer += 4;
366 }
367
368 /* requests buffer space for the conformance value */
369 static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg)
370 {
371     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
372     pStubMsg->BufferLength += 4;
373 }
374
375 /* requests buffer space for the variance values */
376 static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg)
377 {
378     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
379     pStubMsg->BufferLength += 8;
380 }
381
382 PFORMAT_STRING ComputeConformanceOrVariance(
383     MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
384     PFORMAT_STRING pFormat, ULONG_PTR def, ULONG *pCount)
385 {
386   BYTE dtype = pFormat[0] & 0xf;
387   short ofs = *(short *)&pFormat[2];
388   LPVOID ptr = NULL;
389   DWORD data = 0;
390
391   if (!IsConformanceOrVariancePresent(pFormat)) {
392     /* null descriptor */
393     *pCount = def;
394     goto finish_conf;
395   }
396
397   switch (pFormat[0] & 0xf0) {
398   case RPC_FC_NORMAL_CONFORMANCE:
399     TRACE("normal conformance, ofs=%d\n", ofs);
400     ptr = pMemory;
401     break;
402   case RPC_FC_POINTER_CONFORMANCE:
403     TRACE("pointer conformance, ofs=%d\n", ofs);
404     ptr = pStubMsg->Memory;
405     break;
406   case RPC_FC_TOP_LEVEL_CONFORMANCE:
407     TRACE("toplevel conformance, ofs=%d\n", ofs);
408     if (pStubMsg->StackTop) {
409       ptr = pStubMsg->StackTop;
410     }
411     else {
412       /* -Os mode, *pCount is already set */
413       goto finish_conf;
414     }
415     break;
416   case RPC_FC_CONSTANT_CONFORMANCE:
417     data = ofs | ((DWORD)pFormat[1] << 16);
418     TRACE("constant conformance, val=%ld\n", data);
419     *pCount = data;
420     goto finish_conf;
421   case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
422     FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs);
423     if (pStubMsg->StackTop) {
424       ptr = pStubMsg->StackTop;
425     }
426     else {
427       /* ? */
428       goto done_conf_grab;
429     }
430     break;
431   default:
432     FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
433   }
434
435   switch (pFormat[1]) {
436   case RPC_FC_DEREFERENCE:
437     ptr = *(LPVOID*)((char *)ptr + ofs);
438     break;
439   case RPC_FC_CALLBACK:
440   {
441     unsigned char *old_stack_top = pStubMsg->StackTop;
442     pStubMsg->StackTop = ptr;
443
444     /* ofs is index into StubDesc->apfnExprEval */
445     TRACE("callback conformance into apfnExprEval[%d]\n", ofs);
446     pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg);
447
448     pStubMsg->StackTop = old_stack_top;
449     goto finish_conf;
450   }
451   default:
452     ptr = (char *)ptr + ofs;
453     break;
454   }
455
456   switch (dtype) {
457   case RPC_FC_LONG:
458   case RPC_FC_ULONG:
459     data = *(DWORD*)ptr;
460     break;
461   case RPC_FC_SHORT:
462     data = *(SHORT*)ptr;
463     break;
464   case RPC_FC_USHORT:
465     data = *(USHORT*)ptr;
466     break;
467   case RPC_FC_CHAR:
468   case RPC_FC_SMALL:
469     data = *(CHAR*)ptr;
470     break;
471   case RPC_FC_BYTE:
472   case RPC_FC_USMALL:
473     data = *(UCHAR*)ptr;
474     break;
475   default:
476     FIXME("unknown conformance data type %x\n", dtype);
477     goto done_conf_grab;
478   }
479   TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);
480
481 done_conf_grab:
482   switch (pFormat[1]) {
483   case 0: /* no op */
484     *pCount = data;
485     break;
486   case RPC_FC_DEREFERENCE:
487     /* already handled */
488     break;
489   case RPC_FC_ADD_1:
490     *pCount = data + 1;
491     break;
492   case RPC_FC_SUB_1:
493     *pCount = data - 1;
494     break;
495   case RPC_FC_MULT_2:
496     *pCount = data * 2;
497     break;
498   case RPC_FC_DIV_2:
499     *pCount = data / 2;
500     break;
501   default:
502     FIXME("unknown conformance op %d\n", pFormat[1]);
503     goto finish_conf;
504   }
505
506 finish_conf:
507   TRACE("resulting conformance is %ld\n", *pCount);
508   if (pStubMsg->fHasNewCorrDesc)
509     return pFormat+6;
510   else
511     return pFormat+4;
512 }
513
514
515 /*
516  * NdrConformantString:
517  * 
518  * What MS calls a ConformantString is, in DCE terminology,
519  * a Varying-Conformant String.
520  * [
521  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
522  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
523  *           into unmarshalled string) 
524  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
525  *   [ 
526  *     data: CHARTYPE[maxlen]
527  *   ] 
528  * ], where CHARTYPE is the appropriate character type (specified externally)
529  *
530  */
531
532 /***********************************************************************
533  *            NdrConformantStringMarshall [RPCRT4.@]
534  */
535 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
536   unsigned char *pszMessage, PFORMAT_STRING pFormat)
537
538   unsigned long esize;
539
540   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
541   
542   if (*pFormat == RPC_FC_C_CSTRING) {
543     TRACE("string=%s\n", debugstr_a((char*)pszMessage));
544     pStubMsg->ActualCount = strlen((char*)pszMessage)+1;
545     esize = 1;
546   }
547   else if (*pFormat == RPC_FC_C_WSTRING) {
548     TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
549     pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1;
550     esize = 2;
551   }
552   else {
553     ERR("Unhandled string type: %#x\n", *pFormat); 
554     /* FIXME: raise an exception. */
555     return NULL;
556   }
557
558   if (pFormat[1] == RPC_FC_STRING_SIZED)
559     pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0);
560   else
561     pStubMsg->MaxCount = pStubMsg->ActualCount;
562   pStubMsg->Offset = 0;
563   WriteConformance(pStubMsg);
564   WriteVariance(pStubMsg);
565
566   memcpy(pStubMsg->Buffer, pszMessage, pStubMsg->ActualCount*esize); /* the string itself */
567   pStubMsg->Buffer += pStubMsg->ActualCount*esize;
568
569   STD_OVERFLOW_CHECK(pStubMsg);
570
571   /* success */
572   return NULL; /* is this always right? */
573 }
574
575 /***********************************************************************
576  *           NdrConformantStringBufferSize [RPCRT4.@]
577  */
578 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
579   unsigned char* pMemory, PFORMAT_STRING pFormat)
580 {
581   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
582
583   SizeConformance(pStubMsg);
584   SizeVariance(pStubMsg);
585
586   if (*pFormat == RPC_FC_C_CSTRING) {
587     /* we need + 1 octet for '\0' */
588     TRACE("string=%s\n", debugstr_a((char*)pMemory));
589     pStubMsg->BufferLength += strlen((char*)pMemory) + 1;
590   }
591   else if (*pFormat == RPC_FC_C_WSTRING) {
592     /* we need + 2 octets for L'\0' */
593     TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
594     pStubMsg->BufferLength += strlenW((LPWSTR)pMemory)*2 + 2;
595   }
596   else {
597     ERR("Unhandled string type: %#x\n", *pFormat); 
598     /* FIXME: raise an exception */
599   }
600 }
601
602 /************************************************************************
603  *            NdrConformantStringMemorySize [RPCRT4.@]
604  */
605 unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
606   PFORMAT_STRING pFormat )
607 {
608   unsigned long rslt = 0;
609
610   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
611    
612   assert(pStubMsg && pFormat);
613
614   if (*pFormat == RPC_FC_C_CSTRING) {
615     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
616   }
617   else if (*pFormat == RPC_FC_C_WSTRING) {
618     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */
619   }
620   else {
621     ERR("Unhandled string type: %#x\n", *pFormat);
622     /* FIXME: raise an exception */
623   }
624
625   if (pFormat[1] != RPC_FC_PAD) {
626     FIXME("sized string format=%d\n", pFormat[1]);
627   }
628
629   TRACE("  --> %lu\n", rslt);
630   return rslt;
631 }
632
633 /************************************************************************
634  *           NdrConformantStringUnmarshall [RPCRT4.@]
635  */
636 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
637   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
638 {
639   unsigned long len, esize;
640
641   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
642     pStubMsg, *ppMemory, pFormat, fMustAlloc);
643
644   assert(pFormat && ppMemory && pStubMsg);
645
646   ReadConformance(pStubMsg, NULL);
647   ReadVariance(pStubMsg, NULL);
648
649   if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
650   else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
651   else {
652     ERR("Unhandled string type: %#x\n", *pFormat);
653     /* FIXME: raise an exception */
654     esize = 0;
655   }
656
657   len = pStubMsg->ActualCount;
658
659   if (fMustAlloc || !*ppMemory)
660     *ppMemory = NdrAllocate(pStubMsg, len*esize);
661
662   memcpy(*ppMemory, pStubMsg->Buffer, len*esize);
663
664   pStubMsg->Buffer += len*esize;
665
666   if (*pFormat == RPC_FC_C_CSTRING) {
667     TRACE("string=%s\n", debugstr_a((char*)*ppMemory));
668   }
669   else if (*pFormat == RPC_FC_C_WSTRING) {
670     TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory));
671   }
672
673   return NULL; /* FIXME: is this always right? */
674 }
675
676 /***********************************************************************
677  *           NdrNonConformantStringMarshall [RPCRT4.@]
678  */
679 unsigned char *  WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg,
680                                 unsigned char *pMemory,
681                                 PFORMAT_STRING pFormat)
682 {
683     FIXME("stub\n");
684     return NULL;
685 }
686
687 /***********************************************************************
688  *           NdrNonConformantStringUnmarshall [RPCRT4.@]
689  */
690 unsigned char *  WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
691                                 unsigned char **ppMemory,
692                                 PFORMAT_STRING pFormat,
693                                 unsigned char fMustAlloc)
694 {
695     FIXME("stub\n");
696     return NULL;
697 }
698
699 /***********************************************************************
700  *           NdrNonConformantStringBufferSize [RPCRT4.@]
701  */
702 void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
703                                 unsigned char *pMemory,
704                                 PFORMAT_STRING pFormat)
705 {
706     FIXME("stub\n");
707 }
708
709 /***********************************************************************
710  *           NdrNonConformantStringMemorySize [RPCRT4.@]
711  */
712 unsigned long WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
713                                 PFORMAT_STRING pFormat)
714 {
715     FIXME("stub\n");
716     return 0;
717 }
718
719 static inline void dump_pointer_attr(unsigned char attr)
720 {
721     if (attr & RPC_FC_P_ALLOCALLNODES)
722         TRACE(" RPC_FC_P_ALLOCALLNODES");
723     if (attr & RPC_FC_P_DONTFREE)
724         TRACE(" RPC_FC_P_DONTFREE");
725     if (attr & RPC_FC_P_ONSTACK)
726         TRACE(" RPC_FC_P_ONSTACK");
727     if (attr & RPC_FC_P_SIMPLEPOINTER)
728         TRACE(" RPC_FC_P_SIMPLEPOINTER");
729     if (attr & RPC_FC_P_DEREF)
730         TRACE(" RPC_FC_P_DEREF");
731     TRACE("\n");
732 }
733
734 /***********************************************************************
735  *           PointerMarshall
736  */
737 void WINAPI PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
738                             unsigned char *Buffer,
739                             unsigned char *Pointer,
740                             PFORMAT_STRING pFormat)
741 {
742   unsigned type = pFormat[0], attr = pFormat[1];
743   PFORMAT_STRING desc;
744   NDR_MARSHALL m;
745
746   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
747   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
748   pFormat += 2;
749   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
750   else desc = pFormat + *(const SHORT*)pFormat;
751
752   switch (type) {
753   case RPC_FC_RP: /* ref pointer (always non-null) */
754 #if 0 /* this causes problems for InstallShield so is disabled - we need more tests */
755     if (!Pointer)
756       RpcRaiseException(RPC_X_NULL_REF_POINTER);
757 #endif
758     break;
759   case RPC_FC_UP: /* unique pointer */
760   case RPC_FC_OP: /* object pointer - same as unique here */
761     TRACE("writing %p to buffer\n", Pointer);
762     NDR_LOCAL_UINT32_WRITE(Buffer, (unsigned long)Pointer);
763     break;
764   case RPC_FC_FP:
765   default:
766     FIXME("unhandled ptr type=%02x\n", type);
767     RpcRaiseException(RPC_X_BAD_STUB_DATA);
768   }
769
770   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
771
772   if (Pointer) {
773     if (attr & RPC_FC_P_DEREF) {
774       Pointer = *(unsigned char**)Pointer;
775       TRACE("deref => %p\n", Pointer);
776     }
777     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
778     if (m) m(pStubMsg, Pointer, desc);
779     else FIXME("no marshaller for data type=%02x\n", *desc);
780   }
781
782   STD_OVERFLOW_CHECK(pStubMsg);
783 }
784
785 /***********************************************************************
786  *           PointerUnmarshall
787  */
788 void WINAPI PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
789                               unsigned char *Buffer,
790                               unsigned char **pPointer,
791                               PFORMAT_STRING pFormat,
792                               unsigned char fMustAlloc)
793 {
794   unsigned type = pFormat[0], attr = pFormat[1];
795   PFORMAT_STRING desc;
796   NDR_UNMARSHALL m;
797   DWORD pointer_id = 0;
798
799   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc);
800   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
801   pFormat += 2;
802   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
803   else desc = pFormat + *(const SHORT*)pFormat;
804
805   switch (type) {
806   case RPC_FC_RP: /* ref pointer (always non-null) */
807     pointer_id = ~0UL;
808     break;
809   case RPC_FC_UP: /* unique pointer */
810     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
811     TRACE("pointer_id is 0x%08lx\n", pointer_id);
812     break;
813   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
814     pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
815     TRACE("pointer_id is 0x%08lx\n", pointer_id);
816     if (*pPointer)
817         FIXME("free object pointer %p\n", *pPointer);
818     break;
819   case RPC_FC_FP:
820   default:
821     FIXME("unhandled ptr type=%02x\n", type);
822     RpcRaiseException(RPC_X_BAD_STUB_DATA);
823   }
824
825   if (pointer_id) {
826     if (attr & RPC_FC_P_DEREF) {
827       if (!*pPointer || fMustAlloc)
828         *pPointer = NdrAllocate(pStubMsg, sizeof(void *));
829       pPointer = *(unsigned char***)pPointer;
830       TRACE("deref => %p\n", pPointer);
831     }
832     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
833     if (m) m(pStubMsg, pPointer, desc, fMustAlloc);
834     else FIXME("no unmarshaller for data type=%02x\n", *desc);
835   }
836
837   TRACE("pointer=%p\n", *pPointer);
838 }
839
840 /***********************************************************************
841  *           PointerBufferSize
842  */
843 void WINAPI PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
844                               unsigned char *Pointer,
845                               PFORMAT_STRING pFormat)
846 {
847   unsigned type = pFormat[0], attr = pFormat[1];
848   PFORMAT_STRING desc;
849   NDR_BUFFERSIZE m;
850
851   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
852   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
853   pFormat += 2;
854   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
855   else desc = pFormat + *(const SHORT*)pFormat;
856
857   switch (type) {
858   case RPC_FC_RP: /* ref pointer (always non-null) */
859     break;
860   case RPC_FC_OP:
861   case RPC_FC_UP:
862     /* NULL pointer has no further representation */
863     if (!Pointer)
864         return;
865     break;
866   case RPC_FC_FP:
867   default:
868     FIXME("unhandled ptr type=%02x\n", type);
869     RpcRaiseException(RPC_X_BAD_STUB_DATA);
870   }
871
872   if (attr & RPC_FC_P_DEREF) {
873     Pointer = *(unsigned char**)Pointer;
874     TRACE("deref => %p\n", Pointer);
875   }
876
877   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
878   if (m) m(pStubMsg, Pointer, desc);
879   else FIXME("no buffersizer for data type=%02x\n", *desc);
880 }
881
882 /***********************************************************************
883  *           PointerMemorySize [RPCRT4.@]
884  */
885 unsigned long WINAPI PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
886                                        unsigned char *Buffer,
887                                        PFORMAT_STRING pFormat)
888 {
889   unsigned type = pFormat[0], attr = pFormat[1];
890   PFORMAT_STRING desc;
891   NDR_MEMORYSIZE m;
892
893   FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat);
894   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
895   pFormat += 2;
896   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
897   else desc = pFormat + *(const SHORT*)pFormat;
898
899   switch (type) {
900   case RPC_FC_RP: /* ref pointer (always non-null) */
901     break;
902   default:
903     FIXME("unhandled ptr type=%02x\n", type);
904     RpcRaiseException(RPC_X_BAD_STUB_DATA);
905   }
906
907   if (attr & RPC_FC_P_DEREF) {
908     TRACE("deref\n");
909   }
910
911   m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
912   if (m) m(pStubMsg, desc);
913   else FIXME("no memorysizer for data type=%02x\n", *desc);
914
915   return 0;
916 }
917
918 /***********************************************************************
919  *           PointerFree [RPCRT4.@]
920  */
921 void WINAPI PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
922                         unsigned char *Pointer,
923                         PFORMAT_STRING pFormat)
924 {
925   unsigned type = pFormat[0], attr = pFormat[1];
926   PFORMAT_STRING desc;
927   NDR_FREE m;
928
929   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
930   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
931   if (attr & RPC_FC_P_DONTFREE) return;
932   pFormat += 2;
933   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
934   else desc = pFormat + *(const SHORT*)pFormat;
935
936   if (!Pointer) return;
937
938   if (attr & RPC_FC_P_DEREF) {
939     Pointer = *(unsigned char**)Pointer;
940     TRACE("deref => %p\n", Pointer);
941   }
942
943   m = NdrFreer[*desc & NDR_TABLE_MASK];
944   if (m) m(pStubMsg, Pointer, desc);
945
946   /* hmm... is this sensible?
947    * perhaps we should check if the memory comes from NdrAllocate,
948    * and deallocate only if so - checking if the pointer is between
949    * BufferStart and BufferEnd is probably no good since the buffer
950    * may be reallocated when the server wants to marshal the reply */
951   switch (*desc) {
952   case RPC_FC_BOGUS_STRUCT:
953   case RPC_FC_BOGUS_ARRAY:
954   case RPC_FC_USER_MARSHAL:
955   case RPC_FC_CARRAY:
956   case RPC_FC_CVARRAY:
957     break;
958   default:
959     FIXME("unhandled data type=%02x\n", *desc);
960     break;
961   case RPC_FC_C_CSTRING:
962   case RPC_FC_C_WSTRING:
963     if (pStubMsg->ReuseBuffer) goto notfree;
964     break;
965   case RPC_FC_IP:
966     goto notfree;
967   }
968
969   if (attr & RPC_FC_P_ONSTACK) {
970     TRACE("not freeing stack ptr %p\n", Pointer);
971     return;
972   }
973   TRACE("freeing %p\n", Pointer);
974   NdrFree(pStubMsg, Pointer);
975   return;
976 notfree:
977   TRACE("not freeing %p\n", Pointer);
978 }
979
980 /***********************************************************************
981  *           EmbeddedPointerMarshall
982  */
983 unsigned char * WINAPI EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
984                                                unsigned char *pMemory,
985                                                PFORMAT_STRING pFormat)
986 {
987   unsigned char *Mark = pStubMsg->BufferMark;
988   unsigned long Offset = pStubMsg->Offset;
989   unsigned ofs, rep, count, stride, xofs;
990   unsigned i;
991
992   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
993
994   if (*pFormat != RPC_FC_PP) return NULL;
995   pFormat += 2;
996
997   while (pFormat[0] != RPC_FC_END) {
998     switch (pFormat[0]) {
999     default:
1000       FIXME("unknown repeat type %d\n", pFormat[0]);
1001     case RPC_FC_NO_REPEAT:
1002       rep = 1;
1003       stride = 0;
1004       ofs = 0;
1005       count = 1;
1006       xofs = 0;
1007       pFormat += 2;
1008       break;
1009     case RPC_FC_FIXED_REPEAT:
1010       rep = *(const WORD*)&pFormat[2];
1011       stride = *(const WORD*)&pFormat[4];
1012       ofs = *(const WORD*)&pFormat[6];
1013       count = *(const WORD*)&pFormat[8];
1014       xofs = 0;
1015       pFormat += 10;
1016       break;
1017     case RPC_FC_VARIABLE_REPEAT:
1018       rep = pStubMsg->MaxCount;
1019       stride = *(const WORD*)&pFormat[2];
1020       ofs = *(const WORD*)&pFormat[4];
1021       count = *(const WORD*)&pFormat[6];
1022       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1023       pFormat += 8;
1024       break;
1025     }
1026     for (i = 0; i < rep; i++) {
1027       PFORMAT_STRING info = pFormat;
1028       unsigned char *membase = pMemory + (i * stride);
1029       unsigned char *bufbase = Mark + (i * stride);
1030       unsigned u;
1031       /* ofs doesn't seem to matter in this context */
1032       for (u=0; u<count; u++,info+=8) {
1033         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1034         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1035         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
1036       }
1037     }
1038     pFormat += 8 * count;
1039   }
1040
1041   STD_OVERFLOW_CHECK(pStubMsg);
1042
1043   return NULL;
1044 }
1045
1046 /***********************************************************************
1047  *           EmbeddedPointerUnmarshall
1048  */
1049 unsigned char * WINAPI EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1050                                                  unsigned char **ppMemory,
1051                                                  PFORMAT_STRING pFormat,
1052                                                  unsigned char fMustAlloc)
1053 {
1054   unsigned char *Mark = pStubMsg->BufferMark;
1055   unsigned long Offset = pStubMsg->Offset;
1056   unsigned ofs, rep, count, stride, xofs;
1057   unsigned i;
1058
1059   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1060
1061   if (*pFormat != RPC_FC_PP) return NULL;
1062   pFormat += 2;
1063
1064   while (pFormat[0] != RPC_FC_END) {
1065     TRACE("pFormat[0] = 0x%x\n", pFormat[0]);
1066     switch (pFormat[0]) {
1067     default:
1068       FIXME("unknown repeat type %d\n", pFormat[0]);
1069     case RPC_FC_NO_REPEAT:
1070       rep = 1;
1071       stride = 0;
1072       ofs = 0;
1073       count = 1;
1074       xofs = 0;
1075       pFormat += 2;
1076       break;
1077     case RPC_FC_FIXED_REPEAT:
1078       rep = *(const WORD*)&pFormat[2];
1079       stride = *(const WORD*)&pFormat[4];
1080       ofs = *(const WORD*)&pFormat[6];
1081       count = *(const WORD*)&pFormat[8];
1082       xofs = 0;
1083       pFormat += 10;
1084       break;
1085     case RPC_FC_VARIABLE_REPEAT:
1086       rep = pStubMsg->MaxCount;
1087       stride = *(const WORD*)&pFormat[2];
1088       ofs = *(const WORD*)&pFormat[4];
1089       count = *(const WORD*)&pFormat[6];
1090       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1091       pFormat += 8;
1092       break;
1093     }
1094     /* ofs doesn't seem to matter in this context */
1095     for (i = 0; i < rep; i++) {
1096       PFORMAT_STRING info = pFormat;
1097       unsigned char *membase = *ppMemory + (i * stride);
1098       unsigned char *bufbase = Mark + (i * stride);
1099       unsigned u;
1100       for (u=0; u<count; u++,info+=8) {
1101         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1102         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1103         *(void **)memptr = NULL;
1104         PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, fMustAlloc);
1105       }
1106     }
1107     pFormat += 8 * count;
1108   }
1109
1110   return NULL;
1111 }
1112
1113 /***********************************************************************
1114  *           EmbeddedPointerBufferSize
1115  */
1116 void WINAPI EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1117                                       unsigned char *pMemory,
1118                                       PFORMAT_STRING pFormat)
1119 {
1120   unsigned long Offset = pStubMsg->Offset;
1121   unsigned ofs, rep, count, stride, xofs;
1122   unsigned i;
1123
1124   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1125
1126   if (pStubMsg->IgnoreEmbeddedPointers) return;
1127
1128   if (*pFormat != RPC_FC_PP) return;
1129   pFormat += 2;
1130
1131   while (pFormat[0] != RPC_FC_END) {
1132     switch (pFormat[0]) {
1133     default:
1134       FIXME("unknown repeat type %d\n", pFormat[0]);
1135     case RPC_FC_NO_REPEAT:
1136       rep = 1;
1137       stride = 0;
1138       ofs = 0;
1139       count = 1;
1140       xofs = 0;
1141       pFormat += 2;
1142       break;
1143     case RPC_FC_FIXED_REPEAT:
1144       rep = *(const WORD*)&pFormat[2];
1145       stride = *(const WORD*)&pFormat[4];
1146       ofs = *(const WORD*)&pFormat[6];
1147       count = *(const WORD*)&pFormat[8];
1148       xofs = 0;
1149       pFormat += 10;
1150       break;
1151     case RPC_FC_VARIABLE_REPEAT:
1152       rep = pStubMsg->MaxCount;
1153       stride = *(const WORD*)&pFormat[2];
1154       ofs = *(const WORD*)&pFormat[4];
1155       count = *(const WORD*)&pFormat[6];
1156       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1157       pFormat += 8;
1158       break;
1159     }
1160     /* ofs doesn't seem to matter in this context */
1161     for (i = 0; i < rep; i++) {
1162       PFORMAT_STRING info = pFormat;
1163       unsigned char *membase = pMemory + (i * stride);
1164       unsigned u;
1165       for (u=0; u<count; u++,info+=8) {
1166         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1167         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
1168       }
1169     }
1170     pFormat += 8 * count;
1171   }
1172 }
1173
1174 /***********************************************************************
1175  *           EmbeddedPointerMemorySize
1176  */
1177 unsigned long WINAPI EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1178                                                PFORMAT_STRING pFormat)
1179 {
1180   unsigned long Offset = pStubMsg->Offset;
1181   unsigned char *Mark = pStubMsg->BufferMark;
1182   unsigned ofs, rep, count, stride, xofs;
1183   unsigned i;
1184
1185   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1186
1187   if (*pFormat != RPC_FC_PP) return 0;
1188   pFormat += 2;
1189
1190   while (pFormat[0] != RPC_FC_END) {
1191     switch (pFormat[0]) {
1192     default:
1193       FIXME("unknown repeat type %d\n", pFormat[0]);
1194     case RPC_FC_NO_REPEAT:
1195       rep = 1;
1196       stride = 0;
1197       ofs = 0;
1198       count = 1;
1199       xofs = 0;
1200       pFormat += 2;
1201       break;
1202     case RPC_FC_FIXED_REPEAT:
1203       rep = *(const WORD*)&pFormat[2];
1204       stride = *(const WORD*)&pFormat[4];
1205       ofs = *(const WORD*)&pFormat[6];
1206       count = *(const WORD*)&pFormat[8];
1207       xofs = 0;
1208       pFormat += 10;
1209       break;
1210     case RPC_FC_VARIABLE_REPEAT:
1211       rep = pStubMsg->MaxCount;
1212       stride = *(const WORD*)&pFormat[2];
1213       ofs = *(const WORD*)&pFormat[4];
1214       count = *(const WORD*)&pFormat[6];
1215       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1216       pFormat += 8;
1217       break;
1218     }
1219     /* ofs doesn't seem to matter in this context */
1220     for (i = 0; i < rep; i++) {
1221       PFORMAT_STRING info = pFormat;
1222       unsigned char *bufbase = Mark + (i * stride);
1223       unsigned u;
1224       for (u=0; u<count; u++,info+=8) {
1225         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
1226         PointerMemorySize(pStubMsg, bufptr, info+4);
1227       }
1228     }
1229     pFormat += 8 * count;
1230   }
1231
1232   return 0;
1233 }
1234
1235 /***********************************************************************
1236  *           EmbeddedPointerFree
1237  */
1238 void WINAPI EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1239                                 unsigned char *pMemory,
1240                                 PFORMAT_STRING pFormat)
1241 {
1242   unsigned long Offset = pStubMsg->Offset;
1243   unsigned ofs, rep, count, stride, xofs;
1244   unsigned i;
1245
1246   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1247   if (*pFormat != RPC_FC_PP) return;
1248   pFormat += 2;
1249
1250   while (pFormat[0] != RPC_FC_END) {
1251     switch (pFormat[0]) {
1252     default:
1253       FIXME("unknown repeat type %d\n", pFormat[0]);
1254     case RPC_FC_NO_REPEAT:
1255       rep = 1;
1256       stride = 0;
1257       ofs = 0;
1258       count = 1;
1259       xofs = 0;
1260       pFormat += 2;
1261       break;
1262     case RPC_FC_FIXED_REPEAT:
1263       rep = *(const WORD*)&pFormat[2];
1264       stride = *(const WORD*)&pFormat[4];
1265       ofs = *(const WORD*)&pFormat[6];
1266       count = *(const WORD*)&pFormat[8];
1267       xofs = 0;
1268       pFormat += 10;
1269       break;
1270     case RPC_FC_VARIABLE_REPEAT:
1271       rep = pStubMsg->MaxCount;
1272       stride = *(const WORD*)&pFormat[2];
1273       ofs = *(const WORD*)&pFormat[4];
1274       count = *(const WORD*)&pFormat[6];
1275       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1276       pFormat += 8;
1277       break;
1278     }
1279     /* ofs doesn't seem to matter in this context */
1280     for (i = 0; i < rep; i++) {
1281       PFORMAT_STRING info = pFormat;
1282       unsigned char *membase = pMemory + (i * stride);
1283       unsigned u;
1284       for (u=0; u<count; u++,info+=8) {
1285         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1286         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1287       }
1288     }
1289     pFormat += 8 * count;
1290   }
1291 }
1292
1293 /***********************************************************************
1294  *           NdrPointerMarshall [RPCRT4.@]
1295  */
1296 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1297                                           unsigned char *pMemory,
1298                                           PFORMAT_STRING pFormat)
1299 {
1300   unsigned char *Buffer;
1301
1302   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1303
1304   /* incremement the buffer here instead of in PointerMarshall,
1305    * as that is used by embedded pointers which already handle the incrementing
1306    * the buffer, and shouldn't write any additional pointer data to the wire */
1307   if (*pFormat != RPC_FC_RP)
1308   {
1309     ALIGN_POINTER(pStubMsg->Buffer, 4);
1310     Buffer = pStubMsg->Buffer;
1311     pStubMsg->Buffer += 4;
1312   }
1313   else
1314     Buffer = pStubMsg->Buffer;
1315
1316   PointerMarshall(pStubMsg, Buffer, pMemory, pFormat);
1317
1318   STD_OVERFLOW_CHECK(pStubMsg);
1319
1320   return NULL;
1321 }
1322
1323 /***********************************************************************
1324  *           NdrPointerUnmarshall [RPCRT4.@]
1325  */
1326 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1327                                             unsigned char **ppMemory,
1328                                             PFORMAT_STRING pFormat,
1329                                             unsigned char fMustAlloc)
1330 {
1331   unsigned char *Buffer;
1332
1333   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1334
1335   /* incremement the buffer here instead of in PointerUnmarshall,
1336    * as that is used by embedded pointers which already handle the incrementing
1337    * the buffer, and shouldn't read any additional pointer data from the
1338    * buffer */
1339   if (*pFormat != RPC_FC_RP)
1340   {
1341     ALIGN_POINTER(pStubMsg->Buffer, 4);
1342     Buffer = pStubMsg->Buffer;
1343     pStubMsg->Buffer += 4;
1344   }
1345   else
1346     Buffer = pStubMsg->Buffer;
1347
1348   PointerUnmarshall(pStubMsg, Buffer, ppMemory, pFormat, fMustAlloc);
1349
1350   return NULL;
1351 }
1352
1353 /***********************************************************************
1354  *           NdrPointerBufferSize [RPCRT4.@]
1355  */
1356 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1357                                       unsigned char *pMemory,
1358                                       PFORMAT_STRING pFormat)
1359 {
1360   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1361
1362   /* incremement the buffer length here instead of in PointerBufferSize,
1363    * as that is used by embedded pointers which already handle the buffer
1364    * length, and shouldn't write anything more to the wire */
1365   if (*pFormat != RPC_FC_RP)
1366   {
1367     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
1368     pStubMsg->BufferLength += 4;
1369   }
1370
1371   PointerBufferSize(pStubMsg, pMemory, pFormat);
1372 }
1373
1374 /***********************************************************************
1375  *           NdrPointerMemorySize [RPCRT4.@]
1376  */
1377 unsigned long WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1378                                           PFORMAT_STRING pFormat)
1379 {
1380   /* unsigned size = *(LPWORD)(pFormat+2); */
1381   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1382   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1383   return 0;
1384 }
1385
1386 /***********************************************************************
1387  *           NdrPointerFree [RPCRT4.@]
1388  */
1389 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1390                            unsigned char *pMemory,
1391                            PFORMAT_STRING pFormat)
1392 {
1393   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1394   PointerFree(pStubMsg, pMemory, pFormat);
1395 }
1396
1397 /***********************************************************************
1398  *           NdrSimpleStructMarshall [RPCRT4.@]
1399  */
1400 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1401                                                unsigned char *pMemory,
1402                                                PFORMAT_STRING pFormat)
1403 {
1404   unsigned size = *(const WORD*)(pFormat+2);
1405   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1406
1407   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1408
1409   memcpy(pStubMsg->Buffer, pMemory, size);
1410   pStubMsg->BufferMark = pStubMsg->Buffer;
1411   pStubMsg->Buffer += size;
1412
1413   if (pFormat[0] != RPC_FC_STRUCT)
1414     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1415
1416   STD_OVERFLOW_CHECK(pStubMsg);
1417
1418   return NULL;
1419 }
1420
1421 /***********************************************************************
1422  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1423  */
1424 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1425                                                  unsigned char **ppMemory,
1426                                                  PFORMAT_STRING pFormat,
1427                                                  unsigned char fMustAlloc)
1428 {
1429   unsigned size = *(const WORD*)(pFormat+2);
1430   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1431
1432   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1433
1434   if (fMustAlloc) {
1435     *ppMemory = NdrAllocate(pStubMsg, size);
1436     memcpy(*ppMemory, pStubMsg->Buffer, size);
1437   } else {
1438     if (pStubMsg->ReuseBuffer && !*ppMemory)
1439       /* for servers, we may just point straight into the RPC buffer, I think
1440        * (I guess that's what MS does since MIDL code doesn't try to free) */
1441       *ppMemory = pStubMsg->Buffer;
1442     else
1443       /* for clients, memory should be provided by caller */
1444       memcpy(*ppMemory, pStubMsg->Buffer, size);
1445   }
1446
1447   pStubMsg->BufferMark = pStubMsg->Buffer;
1448   pStubMsg->Buffer += size;
1449
1450   if (pFormat[0] != RPC_FC_STRUCT)
1451     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1452
1453   return NULL;
1454 }
1455
1456
1457 /***********************************************************************
1458  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1459  */
1460 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1461                                    unsigned char FormatChar )
1462 {
1463     FIXME("stub\n");
1464 }
1465
1466
1467 /***********************************************************************
1468  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1469  */
1470 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1471                                      unsigned char FormatChar )
1472 {
1473     FIXME("stub\n");
1474 }
1475
1476
1477 /***********************************************************************
1478  *           NdrSimpleStructBufferSize [RPCRT4.@]
1479  */
1480 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1481                                       unsigned char *pMemory,
1482                                       PFORMAT_STRING pFormat)
1483 {
1484   unsigned size = *(const WORD*)(pFormat+2);
1485   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1486
1487   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1488
1489   pStubMsg->BufferLength += size;
1490   if (pFormat[0] != RPC_FC_STRUCT)
1491     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1492 }
1493
1494 /***********************************************************************
1495  *           NdrSimpleStructMemorySize [RPCRT4.@]
1496  */
1497 unsigned long WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1498                                                PFORMAT_STRING pFormat)
1499 {
1500   unsigned short size = *(LPWORD)(pFormat+2);
1501
1502   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1503
1504   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1505   pStubMsg->MemorySize += size;
1506   pStubMsg->Buffer += size;
1507
1508   if (pFormat[0] != RPC_FC_STRUCT)
1509     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1510   return size;
1511 }
1512
1513 /***********************************************************************
1514  *           NdrSimpleStructFree [RPCRT4.@]
1515  */
1516 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1517                                 unsigned char *pMemory,
1518                                 PFORMAT_STRING pFormat)
1519 {
1520   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1521   if (pFormat[0] != RPC_FC_STRUCT)
1522     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1523 }
1524
1525
1526 static unsigned long EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg,
1527                                          PFORMAT_STRING pFormat)
1528 {
1529   switch (*pFormat) {
1530   case RPC_FC_STRUCT:
1531   case RPC_FC_PSTRUCT:
1532   case RPC_FC_CSTRUCT:
1533   case RPC_FC_BOGUS_STRUCT:
1534     return *(const WORD*)&pFormat[2];
1535   case RPC_FC_USER_MARSHAL:
1536     return *(const WORD*)&pFormat[4];
1537   case RPC_FC_NON_ENCAPSULATED_UNION:
1538     pFormat += 2;
1539     if (pStubMsg->fHasNewCorrDesc)
1540         pFormat += 6;
1541     else
1542         pFormat += 4;
1543
1544     pFormat += *(const SHORT*)pFormat;
1545     return *(const SHORT*)pFormat;
1546   case RPC_FC_IP:
1547     return sizeof(void *);
1548   default:
1549     FIXME("unhandled embedded type %02x\n", *pFormat);
1550   }
1551   return 0;
1552 }
1553
1554
1555 static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1556                                                PFORMAT_STRING pFormat)
1557 {
1558   NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK];
1559
1560   if (!m)
1561   {
1562     FIXME("no memorysizer for data type=%02x\n", *pFormat);
1563     return 0;
1564   }
1565
1566   return m(pStubMsg, pFormat);
1567 }
1568
1569
1570 static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1571                                        unsigned char *pMemory,
1572                                        PFORMAT_STRING pFormat,
1573                                        PFORMAT_STRING pPointer)
1574 {
1575   PFORMAT_STRING desc;
1576   NDR_MARSHALL m;
1577   unsigned long size;
1578
1579   while (*pFormat != RPC_FC_END) {
1580     switch (*pFormat) {
1581     case RPC_FC_SHORT:
1582     case RPC_FC_USHORT:
1583       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1584       memcpy(pStubMsg->Buffer, pMemory, 2);
1585       pStubMsg->Buffer += 2;
1586       pMemory += 2;
1587       break;
1588     case RPC_FC_LONG:
1589     case RPC_FC_ULONG:
1590     case RPC_FC_ENUM32:
1591       TRACE("long=%ld <= %p\n", *(DWORD*)pMemory, pMemory);
1592       memcpy(pStubMsg->Buffer, pMemory, 4);
1593       pStubMsg->Buffer += 4;
1594       pMemory += 4;
1595       break;
1596     case RPC_FC_POINTER:
1597       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1598       NdrPointerMarshall(pStubMsg, *(unsigned char**)pMemory, pPointer);
1599       pPointer += 4;
1600       pMemory += 4;
1601       break;
1602     case RPC_FC_ALIGNM4:
1603       ALIGN_POINTER(pMemory, 4);
1604       break;
1605     case RPC_FC_ALIGNM8:
1606       ALIGN_POINTER(pMemory, 8);
1607       break;
1608     case RPC_FC_STRUCTPAD2:
1609       pMemory += 2;
1610       break;
1611     case RPC_FC_EMBEDDED_COMPLEX:
1612       pMemory += pFormat[1];
1613       pFormat += 2;
1614       desc = pFormat + *(const SHORT*)pFormat;
1615       size = EmbeddedComplexSize(pStubMsg, desc);
1616       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1617       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1618       if (m) m(pStubMsg, pMemory, desc);
1619       else FIXME("no marshaller for embedded type %02x\n", *desc);
1620       pMemory += size;
1621       pFormat += 2;
1622       continue;
1623     case RPC_FC_PAD:
1624       break;
1625     default:
1626       FIXME("unhandled format %02x\n", *pFormat);
1627     }
1628     pFormat++;
1629   }
1630
1631   return pMemory;
1632 }
1633
1634 static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1635                                          unsigned char *pMemory,
1636                                          PFORMAT_STRING pFormat,
1637                                          PFORMAT_STRING pPointer,
1638                                          unsigned char fMustAlloc)
1639 {
1640   PFORMAT_STRING desc;
1641   NDR_UNMARSHALL m;
1642   unsigned long size;
1643
1644   while (*pFormat != RPC_FC_END) {
1645     switch (*pFormat) {
1646     case RPC_FC_SHORT:
1647     case RPC_FC_USHORT:
1648       memcpy(pMemory, pStubMsg->Buffer, 2);
1649       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1650       pStubMsg->Buffer += 2;
1651       pMemory += 2;
1652       break;
1653     case RPC_FC_LONG:
1654     case RPC_FC_ULONG:
1655     case RPC_FC_ENUM32:
1656       memcpy(pMemory, pStubMsg->Buffer, 4);
1657       TRACE("long=%ld => %p\n", *(DWORD*)pMemory, pMemory);
1658       pStubMsg->Buffer += 4;
1659       pMemory += 4;
1660       break;
1661     case RPC_FC_POINTER:
1662       *(unsigned char**)pMemory = NULL;
1663       TRACE("pointer => %p\n", pMemory);
1664       NdrPointerUnmarshall(pStubMsg, (unsigned char**)pMemory, pPointer, fMustAlloc);
1665       pPointer += 4;
1666       pMemory += 4;
1667       break;
1668     case RPC_FC_ALIGNM4:
1669       ALIGN_POINTER(pMemory, 4);
1670       break;
1671     case RPC_FC_ALIGNM8:
1672       ALIGN_POINTER(pMemory, 8);
1673       break;
1674     case RPC_FC_STRUCTPAD2:
1675       pMemory += 2;
1676       break;
1677     case RPC_FC_EMBEDDED_COMPLEX:
1678       pMemory += pFormat[1];
1679       pFormat += 2;
1680       desc = pFormat + *(const SHORT*)pFormat;
1681       size = EmbeddedComplexSize(pStubMsg, desc);
1682       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1683       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1684       memset(pMemory, 0, size); /* just in case */
1685       if (m) m(pStubMsg, &pMemory, desc, fMustAlloc);
1686       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
1687       pMemory += size;
1688       pFormat += 2;
1689       continue;
1690     case RPC_FC_PAD:
1691       break;
1692     default:
1693       FIXME("unhandled format %d\n", *pFormat);
1694     }
1695     pFormat++;
1696   }
1697
1698   return pMemory;
1699 }
1700
1701 static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1702                                          unsigned char *pMemory,
1703                                          PFORMAT_STRING pFormat,
1704                                          PFORMAT_STRING pPointer)
1705 {
1706   PFORMAT_STRING desc;
1707   NDR_BUFFERSIZE m;
1708   unsigned long size;
1709
1710   while (*pFormat != RPC_FC_END) {
1711     switch (*pFormat) {
1712     case RPC_FC_SHORT:
1713     case RPC_FC_USHORT:
1714       pStubMsg->BufferLength += 2;
1715       pMemory += 2;
1716       break;
1717     case RPC_FC_LONG:
1718     case RPC_FC_ULONG:
1719     case RPC_FC_ENUM32:
1720       pStubMsg->BufferLength += 4;
1721       pMemory += 4;
1722       break;
1723     case RPC_FC_POINTER:
1724       NdrPointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
1725       pPointer += 4;
1726       pMemory += 4;
1727       break;
1728     case RPC_FC_ALIGNM4:
1729       ALIGN_POINTER(pMemory, 4);
1730       break;
1731     case RPC_FC_ALIGNM8:
1732       ALIGN_POINTER(pMemory, 8);
1733       break;
1734     case RPC_FC_STRUCTPAD2:
1735       pMemory += 2;
1736       break;
1737     case RPC_FC_EMBEDDED_COMPLEX:
1738       pMemory += pFormat[1];
1739       pFormat += 2;
1740       desc = pFormat + *(const SHORT*)pFormat;
1741       size = EmbeddedComplexSize(pStubMsg, desc);
1742       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1743       if (m) m(pStubMsg, pMemory, desc);
1744       else FIXME("no buffersizer for embedded type %02x\n", *desc);
1745       pMemory += size;
1746       pFormat += 2;
1747       continue;
1748     case RPC_FC_PAD:
1749       break;
1750     default:
1751       FIXME("unhandled format %d\n", *pFormat);
1752     }
1753     pFormat++;
1754   }
1755
1756   return pMemory;
1757 }
1758
1759 static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
1760                                    unsigned char *pMemory,
1761                                    PFORMAT_STRING pFormat,
1762                                    PFORMAT_STRING pPointer)
1763 {
1764   PFORMAT_STRING desc;
1765   NDR_FREE m;
1766   unsigned long size;
1767
1768   while (*pFormat != RPC_FC_END) {
1769     switch (*pFormat) {
1770     case RPC_FC_SHORT:
1771     case RPC_FC_USHORT:
1772       pMemory += 2;
1773       break;
1774     case RPC_FC_LONG:
1775     case RPC_FC_ULONG:
1776     case RPC_FC_ENUM32:
1777       pMemory += 4;
1778       break;
1779     case RPC_FC_POINTER:
1780       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
1781       pPointer += 4;
1782       pMemory += 4;
1783       break;
1784     case RPC_FC_ALIGNM4:
1785       ALIGN_POINTER(pMemory, 4);
1786       break;
1787     case RPC_FC_ALIGNM8:
1788       ALIGN_POINTER(pMemory, 8);
1789       break;
1790     case RPC_FC_STRUCTPAD2:
1791       pMemory += 2;
1792       break;
1793     case RPC_FC_EMBEDDED_COMPLEX:
1794       pMemory += pFormat[1];
1795       pFormat += 2;
1796       desc = pFormat + *(const SHORT*)pFormat;
1797       size = EmbeddedComplexSize(pStubMsg, desc);
1798       m = NdrFreer[*desc & NDR_TABLE_MASK];
1799       if (m) m(pStubMsg, pMemory, desc);
1800       else FIXME("no freer for embedded type %02x\n", *desc);
1801       pMemory += size;
1802       pFormat += 2;
1803       continue;
1804     case RPC_FC_PAD:
1805       break;
1806     default:
1807       FIXME("unhandled format %d\n", *pFormat);
1808     }
1809     pFormat++;
1810   }
1811
1812   return pMemory;
1813 }
1814
1815 static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1816                                        PFORMAT_STRING pFormat)
1817 {
1818   PFORMAT_STRING desc;
1819   unsigned long size = 0;
1820
1821   while (*pFormat != RPC_FC_END) {
1822     switch (*pFormat) {
1823     case RPC_FC_SHORT:
1824     case RPC_FC_USHORT:
1825       size += 2;
1826       pStubMsg->Buffer += 2;
1827       break;
1828     case RPC_FC_LONG:
1829     case RPC_FC_ULONG:
1830       size += 4;
1831       pStubMsg->Buffer += 4;
1832       break;
1833     case RPC_FC_POINTER:
1834       size += 4;
1835       pStubMsg->Buffer += 4;
1836       break;
1837     case RPC_FC_ALIGNM4:
1838       ALIGN_LENGTH(size, 4);
1839       ALIGN_POINTER(pStubMsg->Buffer, 4);
1840       break;
1841     case RPC_FC_ALIGNM8:
1842       ALIGN_LENGTH(size, 8);
1843       ALIGN_POINTER(pStubMsg->Buffer, 8);
1844       break;
1845     case RPC_FC_STRUCTPAD2:
1846       size += 2;
1847       pStubMsg->Buffer += 2;
1848       break;
1849     case RPC_FC_EMBEDDED_COMPLEX:
1850       size += pFormat[1];
1851       pFormat += 2;
1852       desc = pFormat + *(const SHORT*)pFormat;
1853       size += EmbeddedComplexMemorySize(pStubMsg, desc);
1854       pFormat += 2;
1855       continue;
1856     case RPC_FC_PAD:
1857       break;
1858     default:
1859       FIXME("unhandled format %d\n", *pFormat);
1860     }
1861     pFormat++;
1862   }
1863
1864   return size;
1865 }
1866
1867 /***********************************************************************
1868  *           NdrComplexStructMarshall [RPCRT4.@]
1869  */
1870 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1871                                                 unsigned char *pMemory,
1872                                                 PFORMAT_STRING pFormat)
1873 {
1874   PFORMAT_STRING conf_array = NULL;
1875   PFORMAT_STRING pointer_desc = NULL;
1876   unsigned char *OldMemory = pStubMsg->Memory;
1877
1878   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1879
1880   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1881
1882   pFormat += 4;
1883   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1884   pFormat += 2;
1885   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1886   pFormat += 2;
1887
1888   pStubMsg->Memory = pMemory;
1889
1890   ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
1891
1892   if (conf_array)
1893     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
1894
1895   pStubMsg->Memory = OldMemory;
1896
1897   STD_OVERFLOW_CHECK(pStubMsg);
1898
1899   return NULL;
1900 }
1901
1902 /***********************************************************************
1903  *           NdrComplexStructUnmarshall [RPCRT4.@]
1904  */
1905 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1906                                                   unsigned char **ppMemory,
1907                                                   PFORMAT_STRING pFormat,
1908                                                   unsigned char fMustAlloc)
1909 {
1910   unsigned size = *(const WORD*)(pFormat+2);
1911   PFORMAT_STRING conf_array = NULL;
1912   PFORMAT_STRING pointer_desc = NULL;
1913   unsigned char *pMemory;
1914
1915   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1916
1917   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1918
1919   if (fMustAlloc || !*ppMemory)
1920   {
1921     *ppMemory = NdrAllocate(pStubMsg, size);
1922     memset(*ppMemory, 0, size);
1923   }
1924
1925   pFormat += 4;
1926   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1927   pFormat += 2;
1928   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1929   pFormat += 2;
1930
1931   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
1932
1933   if (conf_array)
1934     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
1935
1936   return NULL;
1937 }
1938
1939 /***********************************************************************
1940  *           NdrComplexStructBufferSize [RPCRT4.@]
1941  */
1942 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1943                                        unsigned char *pMemory,
1944                                        PFORMAT_STRING pFormat)
1945 {
1946   PFORMAT_STRING conf_array = NULL;
1947   PFORMAT_STRING pointer_desc = NULL;
1948   unsigned char *OldMemory = pStubMsg->Memory;
1949
1950   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1951
1952   ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1);
1953
1954   pFormat += 4;
1955   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1956   pFormat += 2;
1957   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1958   pFormat += 2;
1959
1960   pStubMsg->Memory = pMemory;
1961
1962   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
1963
1964   if (conf_array)
1965     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
1966
1967   pStubMsg->Memory = OldMemory;
1968 }
1969
1970 /***********************************************************************
1971  *           NdrComplexStructMemorySize [RPCRT4.@]
1972  */
1973 unsigned long WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1974                                                 PFORMAT_STRING pFormat)
1975 {
1976   unsigned size = *(const WORD*)(pFormat+2);
1977   PFORMAT_STRING conf_array = NULL;
1978   PFORMAT_STRING pointer_desc = NULL;
1979
1980   TRACE("(%p,%p)\n", pStubMsg, pFormat);
1981
1982   ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1);
1983
1984   pFormat += 4;
1985   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1986   pFormat += 2;
1987   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1988   pFormat += 2;
1989
1990   ComplexStructMemorySize(pStubMsg, pFormat);
1991
1992   if (conf_array)
1993     NdrConformantArrayMemorySize(pStubMsg, conf_array);
1994
1995   return size;
1996 }
1997
1998 /***********************************************************************
1999  *           NdrComplexStructFree [RPCRT4.@]
2000  */
2001 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2002                                  unsigned char *pMemory,
2003                                  PFORMAT_STRING pFormat)
2004 {
2005   PFORMAT_STRING conf_array = NULL;
2006   PFORMAT_STRING pointer_desc = NULL;
2007   unsigned char *OldMemory = pStubMsg->Memory;
2008
2009   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2010
2011   pFormat += 4;
2012   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
2013   pFormat += 2;
2014   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
2015   pFormat += 2;
2016
2017   pStubMsg->Memory = pMemory;
2018
2019   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
2020
2021   if (conf_array)
2022     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
2023
2024   pStubMsg->Memory = OldMemory;
2025 }
2026
2027 /***********************************************************************
2028  *           NdrConformantArrayMarshall [RPCRT4.@]
2029  */
2030 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2031                                                   unsigned char *pMemory,
2032                                                   PFORMAT_STRING pFormat)
2033 {
2034   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2035   unsigned char alignment = pFormat[1] + 1;
2036
2037   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2038   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2039
2040   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2041   size = pStubMsg->MaxCount;
2042
2043   WriteConformance(pStubMsg);
2044
2045   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2046
2047   memcpy(pStubMsg->Buffer, pMemory, size*esize);
2048   pStubMsg->BufferMark = pStubMsg->Buffer;
2049   pStubMsg->Buffer += size*esize;
2050
2051   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2052
2053   STD_OVERFLOW_CHECK(pStubMsg);
2054
2055   return NULL;
2056 }
2057
2058 /***********************************************************************
2059  *           NdrConformantArrayUnmarshall [RPCRT4.@]
2060  */
2061 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2062                                                     unsigned char **ppMemory,
2063                                                     PFORMAT_STRING pFormat,
2064                                                     unsigned char fMustAlloc)
2065 {
2066   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2067   unsigned char alignment = pFormat[1] + 1;
2068
2069   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2070   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2071
2072   pFormat = ReadConformance(pStubMsg, pFormat+4);
2073   size = pStubMsg->MaxCount;
2074
2075   if (fMustAlloc || !*ppMemory)
2076     *ppMemory = NdrAllocate(pStubMsg, size*esize);
2077
2078   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2079
2080   memcpy(*ppMemory, pStubMsg->Buffer, size*esize);
2081
2082   pStubMsg->BufferMark = pStubMsg->Buffer;
2083   pStubMsg->Buffer += size*esize;
2084
2085   EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2086
2087   return NULL;
2088 }
2089
2090 /***********************************************************************
2091  *           NdrConformantArrayBufferSize [RPCRT4.@]
2092  */
2093 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2094                                          unsigned char *pMemory,
2095                                          PFORMAT_STRING pFormat)
2096 {
2097   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2098   unsigned char alignment = pFormat[1] + 1;
2099
2100   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2101   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2102
2103   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2104   size = pStubMsg->MaxCount;
2105
2106   SizeConformance(pStubMsg);
2107
2108   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2109
2110   /* conformance value plus array */
2111   pStubMsg->BufferLength += size*esize;
2112
2113   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2114 }
2115
2116 /***********************************************************************
2117  *           NdrConformantArrayMemorySize [RPCRT4.@]
2118  */
2119 unsigned long WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2120                                                   PFORMAT_STRING pFormat)
2121 {
2122   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
2123   unsigned char alignment = pFormat[1] + 1;
2124
2125   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2126   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2127
2128   pFormat = ReadConformance(pStubMsg, pFormat+4);
2129   size = pStubMsg->MaxCount;
2130   pStubMsg->MemorySize += size*esize;
2131
2132   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2133   pStubMsg->BufferMark = pStubMsg->Buffer;
2134   pStubMsg->Buffer += size*esize;
2135
2136   EmbeddedPointerMemorySize(pStubMsg, pFormat);
2137
2138   return pStubMsg->MemorySize;
2139 }
2140
2141 /***********************************************************************
2142  *           NdrConformantArrayFree [RPCRT4.@]
2143  */
2144 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2145                                    unsigned char *pMemory,
2146                                    PFORMAT_STRING pFormat)
2147 {
2148   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2149   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
2150
2151   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2152 }
2153
2154
2155 /***********************************************************************
2156  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
2157  */
2158 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
2159                                                          unsigned char* pMemory,
2160                                                          PFORMAT_STRING pFormat )
2161 {
2162     unsigned char alignment = pFormat[1] + 1;
2163     DWORD esize = *(const WORD*)(pFormat+2);
2164
2165     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2166
2167     if (pFormat[0] != RPC_FC_CVARRAY)
2168     {
2169         ERR("invalid format type %x\n", pFormat[0]);
2170         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2171         return NULL;
2172     }
2173
2174     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2175     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2176
2177     WriteConformance(pStubMsg);
2178     WriteVariance(pStubMsg);
2179
2180     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2181
2182     memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, pStubMsg->ActualCount*esize);
2183     pStubMsg->BufferMark = pStubMsg->Buffer;
2184     pStubMsg->Buffer += pStubMsg->ActualCount*esize;
2185
2186     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2187
2188     STD_OVERFLOW_CHECK(pStubMsg);
2189
2190     return NULL;
2191 }
2192
2193
2194 /***********************************************************************
2195  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
2196  */
2197 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
2198                                                            unsigned char** ppMemory,
2199                                                            PFORMAT_STRING pFormat,
2200                                                            unsigned char fMustAlloc )
2201 {
2202     unsigned char alignment = pFormat[1] + 1;
2203     DWORD esize = *(const WORD*)(pFormat+2);
2204
2205     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2206
2207     if (pFormat[0] != RPC_FC_CVARRAY)
2208     {
2209         ERR("invalid format type %x\n", pFormat[0]);
2210         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2211         return NULL;
2212     }
2213
2214     pFormat = ReadConformance(pStubMsg, pFormat);
2215     pFormat = ReadVariance(pStubMsg, pFormat);
2216
2217     ALIGN_POINTER(pStubMsg->Buffer, alignment);
2218
2219     if (!*ppMemory || fMustAlloc)
2220         *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
2221     memcpy(*ppMemory + pStubMsg->Offset, pStubMsg->Buffer, pStubMsg->ActualCount * esize);
2222     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
2223
2224     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2225
2226     return NULL;
2227 }
2228
2229
2230 /***********************************************************************
2231  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
2232  */
2233 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
2234                                            unsigned char* pMemory,
2235                                            PFORMAT_STRING pFormat )
2236 {
2237     TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2238
2239     if (pFormat[0] != RPC_FC_CVARRAY)
2240     {
2241         ERR("invalid format type %x\n", pFormat[0]);
2242         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2243         return;
2244     }
2245
2246     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2247     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2248
2249     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
2250 }
2251
2252
2253 /***********************************************************************
2254  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
2255  */
2256 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
2257                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
2258 {
2259     unsigned char alignment = pFormat[1] + 1;
2260     DWORD esize = *(const WORD*)(pFormat+2);
2261
2262     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2263
2264     if (pFormat[0] != RPC_FC_CVARRAY)
2265     {
2266         ERR("invalid format type %x\n", pFormat[0]);
2267         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2268         return;
2269     }
2270
2271     /* compute size */
2272     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
2273     /* compute length */
2274     pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0);
2275
2276     SizeConformance(pStubMsg);
2277     SizeVariance(pStubMsg);
2278
2279     ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2280
2281     pStubMsg->BufferLength += pStubMsg->ActualCount*esize;
2282
2283     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2284 }
2285
2286
2287 /***********************************************************************
2288  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
2289  */
2290 unsigned long WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
2291                                                           PFORMAT_STRING pFormat )
2292 {
2293     FIXME( "stub\n" );
2294     return 0;
2295 }
2296
2297
2298 /***********************************************************************
2299  *           NdrComplexArrayMarshall [RPCRT4.@]
2300  */
2301 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2302                                                unsigned char *pMemory,
2303                                                PFORMAT_STRING pFormat)
2304 {
2305   ULONG i, count, def;
2306   BOOL variance_present;
2307   unsigned char alignment;
2308
2309   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2310
2311   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2312   {
2313       ERR("invalid format type %x\n", pFormat[0]);
2314       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2315       return NULL;
2316   }
2317
2318   alignment = pFormat[1] + 1;
2319
2320   def = *(const WORD*)&pFormat[2];
2321   pFormat += 4;
2322
2323   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2324   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2325
2326   variance_present = IsConformanceOrVariancePresent(pFormat);
2327   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2328   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2329
2330   WriteConformance(pStubMsg);
2331   if (variance_present)
2332     WriteVariance(pStubMsg);
2333
2334   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2335
2336   count = pStubMsg->ActualCount;
2337   for (i = 0; i < count; i++)
2338     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
2339
2340   STD_OVERFLOW_CHECK(pStubMsg);
2341
2342   return NULL;
2343 }
2344
2345 /***********************************************************************
2346  *           NdrComplexArrayUnmarshall [RPCRT4.@]
2347  */
2348 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2349                                                  unsigned char **ppMemory,
2350                                                  PFORMAT_STRING pFormat,
2351                                                  unsigned char fMustAlloc)
2352 {
2353   ULONG i, count, esize;
2354   unsigned char alignment;
2355   unsigned char *pMemory;
2356   unsigned char *Buffer;
2357
2358   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2359
2360   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2361   {
2362       ERR("invalid format type %x\n", pFormat[0]);
2363       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2364       return NULL;
2365   }
2366
2367   alignment = pFormat[1] + 1;
2368
2369   pFormat += 4;
2370
2371   pFormat = ReadConformance(pStubMsg, pFormat);
2372   pFormat = ReadVariance(pStubMsg, pFormat);
2373
2374   Buffer = pStubMsg->Buffer;
2375   esize = ComplexStructMemorySize(pStubMsg, pFormat);
2376   pStubMsg->Buffer = Buffer;
2377
2378   if (fMustAlloc || !*ppMemory)
2379   {
2380     *ppMemory = NdrAllocate(pStubMsg, pStubMsg->MaxCount * esize);
2381     memset(*ppMemory, 0, pStubMsg->MaxCount * esize);
2382   }
2383
2384   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2385
2386   pMemory = *ppMemory;
2387   count = pStubMsg->ActualCount;
2388   for (i = 0; i < count; i++)
2389     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
2390
2391   return NULL;
2392 }
2393
2394 /***********************************************************************
2395  *           NdrComplexArrayBufferSize [RPCRT4.@]
2396  */
2397 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2398                                       unsigned char *pMemory,
2399                                       PFORMAT_STRING pFormat)
2400 {
2401   ULONG i, count, def;
2402   unsigned char alignment;
2403   BOOL variance_present;
2404
2405   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2406
2407   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2408   {
2409       ERR("invalid format type %x\n", pFormat[0]);
2410       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2411       return;
2412   }
2413
2414   alignment = pFormat[1] + 1;
2415
2416   def = *(const WORD*)&pFormat[2];
2417   pFormat += 4;
2418
2419   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2420   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2421   SizeConformance(pStubMsg);
2422
2423   variance_present = IsConformanceOrVariancePresent(pFormat);
2424   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2425   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2426
2427   if (variance_present)
2428     SizeVariance(pStubMsg);
2429
2430   ALIGN_LENGTH(pStubMsg->BufferLength, alignment);
2431
2432   count = pStubMsg->ActualCount;
2433   for (i = 0; i < count; i++)
2434     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
2435 }
2436
2437 /***********************************************************************
2438  *           NdrComplexArrayMemorySize [RPCRT4.@]
2439  */
2440 unsigned long WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2441                                                PFORMAT_STRING pFormat)
2442 {
2443   ULONG i, count, esize;
2444   unsigned char alignment;
2445   unsigned char *Buffer;
2446   unsigned long SavedMemorySize;
2447   unsigned long MemorySize;
2448
2449   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2450
2451   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2452   {
2453       ERR("invalid format type %x\n", pFormat[0]);
2454       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2455       return 0;
2456   }
2457
2458   alignment = pFormat[1] + 1;
2459
2460   pFormat += 4;
2461
2462   pFormat = ReadConformance(pStubMsg, pFormat);
2463   pFormat = ReadVariance(pStubMsg, pFormat);
2464
2465   ALIGN_POINTER(pStubMsg->Buffer, alignment);
2466
2467   SavedMemorySize = pStubMsg->MemorySize;
2468
2469   Buffer = pStubMsg->Buffer;
2470   esize = ComplexStructMemorySize(pStubMsg, pFormat);
2471   pStubMsg->Buffer = Buffer;
2472
2473   MemorySize = esize * pStubMsg->MaxCount;
2474
2475   count = pStubMsg->ActualCount;
2476   for (i = 0; i < count; i++)
2477     ComplexStructMemorySize(pStubMsg, pFormat);
2478
2479   pStubMsg->MemorySize = SavedMemorySize;
2480
2481   pStubMsg->MemorySize += MemorySize;
2482   return MemorySize;
2483 }
2484
2485 /***********************************************************************
2486  *           NdrComplexArrayFree [RPCRT4.@]
2487  */
2488 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2489                                 unsigned char *pMemory,
2490                                 PFORMAT_STRING pFormat)
2491 {
2492   ULONG i, count, def;
2493
2494   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2495
2496   if (pFormat[0] != RPC_FC_BOGUS_ARRAY)
2497   {
2498       ERR("invalid format type %x\n", pFormat[0]);
2499       RpcRaiseException(RPC_S_INTERNAL_ERROR);
2500       return;
2501   }
2502
2503   def = *(const WORD*)&pFormat[2];
2504   pFormat += 4;
2505
2506   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2507   TRACE("conformance = %ld\n", pStubMsg->MaxCount);
2508
2509   pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount);
2510   TRACE("variance = %ld\n", pStubMsg->ActualCount);
2511
2512   count = pStubMsg->ActualCount;
2513   for (i = 0; i < count; i++)
2514     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2515 }
2516
2517 unsigned long UserMarshalFlags(PMIDL_STUB_MESSAGE pStubMsg)
2518 {
2519   return MAKELONG(pStubMsg->dwDestContext,
2520                   pStubMsg->RpcMsg->DataRepresentation);
2521 }
2522
2523 #define USER_MARSHAL_PTR_PREFIX \
2524         ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
2525         ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
2526
2527 /***********************************************************************
2528  *           NdrUserMarshalMarshall [RPCRT4.@]
2529  */
2530 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2531                                               unsigned char *pMemory,
2532                                               PFORMAT_STRING pFormat)
2533 {
2534   unsigned flags = pFormat[1];
2535   unsigned index = *(const WORD*)&pFormat[2];
2536   unsigned long uflag = UserMarshalFlags(pStubMsg);
2537   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2538   TRACE("index=%d\n", index);
2539
2540   if (flags & USER_MARSHAL_POINTER)
2541   {
2542     ALIGN_POINTER(pStubMsg->Buffer, 4);
2543     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX);
2544     pStubMsg->Buffer += 4;
2545     ALIGN_POINTER(pStubMsg->Buffer, 8);
2546   }
2547   else
2548     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2549
2550   pStubMsg->Buffer =
2551     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
2552       &uflag, pStubMsg->Buffer, pMemory);
2553
2554   STD_OVERFLOW_CHECK(pStubMsg);
2555
2556   return NULL;
2557 }
2558
2559 /***********************************************************************
2560  *           NdrUserMarshalUnmarshall [RPCRT4.@]
2561  */
2562 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2563                                                  unsigned char **ppMemory,
2564                                                  PFORMAT_STRING pFormat,
2565                                                  unsigned char fMustAlloc)
2566 {
2567   unsigned flags = pFormat[1];
2568   unsigned index = *(const WORD*)&pFormat[2];
2569   DWORD memsize = *(const WORD*)&pFormat[4];
2570   unsigned long uflag = UserMarshalFlags(pStubMsg);
2571   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2572   TRACE("index=%d\n", index);
2573
2574   if (flags & USER_MARSHAL_POINTER)
2575   {
2576     ALIGN_POINTER(pStubMsg->Buffer, 4);
2577     /* skip pointer prefix */
2578     pStubMsg->Buffer += 4;
2579     ALIGN_POINTER(pStubMsg->Buffer, 8);
2580   }
2581   else
2582     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2583
2584   if (fMustAlloc || !*ppMemory)
2585     *ppMemory = NdrAllocate(pStubMsg, memsize);
2586
2587   pStubMsg->Buffer =
2588     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
2589       &uflag, pStubMsg->Buffer, *ppMemory);
2590
2591   return NULL;
2592 }
2593
2594 /***********************************************************************
2595  *           NdrUserMarshalBufferSize [RPCRT4.@]
2596  */
2597 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2598                                       unsigned char *pMemory,
2599                                       PFORMAT_STRING pFormat)
2600 {
2601   unsigned flags = pFormat[1];
2602   unsigned index = *(const WORD*)&pFormat[2];
2603   DWORD bufsize = *(const WORD*)&pFormat[6];
2604   unsigned long uflag = UserMarshalFlags(pStubMsg);
2605   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2606   TRACE("index=%d\n", index);
2607
2608   if (flags & USER_MARSHAL_POINTER)
2609   {
2610     ALIGN_LENGTH(pStubMsg->BufferLength, 4);
2611     /* skip pointer prefix */
2612     pStubMsg->BufferLength += 4;
2613     ALIGN_LENGTH(pStubMsg->BufferLength, 8);
2614   }
2615   else
2616     ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1);
2617
2618   if (bufsize) {
2619     TRACE("size=%ld\n", bufsize);
2620     pStubMsg->BufferLength += bufsize;
2621     return;
2622   }
2623
2624   pStubMsg->BufferLength =
2625     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
2626       &uflag, pStubMsg->BufferLength, pMemory);
2627 }
2628
2629 /***********************************************************************
2630  *           NdrUserMarshalMemorySize [RPCRT4.@]
2631  */
2632 unsigned long WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2633                                               PFORMAT_STRING pFormat)
2634 {
2635   unsigned flags = pFormat[1];
2636   unsigned index = *(const WORD*)&pFormat[2];
2637   DWORD memsize = *(const WORD*)&pFormat[4];
2638   DWORD bufsize = *(const WORD*)&pFormat[6];
2639
2640   TRACE("(%p,%p)\n", pStubMsg, pFormat);
2641   TRACE("index=%d\n", index);
2642
2643   pStubMsg->MemorySize += memsize;
2644
2645   if (flags & USER_MARSHAL_POINTER)
2646   {
2647     ALIGN_POINTER(pStubMsg->Buffer, 4);
2648     /* skip pointer prefix */
2649     pStubMsg->Buffer += 4;
2650     ALIGN_POINTER(pStubMsg->Buffer, 8);
2651   }
2652   else
2653     ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1);
2654
2655   pStubMsg->Buffer += bufsize;
2656
2657   return pStubMsg->MemorySize;
2658 }
2659
2660 /***********************************************************************
2661  *           NdrUserMarshalFree [RPCRT4.@]
2662  */
2663 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
2664                                 unsigned char *pMemory,
2665                                 PFORMAT_STRING pFormat)
2666 {
2667 /*  unsigned flags = pFormat[1]; */
2668   unsigned index = *(const WORD*)&pFormat[2];
2669   unsigned long uflag = UserMarshalFlags(pStubMsg);
2670   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2671   TRACE("index=%d\n", index);
2672
2673   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
2674     &uflag, pMemory);
2675 }
2676
2677 /***********************************************************************
2678  *           NdrClearOutParameters [RPCRT4.@]
2679  */
2680 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
2681                                   PFORMAT_STRING pFormat,
2682                                   void *ArgAddr)
2683 {
2684   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
2685 }
2686
2687 /***********************************************************************
2688  *           NdrConvert [RPCRT4.@]
2689  */
2690 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
2691 {
2692   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
2693   /* FIXME: since this stub doesn't do any converting, the proper behavior
2694      is to raise an exception */
2695 }
2696
2697 /***********************************************************************
2698  *           NdrConvert2 [RPCRT4.@]
2699  */
2700 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )
2701 {
2702   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n",
2703     pStubMsg, pFormat, NumberParams);
2704   /* FIXME: since this stub doesn't do any converting, the proper behavior
2705      is to raise an exception */
2706 }
2707
2708 typedef struct _NDR_CSTRUCT_FORMAT
2709 {
2710     unsigned char type;
2711     unsigned char alignment;
2712     unsigned short memory_size;
2713     short offset_to_array_description;
2714 } NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT;
2715
2716 /***********************************************************************
2717  *           NdrConformantStructMarshall [RPCRT4.@]
2718  */
2719 unsigned char *  WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2720                                 unsigned char *pMemory,
2721                                 PFORMAT_STRING pFormat)
2722 {
2723     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2724     PFORMAT_STRING pCArrayFormat;
2725     ULONG esize;
2726
2727     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2728
2729     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2730     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2731     {
2732         ERR("invalid format type %x\n", pCStructFormat->type);
2733         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2734         return NULL;
2735     }
2736
2737     pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2738         pCStructFormat->offset_to_array_description;
2739     if (*pCArrayFormat != RPC_FC_CARRAY)
2740     {
2741         ERR("invalid array format type %x\n", pCStructFormat->type);
2742         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2743         return NULL;
2744     }
2745     esize = *(const WORD*)(pCArrayFormat+2);
2746
2747     ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size,
2748                        pCArrayFormat + 4, 0);
2749
2750     WriteConformance(pStubMsg);
2751
2752     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
2753
2754     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2755
2756     /* copy constant sized part of struct */
2757     pStubMsg->BufferMark = pStubMsg->Buffer;
2758     memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size + pStubMsg->MaxCount * esize);
2759     pStubMsg->Buffer += pCStructFormat->memory_size + pStubMsg->MaxCount * esize;
2760
2761     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2762         EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2763
2764     STD_OVERFLOW_CHECK(pStubMsg);
2765
2766     return NULL;
2767 }
2768
2769 /***********************************************************************
2770  *           NdrConformantStructUnmarshall [RPCRT4.@]
2771  */
2772 unsigned char *  WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2773                                 unsigned char **ppMemory,
2774                                 PFORMAT_STRING pFormat,
2775                                 unsigned char fMustAlloc)
2776 {
2777     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2778     PFORMAT_STRING pCArrayFormat;
2779     ULONG esize;
2780
2781     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2782
2783     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2784     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2785     {
2786         ERR("invalid format type %x\n", pCStructFormat->type);
2787         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2788         return NULL;
2789     }
2790     pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2791         pCStructFormat->offset_to_array_description;
2792     if (*pCArrayFormat != RPC_FC_CARRAY)
2793     {
2794         ERR("invalid array format type %x\n", pCStructFormat->type);
2795         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2796         return NULL;
2797     }
2798     esize = *(const WORD*)(pCArrayFormat+2);
2799
2800     pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4);
2801
2802     ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1);
2803
2804     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2805
2806     /* work out how much memory to allocate if we need to do so */
2807     if (!*ppMemory || fMustAlloc)
2808     {
2809         SIZE_T size = pCStructFormat->memory_size + pStubMsg->MaxCount * esize;
2810         *ppMemory = NdrAllocate(pStubMsg, size);
2811     }
2812
2813     /* now copy the data */
2814     pStubMsg->BufferMark = pStubMsg->Buffer;
2815     memcpy(*ppMemory, pStubMsg->Buffer, pCStructFormat->memory_size + pStubMsg->MaxCount * esize);
2816     pStubMsg->Buffer += pCStructFormat->memory_size + pStubMsg->MaxCount * esize;
2817
2818     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2819         EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
2820
2821     return NULL;
2822 }
2823
2824 /***********************************************************************
2825  *           NdrConformantStructBufferSize [RPCRT4.@]
2826  */
2827 void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2828                                 unsigned char *pMemory,
2829                                 PFORMAT_STRING pFormat)
2830 {
2831     const NDR_CSTRUCT_FORMAT * pCStructFormat = (NDR_CSTRUCT_FORMAT*)pFormat;
2832     PFORMAT_STRING pCArrayFormat;
2833     ULONG esize;
2834
2835     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2836
2837     pFormat += sizeof(NDR_CSTRUCT_FORMAT);
2838     if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT))
2839     {
2840         ERR("invalid format type %x\n", pCStructFormat->type);
2841         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2842         return;
2843     }
2844     pCArrayFormat = (unsigned char*)&pCStructFormat->offset_to_array_description +
2845         pCStructFormat->offset_to_array_description;
2846     if (*pCArrayFormat != RPC_FC_CARRAY)
2847     {
2848         ERR("invalid array format type %x\n", pCStructFormat->type);
2849         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2850         return;
2851     }
2852     esize = *(const WORD*)(pCArrayFormat+2);
2853
2854     pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0);
2855     SizeConformance(pStubMsg);
2856
2857     ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1);
2858
2859     TRACE("memory_size = %d\n", pCStructFormat->memory_size);
2860
2861     pStubMsg->BufferLength += pCStructFormat->memory_size + esize * pStubMsg->MaxCount;
2862
2863     if (pCStructFormat->type == RPC_FC_CPSTRUCT)
2864         EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
2865 }
2866
2867 /***********************************************************************
2868  *           NdrConformantStructMemorySize [RPCRT4.@]
2869  */
2870 unsigned long WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2871                                 PFORMAT_STRING pFormat)
2872 {
2873     FIXME("stub\n");
2874     return 0;
2875 }
2876
2877 /***********************************************************************
2878  *           NdrConformantStructFree [RPCRT4.@]
2879  */
2880 void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg,
2881                                 unsigned char *pMemory,
2882                                 PFORMAT_STRING pFormat)
2883 {
2884     FIXME("stub\n");
2885 }
2886
2887 /***********************************************************************
2888  *           NdrConformantVaryingStructMarshall [RPCRT4.@]
2889  */
2890 unsigned char *  WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2891                                 unsigned char *pMemory,
2892                                 PFORMAT_STRING pFormat)
2893 {
2894     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
2895     PFORMAT_STRING pCVArrayFormat;
2896     ULONG esize;
2897
2898     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
2899
2900     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
2901     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
2902     {
2903         ERR("invalid format type %x\n", pCVStructFormat->type);
2904         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2905         return NULL;
2906     }
2907
2908     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
2909         pCVStructFormat->offset_to_array_description;
2910     switch (*pCVArrayFormat)
2911     {
2912     case RPC_FC_CVARRAY:
2913         esize = *(const WORD*)(pCVArrayFormat+2);
2914
2915         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
2916                                             pCVArrayFormat + 4, 0);
2917         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
2918                                          pCVArrayFormat, 0);
2919         break;
2920     case RPC_FC_C_CSTRING:
2921         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
2922         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
2923         esize = sizeof(char);
2924         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
2925             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
2926                                                 pCVArrayFormat + 2, 0);
2927         else
2928             pStubMsg->MaxCount = pStubMsg->ActualCount;
2929         break;
2930     case RPC_FC_C_WSTRING:
2931         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
2932         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
2933         esize = sizeof(WCHAR);
2934         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
2935             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
2936                                                 pCVArrayFormat + 2, 0);
2937         else
2938             pStubMsg->MaxCount = pStubMsg->ActualCount;
2939         break;
2940     default:
2941         ERR("invalid array format type %x\n", *pCVArrayFormat);
2942         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2943         return NULL;
2944     }
2945
2946     WriteConformance(pStubMsg);
2947
2948     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
2949
2950     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
2951
2952     /* write constant sized part */
2953     pStubMsg->BufferMark = pStubMsg->Buffer;
2954     memcpy(pStubMsg->Buffer, pMemory, pCVStructFormat->memory_size);
2955     pStubMsg->Buffer += pCVStructFormat->memory_size;
2956
2957     WriteVariance(pStubMsg);
2958
2959     /* write array part */
2960     memcpy(pStubMsg->Buffer, pMemory + pCVStructFormat->memory_size, pStubMsg->ActualCount * esize);
2961     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
2962
2963     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
2964
2965     STD_OVERFLOW_CHECK(pStubMsg);
2966
2967     return NULL;
2968 }
2969
2970 /***********************************************************************
2971  *           NdrConformantVaryingStructUnmarshall [RPCRT4.@]
2972  */
2973 unsigned char *  WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2974                                 unsigned char **ppMemory,
2975                                 PFORMAT_STRING pFormat,
2976                                 unsigned char fMustAlloc)
2977 {
2978     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
2979     PFORMAT_STRING pCVArrayFormat;
2980     ULONG esize;
2981     unsigned char cvarray_type;
2982
2983     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2984
2985     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
2986     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
2987     {
2988         ERR("invalid format type %x\n", pCVStructFormat->type);
2989         RpcRaiseException(RPC_S_INTERNAL_ERROR);
2990         return NULL;
2991     }
2992
2993     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
2994         pCVStructFormat->offset_to_array_description;
2995     cvarray_type = *pCVArrayFormat;
2996     switch (cvarray_type)
2997     {
2998     case RPC_FC_CVARRAY:
2999         esize = *(const WORD*)(pCVArrayFormat+2);
3000         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3001         break;
3002     case RPC_FC_C_CSTRING:
3003         esize = sizeof(char);
3004         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3005             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3006         else
3007             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3008         break;
3009     case RPC_FC_C_WSTRING:
3010         esize = sizeof(WCHAR);
3011         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3012             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3013         else
3014             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3015         break;
3016     default:
3017         ERR("invalid array format type %x\n", *pCVArrayFormat);
3018         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3019         return NULL;
3020     }
3021
3022     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3023
3024     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3025
3026     /* work out how much memory to allocate if we need to do so */
3027     if (!*ppMemory || fMustAlloc)
3028     {
3029         SIZE_T size = pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3030         *ppMemory = NdrAllocate(pStubMsg, size);
3031     }
3032
3033     /* copy the constant data */
3034     pStubMsg->BufferMark = pStubMsg->Buffer;
3035     memcpy(*ppMemory, pStubMsg->Buffer, pCVStructFormat->memory_size);
3036     pStubMsg->Buffer += pCVStructFormat->memory_size;
3037
3038     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat);
3039
3040     /* copy the array data */
3041     memcpy(*ppMemory + pCVStructFormat->memory_size, pStubMsg->Buffer,
3042            pStubMsg->ActualCount * esize);
3043     pStubMsg->Buffer += pStubMsg->ActualCount * esize;
3044
3045     if (cvarray_type == RPC_FC_C_CSTRING)
3046         TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size)));
3047     else if (cvarray_type == RPC_FC_C_WSTRING)
3048         TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size)));
3049
3050     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3051
3052     return NULL;
3053 }
3054
3055 /***********************************************************************
3056  *           NdrConformantVaryingStructBufferSize [RPCRT4.@]
3057  */
3058 void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3059                                 unsigned char *pMemory,
3060                                 PFORMAT_STRING pFormat)
3061 {
3062     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3063     PFORMAT_STRING pCVArrayFormat;
3064     ULONG esize;
3065
3066     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3067
3068     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3069     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3070     {
3071         ERR("invalid format type %x\n", pCVStructFormat->type);
3072         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3073         return;
3074     }
3075
3076     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3077         pCVStructFormat->offset_to_array_description;
3078     switch (*pCVArrayFormat)
3079     {
3080     case RPC_FC_CVARRAY:
3081         esize = *(const WORD*)(pCVArrayFormat+2);
3082
3083         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3084                                             pCVArrayFormat + 4, 0);
3085         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3086                                          pCVArrayFormat + 4, 0);
3087         break;
3088     case RPC_FC_C_CSTRING:
3089         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3090         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3091         esize = sizeof(char);
3092         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3093             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3094                                                 pCVArrayFormat + 2, 0);
3095         else
3096             pStubMsg->MaxCount = pStubMsg->ActualCount;
3097         break;
3098     case RPC_FC_C_WSTRING:
3099         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3100         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3101         esize = sizeof(WCHAR);
3102         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3103             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3104                                                 pCVArrayFormat + 2, 0);
3105         else
3106             pStubMsg->MaxCount = pStubMsg->ActualCount;
3107         break;
3108     default:
3109         ERR("invalid array format type %x\n", *pCVArrayFormat);
3110         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3111         return;
3112     }
3113
3114     SizeConformance(pStubMsg);
3115
3116     ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1);
3117
3118     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3119
3120     pStubMsg->BufferLength += pCVStructFormat->memory_size;
3121     SizeVariance(pStubMsg);
3122     pStubMsg->BufferLength += esize * pStubMsg->MaxCount;
3123
3124     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3125 }
3126
3127 /***********************************************************************
3128  *           NdrConformantVaryingStructMemorySize [RPCRT4.@]
3129  */
3130 unsigned long WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3131                                 PFORMAT_STRING pFormat)
3132 {
3133     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3134     PFORMAT_STRING pCVArrayFormat;
3135     ULONG esize;
3136     unsigned char cvarray_type;
3137
3138     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3139
3140     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3141     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3142     {
3143         ERR("invalid format type %x\n", pCVStructFormat->type);
3144         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3145         return 0;
3146     }
3147
3148     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3149         pCVStructFormat->offset_to_array_description;
3150     cvarray_type = *pCVArrayFormat;
3151     switch (cvarray_type)
3152     {
3153     case RPC_FC_CVARRAY:
3154         esize = *(const WORD*)(pCVArrayFormat+2);
3155         pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4);
3156         break;
3157     case RPC_FC_C_CSTRING:
3158         esize = sizeof(char);
3159         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3160             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3161         else
3162             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3163         break;
3164     case RPC_FC_C_WSTRING:
3165         esize = sizeof(WCHAR);
3166         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3167             pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2);
3168         else
3169             pCVArrayFormat = ReadConformance(pStubMsg, NULL);
3170         break;
3171     default:
3172         ERR("invalid array format type %x\n", *pCVArrayFormat);
3173         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3174         return 0;
3175     }
3176
3177     ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1);
3178
3179     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3180
3181     pStubMsg->Buffer += pCVStructFormat->memory_size;
3182     pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat);
3183     pStubMsg->Buffer += pCVStructFormat->memory_size + pStubMsg->ActualCount * esize;
3184
3185     pStubMsg->MemorySize += pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3186
3187     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3188
3189     return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize;
3190 }
3191
3192 /***********************************************************************
3193  *           NdrConformantVaryingStructFree [RPCRT4.@]
3194  */
3195 void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg,
3196                                 unsigned char *pMemory,
3197                                 PFORMAT_STRING pFormat)
3198 {
3199     const NDR_CVSTRUCT_FORMAT * pCVStructFormat = (NDR_CVSTRUCT_FORMAT*)pFormat;
3200     PFORMAT_STRING pCVArrayFormat;
3201     ULONG esize;
3202
3203     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3204
3205     pFormat += sizeof(NDR_CVSTRUCT_FORMAT);
3206     if (pCVStructFormat->type != RPC_FC_CVSTRUCT)
3207     {
3208         ERR("invalid format type %x\n", pCVStructFormat->type);
3209         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3210         return;
3211     }
3212
3213     pCVArrayFormat = (unsigned char*)&pCVStructFormat->offset_to_array_description +
3214         pCVStructFormat->offset_to_array_description;
3215     switch (*pCVArrayFormat)
3216     {
3217     case RPC_FC_CVARRAY:
3218         esize = *(const WORD*)(pCVArrayFormat+2);
3219
3220         pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3221                                             pCVArrayFormat + 4, 0);
3222         pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3223                                          pCVArrayFormat, 0);
3224         break;
3225     case RPC_FC_C_CSTRING:
3226         TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size));
3227         pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1;
3228         esize = sizeof(char);
3229         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3230             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3231                                                 pCVArrayFormat + 2, 0);
3232         else
3233             pStubMsg->MaxCount = pStubMsg->ActualCount;
3234         break;
3235     case RPC_FC_C_WSTRING:
3236         TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size));
3237         pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1;
3238         esize = sizeof(WCHAR);
3239         if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED)
3240             pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size,
3241                                                 pCVArrayFormat + 2, 0);
3242         else
3243             pStubMsg->MaxCount = pStubMsg->ActualCount;
3244         break;
3245     default:
3246         ERR("invalid array format type %x\n", *pCVArrayFormat);
3247         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3248         return;
3249     }
3250
3251     TRACE("memory_size = %d\n", pCVStructFormat->memory_size);
3252
3253     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3254 }
3255
3256 typedef struct
3257 {
3258     unsigned char type;
3259     unsigned char alignment;
3260     unsigned short total_size;
3261 } NDR_SMFARRAY_FORMAT;
3262
3263 typedef struct
3264 {
3265     unsigned char type;
3266     unsigned char alignment;
3267     unsigned long total_size;
3268 } NDR_LGFARRAY_FORMAT;
3269
3270 /***********************************************************************
3271  *           NdrFixedArrayMarshall [RPCRT4.@]
3272  */
3273 unsigned char *  WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3274                                 unsigned char *pMemory,
3275                                 PFORMAT_STRING pFormat)
3276 {
3277     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3278     unsigned long total_size;
3279
3280     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3281
3282     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3283         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3284     {
3285         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3286         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3287         return NULL;
3288     }
3289
3290     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3291
3292     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3293     {
3294         total_size = pSmFArrayFormat->total_size;
3295         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3296     }
3297     else
3298     {
3299         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3300         total_size = pLgFArrayFormat->total_size;
3301         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3302     }
3303     memcpy(pStubMsg->Buffer, pMemory, total_size);
3304     pStubMsg->Buffer += total_size;
3305
3306     pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
3307
3308     return NULL;
3309 }
3310
3311 /***********************************************************************
3312  *           NdrFixedArrayUnmarshall [RPCRT4.@]
3313  */
3314 unsigned char *  WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3315                                 unsigned char **ppMemory,
3316                                 PFORMAT_STRING pFormat,
3317                                 unsigned char fMustAlloc)
3318 {
3319     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3320     unsigned long total_size;
3321
3322     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3323
3324     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3325         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3326     {
3327         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3328         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3329         return NULL;
3330     }
3331
3332     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3333
3334     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3335     {
3336         total_size = pSmFArrayFormat->total_size;
3337         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3338     }
3339     else
3340     {
3341         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3342         total_size = pLgFArrayFormat->total_size;
3343         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3344     }
3345
3346     if (fMustAlloc || !*ppMemory)
3347         *ppMemory = NdrAllocate(pStubMsg, total_size);
3348     memcpy(*ppMemory, pStubMsg->Buffer, total_size);
3349     pStubMsg->Buffer += total_size;
3350
3351     pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
3352
3353     return NULL;
3354 }
3355
3356 /***********************************************************************
3357  *           NdrFixedArrayBufferSize [RPCRT4.@]
3358  */
3359 void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3360                                 unsigned char *pMemory,
3361                                 PFORMAT_STRING pFormat)
3362 {
3363     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3364     unsigned long total_size;
3365
3366     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3367
3368     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3369         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3370     {
3371         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3372         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3373         return;
3374     }
3375
3376     ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1);
3377
3378     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3379     {
3380         total_size = pSmFArrayFormat->total_size;
3381         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3382     }
3383     else
3384     {
3385         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3386         total_size = pLgFArrayFormat->total_size;
3387         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3388     }
3389     pStubMsg->BufferLength += total_size;
3390
3391     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
3392 }
3393
3394 /***********************************************************************
3395  *           NdrFixedArrayMemorySize [RPCRT4.@]
3396  */
3397 unsigned long WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3398                                 PFORMAT_STRING pFormat)
3399 {
3400     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3401     unsigned long total_size;
3402
3403     TRACE("(%p, %p)\n", pStubMsg, pFormat);
3404
3405     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3406         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3407     {
3408         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3409         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3410         return 0;
3411     }
3412
3413     ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1);
3414
3415     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3416     {
3417         total_size = pSmFArrayFormat->total_size;
3418         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3419     }
3420     else
3421     {
3422         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3423         total_size = pLgFArrayFormat->total_size;
3424         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3425     }
3426     pStubMsg->Buffer += total_size;
3427     pStubMsg->MemorySize += total_size;
3428
3429     EmbeddedPointerMemorySize(pStubMsg, pFormat);
3430
3431     return total_size;
3432 }
3433
3434 /***********************************************************************
3435  *           NdrFixedArrayFree [RPCRT4.@]
3436  */
3437 void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3438                                 unsigned char *pMemory,
3439                                 PFORMAT_STRING pFormat)
3440 {
3441     const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat;
3442
3443     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3444
3445     if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) &&
3446         (pSmFArrayFormat->type != RPC_FC_LGFARRAY))
3447     {
3448         ERR("invalid format type %x\n", pSmFArrayFormat->type);
3449         RpcRaiseException(RPC_S_INTERNAL_ERROR);
3450         return;
3451     }
3452
3453     if (pSmFArrayFormat->type == RPC_FC_SMFARRAY)
3454         pFormat = (unsigned char *)(pSmFArrayFormat + 1);
3455     else
3456     {
3457         const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat;
3458         pFormat = (unsigned char *)(pLgFArrayFormat + 1);
3459     }
3460
3461     EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
3462 }
3463
3464 /***********************************************************************
3465  *           NdrVaryingArrayMarshall [RPCRT4.@]
3466  */
3467 unsigned char *  WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3468                                 unsigned char *pMemory,
3469                                 PFORMAT_STRING pFormat)
3470 {
3471     FIXME("stub\n");
3472     return NULL;
3473 }
3474
3475 /***********************************************************************
3476  *           NdrVaryingArrayUnmarshall [RPCRT4.@]
3477  */
3478 unsigned char *  WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3479                                 unsigned char **ppMemory,
3480                                 PFORMAT_STRING pFormat,
3481                                 unsigned char fMustAlloc)
3482 {
3483     FIXME("stub\n");
3484     return NULL;
3485 }
3486
3487 /***********************************************************************
3488  *           NdrVaryingArrayBufferSize [RPCRT4.@]
3489  */
3490 void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3491                                 unsigned char *pMemory,
3492                                 PFORMAT_STRING pFormat)
3493 {
3494     FIXME("stub\n");
3495 }
3496
3497 /***********************************************************************
3498  *           NdrVaryingArrayMemorySize [RPCRT4.@]
3499  */
3500 unsigned long WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3501                                 PFORMAT_STRING pFormat)
3502 {
3503     FIXME("stub\n");
3504     return 0;
3505 }
3506
3507 /***********************************************************************
3508  *           NdrVaryingArrayFree [RPCRT4.@]
3509  */
3510 void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
3511                                 unsigned char *pMemory,
3512                                 PFORMAT_STRING pFormat)
3513 {
3514     FIXME("stub\n");
3515 }
3516
3517 /***********************************************************************
3518  *           NdrEncapsulatedUnionMarshall [RPCRT4.@]
3519  */
3520 unsigned char *  WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3521                                 unsigned char *pMemory,
3522                                 PFORMAT_STRING pFormat)
3523 {
3524     FIXME("stub\n");
3525     return NULL;
3526 }
3527
3528 /***********************************************************************
3529  *           NdrEncapsulatedUnionUnmarshall [RPCRT4.@]
3530  */
3531 unsigned char *  WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3532                                 unsigned char **ppMemory,
3533                                 PFORMAT_STRING pFormat,
3534                                 unsigned char fMustAlloc)
3535 {
3536     FIXME("stub\n");
3537     return NULL;
3538 }
3539
3540 /***********************************************************************
3541  *           NdrEncapsulatedUnionBufferSize [RPCRT4.@]
3542  */
3543 void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3544                                 unsigned char *pMemory,
3545                                 PFORMAT_STRING pFormat)
3546 {
3547     FIXME("stub\n");
3548 }
3549
3550 /***********************************************************************
3551  *           NdrEncapsulatedUnionMemorySize [RPCRT4.@]
3552  */
3553 unsigned long WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3554                                 PFORMAT_STRING pFormat)
3555 {
3556     FIXME("stub\n");
3557     return 0;
3558 }
3559
3560 /***********************************************************************
3561  *           NdrEncapsulatedUnionFree [RPCRT4.@]
3562  */
3563 void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
3564                                 unsigned char *pMemory,
3565                                 PFORMAT_STRING pFormat)
3566 {
3567     FIXME("stub\n");
3568 }
3569
3570 static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg,
3571                                                              unsigned long discriminant,
3572                                                              PFORMAT_STRING pFormat)
3573 {
3574     unsigned short num_arms, arm, type;
3575
3576     num_arms = *(const SHORT*)pFormat & 0x0fff;
3577     pFormat += 2;
3578     for(arm = 0; arm < num_arms; arm++)
3579     {
3580         if(discriminant == *(const ULONG*)pFormat)
3581         {
3582             pFormat += 4;
3583             break;
3584         }
3585         pFormat += 6;
3586     }
3587
3588     type = *(const unsigned short*)pFormat;
3589     TRACE("type %04x\n", type);
3590     if(arm == num_arms) /* default arm extras */
3591     {
3592         if(type == 0xffff)
3593         {
3594             ERR("no arm for 0x%lx and no default case\n", discriminant);
3595             RpcRaiseException(RPC_S_INVALID_TAG);
3596             return NULL;
3597         }
3598         if(type == 0)
3599         {
3600             TRACE("falling back to empty default case for 0x%lx\n", discriminant);
3601             return NULL;
3602         }
3603     }
3604     return pFormat;
3605 }
3606
3607 static PFORMAT_STRING get_non_encapsulated_union_arm(PMIDL_STUB_MESSAGE pStubMsg,
3608                                                      ULONG value,
3609                                                      PFORMAT_STRING pFormat)
3610 {
3611     pFormat += *(const SHORT*)pFormat;
3612     pFormat += 2;
3613
3614     return get_arm_offset_from_union_arm_selector(pStubMsg, value, pFormat);
3615 }
3616
3617 /***********************************************************************
3618  *           NdrNonEncapsulatedUnionMarshall [RPCRT4.@]
3619  */
3620 unsigned char *  WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3621                                 unsigned char *pMemory,
3622                                 PFORMAT_STRING pFormat)
3623 {
3624     unsigned short type;
3625     unsigned char switch_type;
3626
3627     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3628     pFormat++;
3629
3630     switch_type = *pFormat;
3631     pFormat++;
3632
3633     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
3634     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
3635     /* Marshall discriminant */
3636     NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
3637
3638     pFormat = get_non_encapsulated_union_arm(pStubMsg, pStubMsg->MaxCount, pFormat);
3639     if(!pFormat)
3640         return NULL;
3641
3642     type = *(const unsigned short*)pFormat;
3643     if((type & 0xff00) == 0x8000)
3644     {
3645         unsigned char basetype = LOBYTE(type);
3646         return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype);
3647     }
3648     else
3649     {
3650         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3651         NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK];
3652         if (m)
3653         {
3654             unsigned char *saved_buffer = NULL;
3655             switch(*desc)
3656             {
3657             case RPC_FC_RP:
3658             case RPC_FC_UP:
3659             case RPC_FC_OP:
3660             case RPC_FC_FP:
3661                 saved_buffer = pStubMsg->Buffer;
3662                 pStubMsg->Buffer += 4; /* for pointer ID */
3663                 PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc);
3664                 break;
3665             default:
3666                 m(pStubMsg, pMemory, desc);
3667             }
3668         }
3669         else FIXME("no marshaller for embedded type %02x\n", *desc);
3670     }
3671     return NULL;
3672 }
3673
3674 static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg,
3675                                     PFORMAT_STRING *ppFormat)
3676 {
3677     long discriminant = 0;
3678
3679     switch(**ppFormat)
3680     {
3681     case RPC_FC_BYTE:
3682     case RPC_FC_CHAR:
3683     case RPC_FC_SMALL:
3684     case RPC_FC_USMALL:
3685         discriminant = *(UCHAR *)pStubMsg->Buffer;
3686         pStubMsg->Buffer += sizeof(UCHAR);
3687         break;
3688     case RPC_FC_WCHAR:
3689     case RPC_FC_SHORT:
3690     case RPC_FC_USHORT:
3691         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
3692         discriminant = *(USHORT *)pStubMsg->Buffer;
3693         pStubMsg->Buffer += sizeof(USHORT);
3694         break;
3695     case RPC_FC_LONG:
3696     case RPC_FC_ULONG:
3697         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
3698         discriminant = *(ULONG *)pStubMsg->Buffer;
3699         pStubMsg->Buffer += sizeof(ULONG);
3700         break;
3701     default:
3702         FIXME("Unhandled base type: 0x%02x\n", **ppFormat);
3703     }
3704     (*ppFormat)++;
3705
3706     if (pStubMsg->fHasNewCorrDesc)
3707         *ppFormat += 6;
3708     else
3709         *ppFormat += 4;
3710     return discriminant;
3711 }
3712
3713 /**********************************************************************
3714  *           NdrNonEncapsulatedUnionUnmarshall[RPCRT4.@]
3715  */
3716 unsigned char *  WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3717                                 unsigned char **ppMemory,
3718                                 PFORMAT_STRING pFormat,
3719                                 unsigned char fMustAlloc)
3720 {
3721     long discriminant;
3722     unsigned short type, size;
3723
3724     TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
3725     pFormat++;
3726
3727     /* Unmarshall discriminant */
3728     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
3729     TRACE("unmarshalled discriminant %lx\n", discriminant);
3730
3731     pFormat += *(const SHORT*)pFormat;
3732
3733     size = *(const unsigned short*)pFormat;
3734     pFormat += 2;
3735
3736     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
3737     if(!pFormat)
3738         return NULL;
3739
3740     if(!*ppMemory || fMustAlloc)
3741         *ppMemory = NdrAllocate(pStubMsg, size);
3742
3743     type = *(const unsigned short*)pFormat;
3744     if((type & 0xff00) == 0x8000)
3745     {
3746         unsigned char basetype = LOBYTE(type);
3747         return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, fMustAlloc);
3748     }
3749     else
3750     {
3751         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3752         NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
3753         if (m)
3754         {
3755             unsigned char *saved_buffer = NULL;
3756             switch(*desc)
3757             {
3758             case RPC_FC_RP:
3759             case RPC_FC_UP:
3760             case RPC_FC_OP:
3761             case RPC_FC_FP:
3762                 **(void***)ppMemory = NULL;
3763                 ALIGN_POINTER(pStubMsg->Buffer, 4);
3764                 saved_buffer = pStubMsg->Buffer;
3765                 pStubMsg->Buffer += 4; /* for pointer ID */
3766                 PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, fMustAlloc);
3767                 break;
3768             default:
3769                 m(pStubMsg, ppMemory, desc, fMustAlloc);
3770             }
3771         }
3772         else FIXME("no marshaller for embedded type %02x\n", *desc);
3773     }
3774     return NULL;
3775 }
3776
3777 /***********************************************************************
3778  *           NdrNonEncapsulatedUnionBufferSize [RPCRT4.@]
3779  */
3780 void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3781                                 unsigned char *pMemory,
3782                                 PFORMAT_STRING pFormat)
3783 {
3784     unsigned short type;
3785     unsigned char switch_type;
3786
3787     TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat);
3788     pFormat++;
3789
3790     switch_type = *pFormat;
3791     pFormat++;
3792
3793     pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0);
3794     TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount);
3795     /* Add discriminant size */
3796     NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type);
3797
3798     pFormat = get_non_encapsulated_union_arm(pStubMsg, pStubMsg->MaxCount, pFormat);
3799     if(!pFormat)
3800         return;
3801
3802     type = *(const unsigned short*)pFormat;
3803     if((type & 0xff00) == 0x8000)
3804     {
3805         unsigned char basetype = LOBYTE(type);
3806         NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype);
3807     }
3808     else
3809     {
3810         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3811         NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
3812         if (m)
3813         {
3814             switch(*desc)
3815             {
3816             case RPC_FC_RP:
3817             case RPC_FC_UP:
3818             case RPC_FC_OP:
3819             case RPC_FC_FP:
3820                 ALIGN_LENGTH(pStubMsg->BufferLength, 4);
3821                 pStubMsg->BufferLength += 4; /* for pointer ID */
3822                 PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc);
3823                 break;
3824             default:
3825                 m(pStubMsg, pMemory, desc);
3826             }
3827         }
3828         else FIXME("no buffersizer for embedded type %02x\n", *desc);
3829     }
3830     return;
3831 }
3832
3833 /***********************************************************************
3834  *           NdrNonEncapsulatedUnionMemorySize [RPCRT4.@]
3835  */
3836 unsigned long WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3837                                 PFORMAT_STRING pFormat)
3838 {
3839     unsigned long discriminant;
3840     unsigned short type, size;
3841
3842     pFormat++;
3843     /* Unmarshall discriminant */
3844     discriminant = unmarshall_discriminant(pStubMsg, &pFormat);
3845     TRACE("unmarshalled discriminant 0x%lx\n", discriminant);
3846
3847     pFormat += *(const SHORT*)pFormat;
3848
3849     size = *(const unsigned short*)pFormat;
3850     pFormat += 2;
3851
3852     pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat);
3853     if(!pFormat)
3854         return 0;
3855
3856     pStubMsg->Memory += size;
3857
3858     type = *(const unsigned short*)pFormat;
3859     if((type & 0xff00) == 0x8000)
3860     {
3861         return NdrBaseTypeMemorySize(pStubMsg, pFormat);
3862     }
3863     else
3864     {
3865         PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat;
3866         NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
3867         unsigned char *saved_buffer;
3868         if (m)
3869         {
3870             switch(*desc)
3871             {
3872             case RPC_FC_RP:
3873             case RPC_FC_UP:
3874             case RPC_FC_OP:
3875             case RPC_FC_FP:
3876                 ALIGN_POINTER(pStubMsg->Buffer, 4);
3877                 saved_buffer = pStubMsg->Buffer;
3878                 pStubMsg->Buffer += 4;
3879                 ALIGN_LENGTH(pStubMsg->MemorySize, 4);
3880                 pStubMsg->MemorySize += 4;
3881                 PointerMemorySize(pStubMsg, saved_buffer, pFormat);
3882                 break;
3883             default:
3884                 return m(pStubMsg, desc);
3885             }
3886         }
3887         else FIXME("no marshaller for embedded type %02x\n", *desc);
3888     }
3889
3890     TRACE("size %d\n", size);
3891     return size;
3892 }
3893
3894 /***********************************************************************
3895  *           NdrNonEncapsulatedUnionFree [RPCRT4.@]
3896  */
3897 void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg,
3898                                 unsigned char *pMemory,
3899                                 PFORMAT_STRING pFormat)
3900 {
3901     FIXME("stub\n");
3902 }
3903
3904 /***********************************************************************
3905  *           NdrByteCountPointerMarshall [RPCRT4.@]
3906  */
3907 unsigned char *  WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3908                                 unsigned char *pMemory,
3909                                 PFORMAT_STRING pFormat)
3910 {
3911     FIXME("stub\n");
3912     return NULL;
3913 }
3914
3915 /***********************************************************************
3916  *           NdrByteCountPointerUnmarshall [RPCRT4.@]
3917  */
3918 unsigned char *  WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3919                                 unsigned char **ppMemory,
3920                                 PFORMAT_STRING pFormat,
3921                                 unsigned char fMustAlloc)
3922 {
3923     FIXME("stub\n");
3924     return NULL;
3925 }
3926
3927 /***********************************************************************
3928  *           NdrByteCountPointerBufferSize [RPCRT4.@]
3929  */
3930 void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3931                                 unsigned char *pMemory,
3932                                 PFORMAT_STRING pFormat)
3933 {
3934     FIXME("stub\n");
3935 }
3936
3937 /***********************************************************************
3938  *           NdrByteCountPointerMemorySize [RPCRT4.@]
3939  */
3940 unsigned long WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3941                                 PFORMAT_STRING pFormat)
3942 {
3943     FIXME("stub\n");
3944     return 0;
3945 }
3946
3947 /***********************************************************************
3948  *           NdrByteCountPointerFree [RPCRT4.@]
3949  */
3950 void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
3951                                 unsigned char *pMemory,
3952                                 PFORMAT_STRING pFormat)
3953 {
3954     FIXME("stub\n");
3955 }
3956
3957 /***********************************************************************
3958  *           NdrXmitOrRepAsMarshall [RPCRT4.@]
3959  */
3960 unsigned char *  WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg,
3961                                 unsigned char *pMemory,
3962                                 PFORMAT_STRING pFormat)
3963 {
3964     FIXME("stub\n");
3965     return NULL;
3966 }
3967
3968 /***********************************************************************
3969  *           NdrXmitOrRepAsUnmarshall [RPCRT4.@]
3970  */
3971 unsigned char *  WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
3972                                 unsigned char **ppMemory,
3973                                 PFORMAT_STRING pFormat,
3974                                 unsigned char fMustAlloc)
3975 {
3976     FIXME("stub\n");
3977     return NULL;
3978 }
3979
3980 /***********************************************************************
3981  *           NdrXmitOrRepAsBufferSize [RPCRT4.@]
3982  */
3983 void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
3984                                 unsigned char *pMemory,
3985                                 PFORMAT_STRING pFormat)
3986 {
3987     FIXME("stub\n");
3988 }
3989
3990 /***********************************************************************
3991  *           NdrXmitOrRepAsMemorySize [RPCRT4.@]
3992  */
3993 unsigned long WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
3994                                 PFORMAT_STRING pFormat)
3995 {
3996     FIXME("stub\n");
3997     return 0;
3998 }
3999
4000 /***********************************************************************
4001  *           NdrXmitOrRepAsFree [RPCRT4.@]
4002  */
4003 void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg,
4004                                 unsigned char *pMemory,
4005                                 PFORMAT_STRING pFormat)
4006 {
4007     FIXME("stub\n");
4008 }
4009
4010 /***********************************************************************
4011  *           NdrBaseTypeMarshall [internal]
4012  */
4013 static unsigned char *WINAPI NdrBaseTypeMarshall(
4014     PMIDL_STUB_MESSAGE pStubMsg,
4015     unsigned char *pMemory,
4016     PFORMAT_STRING pFormat)
4017 {
4018     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4019
4020     switch(*pFormat)
4021     {
4022     case RPC_FC_BYTE:
4023     case RPC_FC_CHAR:
4024     case RPC_FC_SMALL:
4025     case RPC_FC_USMALL:
4026         *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory;
4027         pStubMsg->Buffer += sizeof(UCHAR);
4028         TRACE("value: 0x%02x\n", *(UCHAR *)pMemory);
4029         break;
4030     case RPC_FC_WCHAR:
4031     case RPC_FC_SHORT:
4032     case RPC_FC_USHORT:
4033         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4034         *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory;
4035         pStubMsg->Buffer += sizeof(USHORT);
4036         TRACE("value: 0x%04x\n", *(USHORT *)pMemory);
4037         break;
4038     case RPC_FC_LONG:
4039     case RPC_FC_ULONG:
4040     case RPC_FC_ERROR_STATUS_T:
4041     case RPC_FC_ENUM32:
4042         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4043         *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory;
4044         pStubMsg->Buffer += sizeof(ULONG);
4045         TRACE("value: 0x%08lx\n", *(ULONG *)pMemory);
4046         break;
4047     case RPC_FC_FLOAT:
4048         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
4049         *(float *)pStubMsg->Buffer = *(float *)pMemory;
4050         pStubMsg->Buffer += sizeof(float);
4051         break;
4052     case RPC_FC_DOUBLE:
4053         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
4054         *(double *)pStubMsg->Buffer = *(double *)pMemory;
4055         pStubMsg->Buffer += sizeof(double);
4056         break;
4057     case RPC_FC_HYPER:
4058         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
4059         *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory;
4060         pStubMsg->Buffer += sizeof(ULONGLONG);
4061         TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory));
4062         break;
4063     case RPC_FC_ENUM16:
4064         /* only 16-bits on the wire, so do a sanity check */
4065         if (*(UINT *)pMemory > USHRT_MAX)
4066             RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE);
4067         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4068         *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory;
4069         pStubMsg->Buffer += sizeof(USHORT);
4070         TRACE("value: 0x%04x\n", *(UINT *)pMemory);
4071         break;
4072     default:
4073         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4074     }
4075
4076     STD_OVERFLOW_CHECK(pStubMsg);
4077
4078     /* FIXME: what is the correct return value? */
4079     return NULL;
4080 }
4081
4082 /***********************************************************************
4083  *           NdrBaseTypeUnmarshall [internal]
4084  */
4085 static unsigned char *WINAPI NdrBaseTypeUnmarshall(
4086     PMIDL_STUB_MESSAGE pStubMsg,
4087     unsigned char **ppMemory,
4088     PFORMAT_STRING pFormat,
4089     unsigned char fMustAlloc)
4090 {
4091     TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false");
4092
4093     if (fMustAlloc || !*ppMemory)
4094     {
4095         unsigned char *Buffer = pStubMsg->Buffer;
4096         unsigned long MemorySize = pStubMsg->MemorySize;
4097         *ppMemory = NdrAllocate(pStubMsg, NdrBaseTypeMemorySize(pStubMsg, pFormat));
4098         pStubMsg->MemorySize = MemorySize;
4099         pStubMsg->Buffer = Buffer;
4100     }
4101
4102     TRACE("*ppMemory: %p\n", *ppMemory);
4103
4104     switch(*pFormat)
4105     {
4106     case RPC_FC_BYTE:
4107     case RPC_FC_CHAR:
4108     case RPC_FC_SMALL:
4109     case RPC_FC_USMALL:
4110         **(UCHAR **)ppMemory = *(UCHAR *)pStubMsg->Buffer;
4111         pStubMsg->Buffer += sizeof(UCHAR);
4112         TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory);
4113         break;
4114     case RPC_FC_WCHAR:
4115     case RPC_FC_SHORT:
4116     case RPC_FC_USHORT:
4117         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4118         **(USHORT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
4119         pStubMsg->Buffer += sizeof(USHORT);
4120         TRACE("value: 0x%04x\n", **(USHORT **)ppMemory);
4121         break;
4122     case RPC_FC_LONG:
4123     case RPC_FC_ULONG:
4124     case RPC_FC_ERROR_STATUS_T:
4125     case RPC_FC_ENUM32:
4126         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG));
4127         **(ULONG **)ppMemory = *(ULONG *)pStubMsg->Buffer;
4128         pStubMsg->Buffer += sizeof(ULONG);
4129         TRACE("value: 0x%08lx\n", **(ULONG **)ppMemory);
4130         break;
4131    case RPC_FC_FLOAT:
4132         ALIGN_POINTER(pStubMsg->Buffer, sizeof(float));
4133         **(float **)ppMemory = *(float *)pStubMsg->Buffer;
4134         pStubMsg->Buffer += sizeof(float);
4135         TRACE("value: %f\n", **(float **)ppMemory);
4136         break;
4137     case RPC_FC_DOUBLE:
4138         ALIGN_POINTER(pStubMsg->Buffer, sizeof(double));
4139         **(double **)ppMemory = *(double*)pStubMsg->Buffer;
4140         pStubMsg->Buffer += sizeof(double);
4141         TRACE("value: %f\n", **(double **)ppMemory);
4142         break;
4143     case RPC_FC_HYPER:
4144         ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG));
4145         **(ULONGLONG **)ppMemory = *(ULONGLONG *)pStubMsg->Buffer;
4146         pStubMsg->Buffer += sizeof(ULONGLONG);
4147         TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory));
4148         break;
4149     case RPC_FC_ENUM16:
4150         ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT));
4151         /* 16-bits on the wire, but int in memory */
4152         **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer;
4153         pStubMsg->Buffer += sizeof(USHORT);
4154         TRACE("value: 0x%08x\n", **(UINT **)ppMemory);
4155         break;
4156     default:
4157         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4158     }
4159
4160     /* FIXME: what is the correct return value? */
4161
4162     return NULL;
4163 }
4164
4165 /***********************************************************************
4166  *           NdrBaseTypeBufferSize [internal]
4167  */
4168 static void WINAPI NdrBaseTypeBufferSize(
4169     PMIDL_STUB_MESSAGE pStubMsg,
4170     unsigned char *pMemory,
4171     PFORMAT_STRING pFormat)
4172 {
4173     TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4174
4175     switch(*pFormat)
4176     {
4177     case RPC_FC_BYTE:
4178     case RPC_FC_CHAR:
4179     case RPC_FC_SMALL:
4180     case RPC_FC_USMALL:
4181         pStubMsg->BufferLength += sizeof(UCHAR);
4182         break;
4183     case RPC_FC_WCHAR:
4184     case RPC_FC_SHORT:
4185     case RPC_FC_USHORT:
4186     case RPC_FC_ENUM16:
4187         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT));
4188         pStubMsg->BufferLength += sizeof(USHORT);
4189         break;
4190     case RPC_FC_LONG:
4191     case RPC_FC_ULONG:
4192     case RPC_FC_ENUM32:
4193         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG));
4194         pStubMsg->BufferLength += sizeof(ULONG);
4195         break;
4196     case RPC_FC_FLOAT:
4197         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float));
4198         pStubMsg->BufferLength += sizeof(float);
4199         break;
4200     case RPC_FC_DOUBLE:
4201         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double));
4202         pStubMsg->BufferLength += sizeof(double);
4203         break;
4204     case RPC_FC_HYPER:
4205         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG));
4206         pStubMsg->BufferLength += sizeof(ULONGLONG);
4207         break;
4208     case RPC_FC_ERROR_STATUS_T:
4209         ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t));
4210         pStubMsg->BufferLength += sizeof(error_status_t);
4211         break;
4212     default:
4213         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4214     }
4215 }
4216
4217 /***********************************************************************
4218  *           NdrBaseTypeMemorySize [internal]
4219  */
4220 static unsigned long WINAPI NdrBaseTypeMemorySize(
4221     PMIDL_STUB_MESSAGE pStubMsg,
4222     PFORMAT_STRING pFormat)
4223 {
4224     switch(*pFormat)
4225     {
4226     case RPC_FC_BYTE:
4227     case RPC_FC_CHAR:
4228     case RPC_FC_SMALL:
4229     case RPC_FC_USMALL:
4230         pStubMsg->Buffer += sizeof(UCHAR);
4231         pStubMsg->MemorySize += sizeof(UCHAR);
4232         return sizeof(UCHAR);
4233     case RPC_FC_WCHAR:
4234     case RPC_FC_SHORT:
4235     case RPC_FC_USHORT:
4236         pStubMsg->Buffer += sizeof(USHORT);
4237         pStubMsg->MemorySize += sizeof(USHORT);
4238         return sizeof(USHORT);
4239     case RPC_FC_LONG:
4240     case RPC_FC_ULONG:
4241         pStubMsg->Buffer += sizeof(ULONG);
4242         pStubMsg->MemorySize += sizeof(ULONG);
4243         return sizeof(ULONG);
4244     case RPC_FC_FLOAT:
4245         pStubMsg->Buffer += sizeof(float);
4246         pStubMsg->MemorySize += sizeof(float);
4247         return sizeof(float);
4248     case RPC_FC_DOUBLE:
4249         pStubMsg->Buffer += sizeof(double);
4250         pStubMsg->MemorySize += sizeof(double);
4251         return sizeof(double);
4252     case RPC_FC_HYPER:
4253         pStubMsg->Buffer += sizeof(ULONGLONG);
4254         pStubMsg->MemorySize += sizeof(ULONGLONG);
4255         return sizeof(ULONGLONG);
4256     case RPC_FC_ERROR_STATUS_T:
4257         pStubMsg->Buffer += sizeof(error_status_t);
4258         pStubMsg->MemorySize += sizeof(error_status_t);
4259         return sizeof(error_status_t);
4260     case RPC_FC_ENUM16:
4261     case RPC_FC_ENUM32:
4262         pStubMsg->Buffer += sizeof(INT);
4263         pStubMsg->MemorySize += sizeof(INT);
4264         return sizeof(INT);
4265     default:
4266         FIXME("Unhandled base type: 0x%02x\n", *pFormat);
4267        return 0;
4268     }
4269 }
4270
4271 /***********************************************************************
4272  *           NdrBaseTypeFree [internal]
4273  */
4274 static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg,
4275                                 unsigned char *pMemory,
4276                                 PFORMAT_STRING pFormat)
4277 {
4278    TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat);
4279
4280    /* nothing to do */
4281 }
4282
4283 /***********************************************************************
4284  *           NdrClientContextMarshall
4285  */
4286 void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4287                                      NDR_CCONTEXT ContextHandle,
4288                                      int fCheck)
4289 {
4290     FIXME("(%p, %p, %d): stub\n", pStubMsg, ContextHandle, fCheck);
4291 }
4292
4293 /***********************************************************************
4294  *           NdrClientContextUnmarshall
4295  */
4296 void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4297                                        NDR_CCONTEXT * pContextHandle,
4298                                        RPC_BINDING_HANDLE BindHandle)
4299 {
4300     FIXME("(%p, %p, %p): stub\n", pStubMsg, pContextHandle, BindHandle);
4301 }
4302
4303 void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4304                                      NDR_SCONTEXT ContextHandle,
4305                                      NDR_RUNDOWN RundownRoutine )
4306 {
4307     FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine);
4308 }
4309
4310 NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg)
4311 {
4312     FIXME("(%p): stub\n", pStubMsg);
4313     return NULL;
4314 }
4315
4316 void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg,
4317                                  unsigned char* pMemory,
4318                                  PFORMAT_STRING pFormat)
4319 {
4320     FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat);
4321 }
4322
4323 NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg,
4324                                                PFORMAT_STRING pFormat)
4325 {
4326     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
4327     return NULL;
4328 }
4329
4330 void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg,
4331                                         NDR_SCONTEXT ContextHandle,
4332                                         NDR_RUNDOWN RundownRoutine,
4333                                         PFORMAT_STRING pFormat)
4334 {
4335     FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat);
4336 }
4337
4338 NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
4339                                                   PFORMAT_STRING pFormat)
4340 {
4341     FIXME("(%p, %p): stub\n", pStubMsg, pFormat);
4342     return NULL;
4343 }
4344
4345 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
4346 {
4347     FIXME("(%p): stub\n", CContext);
4348     return NULL;
4349 }