ERROR_IO_PENDING is expected, so don't return an error.
[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
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winerror.h"
33 #include "winreg.h"
34
35 #include "ndr_misc.h"
36 #include "rpcndr.h"
37
38 #include "wine/unicode.h"
39 #include "wine/rpcfc.h"
40
41 #include "wine/debug.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(ole);
44
45 #define BUFFER_PARANOIA 20
46
47 #if defined(__i386__)
48   #define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
49     (*((UINT32 *)(pchar)) = (uint32))
50
51   #define LITTLE_ENDIAN_UINT32_READ(pchar) \
52     (*((UINT32 *)(pchar)))
53 #else
54   /* these would work for i386 too, but less efficient */
55   #define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \
56     (*(pchar)     = LOBYTE(LOWORD(uint32)), \
57      *((pchar)+1) = HIBYTE(LOWORD(uint32)), \
58      *((pchar)+2) = LOBYTE(HIWORD(uint32)), \
59      *((pchar)+3) = HIBYTE(HIWORD(uint32)), \
60      (uint32)) /* allow as r-value */
61
62   #define LITTLE_ENDIAN_UINT32_READ(pchar) \
63     (MAKELONG( \
64       MAKEWORD(*(pchar), *((pchar)+1)), \
65       MAKEWORD(*((pchar)+2), *((pchar)+3))))
66 #endif
67
68 #define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \
69   (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \
70    *((pchar)+2) = HIBYTE(LOWORD(uint32)), \
71    *((pchar)+1) = LOBYTE(HIWORD(uint32)), \
72    *(pchar)     = HIBYTE(HIWORD(uint32)), \
73    (uint32)) /* allow as r-value */
74
75 #define BIG_ENDIAN_UINT32_READ(pchar) \
76   (MAKELONG( \
77     MAKEWORD(*((pchar)+3), *((pchar)+2)), \
78     MAKEWORD(*((pchar)+1), *(pchar))))
79
80 #ifdef NDR_LOCAL_IS_BIG_ENDIAN
81   #define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
82     BIG_ENDIAN_UINT32_WRITE(pchar, uint32)
83   #define NDR_LOCAL_UINT32_READ(pchar) \
84     BIG_ENDIAN_UINT32_READ(pchar)
85 #else
86   #define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \
87     LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32)
88   #define NDR_LOCAL_UINT32_READ(pchar) \
89     LITTLE_ENDIAN_UINT32_READ(pchar)
90 #endif
91
92 /* _Align must be the desired alignment minus 1,
93  * e.g. ALIGN_LENGTH(len, 3) to align on a dword boundary. */
94 #define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
95 #define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
96 #define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align)
97 #define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align)
98
99 #define STD_OVERFLOW_CHECK(_Msg) do { \
100     TRACE("buffer=%d/%ld\n", _Msg->Buffer - _Msg->BufferStart, _Msg->BufferLength); \
101     if (_Msg->Buffer > _Msg->BufferEnd) ERR("buffer overflow %d bytes\n", _Msg->Buffer - _Msg->BufferEnd); \
102   } while (0)
103
104 #define NDR_TABLE_SIZE 128
105 #define NDR_TABLE_MASK 127
106
107 NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = {
108   0, 0, 0, 0, 0, 0, 0, 0,
109   0, 0, 0, 0, 0, 0, 0, 0,
110   /* 0x10 */
111   0,
112   /* 0x11 */
113   NdrPointerMarshall, NdrPointerMarshall,
114   NdrPointerMarshall, NdrPointerMarshall,
115   /* 0x15 */
116   NdrSimpleStructMarshall, NdrSimpleStructMarshall,
117   0, 0, 0,
118   NdrComplexStructMarshall,
119   /* 0x1b */
120   NdrConformantArrayMarshall, 0, 0, 0, 0, 0,
121   NdrComplexArrayMarshall,
122   /* 0x22 */
123   NdrConformantStringMarshall, 0, 0,
124   NdrConformantStringMarshall, 0, 0, 0, 0,
125   /* 0x2a */
126   0, 0, 0, 0, 0,
127   /* 0x2f */
128   NdrInterfacePointerMarshall,
129   /* 0xb0 */
130   0, 0, 0, 0,
131   NdrUserMarshalMarshall
132 };
133 NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = {
134   0, 0, 0, 0, 0, 0, 0, 0,
135   0, 0, 0, 0, 0, 0, 0, 0,
136   /* 0x10 */
137   0,
138   /* 0x11 */
139   NdrPointerUnmarshall, NdrPointerUnmarshall,
140   NdrPointerUnmarshall, NdrPointerUnmarshall,
141   /* 0x15 */
142   NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall,
143   0, 0, 0,
144   NdrComplexStructUnmarshall,
145   /* 0x1b */
146   NdrConformantArrayUnmarshall, 0, 0, 0, 0, 0,
147   NdrComplexArrayUnmarshall,
148   /* 0x22 */
149   NdrConformantStringUnmarshall, 0, 0,
150   NdrConformantStringUnmarshall, 0, 0, 0, 0,
151   /* 0x2a */
152   0, 0, 0, 0, 0,
153   /* 0x2f */
154   NdrInterfacePointerUnmarshall,
155   /* 0xb0 */
156   0, 0, 0, 0,
157   NdrUserMarshalUnmarshall
158 };
159 NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = {
160   0, 0, 0, 0, 0, 0, 0, 0,
161   0, 0, 0, 0, 0, 0, 0, 0,
162   /* 0x10 */
163   0,
164   /* 0x11 */
165   NdrPointerBufferSize, NdrPointerBufferSize,
166   NdrPointerBufferSize, NdrPointerBufferSize,
167   /* 0x15 */
168   NdrSimpleStructBufferSize, NdrSimpleStructBufferSize,
169   0, 0, 0,
170   NdrComplexStructBufferSize,
171   /* 0x1b */
172   NdrConformantArrayBufferSize, 0, 0, 0, 0, 0,
173   NdrComplexArrayBufferSize,
174   /* 0x22 */
175   NdrConformantStringBufferSize, 0, 0,
176   NdrConformantStringBufferSize, 0, 0, 0, 0,
177   /* 0x2a */
178   0, 0, 0, 0, 0,
179   /* 0x2f */
180   NdrInterfacePointerBufferSize,
181   /* 0xb0 */
182   0, 0, 0, 0,
183   NdrUserMarshalBufferSize
184 };
185 NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = {
186   0, 0, 0, 0, 0, 0, 0, 0,
187   0, 0, 0, 0, 0, 0, 0, 0,
188   /* 0x10 */
189   0,
190   /* 0x11 */
191   NdrPointerMemorySize, NdrPointerMemorySize,
192   NdrPointerMemorySize, NdrPointerMemorySize,
193   /* 0x15 */
194   NdrSimpleStructMemorySize, NdrSimpleStructMemorySize,
195   0, 0, 0,
196   NdrComplexStructMemorySize,
197   /* 0x1b */
198   NdrConformantArrayMemorySize, 0, 0, 0, 0, 0,
199   NdrComplexArrayMemorySize,
200   /* 0x22 */
201   NdrConformantStringMemorySize, 0, 0,
202   NdrConformantStringMemorySize, 0, 0, 0, 0,
203   /* 0x2a */
204   0, 0, 0, 0, 0,
205   /* 0x2f */
206   NdrInterfacePointerMemorySize,
207   /* 0xb0 */
208   0, 0, 0, 0,
209   NdrUserMarshalMemorySize
210 };
211 NDR_FREE NdrFreer[NDR_TABLE_SIZE] = {
212   0, 0, 0, 0, 0, 0, 0, 0,
213   0, 0, 0, 0, 0, 0, 0, 0,
214   /* 0x10 */
215   0,
216   /* 0x11 */
217   NdrPointerFree, NdrPointerFree,
218   NdrPointerFree, NdrPointerFree,
219   /* 0x15 */
220   NdrSimpleStructFree, NdrSimpleStructFree,
221   0, 0, 0,
222   NdrComplexStructFree,
223   /* 0x1b */
224   NdrConformantArrayFree, 0, 0, 0, 0, 0,
225   NdrComplexArrayFree,
226   /* 0x22 */
227   0, 0, 0, 0, 0, 0, 0, 0,
228   /* 0x2a */
229   0, 0, 0, 0, 0,
230   /* 0x2f */
231   NdrInterfacePointerFree,
232   /* 0xb0 */
233   0, 0, 0, 0,
234   NdrUserMarshalFree
235 };
236
237 void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len)
238 {
239   /* hmm, this is probably supposed to do more? */
240   return pStubMsg->pfnAllocate(len);
241 }
242
243 static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer)
244 {
245   pStubMsg->pfnFree(Pointer);
246 }
247
248 PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
249 {
250   pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
251   pStubMsg->Buffer += 4;
252   TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount);
253   return pFormat+4;
254 }
255
256 PFORMAT_STRING ComputeConformance(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory,
257                                   PFORMAT_STRING pFormat, ULONG_PTR def)
258 {
259   BYTE dtype = pFormat[0] & 0xf;
260   DWORD ofs = (DWORD)pFormat[2] | ((DWORD)pFormat[3] << 8);
261   LPVOID ptr = NULL;
262   DWORD data = 0;
263
264   if (pFormat[0] == 0xff) {
265     /* null descriptor */
266     pStubMsg->MaxCount = def;
267     goto finish_conf;
268   }
269
270   switch (pFormat[0] & 0xf0) {
271   case RPC_FC_NORMAL_CONFORMANCE:
272     TRACE("normal conformance, ofs=%ld\n", ofs);
273     ptr = pMemory + ofs;
274     break;
275   case RPC_FC_POINTER_CONFORMANCE:
276     TRACE("pointer conformance, ofs=%ld\n", ofs);
277     ptr = pStubMsg->Memory + ofs;
278     break;
279   case RPC_FC_TOP_LEVEL_CONFORMANCE:
280     TRACE("toplevel conformance, ofs=%ld\n", ofs);
281     if (pStubMsg->StackTop) {
282       ptr = pStubMsg->StackTop + ofs;
283     }
284     else {
285       /* -Os mode, MaxCount is already set */
286       goto finish_conf;
287     }
288     break;
289   case RPC_FC_CONSTANT_CONFORMANCE:
290     data = ofs | ((DWORD)pFormat[1] << 16);
291     TRACE("constant conformance, val=%ld\n", data);
292     pStubMsg->MaxCount = data;
293     goto finish_conf;
294   case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE:
295     FIXME("toplevel multidimensional conformance, ofs=%ld\n", ofs);
296     if (pStubMsg->StackTop) {
297       ptr = pStubMsg->StackTop + ofs;
298     }
299     else {
300       /* ? */
301       goto done_conf_grab;
302     }
303     break;
304   default:
305     FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0);
306   }
307
308   switch (pFormat[1]) {
309   case RPC_FC_DEREFERENCE:
310     ptr = *(LPVOID*)ptr;
311     break;
312   case RPC_FC_CALLBACK:
313     /* ofs is index into StubDesc->apfnExprEval */
314     FIXME("handle callback\n");
315     goto finish_conf;
316   default:
317     break;
318   }
319
320   switch (dtype) {
321   case RPC_FC_LONG:
322   case RPC_FC_ULONG:
323     data = *(DWORD*)ptr;
324     break;
325   case RPC_FC_SHORT:
326     data = *(SHORT*)ptr;
327     break;
328   case RPC_FC_USHORT:
329     data = *(USHORT*)ptr;
330     break;
331   case RPC_FC_SMALL:
332     data = *(CHAR*)ptr;
333     break;
334   case RPC_FC_USMALL:
335     data = *(UCHAR*)ptr;
336     break;
337   default:
338     FIXME("unknown conformance data type %x\n", dtype);
339     goto done_conf_grab;
340   }
341   TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data);
342
343 done_conf_grab:
344   switch (pFormat[1]) {
345   case 0: /* no op */
346     pStubMsg->MaxCount = data;
347     break;
348   case RPC_FC_DEREFERENCE:
349     /* already handled */
350     break;
351   default:
352     FIXME("unknown conformance op %d\n", pFormat[1]);
353     goto finish_conf;
354   }
355
356 finish_conf:
357   TRACE("resulting conformance is %ld\n", pStubMsg->MaxCount);
358   return pFormat+4;
359 }
360
361
362 /*
363  * NdrConformantString:
364  * 
365  * What MS calls a ConformantString is, in DCE terminology,
366  * a Varying-Conformant String.
367  * [
368  *   maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0')
369  *   offset: DWORD (actual string data begins at (offset) CHARTYPE's
370  *           into unmarshalled string) 
371  *   length: DWORD (# of CHARTYPE characters, inclusive of '\0')
372  *   [ 
373  *     data: CHARTYPE[maxlen]
374  *   ] 
375  * ], where CHARTYPE is the appropriate character type (specified externally)
376  *
377  */
378
379 /***********************************************************************
380  *            NdrConformantStringMarshall [RPCRT4.@]
381  */
382 unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg,
383   unsigned char *pszMessage, PFORMAT_STRING pFormat)
384
385   unsigned long len, esize;
386   unsigned char *c;
387
388   TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat);
389   
390   assert(pFormat);
391   if (*pFormat == RPC_FC_C_CSTRING) {
392     TRACE("string=%s\n", debugstr_a(pszMessage));
393     len = strlen(pszMessage)+1;
394     esize = 1;
395   }
396   else if (*pFormat == RPC_FC_C_WSTRING) {
397     TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage));
398     len = strlenW((LPWSTR)pszMessage)+1;
399     esize = 2;
400   }
401   else {
402     ERR("Unhandled string type: %#x\n", *pFormat); 
403     /* FIXME: raise an exception. */
404     return NULL;
405   }
406
407   if (pFormat[1] != RPC_FC_PAD) {
408     FIXME("sized string format=%d\n", pFormat[1]);
409   }
410
411   assert( (pStubMsg->BufferLength >= (len*esize + 13)) && (pStubMsg->Buffer != NULL) );
412
413   c = pStubMsg->Buffer;
414   memset(c, 0, 12);
415   NDR_LOCAL_UINT32_WRITE(c, len); /* max length: strlen + 1 (for '\0') */
416   c += 8;                         /* offset: 0 */
417   NDR_LOCAL_UINT32_WRITE(c, len); /* actual length: (same) */
418   c += 4;
419   memcpy(c, pszMessage, len*esize); /* the string itself */
420   c += len*esize;
421   pStubMsg->Buffer = c;
422
423   STD_OVERFLOW_CHECK(pStubMsg);
424
425   /* success */
426   return NULL; /* is this always right? */
427 }
428
429 /***********************************************************************
430  *           NdrConformantStringBufferSize [RPCRT4.@]
431  */
432 void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
433   unsigned char* pMemory, PFORMAT_STRING pFormat)
434 {
435   TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat);
436
437   assert(pFormat);
438   if (*pFormat == RPC_FC_C_CSTRING) {
439     /* we need 12 octets for the [maxlen, offset, len] DWORDS, + 1 octet for '\0' */
440     TRACE("string=%s\n", debugstr_a(pMemory));
441     pStubMsg->BufferLength += strlen(pMemory) + 13 + BUFFER_PARANOIA;
442   }
443   else if (*pFormat == RPC_FC_C_WSTRING) {
444     /* we need 12 octets for the [maxlen, offset, len] DWORDS, + 2 octets for L'\0' */
445     TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory));
446     pStubMsg->BufferLength += strlenW((LPWSTR)pMemory)*2 + 14 + BUFFER_PARANOIA;
447   }
448   else {
449     ERR("Unhandled string type: %#x\n", *pFormat); 
450     /* FIXME: raise an exception */
451   }
452
453   if (pFormat[1] != RPC_FC_PAD) {
454     FIXME("sized string format=%d\n", pFormat[1]);
455   }
456 }
457
458 /************************************************************************
459  *            NdrConformantStringMemorySize [RPCRT4.@]
460  */
461 unsigned long WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
462   PFORMAT_STRING pFormat )
463 {
464   unsigned long rslt = 0;
465
466   TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat);
467    
468   assert(pStubMsg && pFormat);
469
470   if (*pFormat == RPC_FC_C_CSTRING) {
471     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */
472   }
473   else if (*pFormat == RPC_FC_C_WSTRING) {
474     rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */
475   }
476   else {
477     ERR("Unhandled string type: %#x\n", *pFormat);
478     /* FIXME: raise an exception */
479   }
480
481   if (pFormat[1] != RPC_FC_PAD) {
482     FIXME("sized string format=%d\n", pFormat[1]);
483   }
484
485   TRACE("  --> %lu\n", rslt);
486   return rslt;
487 }
488
489 /************************************************************************
490  *           NdrConformantStringUnmarshall [RPCRT4.@]
491  */
492 unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
493   unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc )
494 {
495   unsigned long len, esize, ofs;
496   unsigned char *pMem;
497
498   TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n",
499     pStubMsg, *ppMemory, pFormat, fMustAlloc);
500
501   assert(pFormat && ppMemory && pStubMsg);
502
503   pStubMsg->Buffer += 4;
504   ofs = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
505   pStubMsg->Buffer += 4;
506   len = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
507   pStubMsg->Buffer += 4;
508
509   if (*pFormat == RPC_FC_C_CSTRING) esize = 1;
510   else if (*pFormat == RPC_FC_C_WSTRING) esize = 2;
511   else {
512     ERR("Unhandled string type: %#x\n", *pFormat);
513     /* FIXME: raise an exception */
514     esize = 0;
515   }
516
517   if (pFormat[1] != RPC_FC_PAD) {
518     FIXME("sized string format=%d\n", pFormat[1]);
519   }
520
521   if (fMustAlloc) {
522     *ppMemory = NdrAllocate(pStubMsg, len*esize + BUFFER_PARANOIA);
523   } else {
524     if (pStubMsg->ReuseBuffer && !*ppMemory)
525       /* for servers, we may just point straight into the RPC buffer, I think
526        * (I guess that's what MS does since MIDL code doesn't try to free) */
527       *ppMemory = pStubMsg->Buffer - ofs*esize;
528     /* for clients, memory should be provided by caller */
529   }
530
531   pMem = *ppMemory + ofs*esize;
532
533   if (pMem != pStubMsg->Buffer)
534     memcpy(pMem, pStubMsg->Buffer, len*esize);
535
536   pStubMsg->Buffer += len*esize;
537
538   if (*pFormat == RPC_FC_C_CSTRING) {
539     TRACE("string=%s\n", debugstr_a(pMem));
540   }
541   else if (*pFormat == RPC_FC_C_WSTRING) {
542     TRACE("string=%s\n", debugstr_w((LPWSTR)pMem));
543   }
544
545   return NULL; /* FIXME: is this always right? */
546 }
547
548 /***********************************************************************
549  *           PointerMarshall
550  */
551 void WINAPI PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
552                             unsigned char *Buffer,
553                             unsigned char *Pointer,
554                             PFORMAT_STRING pFormat)
555 {
556   unsigned type = pFormat[0], attr = pFormat[1];
557   PFORMAT_STRING desc;
558   NDR_MARSHALL m;
559
560   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
561   TRACE("type=%d, attr=%d\n", type, attr);
562   pFormat += 2;
563   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
564   else desc = pFormat + *(const SHORT*)pFormat;
565   if (attr & RPC_FC_P_DEREF) {
566     Pointer = *(unsigned char**)Pointer;
567     TRACE("deref => %p\n", Pointer);
568   }
569
570   *(LPVOID*)Buffer = 0;
571
572   switch (type) {
573   case RPC_FC_RP: /* ref pointer (always non-null) */
574     break;
575   default:
576     FIXME("unhandled ptr type=%02x\n", type);
577   }
578
579   m = NdrMarshaller[*desc & NDR_TABLE_MASK];
580   if (m) m(pStubMsg, Pointer, desc);
581   else FIXME("no marshaller for data type=%02x\n", *desc);
582
583   STD_OVERFLOW_CHECK(pStubMsg);
584 }
585
586 /***********************************************************************
587  *           PointerUnmarshall
588  */
589 void WINAPI PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
590                               unsigned char *Buffer,
591                               unsigned char **pPointer,
592                               PFORMAT_STRING pFormat,
593                               unsigned char fMustAlloc)
594 {
595   unsigned type = pFormat[0], attr = pFormat[1];
596   PFORMAT_STRING desc;
597   NDR_UNMARSHALL m;
598
599   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc);
600   TRACE("type=%d, attr=%d\n", type, attr);
601   pFormat += 2;
602   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
603   else desc = pFormat + *(const SHORT*)pFormat;
604   if (attr & RPC_FC_P_DEREF) {
605     pPointer = *(unsigned char***)pPointer;
606     TRACE("deref => %p\n", pPointer);
607   }
608
609   switch (type) {
610   case RPC_FC_RP: /* ref pointer (always non-null) */
611     break;
612   default:
613     FIXME("unhandled ptr type=%02x\n", type);
614   }
615
616   *pPointer = NULL;
617
618   m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
619   if (m) m(pStubMsg, pPointer, desc, fMustAlloc);
620   else FIXME("no unmarshaller for data type=%02x\n", *desc);
621   TRACE("pointer=%p\n", *pPointer);
622 }
623
624 /***********************************************************************
625  *           PointerBufferSize
626  */
627 void WINAPI PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
628                               unsigned char *Pointer,
629                               PFORMAT_STRING pFormat)
630 {
631   unsigned type = pFormat[0], attr = pFormat[1];
632   PFORMAT_STRING desc;
633   NDR_BUFFERSIZE m;
634
635   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
636   TRACE("type=%d, attr=%d\n", type, attr);
637   pFormat += 2;
638   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
639   else desc = pFormat + *(const SHORT*)pFormat;
640   if (attr & RPC_FC_P_DEREF) {
641     Pointer = *(unsigned char**)Pointer;
642     TRACE("deref => %p\n", Pointer);
643   }
644
645   switch (type) {
646   case RPC_FC_RP: /* ref pointer (always non-null) */
647     break;
648   default:
649     FIXME("unhandled ptr type=%02x\n", type);
650   }
651
652   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
653   if (m) m(pStubMsg, Pointer, desc);
654   else FIXME("no buffersizer for data type=%02x\n", *desc);
655 }
656
657 /***********************************************************************
658  *           PointerMemorySize [RPCRT4.@]
659  */
660 unsigned long WINAPI PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
661                                        unsigned char *Buffer,
662                                        PFORMAT_STRING pFormat)
663 {
664   unsigned type = pFormat[0], attr = pFormat[1];
665   PFORMAT_STRING desc;
666   NDR_MEMORYSIZE m;
667
668   FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat);
669   TRACE("type=%d, attr=%d\n", type, attr);
670   pFormat += 2;
671   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
672   else desc = pFormat + *(const SHORT*)pFormat;
673   if (attr & RPC_FC_P_DEREF) {
674     TRACE("deref\n");
675   }
676
677   switch (type) {
678   case RPC_FC_RP: /* ref pointer (always non-null) */
679     break;
680   default:
681     FIXME("unhandled ptr type=%02x\n", type);
682   }
683
684   m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
685   if (m) m(pStubMsg, desc);
686   else FIXME("no memorysizer for data type=%02x\n", *desc);
687
688   return 0;
689 }
690
691 /***********************************************************************
692  *           PointerFree [RPCRT4.@]
693  */
694 void WINAPI PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
695                         unsigned char *Pointer,
696                         PFORMAT_STRING pFormat)
697 {
698   unsigned type = pFormat[0], attr = pFormat[1];
699   PFORMAT_STRING desc;
700   NDR_FREE m;
701
702   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
703   TRACE("type=%d, attr=%d\n", type, attr);
704   if (attr & RPC_FC_P_DONTFREE) return;
705   pFormat += 2;
706   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
707   else desc = pFormat + *(const SHORT*)pFormat;
708   if (attr & RPC_FC_P_DEREF) {
709     Pointer = *(unsigned char**)Pointer;
710     TRACE("deref => %p\n", Pointer);
711   }
712
713   if (!Pointer) return;
714
715   m = NdrFreer[*desc & NDR_TABLE_MASK];
716   if (m) m(pStubMsg, Pointer, desc);
717
718   /* hmm... is this sensible?
719    * perhaps we should check if the memory comes from NdrAllocate,
720    * and deallocate only if so - checking if the pointer is between
721    * BufferStart and BufferEnd is probably no good since the buffer
722    * may be reallocated when the server wants to marshal the reply */
723   switch (*desc) {
724   case RPC_FC_BOGUS_STRUCT:
725   case RPC_FC_BOGUS_ARRAY:
726   case RPC_FC_USER_MARSHAL:
727     break;
728   default:
729     FIXME("unhandled data type=%02x\n", *desc);
730   case RPC_FC_CARRAY:
731   case RPC_FC_C_CSTRING:
732   case RPC_FC_C_WSTRING:
733     if (pStubMsg->ReuseBuffer) goto notfree;
734     break;
735   case RPC_FC_IP:
736     goto notfree;
737   }
738
739   if (attr & RPC_FC_P_ONSTACK) {
740     TRACE("not freeing stack ptr %p\n", Pointer);
741     return;
742   }
743   TRACE("freeing %p\n", Pointer);
744   NdrFree(pStubMsg, Pointer);
745   return;
746 notfree:
747   TRACE("not freeing %p\n", Pointer);
748 }
749
750 /***********************************************************************
751  *           EmbeddedPointerMarshall
752  */
753 unsigned char * WINAPI EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
754                                                unsigned char *pMemory,
755                                                PFORMAT_STRING pFormat)
756 {
757   unsigned char *Mark = pStubMsg->BufferMark;
758   unsigned long Offset = pStubMsg->Offset;
759   unsigned ofs, rep, count, stride, xofs;
760
761   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
762
763   if (*pFormat != RPC_FC_PP) return NULL;
764   pFormat += 2;
765
766   while (pFormat[0] != RPC_FC_END) {
767     switch (pFormat[0]) {
768     default:
769       FIXME("unknown repeat type %d\n", pFormat[0]);
770     case RPC_FC_NO_REPEAT:
771       rep = 1;
772       stride = 0;
773       ofs = 0;
774       count = 1;
775       xofs = 0;
776       pFormat += 2;
777       break;
778     case RPC_FC_FIXED_REPEAT:
779       rep = *(const WORD*)&pFormat[2];
780       stride = *(const WORD*)&pFormat[4];
781       ofs = *(const WORD*)&pFormat[6];
782       count = *(const WORD*)&pFormat[8];
783       xofs = 0;
784       pFormat += 10;
785       break;
786     case RPC_FC_VARIABLE_REPEAT:
787       rep = pStubMsg->MaxCount;
788       stride = *(const WORD*)&pFormat[2];
789       ofs = *(const WORD*)&pFormat[4];
790       count = *(const WORD*)&pFormat[6];
791       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
792       pFormat += 8;
793       break;
794     }
795     /* ofs doesn't seem to matter in this context */
796     while (rep) {
797       PFORMAT_STRING info = pFormat;
798       unsigned char *membase = pMemory + xofs;
799       unsigned u;
800       for (u=0; u<count; u++,info+=8) {
801         unsigned char *memptr = membase + *(const SHORT*)&info[0];
802         unsigned char *bufptr = Mark + *(const SHORT*)&info[2];
803         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
804       }
805       rep--;
806     }
807     pFormat += 8 * count;
808   }
809
810   STD_OVERFLOW_CHECK(pStubMsg);
811
812   return NULL;
813 }
814
815 /***********************************************************************
816  *           EmbeddedPointerUnmarshall
817  */
818 unsigned char * WINAPI EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
819                                                  unsigned char **ppMemory,
820                                                  PFORMAT_STRING pFormat,
821                                                  unsigned char fMustAlloc)
822 {
823   unsigned char *Mark = pStubMsg->BufferMark;
824   unsigned long Offset = pStubMsg->Offset;
825   unsigned ofs, rep, count, stride, xofs;
826
827   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
828
829   if (*pFormat != RPC_FC_PP) return NULL;
830   pFormat += 2;
831
832   while (pFormat[0] != RPC_FC_END) {
833     switch (pFormat[0]) {
834     default:
835       FIXME("unknown repeat type %d\n", pFormat[0]);
836     case RPC_FC_NO_REPEAT:
837       rep = 1;
838       stride = 0;
839       ofs = 0;
840       count = 1;
841       xofs = 0;
842       pFormat += 2;
843       break;
844     case RPC_FC_FIXED_REPEAT:
845       rep = *(const WORD*)&pFormat[2];
846       stride = *(const WORD*)&pFormat[4];
847       ofs = *(const WORD*)&pFormat[6];
848       count = *(const WORD*)&pFormat[8];
849       xofs = 0;
850       pFormat += 10;
851       break;
852     case RPC_FC_VARIABLE_REPEAT:
853       rep = pStubMsg->MaxCount;
854       stride = *(const WORD*)&pFormat[2];
855       ofs = *(const WORD*)&pFormat[4];
856       count = *(const WORD*)&pFormat[6];
857       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
858       pFormat += 8;
859       break;
860     }
861     /* ofs doesn't seem to matter in this context */
862     while (rep) {
863       PFORMAT_STRING info = pFormat;
864       unsigned char *membase = *ppMemory + xofs;
865       unsigned u;
866       for (u=0; u<count; u++,info+=8) {
867         unsigned char *memptr = membase + *(const SHORT*)&info[0];
868         unsigned char *bufptr = Mark + *(const SHORT*)&info[2];
869         PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, fMustAlloc);
870       }
871       rep--;
872     }
873     pFormat += 8 * count;
874   }
875
876   return NULL;
877 }
878
879 /***********************************************************************
880  *           EmbeddedPointerBufferSize
881  */
882 void WINAPI EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
883                                       unsigned char *pMemory,
884                                       PFORMAT_STRING pFormat)
885 {
886   unsigned long Offset = pStubMsg->Offset;
887   unsigned ofs, rep, count, stride, xofs;
888
889   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
890   if (*pFormat != RPC_FC_PP) return;
891   pFormat += 2;
892
893   while (pFormat[0] != RPC_FC_END) {
894     switch (pFormat[0]) {
895     default:
896       FIXME("unknown repeat type %d\n", pFormat[0]);
897     case RPC_FC_NO_REPEAT:
898       rep = 1;
899       stride = 0;
900       ofs = 0;
901       count = 1;
902       xofs = 0;
903       pFormat += 2;
904       break;
905     case RPC_FC_FIXED_REPEAT:
906       rep = *(const WORD*)&pFormat[2];
907       stride = *(const WORD*)&pFormat[4];
908       ofs = *(const WORD*)&pFormat[6];
909       count = *(const WORD*)&pFormat[8];
910       xofs = 0;
911       pFormat += 10;
912       break;
913     case RPC_FC_VARIABLE_REPEAT:
914       rep = pStubMsg->MaxCount;
915       stride = *(const WORD*)&pFormat[2];
916       ofs = *(const WORD*)&pFormat[4];
917       count = *(const WORD*)&pFormat[6];
918       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
919       pFormat += 8;
920       break;
921     }
922     /* ofs doesn't seem to matter in this context */
923     while (rep) {
924       PFORMAT_STRING info = pFormat;
925       unsigned char *membase = pMemory + xofs;
926       unsigned u;
927       for (u=0; u<count; u++,info+=8) {
928         unsigned char *memptr = membase + *(const SHORT*)&info[0];
929         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
930       }
931       rep--;
932     }
933     pFormat += 8 * count;
934   }
935 }
936
937 /***********************************************************************
938  *           EmbeddedPointerMemorySize
939  */
940 unsigned long WINAPI EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
941                                                PFORMAT_STRING pFormat)
942 {
943   unsigned long Offset = pStubMsg->Offset;
944   unsigned char *Mark = pStubMsg->BufferMark;
945   unsigned ofs, rep, count, stride, xofs;
946
947   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
948   if (*pFormat != RPC_FC_PP) return 0;
949   pFormat += 2;
950
951   while (pFormat[0] != RPC_FC_END) {
952     switch (pFormat[0]) {
953     default:
954       FIXME("unknown repeat type %d\n", pFormat[0]);
955     case RPC_FC_NO_REPEAT:
956       rep = 1;
957       stride = 0;
958       ofs = 0;
959       count = 1;
960       xofs = 0;
961       pFormat += 2;
962       break;
963     case RPC_FC_FIXED_REPEAT:
964       rep = *(const WORD*)&pFormat[2];
965       stride = *(const WORD*)&pFormat[4];
966       ofs = *(const WORD*)&pFormat[6];
967       count = *(const WORD*)&pFormat[8];
968       xofs = 0;
969       pFormat += 10;
970       break;
971     case RPC_FC_VARIABLE_REPEAT:
972       rep = pStubMsg->MaxCount;
973       stride = *(const WORD*)&pFormat[2];
974       ofs = *(const WORD*)&pFormat[4];
975       count = *(const WORD*)&pFormat[6];
976       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
977       pFormat += 8;
978       break;
979     }
980     /* ofs doesn't seem to matter in this context */
981     while (rep) {
982       PFORMAT_STRING info = pFormat;
983       unsigned u;
984       for (u=0; u<count; u++,info+=8) {
985         unsigned char *bufptr = Mark + *(const SHORT*)&info[2];
986         PointerMemorySize(pStubMsg, bufptr, info+4);
987       }
988       rep--;
989     }
990     pFormat += 8 * count;
991   }
992
993   return 0;
994 }
995
996 /***********************************************************************
997  *           EmbeddedPointerFree
998  */
999 void WINAPI EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1000                                 unsigned char *pMemory,
1001                                 PFORMAT_STRING pFormat)
1002 {
1003   unsigned long Offset = pStubMsg->Offset;
1004   unsigned ofs, rep, count, stride, xofs;
1005
1006   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1007   if (*pFormat != RPC_FC_PP) return;
1008   pFormat += 2;
1009
1010   while (pFormat[0] != RPC_FC_END) {
1011     switch (pFormat[0]) {
1012     default:
1013       FIXME("unknown repeat type %d\n", pFormat[0]);
1014     case RPC_FC_NO_REPEAT:
1015       rep = 1;
1016       stride = 0;
1017       ofs = 0;
1018       count = 1;
1019       xofs = 0;
1020       pFormat += 2;
1021       break;
1022     case RPC_FC_FIXED_REPEAT:
1023       rep = *(const WORD*)&pFormat[2];
1024       stride = *(const WORD*)&pFormat[4];
1025       ofs = *(const WORD*)&pFormat[6];
1026       count = *(const WORD*)&pFormat[8];
1027       xofs = 0;
1028       pFormat += 10;
1029       break;
1030     case RPC_FC_VARIABLE_REPEAT:
1031       rep = pStubMsg->MaxCount;
1032       stride = *(const WORD*)&pFormat[2];
1033       ofs = *(const WORD*)&pFormat[4];
1034       count = *(const WORD*)&pFormat[6];
1035       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1036       pFormat += 8;
1037       break;
1038     }
1039     /* ofs doesn't seem to matter in this context */
1040     while (rep) {
1041       PFORMAT_STRING info = pFormat;
1042       unsigned char *membase = pMemory + xofs;
1043       unsigned u;
1044       for (u=0; u<count; u++,info+=8) {
1045         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1046         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1047       }
1048       rep--;
1049     }
1050     pFormat += 8 * count;
1051   }
1052 }
1053
1054 /***********************************************************************
1055  *           NdrPointerMarshall [RPCRT4.@]
1056  */
1057 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1058                                           unsigned char *pMemory,
1059                                           PFORMAT_STRING pFormat)
1060 {
1061   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1062
1063   pStubMsg->BufferMark = pStubMsg->Buffer;
1064   PointerMarshall(pStubMsg, pStubMsg->Buffer, pMemory, pFormat);
1065   pStubMsg->Buffer += 4;
1066
1067   STD_OVERFLOW_CHECK(pStubMsg);
1068
1069   return NULL;
1070 }
1071
1072 /***********************************************************************
1073  *           NdrPointerUnmarshall [RPCRT4.@]
1074  */
1075 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1076                                             unsigned char **ppMemory,
1077                                             PFORMAT_STRING pFormat,
1078                                             unsigned char fMustAlloc)
1079 {
1080   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1081
1082   pStubMsg->BufferMark = pStubMsg->Buffer;
1083   PointerUnmarshall(pStubMsg, pStubMsg->Buffer, ppMemory, pFormat, fMustAlloc);
1084   pStubMsg->Buffer += 4;
1085
1086   return NULL;
1087 }
1088
1089 /***********************************************************************
1090  *           NdrPointerBufferSize [RPCRT4.@]
1091  */
1092 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1093                                       unsigned char *pMemory,
1094                                       PFORMAT_STRING pFormat)
1095 {
1096   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1097   pStubMsg->BufferLength += 4;
1098   PointerBufferSize(pStubMsg, pMemory, pFormat);
1099 }
1100
1101 /***********************************************************************
1102  *           NdrPointerMemorySize [RPCRT4.@]
1103  */
1104 unsigned long WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1105                                           PFORMAT_STRING pFormat)
1106 {
1107   /* unsigned size = *(LPWORD)(pFormat+2); */
1108   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1109   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1110   return 0;
1111 }
1112
1113 /***********************************************************************
1114  *           NdrPointerFree [RPCRT4.@]
1115  */
1116 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1117                            unsigned char *pMemory,
1118                            PFORMAT_STRING pFormat)
1119 {
1120   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1121   PointerFree(pStubMsg, pMemory, pFormat);
1122 }
1123
1124 /***********************************************************************
1125  *           NdrSimpleStructMarshall [RPCRT4.@]
1126  */
1127 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1128                                                unsigned char *pMemory,
1129                                                PFORMAT_STRING pFormat)
1130 {
1131   unsigned size = *(const WORD*)(pFormat+2);
1132   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1133
1134   memcpy(pStubMsg->Buffer, pMemory, size);
1135   pStubMsg->BufferMark = pStubMsg->Buffer;
1136   pStubMsg->Buffer += size;
1137
1138   if (pFormat[0] != RPC_FC_STRUCT)
1139     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1140
1141   STD_OVERFLOW_CHECK(pStubMsg);
1142
1143   return NULL;
1144 }
1145
1146 /***********************************************************************
1147  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1148  */
1149 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1150                                                  unsigned char **ppMemory,
1151                                                  PFORMAT_STRING pFormat,
1152                                                  unsigned char fMustAlloc)
1153 {
1154   unsigned size = *(const WORD*)(pFormat+2);
1155   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1156
1157   if (fMustAlloc) {
1158     *ppMemory = NdrAllocate(pStubMsg, size);
1159     memcpy(*ppMemory, pStubMsg->Buffer, size);
1160   } else {
1161     if (pStubMsg->ReuseBuffer && !*ppMemory)
1162       /* for servers, we may just point straight into the RPC buffer, I think
1163        * (I guess that's what MS does since MIDL code doesn't try to free) */
1164       *ppMemory = pStubMsg->Buffer;
1165     else
1166       /* for clients, memory should be provided by caller */
1167       memcpy(*ppMemory, pStubMsg->Buffer, size);
1168   }
1169
1170   pStubMsg->BufferMark = pStubMsg->Buffer;
1171   pStubMsg->Buffer += size;
1172
1173   if (pFormat[0] != RPC_FC_STRUCT)
1174     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1175
1176   return NULL;
1177 }
1178
1179
1180 /***********************************************************************
1181  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1182  */
1183 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1184                                    unsigned char FormatChar )
1185 {
1186     FIXME("stub\n");
1187 }
1188
1189
1190 /***********************************************************************
1191  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1192  */
1193 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1194                                      unsigned char FormatChar )
1195 {
1196     FIXME("stub\n");
1197 }
1198
1199
1200 /***********************************************************************
1201  *           NdrSimpleStructBufferSize [RPCRT4.@]
1202  */
1203 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1204                                       unsigned char *pMemory,
1205                                       PFORMAT_STRING pFormat)
1206 {
1207   unsigned size = *(const WORD*)(pFormat+2);
1208   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1209   pStubMsg->BufferLength += size;
1210   if (pFormat[0] != RPC_FC_STRUCT)
1211     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1212 }
1213
1214 /***********************************************************************
1215  *           NdrSimpleStructMemorySize [RPCRT4.@]
1216  */
1217 unsigned long WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1218                                                PFORMAT_STRING pFormat)
1219 {
1220   /* unsigned size = *(LPWORD)(pFormat+2); */
1221   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1222   if (pFormat[0] != RPC_FC_STRUCT)
1223     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1224   return 0;
1225 }
1226
1227 /***********************************************************************
1228  *           NdrSimpleStructFree [RPCRT4.@]
1229  */
1230 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1231                                 unsigned char *pMemory,
1232                                 PFORMAT_STRING pFormat)
1233 {
1234   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1235   if (pFormat[0] != RPC_FC_STRUCT)
1236     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1237 }
1238
1239
1240 unsigned long WINAPI EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg,
1241                                          PFORMAT_STRING pFormat)
1242 {
1243   switch (*pFormat) {
1244   case RPC_FC_STRUCT:
1245   case RPC_FC_PSTRUCT:
1246   case RPC_FC_CSTRUCT:
1247   case RPC_FC_BOGUS_STRUCT:
1248     return *(const WORD*)&pFormat[2];
1249   case RPC_FC_USER_MARSHAL:
1250     return *(const WORD*)&pFormat[4];
1251   default:
1252     FIXME("unhandled embedded type %02x\n", *pFormat);
1253   }
1254   return 0;
1255 }
1256
1257
1258 unsigned char * WINAPI ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1259                                        unsigned char *pMemory,
1260                                        PFORMAT_STRING pFormat,
1261                                        PFORMAT_STRING pPointer)
1262 {
1263   PFORMAT_STRING desc;
1264   NDR_MARSHALL m;
1265   unsigned long size;
1266
1267   while (*pFormat != RPC_FC_END) {
1268     switch (*pFormat) {
1269     case RPC_FC_SHORT:
1270     case RPC_FC_USHORT:
1271       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1272       memcpy(pStubMsg->Buffer, pMemory, 2);
1273       pStubMsg->Buffer += 2;
1274       pMemory += 2;
1275       break;
1276     case RPC_FC_LONG:
1277     case RPC_FC_ULONG:
1278       TRACE("long=%ld <= %p\n", *(DWORD*)pMemory, pMemory);
1279       memcpy(pStubMsg->Buffer, pMemory, 4);
1280       pStubMsg->Buffer += 4;
1281       pMemory += 4;
1282       break;
1283     case RPC_FC_POINTER:
1284       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1285       NdrPointerMarshall(pStubMsg, *(unsigned char**)pMemory, pPointer);
1286       pPointer += 4;
1287       pMemory += 4;
1288       break;
1289     case RPC_FC_ALIGNM4:
1290       ALIGN_POINTER(pMemory, 3);
1291       break;
1292     case RPC_FC_ALIGNM8:
1293       ALIGN_POINTER(pMemory, 7);
1294       break;
1295     case RPC_FC_EMBEDDED_COMPLEX:
1296       pMemory += pFormat[1];
1297       pFormat += 2;
1298       desc = pFormat + *(const SHORT*)pFormat;
1299       size = EmbeddedComplexSize(pStubMsg, desc);
1300       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1301       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1302       if (m) m(pStubMsg, pMemory, desc);
1303       else FIXME("no marshaller for embedded type %02x\n", *desc);
1304       pMemory += size;
1305       pFormat += 2;
1306       continue;
1307     case RPC_FC_PAD:
1308       break;
1309     default:
1310       FIXME("unhandled format %02x\n", *pFormat);
1311     }
1312     pFormat++;
1313   }
1314
1315   return pMemory;
1316 }
1317
1318 unsigned char * WINAPI ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1319                                          unsigned char *pMemory,
1320                                          PFORMAT_STRING pFormat,
1321                                          PFORMAT_STRING pPointer,
1322                                          unsigned char fMustAlloc)
1323 {
1324   PFORMAT_STRING desc;
1325   NDR_UNMARSHALL m;
1326   unsigned long size;
1327
1328   while (*pFormat != RPC_FC_END) {
1329     switch (*pFormat) {
1330     case RPC_FC_SHORT:
1331     case RPC_FC_USHORT:
1332       memcpy(pMemory, pStubMsg->Buffer, 2);
1333       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1334       pStubMsg->Buffer += 2;
1335       pMemory += 2;
1336       break;
1337     case RPC_FC_LONG:
1338     case RPC_FC_ULONG:
1339       memcpy(pMemory, pStubMsg->Buffer, 4);
1340       TRACE("long=%ld => %p\n", *(DWORD*)pMemory, pMemory);
1341       pStubMsg->Buffer += 4;
1342       pMemory += 4;
1343       break;
1344     case RPC_FC_POINTER:
1345       *(unsigned char**)pMemory = NULL;
1346       TRACE("pointer => %p\n", pMemory);
1347       NdrPointerUnmarshall(pStubMsg, (unsigned char**)pMemory, pPointer, fMustAlloc);
1348       pPointer += 4;
1349       pMemory += 4;
1350       break;
1351     case RPC_FC_ALIGNM4:
1352       ALIGN_POINTER(pMemory, 3);
1353       break;
1354     case RPC_FC_ALIGNM8:
1355       ALIGN_POINTER(pMemory, 7);
1356       break;
1357     case RPC_FC_EMBEDDED_COMPLEX:
1358       pMemory += pFormat[1];
1359       pFormat += 2;
1360       desc = pFormat + *(const SHORT*)pFormat;
1361       size = EmbeddedComplexSize(pStubMsg, desc);
1362       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1363       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1364       memset(pMemory, 0, size); /* just in case */
1365       if (m) m(pStubMsg, &pMemory, desc, fMustAlloc);
1366       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
1367       pMemory += size;
1368       pFormat += 2;
1369       continue;
1370     case RPC_FC_PAD:
1371       break;
1372     default:
1373       FIXME("unhandled format %d\n", *pFormat);
1374     }
1375     pFormat++;
1376   }
1377
1378   return pMemory;
1379 }
1380
1381 unsigned char * WINAPI ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1382                                          unsigned char *pMemory,
1383                                          PFORMAT_STRING pFormat,
1384                                          PFORMAT_STRING pPointer)
1385 {
1386   PFORMAT_STRING desc;
1387   NDR_BUFFERSIZE m;
1388   unsigned long size;
1389
1390   while (*pFormat != RPC_FC_END) {
1391     switch (*pFormat) {
1392     case RPC_FC_SHORT:
1393     case RPC_FC_USHORT:
1394       pStubMsg->BufferLength += 2;
1395       pMemory += 2;
1396       break;
1397     case RPC_FC_LONG:
1398     case RPC_FC_ULONG:
1399       pStubMsg->BufferLength += 4;
1400       pMemory += 4;
1401       break;
1402     case RPC_FC_POINTER:
1403       NdrPointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
1404       pPointer += 4;
1405       pMemory += 4;
1406       break;
1407     case RPC_FC_ALIGNM4:
1408       ALIGN_POINTER(pMemory, 3);
1409       break;
1410     case RPC_FC_ALIGNM8:
1411       ALIGN_POINTER(pMemory, 7);
1412       break;
1413     case RPC_FC_EMBEDDED_COMPLEX:
1414       pMemory += pFormat[1];
1415       pFormat += 2;
1416       desc = pFormat + *(const SHORT*)pFormat;
1417       size = EmbeddedComplexSize(pStubMsg, desc);
1418       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1419       if (m) m(pStubMsg, pMemory, desc);
1420       else FIXME("no buffersizer for embedded type %02x\n", *desc);
1421       pMemory += size;
1422       pFormat += 2;
1423       continue;
1424     case RPC_FC_PAD:
1425       break;
1426     default:
1427       FIXME("unhandled format %d\n", *pFormat);
1428     }
1429     pFormat++;
1430   }
1431
1432   return pMemory;
1433 }
1434
1435 unsigned char * WINAPI ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
1436                                    unsigned char *pMemory,
1437                                    PFORMAT_STRING pFormat,
1438                                    PFORMAT_STRING pPointer)
1439 {
1440   PFORMAT_STRING desc;
1441   NDR_FREE m;
1442   unsigned long size;
1443
1444   while (*pFormat != RPC_FC_END) {
1445     switch (*pFormat) {
1446     case RPC_FC_SHORT:
1447     case RPC_FC_USHORT:
1448       pMemory += 2;
1449       break;
1450     case RPC_FC_LONG:
1451     case RPC_FC_ULONG:
1452       pMemory += 4;
1453       break;
1454     case RPC_FC_POINTER:
1455       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
1456       pPointer += 4;
1457       pMemory += 4;
1458       break;
1459     case RPC_FC_ALIGNM4:
1460       ALIGN_POINTER(pMemory, 3);
1461       break;
1462     case RPC_FC_ALIGNM8:
1463       ALIGN_POINTER(pMemory, 7);
1464       break;
1465     case RPC_FC_EMBEDDED_COMPLEX:
1466       pMemory += pFormat[1];
1467       pFormat += 2;
1468       desc = pFormat + *(const SHORT*)pFormat;
1469       size = EmbeddedComplexSize(pStubMsg, desc);
1470       m = NdrFreer[*desc & NDR_TABLE_MASK];
1471       if (m) m(pStubMsg, pMemory, desc);
1472       else FIXME("no freer for embedded type %02x\n", *desc);
1473       pMemory += size;
1474       pFormat += 2;
1475       continue;
1476     case RPC_FC_PAD:
1477       break;
1478     default:
1479       FIXME("unhandled format %d\n", *pFormat);
1480     }
1481     pFormat++;
1482   }
1483
1484   return pMemory;
1485 }
1486
1487 unsigned long WINAPI ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,
1488                                        PFORMAT_STRING pFormat)
1489 {
1490   PFORMAT_STRING desc;
1491   unsigned long size = 0;
1492
1493   while (*pFormat != RPC_FC_END) {
1494     switch (*pFormat) {
1495     case RPC_FC_SHORT:
1496     case RPC_FC_USHORT:
1497       size += 2;
1498       break;
1499     case RPC_FC_LONG:
1500     case RPC_FC_ULONG:
1501       size += 4;
1502       break;
1503     case RPC_FC_POINTER:
1504       size += 4;
1505       break;
1506     case RPC_FC_ALIGNM4:
1507       ALIGN_LENGTH(size, 3);
1508       break;
1509     case RPC_FC_ALIGNM8:
1510       ALIGN_LENGTH(size, 7);
1511       break;
1512     case RPC_FC_EMBEDDED_COMPLEX:
1513       size += pFormat[1];
1514       pFormat += 2;
1515       desc = pFormat + *(const SHORT*)pFormat;
1516       size += EmbeddedComplexSize(pStubMsg, desc);
1517       pFormat += 2;
1518       continue;
1519     case RPC_FC_PAD:
1520       break;
1521     default:
1522       FIXME("unhandled format %d\n", *pFormat);
1523     }
1524     pFormat++;
1525   }
1526
1527   return size;
1528 }
1529
1530 /***********************************************************************
1531  *           NdrComplexStructMarshall [RPCRT4.@]
1532  */
1533 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1534                                                 unsigned char *pMemory,
1535                                                 PFORMAT_STRING pFormat)
1536 {
1537   PFORMAT_STRING conf_array = NULL;
1538   PFORMAT_STRING pointer_desc = NULL;
1539   unsigned char *OldMemory = pStubMsg->Memory;
1540
1541   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1542
1543   pFormat += 4;
1544   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1545   pFormat += 2;
1546   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1547   pFormat += 2;
1548
1549   pStubMsg->Memory = pMemory;
1550
1551   ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
1552
1553   if (conf_array)
1554     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
1555
1556   pStubMsg->Memory = OldMemory;
1557
1558   STD_OVERFLOW_CHECK(pStubMsg);
1559
1560   return NULL;
1561 }
1562
1563 /***********************************************************************
1564  *           NdrComplexStructUnmarshall [RPCRT4.@]
1565  */
1566 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1567                                                   unsigned char **ppMemory,
1568                                                   PFORMAT_STRING pFormat,
1569                                                   unsigned char fMustAlloc)
1570 {
1571   unsigned size = *(const WORD*)(pFormat+2);
1572   PFORMAT_STRING conf_array = NULL;
1573   PFORMAT_STRING pointer_desc = NULL;
1574   unsigned char *pMemory;
1575
1576   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1577
1578   if (fMustAlloc || !*ppMemory)
1579     *ppMemory = NdrAllocate(pStubMsg, size);
1580
1581   pFormat += 4;
1582   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1583   pFormat += 2;
1584   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1585   pFormat += 2;
1586
1587   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
1588
1589   if (conf_array)
1590     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
1591
1592   return NULL;
1593 }
1594
1595 /***********************************************************************
1596  *           NdrComplexStructBufferSize [RPCRT4.@]
1597  */
1598 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1599                                        unsigned char *pMemory,
1600                                        PFORMAT_STRING pFormat)
1601 {
1602   PFORMAT_STRING conf_array = NULL;
1603   PFORMAT_STRING pointer_desc = NULL;
1604   unsigned char *OldMemory = pStubMsg->Memory;
1605
1606   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1607
1608   pFormat += 4;
1609   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1610   pFormat += 2;
1611   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1612   pFormat += 2;
1613
1614   pStubMsg->Memory = pMemory;
1615
1616   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
1617
1618   if (conf_array)
1619     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
1620
1621   pStubMsg->Memory = OldMemory;
1622 }
1623
1624 /***********************************************************************
1625  *           NdrComplexStructMemorySize [RPCRT4.@]
1626  */
1627 unsigned long WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1628                                                 PFORMAT_STRING pFormat)
1629 {
1630   /* unsigned size = *(LPWORD)(pFormat+2); */
1631   PFORMAT_STRING conf_array = NULL;
1632   PFORMAT_STRING pointer_desc = NULL;
1633
1634   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1635
1636   pFormat += 4;
1637   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1638   pFormat += 2;
1639   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1640   pFormat += 2;
1641
1642   return 0;
1643 }
1644
1645 /***********************************************************************
1646  *           NdrComplexStructFree [RPCRT4.@]
1647  */
1648 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1649                                  unsigned char *pMemory,
1650                                  PFORMAT_STRING pFormat)
1651 {
1652   PFORMAT_STRING conf_array = NULL;
1653   PFORMAT_STRING pointer_desc = NULL;
1654   unsigned char *OldMemory = pStubMsg->Memory;
1655
1656   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1657
1658   pFormat += 4;
1659   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1660   pFormat += 2;
1661   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1662   pFormat += 2;
1663
1664   pStubMsg->Memory = pMemory;
1665
1666   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
1667
1668   if (conf_array)
1669     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
1670
1671   pStubMsg->Memory = OldMemory;
1672 }
1673
1674 /***********************************************************************
1675  *           NdrConformantArrayMarshall [RPCRT4.@]
1676  */
1677 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1678                                                   unsigned char *pMemory,
1679                                                   PFORMAT_STRING pFormat)
1680 {
1681   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
1682   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1683   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1684
1685   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1686   size = pStubMsg->MaxCount;
1687
1688   NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, size);
1689   pStubMsg->Buffer += 4;
1690
1691   memcpy(pStubMsg->Buffer, pMemory, size*esize);
1692   pStubMsg->BufferMark = pStubMsg->Buffer;
1693   pStubMsg->Buffer += size*esize;
1694
1695   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1696
1697   STD_OVERFLOW_CHECK(pStubMsg);
1698
1699   return NULL;
1700 }
1701
1702 /***********************************************************************
1703  *           NdrConformantArrayUnmarshall [RPCRT4.@]
1704  */
1705 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1706                                                     unsigned char **ppMemory,
1707                                                     PFORMAT_STRING pFormat,
1708                                                     unsigned char fMustAlloc)
1709 {
1710   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
1711   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1712   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1713
1714   pFormat = ReadConformance(pStubMsg, pFormat+4);
1715   size = pStubMsg->MaxCount;
1716
1717   if (fMustAlloc) {
1718     *ppMemory = NdrAllocate(pStubMsg, size*esize);
1719     memcpy(*ppMemory, pStubMsg->Buffer, size*esize);
1720   } else {
1721     if (pStubMsg->ReuseBuffer && !*ppMemory)
1722       /* for servers, we may just point straight into the RPC buffer, I think
1723        * (I guess that's what MS does since MIDL code doesn't try to free) */
1724       *ppMemory = pStubMsg->Buffer;
1725     else
1726       /* for clients, memory should be provided by caller */
1727       memcpy(*ppMemory, pStubMsg->Buffer, size*esize);
1728   }
1729
1730   pStubMsg->BufferMark = pStubMsg->Buffer;
1731   pStubMsg->Buffer += size*esize;
1732
1733   EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
1734
1735   return NULL;
1736 }
1737
1738 /***********************************************************************
1739  *           NdrConformantArrayBufferSize [RPCRT4.@]
1740  */
1741 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1742                                          unsigned char *pMemory,
1743                                          PFORMAT_STRING pFormat)
1744 {
1745   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
1746   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1747   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1748
1749   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1750   size = pStubMsg->MaxCount;
1751
1752   pStubMsg->BufferLength += size*esize;
1753
1754   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1755 }
1756
1757 /***********************************************************************
1758  *           NdrConformantArrayMemorySize [RPCRT4.@]
1759  */
1760 unsigned long WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1761                                                   PFORMAT_STRING pFormat)
1762 {
1763   DWORD size = 0;
1764   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1765   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1766
1767   pFormat = ReadConformance(pStubMsg, pFormat+4);
1768   size = pStubMsg->MaxCount;
1769
1770   EmbeddedPointerMemorySize(pStubMsg, pFormat);
1771
1772   return 0;
1773 }
1774
1775 /***********************************************************************
1776  *           NdrConformantArrayFree [RPCRT4.@]
1777  */
1778 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
1779                                    unsigned char *pMemory,
1780                                    PFORMAT_STRING pFormat)
1781 {
1782   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1783   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1784
1785   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
1786 }
1787
1788
1789 /***********************************************************************
1790  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
1791  */
1792 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
1793                                                          unsigned char* pMemory,
1794                                                          PFORMAT_STRING pFormat )
1795 {
1796     FIXME( "stub\n" );
1797     return NULL;
1798 }
1799
1800
1801 /***********************************************************************
1802  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
1803  */
1804 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
1805                                                            unsigned char** ppMemory,
1806                                                            PFORMAT_STRING pFormat,
1807                                                            unsigned char fMustAlloc )
1808 {
1809     FIXME( "stub\n" );
1810     return NULL;
1811 }
1812
1813
1814 /***********************************************************************
1815  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
1816  */
1817 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
1818                                            unsigned char* pMemory,
1819                                            PFORMAT_STRING pFormat )
1820 {
1821     FIXME( "stub\n" );
1822 }
1823
1824
1825 /***********************************************************************
1826  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
1827  */
1828 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
1829                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
1830 {
1831     FIXME( "stub\n" );
1832 }
1833
1834
1835 /***********************************************************************
1836  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
1837  */
1838 unsigned long WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
1839                                                           PFORMAT_STRING pFormat )
1840 {
1841     FIXME( "stub\n" );
1842     return 0;
1843 }
1844
1845
1846 /***********************************************************************
1847  *           NdrComplexArrayMarshall [RPCRT4.@]
1848  */
1849 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1850                                                unsigned char *pMemory,
1851                                                PFORMAT_STRING pFormat)
1852 {
1853   DWORD size = 0, count, def;
1854   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1855
1856   def = *(const WORD*)&pFormat[2];
1857   pFormat += 4;
1858
1859   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
1860   size = pStubMsg->MaxCount;
1861   TRACE("conformance=%ld\n", size);
1862
1863   if (*(const DWORD*)pFormat != 0xffffffff)
1864     FIXME("compute variance\n");
1865   pFormat += 4;
1866
1867   NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, size);
1868   pStubMsg->Buffer += 4;
1869
1870   for (count=0; count<size; count++)
1871     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
1872
1873   STD_OVERFLOW_CHECK(pStubMsg);
1874
1875   return NULL;
1876 }
1877
1878 /***********************************************************************
1879  *           NdrComplexArrayUnmarshall [RPCRT4.@]
1880  */
1881 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1882                                                  unsigned char **ppMemory,
1883                                                  PFORMAT_STRING pFormat,
1884                                                  unsigned char fMustAlloc)
1885 {
1886   DWORD size = 0, count, esize;
1887   unsigned char *pMemory;
1888   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1889
1890   pFormat += 4;
1891
1892   pFormat = ReadConformance(pStubMsg, pFormat);
1893   size = pStubMsg->MaxCount;
1894   TRACE("conformance=%ld\n", size);
1895
1896   pFormat += 4;
1897
1898   esize = ComplexStructSize(pStubMsg, pFormat);
1899
1900   if (fMustAlloc || !*ppMemory)
1901     *ppMemory = NdrAllocate(pStubMsg, size*esize);
1902
1903   pMemory = *ppMemory;
1904   for (count=0; count<size; count++)
1905     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
1906
1907   return NULL;
1908 }
1909
1910 /***********************************************************************
1911  *           NdrComplexArrayBufferSize [RPCRT4.@]
1912  */
1913 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1914                                       unsigned char *pMemory,
1915                                       PFORMAT_STRING pFormat)
1916 {
1917   DWORD size = 0, count, def;
1918   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1919
1920   def = *(const WORD*)&pFormat[2];
1921   pFormat += 4;
1922
1923   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
1924   size = pStubMsg->MaxCount;
1925   TRACE("conformance=%ld\n", size);
1926
1927   if (*(const DWORD*)pFormat != 0xffffffff)
1928     FIXME("compute variance\n");
1929   pFormat += 4;
1930
1931   for (count=0; count<size; count++)
1932     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
1933 }
1934
1935 /***********************************************************************
1936  *           NdrComplexArrayMemorySize [RPCRT4.@]
1937  */
1938 unsigned long WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1939                                                PFORMAT_STRING pFormat)
1940 {
1941   DWORD size = 0;
1942   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1943
1944   pFormat += 4;
1945
1946   pFormat = ReadConformance(pStubMsg, pFormat);
1947   size = pStubMsg->MaxCount;
1948   TRACE("conformance=%ld\n", size);
1949
1950   pFormat += 4;
1951
1952   return 0;
1953 }
1954
1955 /***********************************************************************
1956  *           NdrComplexArrayFree [RPCRT4.@]
1957  */
1958 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
1959                                 unsigned char *pMemory,
1960                                 PFORMAT_STRING pFormat)
1961 {
1962   DWORD size = 0, count, def;
1963   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1964
1965   def = *(const WORD*)&pFormat[2];
1966   pFormat += 4;
1967
1968   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
1969   size = pStubMsg->MaxCount;
1970   TRACE("conformance=%ld\n", size);
1971
1972   if (*(const DWORD*)pFormat != 0xffffffff)
1973     FIXME("compute variance\n");
1974   pFormat += 4;
1975
1976   for (count=0; count<size; count++)
1977     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
1978 }
1979
1980 unsigned long UserMarshalFlags(PMIDL_STUB_MESSAGE pStubMsg)
1981 {
1982   return MAKELONG(pStubMsg->dwDestContext,
1983                   pStubMsg->RpcMsg->DataRepresentation);
1984 }
1985
1986 /***********************************************************************
1987  *           NdrUserMarshalMarshall [RPCRT4.@]
1988  */
1989 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1990                                               unsigned char *pMemory,
1991                                               PFORMAT_STRING pFormat)
1992 {
1993 /*  unsigned flags = pFormat[1]; */
1994   unsigned index = *(const WORD*)&pFormat[2];
1995   unsigned long uflag = UserMarshalFlags(pStubMsg);
1996   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1997   TRACE("index=%d\n", index);
1998
1999   pStubMsg->Buffer =
2000     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
2001       &uflag, pStubMsg->Buffer, pMemory);
2002
2003   STD_OVERFLOW_CHECK(pStubMsg);
2004
2005   return NULL;
2006 }
2007
2008 /***********************************************************************
2009  *           NdrUserMarshalUnmarshall [RPCRT4.@]
2010  */
2011 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2012                                                  unsigned char **ppMemory,
2013                                                  PFORMAT_STRING pFormat,
2014                                                  unsigned char fMustAlloc)
2015 {
2016 /*  unsigned flags = pFormat[1];*/
2017   unsigned index = *(const WORD*)&pFormat[2];
2018   DWORD memsize = *(const WORD*)&pFormat[4];
2019   unsigned long uflag = UserMarshalFlags(pStubMsg);
2020   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2021   TRACE("index=%d\n", index);
2022
2023   if (fMustAlloc || !*ppMemory)
2024     *ppMemory = NdrAllocate(pStubMsg, memsize);
2025
2026   pStubMsg->Buffer =
2027     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
2028       &uflag, pStubMsg->Buffer, *ppMemory);
2029
2030   return NULL;
2031 }
2032
2033 /***********************************************************************
2034  *           NdrUserMarshalBufferSize [RPCRT4.@]
2035  */
2036 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2037                                       unsigned char *pMemory,
2038                                       PFORMAT_STRING pFormat)
2039 {
2040 /*  unsigned flags = pFormat[1];*/
2041   unsigned index = *(const WORD*)&pFormat[2];
2042   DWORD bufsize = *(const WORD*)&pFormat[6];
2043   unsigned long uflag = UserMarshalFlags(pStubMsg);
2044   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2045   TRACE("index=%d\n", index);
2046
2047   if (bufsize) {
2048     TRACE("size=%ld\n", bufsize);
2049     pStubMsg->BufferLength += bufsize;
2050     return;
2051   }
2052
2053   pStubMsg->BufferLength =
2054     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
2055       &uflag, pStubMsg->BufferLength, pMemory);
2056 }
2057
2058 /***********************************************************************
2059  *           NdrUserMarshalMemorySize [RPCRT4.@]
2060  */
2061 unsigned long WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2062                                               PFORMAT_STRING pFormat)
2063 {
2064   unsigned index = *(const WORD*)&pFormat[2];
2065 /*  DWORD memsize = *(const WORD*)&pFormat[4]; */
2066   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
2067   TRACE("index=%d\n", index);
2068
2069   return 0;
2070 }
2071
2072 /***********************************************************************
2073  *           NdrUserMarshalFree [RPCRT4.@]
2074  */
2075 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
2076                                 unsigned char *pMemory,
2077                                 PFORMAT_STRING pFormat)
2078 {
2079 /*  unsigned flags = pFormat[1]; */
2080   unsigned index = *(const WORD*)&pFormat[2];
2081   unsigned long uflag = UserMarshalFlags(pStubMsg);
2082   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2083   TRACE("index=%d\n", index);
2084
2085   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
2086     &uflag, pMemory);
2087 }
2088
2089 /***********************************************************************
2090  *           NdrClearOutParameters [RPCRT4.@]
2091  */
2092 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
2093                                   PFORMAT_STRING pFormat,
2094                                   void *ArgAddr)
2095 {
2096   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
2097 }
2098
2099 /***********************************************************************
2100  *           NdrConvert [RPCRT4.@]
2101  */
2102 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
2103 {
2104   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
2105   /* FIXME: since this stub doesn't do any converting, the proper behavior
2106      is to raise an exception */
2107 }
2108
2109 /***********************************************************************
2110  *           NdrConvert2 [RPCRT4.@]
2111  */
2112 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )
2113 {
2114   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n",
2115     pStubMsg, pFormat, NumberParams);
2116   /* FIXME: since this stub doesn't do any converting, the proper behavior
2117      is to raise an exception */
2118 }