Implement asn.1 encoding/decoding of times, with tests.
[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 static inline void dump_pointer_attr(unsigned char attr)
549 {
550     if (attr & RPC_FC_P_ALLOCALLNODES)
551         TRACE(" RPC_FC_P_ALLOCALLNODES");
552     if (attr & RPC_FC_P_DONTFREE)
553         TRACE(" RPC_FC_P_DONTFREE");
554     if (attr & RPC_FC_P_ONSTACK)
555         TRACE(" RPC_FC_P_ONSTACK");
556     if (attr & RPC_FC_P_SIMPLEPOINTER)
557         TRACE(" RPC_FC_P_SIMPLEPOINTER");
558     if (attr & RPC_FC_P_DEREF)
559         TRACE(" RPC_FC_P_DEREF");
560     TRACE("\n");
561 }
562
563 /***********************************************************************
564  *           PointerMarshall
565  */
566 void WINAPI PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
567                             unsigned char *Buffer,
568                             unsigned char *Pointer,
569                             PFORMAT_STRING pFormat)
570 {
571   unsigned type = pFormat[0], attr = pFormat[1];
572   PFORMAT_STRING desc;
573   NDR_MARSHALL m;
574
575   TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat);
576   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
577   pFormat += 2;
578   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
579   else desc = pFormat + *(const SHORT*)pFormat;
580   if (attr & RPC_FC_P_DEREF) {
581     Pointer = *(unsigned char**)Pointer;
582     TRACE("deref => %p\n", Pointer);
583   }
584
585   switch (type) {
586   case RPC_FC_RP: /* ref pointer (always non-null) */
587 #if 0 /* this causes problems for InstallShield so is disabled - we need more tests */
588     if (!Pointer)
589       RpcRaiseException(RPC_X_NULL_REF_POINTER);
590 #endif
591     break;
592   case RPC_FC_UP: /* unique pointer */
593   case RPC_FC_OP: /* object pointer - same as unique here */
594     TRACE("writing %p to buffer\n", Pointer);
595     NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, (unsigned long)Pointer);
596     pStubMsg->Buffer += 4;
597     break;
598   case RPC_FC_FP:
599   default:
600     FIXME("unhandled ptr type=%02x\n", type);
601     RpcRaiseException(RPC_X_BAD_STUB_DATA);
602   }
603
604   TRACE("calling marshaller for type 0x%x\n", (int)*desc);
605
606   if (Pointer) {
607     m = NdrMarshaller[*desc & NDR_TABLE_MASK];
608     if (m) m(pStubMsg, Pointer, desc);
609     else FIXME("no marshaller for data type=%02x\n", *desc);
610   }
611
612   STD_OVERFLOW_CHECK(pStubMsg);
613 }
614
615 /***********************************************************************
616  *           PointerUnmarshall
617  */
618 void WINAPI PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
619                               unsigned char *Buffer,
620                               unsigned char **pPointer,
621                               PFORMAT_STRING pFormat,
622                               unsigned char fMustAlloc)
623 {
624   unsigned type = pFormat[0], attr = pFormat[1];
625   PFORMAT_STRING desc;
626   NDR_UNMARSHALL m;
627   DWORD pointer_id = 0;
628
629   TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc);
630   TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
631   pFormat += 2;
632   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
633   else desc = pFormat + *(const SHORT*)pFormat;
634   if (attr & RPC_FC_P_DEREF) {
635     pPointer = *(unsigned char***)pPointer;
636     TRACE("deref => %p\n", pPointer);
637   }
638
639   switch (type) {
640   case RPC_FC_RP: /* ref pointer (always non-null) */
641     pointer_id = ~0UL;
642     break;
643   case RPC_FC_UP: /* unique pointer */
644     pointer_id = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer);
645     pStubMsg->Buffer += 4;
646     break;
647   case RPC_FC_OP: /* object pointer - we must free data before overwriting it */
648   case RPC_FC_FP:
649   default:
650     FIXME("unhandled ptr type=%02x\n", type);
651     RpcRaiseException(RPC_X_BAD_STUB_DATA);
652   }
653
654   *pPointer = NULL;
655
656   if (pointer_id) {
657     m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
658     if (m) m(pStubMsg, pPointer, desc, fMustAlloc);
659     else FIXME("no unmarshaller for data type=%02x\n", *desc);
660   }
661
662   TRACE("pointer=%p\n", *pPointer);
663 }
664
665 /***********************************************************************
666  *           PointerBufferSize
667  */
668 void WINAPI PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
669                               unsigned char *Pointer,
670                               PFORMAT_STRING pFormat)
671 {
672   unsigned type = pFormat[0], attr = pFormat[1];
673   PFORMAT_STRING desc;
674   NDR_BUFFERSIZE m;
675
676   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
677   TRACE("type=%d, attr=%d\n", type, attr);
678   pFormat += 2;
679   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
680   else desc = pFormat + *(const SHORT*)pFormat;
681   if (attr & RPC_FC_P_DEREF) {
682     Pointer = *(unsigned char**)Pointer;
683     TRACE("deref => %p\n", Pointer);
684   }
685
686   switch (type) {
687   case RPC_FC_RP: /* ref pointer (always non-null) */
688     break;
689   case RPC_FC_OP:
690   case RPC_FC_UP:
691     pStubMsg->BufferLength += 4;
692     /* NULL pointer has no further representation */
693     if (!Pointer)
694         return;
695     break;
696   case RPC_FC_FP:
697   default:
698     FIXME("unhandled ptr type=%02x\n", type);
699     RpcRaiseException(RPC_X_BAD_STUB_DATA);
700   }
701
702   m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
703   if (m) m(pStubMsg, Pointer, desc);
704   else FIXME("no buffersizer for data type=%02x\n", *desc);
705 }
706
707 /***********************************************************************
708  *           PointerMemorySize [RPCRT4.@]
709  */
710 unsigned long WINAPI PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
711                                        unsigned char *Buffer,
712                                        PFORMAT_STRING pFormat)
713 {
714   unsigned type = pFormat[0], attr = pFormat[1];
715   PFORMAT_STRING desc;
716   NDR_MEMORYSIZE m;
717
718   FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat);
719   TRACE("type=%d, attr=", type); dump_pointer_attr(attr);
720   pFormat += 2;
721   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
722   else desc = pFormat + *(const SHORT*)pFormat;
723   if (attr & RPC_FC_P_DEREF) {
724     TRACE("deref\n");
725   }
726
727   switch (type) {
728   case RPC_FC_RP: /* ref pointer (always non-null) */
729     break;
730   default:
731     FIXME("unhandled ptr type=%02x\n", type);
732     RpcRaiseException(RPC_X_BAD_STUB_DATA);
733   }
734
735   m = NdrMemorySizer[*desc & NDR_TABLE_MASK];
736   if (m) m(pStubMsg, desc);
737   else FIXME("no memorysizer for data type=%02x\n", *desc);
738
739   return 0;
740 }
741
742 /***********************************************************************
743  *           PointerFree [RPCRT4.@]
744  */
745 void WINAPI PointerFree(PMIDL_STUB_MESSAGE pStubMsg,
746                         unsigned char *Pointer,
747                         PFORMAT_STRING pFormat)
748 {
749   unsigned type = pFormat[0], attr = pFormat[1];
750   PFORMAT_STRING desc;
751   NDR_FREE m;
752
753   TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat);
754   TRACE("type=%d, attr=", type); dump_pointer_attr(attr);
755   if (attr & RPC_FC_P_DONTFREE) return;
756   pFormat += 2;
757   if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat;
758   else desc = pFormat + *(const SHORT*)pFormat;
759   if (attr & RPC_FC_P_DEREF) {
760     Pointer = *(unsigned char**)Pointer;
761     TRACE("deref => %p\n", Pointer);
762   }
763
764   if (!Pointer) return;
765
766   m = NdrFreer[*desc & NDR_TABLE_MASK];
767   if (m) m(pStubMsg, Pointer, desc);
768
769   /* hmm... is this sensible?
770    * perhaps we should check if the memory comes from NdrAllocate,
771    * and deallocate only if so - checking if the pointer is between
772    * BufferStart and BufferEnd is probably no good since the buffer
773    * may be reallocated when the server wants to marshal the reply */
774   switch (*desc) {
775   case RPC_FC_BOGUS_STRUCT:
776   case RPC_FC_BOGUS_ARRAY:
777   case RPC_FC_USER_MARSHAL:
778     break;
779   default:
780     FIXME("unhandled data type=%02x\n", *desc);
781   case RPC_FC_CARRAY:
782   case RPC_FC_C_CSTRING:
783   case RPC_FC_C_WSTRING:
784     if (pStubMsg->ReuseBuffer) goto notfree;
785     break;
786   case RPC_FC_IP:
787     goto notfree;
788   }
789
790   if (attr & RPC_FC_P_ONSTACK) {
791     TRACE("not freeing stack ptr %p\n", Pointer);
792     return;
793   }
794   TRACE("freeing %p\n", Pointer);
795   NdrFree(pStubMsg, Pointer);
796   return;
797 notfree:
798   TRACE("not freeing %p\n", Pointer);
799 }
800
801 /***********************************************************************
802  *           EmbeddedPointerMarshall
803  */
804 unsigned char * WINAPI EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
805                                                unsigned char *pMemory,
806                                                PFORMAT_STRING pFormat)
807 {
808   unsigned char *Mark = pStubMsg->BufferMark;
809   unsigned long Offset = pStubMsg->Offset;
810   unsigned ofs, rep, count, stride, xofs;
811
812   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
813
814   if (*pFormat != RPC_FC_PP) return NULL;
815   pFormat += 2;
816
817   while (pFormat[0] != RPC_FC_END) {
818     switch (pFormat[0]) {
819     default:
820       FIXME("unknown repeat type %d\n", pFormat[0]);
821     case RPC_FC_NO_REPEAT:
822       rep = 1;
823       stride = 0;
824       ofs = 0;
825       count = 1;
826       xofs = 0;
827       pFormat += 2;
828       break;
829     case RPC_FC_FIXED_REPEAT:
830       rep = *(const WORD*)&pFormat[2];
831       stride = *(const WORD*)&pFormat[4];
832       ofs = *(const WORD*)&pFormat[6];
833       count = *(const WORD*)&pFormat[8];
834       xofs = 0;
835       pFormat += 10;
836       break;
837     case RPC_FC_VARIABLE_REPEAT:
838       rep = pStubMsg->MaxCount;
839       stride = *(const WORD*)&pFormat[2];
840       ofs = *(const WORD*)&pFormat[4];
841       count = *(const WORD*)&pFormat[6];
842       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
843       pFormat += 8;
844       break;
845     }
846     /* ofs doesn't seem to matter in this context */
847     while (rep) {
848       PFORMAT_STRING info = pFormat;
849       unsigned char *membase = pMemory + xofs;
850       unsigned u;
851       for (u=0; u<count; u++,info+=8) {
852         unsigned char *memptr = membase + *(const SHORT*)&info[0];
853         unsigned char *bufptr = Mark + *(const SHORT*)&info[2];
854         PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4);
855       }
856       rep--;
857     }
858     pFormat += 8 * count;
859   }
860
861   STD_OVERFLOW_CHECK(pStubMsg);
862
863   return NULL;
864 }
865
866 /***********************************************************************
867  *           EmbeddedPointerUnmarshall
868  */
869 unsigned char * WINAPI EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
870                                                  unsigned char **ppMemory,
871                                                  PFORMAT_STRING pFormat,
872                                                  unsigned char fMustAlloc)
873 {
874   unsigned char *Mark = pStubMsg->BufferMark;
875   unsigned long Offset = pStubMsg->Offset;
876   unsigned ofs, rep, count, stride, xofs;
877
878   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
879
880   if (*pFormat != RPC_FC_PP) return NULL;
881   pFormat += 2;
882
883   while (pFormat[0] != RPC_FC_END) {
884     switch (pFormat[0]) {
885     default:
886       FIXME("unknown repeat type %d\n", pFormat[0]);
887     case RPC_FC_NO_REPEAT:
888       rep = 1;
889       stride = 0;
890       ofs = 0;
891       count = 1;
892       xofs = 0;
893       pFormat += 2;
894       break;
895     case RPC_FC_FIXED_REPEAT:
896       rep = *(const WORD*)&pFormat[2];
897       stride = *(const WORD*)&pFormat[4];
898       ofs = *(const WORD*)&pFormat[6];
899       count = *(const WORD*)&pFormat[8];
900       xofs = 0;
901       pFormat += 10;
902       break;
903     case RPC_FC_VARIABLE_REPEAT:
904       rep = pStubMsg->MaxCount;
905       stride = *(const WORD*)&pFormat[2];
906       ofs = *(const WORD*)&pFormat[4];
907       count = *(const WORD*)&pFormat[6];
908       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
909       pFormat += 8;
910       break;
911     }
912     /* ofs doesn't seem to matter in this context */
913     while (rep) {
914       PFORMAT_STRING info = pFormat;
915       unsigned char *membase = *ppMemory + xofs;
916       unsigned u;
917       for (u=0; u<count; u++,info+=8) {
918         unsigned char *memptr = membase + *(const SHORT*)&info[0];
919         unsigned char *bufptr = Mark + *(const SHORT*)&info[2];
920         PointerUnmarshall(pStubMsg, bufptr, (unsigned char**)memptr, info+4, fMustAlloc);
921       }
922       rep--;
923     }
924     pFormat += 8 * count;
925   }
926
927   return NULL;
928 }
929
930 /***********************************************************************
931  *           EmbeddedPointerBufferSize
932  */
933 void WINAPI EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
934                                       unsigned char *pMemory,
935                                       PFORMAT_STRING pFormat)
936 {
937   unsigned long Offset = pStubMsg->Offset;
938   unsigned ofs, rep, count, stride, xofs;
939
940   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
941   if (*pFormat != RPC_FC_PP) return;
942   pFormat += 2;
943
944   while (pFormat[0] != RPC_FC_END) {
945     switch (pFormat[0]) {
946     default:
947       FIXME("unknown repeat type %d\n", pFormat[0]);
948     case RPC_FC_NO_REPEAT:
949       rep = 1;
950       stride = 0;
951       ofs = 0;
952       count = 1;
953       xofs = 0;
954       pFormat += 2;
955       break;
956     case RPC_FC_FIXED_REPEAT:
957       rep = *(const WORD*)&pFormat[2];
958       stride = *(const WORD*)&pFormat[4];
959       ofs = *(const WORD*)&pFormat[6];
960       count = *(const WORD*)&pFormat[8];
961       xofs = 0;
962       pFormat += 10;
963       break;
964     case RPC_FC_VARIABLE_REPEAT:
965       rep = pStubMsg->MaxCount;
966       stride = *(const WORD*)&pFormat[2];
967       ofs = *(const WORD*)&pFormat[4];
968       count = *(const WORD*)&pFormat[6];
969       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
970       pFormat += 8;
971       break;
972     }
973     /* ofs doesn't seem to matter in this context */
974     while (rep) {
975       PFORMAT_STRING info = pFormat;
976       unsigned char *membase = pMemory + xofs;
977       unsigned u;
978       for (u=0; u<count; u++,info+=8) {
979         unsigned char *memptr = membase + *(const SHORT*)&info[0];
980         PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4);
981       }
982       rep--;
983     }
984     pFormat += 8 * count;
985   }
986 }
987
988 /***********************************************************************
989  *           EmbeddedPointerMemorySize
990  */
991 unsigned long WINAPI EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
992                                                PFORMAT_STRING pFormat)
993 {
994   unsigned long Offset = pStubMsg->Offset;
995   unsigned char *Mark = pStubMsg->BufferMark;
996   unsigned ofs, rep, count, stride, xofs;
997
998   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
999   if (*pFormat != RPC_FC_PP) return 0;
1000   pFormat += 2;
1001
1002   while (pFormat[0] != RPC_FC_END) {
1003     switch (pFormat[0]) {
1004     default:
1005       FIXME("unknown repeat type %d\n", pFormat[0]);
1006     case RPC_FC_NO_REPEAT:
1007       rep = 1;
1008       stride = 0;
1009       ofs = 0;
1010       count = 1;
1011       xofs = 0;
1012       pFormat += 2;
1013       break;
1014     case RPC_FC_FIXED_REPEAT:
1015       rep = *(const WORD*)&pFormat[2];
1016       stride = *(const WORD*)&pFormat[4];
1017       ofs = *(const WORD*)&pFormat[6];
1018       count = *(const WORD*)&pFormat[8];
1019       xofs = 0;
1020       pFormat += 10;
1021       break;
1022     case RPC_FC_VARIABLE_REPEAT:
1023       rep = pStubMsg->MaxCount;
1024       stride = *(const WORD*)&pFormat[2];
1025       ofs = *(const WORD*)&pFormat[4];
1026       count = *(const WORD*)&pFormat[6];
1027       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1028       pFormat += 8;
1029       break;
1030     }
1031     /* ofs doesn't seem to matter in this context */
1032     while (rep) {
1033       PFORMAT_STRING info = pFormat;
1034       unsigned u;
1035       for (u=0; u<count; u++,info+=8) {
1036         unsigned char *bufptr = Mark + *(const SHORT*)&info[2];
1037         PointerMemorySize(pStubMsg, bufptr, info+4);
1038       }
1039       rep--;
1040     }
1041     pFormat += 8 * count;
1042   }
1043
1044   return 0;
1045 }
1046
1047 /***********************************************************************
1048  *           EmbeddedPointerFree
1049  */
1050 void WINAPI EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1051                                 unsigned char *pMemory,
1052                                 PFORMAT_STRING pFormat)
1053 {
1054   unsigned long Offset = pStubMsg->Offset;
1055   unsigned ofs, rep, count, stride, xofs;
1056
1057   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1058   if (*pFormat != RPC_FC_PP) return;
1059   pFormat += 2;
1060
1061   while (pFormat[0] != RPC_FC_END) {
1062     switch (pFormat[0]) {
1063     default:
1064       FIXME("unknown repeat type %d\n", pFormat[0]);
1065     case RPC_FC_NO_REPEAT:
1066       rep = 1;
1067       stride = 0;
1068       ofs = 0;
1069       count = 1;
1070       xofs = 0;
1071       pFormat += 2;
1072       break;
1073     case RPC_FC_FIXED_REPEAT:
1074       rep = *(const WORD*)&pFormat[2];
1075       stride = *(const WORD*)&pFormat[4];
1076       ofs = *(const WORD*)&pFormat[6];
1077       count = *(const WORD*)&pFormat[8];
1078       xofs = 0;
1079       pFormat += 10;
1080       break;
1081     case RPC_FC_VARIABLE_REPEAT:
1082       rep = pStubMsg->MaxCount;
1083       stride = *(const WORD*)&pFormat[2];
1084       ofs = *(const WORD*)&pFormat[4];
1085       count = *(const WORD*)&pFormat[6];
1086       xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
1087       pFormat += 8;
1088       break;
1089     }
1090     /* ofs doesn't seem to matter in this context */
1091     while (rep) {
1092       PFORMAT_STRING info = pFormat;
1093       unsigned char *membase = pMemory + xofs;
1094       unsigned u;
1095       for (u=0; u<count; u++,info+=8) {
1096         unsigned char *memptr = membase + *(const SHORT*)&info[0];
1097         PointerFree(pStubMsg, *(unsigned char**)memptr, info+4);
1098       }
1099       rep--;
1100     }
1101     pFormat += 8 * count;
1102   }
1103 }
1104
1105 /***********************************************************************
1106  *           NdrPointerMarshall [RPCRT4.@]
1107  */
1108 unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1109                                           unsigned char *pMemory,
1110                                           PFORMAT_STRING pFormat)
1111 {
1112   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1113
1114   pStubMsg->BufferMark = pStubMsg->Buffer;
1115   PointerMarshall(pStubMsg, pStubMsg->Buffer, pMemory, pFormat);
1116
1117   STD_OVERFLOW_CHECK(pStubMsg);
1118
1119   return NULL;
1120 }
1121
1122 /***********************************************************************
1123  *           NdrPointerUnmarshall [RPCRT4.@]
1124  */
1125 unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1126                                             unsigned char **ppMemory,
1127                                             PFORMAT_STRING pFormat,
1128                                             unsigned char fMustAlloc)
1129 {
1130   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1131
1132   pStubMsg->BufferMark = pStubMsg->Buffer;
1133   PointerUnmarshall(pStubMsg, pStubMsg->Buffer, ppMemory, pFormat, fMustAlloc);
1134
1135   return NULL;
1136 }
1137
1138 /***********************************************************************
1139  *           NdrPointerBufferSize [RPCRT4.@]
1140  */
1141 void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1142                                       unsigned char *pMemory,
1143                                       PFORMAT_STRING pFormat)
1144 {
1145   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1146   PointerBufferSize(pStubMsg, pMemory, pFormat);
1147 }
1148
1149 /***********************************************************************
1150  *           NdrPointerMemorySize [RPCRT4.@]
1151  */
1152 unsigned long WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1153                                           PFORMAT_STRING pFormat)
1154 {
1155   /* unsigned size = *(LPWORD)(pFormat+2); */
1156   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1157   PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat);
1158   return 0;
1159 }
1160
1161 /***********************************************************************
1162  *           NdrPointerFree [RPCRT4.@]
1163  */
1164 void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
1165                            unsigned char *pMemory,
1166                            PFORMAT_STRING pFormat)
1167 {
1168   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1169   PointerFree(pStubMsg, pMemory, pFormat);
1170 }
1171
1172 /***********************************************************************
1173  *           NdrSimpleStructMarshall [RPCRT4.@]
1174  */
1175 unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1176                                                unsigned char *pMemory,
1177                                                PFORMAT_STRING pFormat)
1178 {
1179   unsigned size = *(const WORD*)(pFormat+2);
1180   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1181
1182   memcpy(pStubMsg->Buffer, pMemory, size);
1183   pStubMsg->BufferMark = pStubMsg->Buffer;
1184   pStubMsg->Buffer += size;
1185
1186   if (pFormat[0] != RPC_FC_STRUCT)
1187     EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4);
1188
1189   STD_OVERFLOW_CHECK(pStubMsg);
1190
1191   return NULL;
1192 }
1193
1194 /***********************************************************************
1195  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1196  */
1197 unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1198                                                  unsigned char **ppMemory,
1199                                                  PFORMAT_STRING pFormat,
1200                                                  unsigned char fMustAlloc)
1201 {
1202   unsigned size = *(const WORD*)(pFormat+2);
1203   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1204
1205   if (fMustAlloc) {
1206     *ppMemory = NdrAllocate(pStubMsg, size);
1207     memcpy(*ppMemory, pStubMsg->Buffer, size);
1208   } else {
1209     if (pStubMsg->ReuseBuffer && !*ppMemory)
1210       /* for servers, we may just point straight into the RPC buffer, I think
1211        * (I guess that's what MS does since MIDL code doesn't try to free) */
1212       *ppMemory = pStubMsg->Buffer;
1213     else
1214       /* for clients, memory should be provided by caller */
1215       memcpy(*ppMemory, pStubMsg->Buffer, size);
1216   }
1217
1218   pStubMsg->BufferMark = pStubMsg->Buffer;
1219   pStubMsg->Buffer += size;
1220
1221   if (pFormat[0] != RPC_FC_STRUCT)
1222     EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc);
1223
1224   return NULL;
1225 }
1226
1227
1228 /***********************************************************************
1229  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1230  */
1231 void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1232                                    unsigned char FormatChar )
1233 {
1234     FIXME("stub\n");
1235 }
1236
1237
1238 /***********************************************************************
1239  *           NdrSimpleStructUnmarshall [RPCRT4.@]
1240  */
1241 void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory,
1242                                      unsigned char FormatChar )
1243 {
1244     FIXME("stub\n");
1245 }
1246
1247
1248 /***********************************************************************
1249  *           NdrSimpleStructBufferSize [RPCRT4.@]
1250  */
1251 void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1252                                       unsigned char *pMemory,
1253                                       PFORMAT_STRING pFormat)
1254 {
1255   unsigned size = *(const WORD*)(pFormat+2);
1256   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1257   pStubMsg->BufferLength += size;
1258   if (pFormat[0] != RPC_FC_STRUCT)
1259     EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4);
1260 }
1261
1262 /***********************************************************************
1263  *           NdrSimpleStructMemorySize [RPCRT4.@]
1264  */
1265 unsigned long WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1266                                                PFORMAT_STRING pFormat)
1267 {
1268   /* unsigned size = *(LPWORD)(pFormat+2); */
1269   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1270   if (pFormat[0] != RPC_FC_STRUCT)
1271     EmbeddedPointerMemorySize(pStubMsg, pFormat+4);
1272   return 0;
1273 }
1274
1275 /***********************************************************************
1276  *           NdrSimpleStructFree [RPCRT4.@]
1277  */
1278 void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1279                                 unsigned char *pMemory,
1280                                 PFORMAT_STRING pFormat)
1281 {
1282   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1283   if (pFormat[0] != RPC_FC_STRUCT)
1284     EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4);
1285 }
1286
1287
1288 unsigned long WINAPI EmbeddedComplexSize(PMIDL_STUB_MESSAGE pStubMsg,
1289                                          PFORMAT_STRING pFormat)
1290 {
1291   switch (*pFormat) {
1292   case RPC_FC_STRUCT:
1293   case RPC_FC_PSTRUCT:
1294   case RPC_FC_CSTRUCT:
1295   case RPC_FC_BOGUS_STRUCT:
1296     return *(const WORD*)&pFormat[2];
1297   case RPC_FC_USER_MARSHAL:
1298     return *(const WORD*)&pFormat[4];
1299   default:
1300     FIXME("unhandled embedded type %02x\n", *pFormat);
1301   }
1302   return 0;
1303 }
1304
1305
1306 unsigned char * WINAPI ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1307                                        unsigned char *pMemory,
1308                                        PFORMAT_STRING pFormat,
1309                                        PFORMAT_STRING pPointer)
1310 {
1311   PFORMAT_STRING desc;
1312   NDR_MARSHALL m;
1313   unsigned long size;
1314
1315   while (*pFormat != RPC_FC_END) {
1316     switch (*pFormat) {
1317     case RPC_FC_SHORT:
1318     case RPC_FC_USHORT:
1319       TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory);
1320       memcpy(pStubMsg->Buffer, pMemory, 2);
1321       pStubMsg->Buffer += 2;
1322       pMemory += 2;
1323       break;
1324     case RPC_FC_LONG:
1325     case RPC_FC_ULONG:
1326       TRACE("long=%ld <= %p\n", *(DWORD*)pMemory, pMemory);
1327       memcpy(pStubMsg->Buffer, pMemory, 4);
1328       pStubMsg->Buffer += 4;
1329       pMemory += 4;
1330       break;
1331     case RPC_FC_POINTER:
1332       TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory);
1333       NdrPointerMarshall(pStubMsg, *(unsigned char**)pMemory, pPointer);
1334       pPointer += 4;
1335       pMemory += 4;
1336       break;
1337     case RPC_FC_ALIGNM4:
1338       ALIGN_POINTER(pMemory, 3);
1339       break;
1340     case RPC_FC_ALIGNM8:
1341       ALIGN_POINTER(pMemory, 7);
1342       break;
1343     case RPC_FC_EMBEDDED_COMPLEX:
1344       pMemory += pFormat[1];
1345       pFormat += 2;
1346       desc = pFormat + *(const SHORT*)pFormat;
1347       size = EmbeddedComplexSize(pStubMsg, desc);
1348       TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory);
1349       m = NdrMarshaller[*desc & NDR_TABLE_MASK];
1350       if (m) m(pStubMsg, pMemory, desc);
1351       else FIXME("no marshaller for embedded type %02x\n", *desc);
1352       pMemory += size;
1353       pFormat += 2;
1354       continue;
1355     case RPC_FC_PAD:
1356       break;
1357     default:
1358       FIXME("unhandled format %02x\n", *pFormat);
1359     }
1360     pFormat++;
1361   }
1362
1363   return pMemory;
1364 }
1365
1366 unsigned char * WINAPI ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1367                                          unsigned char *pMemory,
1368                                          PFORMAT_STRING pFormat,
1369                                          PFORMAT_STRING pPointer,
1370                                          unsigned char fMustAlloc)
1371 {
1372   PFORMAT_STRING desc;
1373   NDR_UNMARSHALL m;
1374   unsigned long size;
1375
1376   while (*pFormat != RPC_FC_END) {
1377     switch (*pFormat) {
1378     case RPC_FC_SHORT:
1379     case RPC_FC_USHORT:
1380       memcpy(pMemory, pStubMsg->Buffer, 2);
1381       TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory);
1382       pStubMsg->Buffer += 2;
1383       pMemory += 2;
1384       break;
1385     case RPC_FC_LONG:
1386     case RPC_FC_ULONG:
1387       memcpy(pMemory, pStubMsg->Buffer, 4);
1388       TRACE("long=%ld => %p\n", *(DWORD*)pMemory, pMemory);
1389       pStubMsg->Buffer += 4;
1390       pMemory += 4;
1391       break;
1392     case RPC_FC_POINTER:
1393       *(unsigned char**)pMemory = NULL;
1394       TRACE("pointer => %p\n", pMemory);
1395       NdrPointerUnmarshall(pStubMsg, (unsigned char**)pMemory, pPointer, fMustAlloc);
1396       pPointer += 4;
1397       pMemory += 4;
1398       break;
1399     case RPC_FC_ALIGNM4:
1400       ALIGN_POINTER(pMemory, 3);
1401       break;
1402     case RPC_FC_ALIGNM8:
1403       ALIGN_POINTER(pMemory, 7);
1404       break;
1405     case RPC_FC_EMBEDDED_COMPLEX:
1406       pMemory += pFormat[1];
1407       pFormat += 2;
1408       desc = pFormat + *(const SHORT*)pFormat;
1409       size = EmbeddedComplexSize(pStubMsg, desc);
1410       TRACE("embedded complex (size=%ld) => %p\n", size, pMemory);
1411       m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
1412       memset(pMemory, 0, size); /* just in case */
1413       if (m) m(pStubMsg, &pMemory, desc, fMustAlloc);
1414       else FIXME("no unmarshaller for embedded type %02x\n", *desc);
1415       pMemory += size;
1416       pFormat += 2;
1417       continue;
1418     case RPC_FC_PAD:
1419       break;
1420     default:
1421       FIXME("unhandled format %d\n", *pFormat);
1422     }
1423     pFormat++;
1424   }
1425
1426   return pMemory;
1427 }
1428
1429 unsigned char * WINAPI ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1430                                          unsigned char *pMemory,
1431                                          PFORMAT_STRING pFormat,
1432                                          PFORMAT_STRING pPointer)
1433 {
1434   PFORMAT_STRING desc;
1435   NDR_BUFFERSIZE m;
1436   unsigned long size;
1437
1438   while (*pFormat != RPC_FC_END) {
1439     switch (*pFormat) {
1440     case RPC_FC_SHORT:
1441     case RPC_FC_USHORT:
1442       pStubMsg->BufferLength += 2;
1443       pMemory += 2;
1444       break;
1445     case RPC_FC_LONG:
1446     case RPC_FC_ULONG:
1447       pStubMsg->BufferLength += 4;
1448       pMemory += 4;
1449       break;
1450     case RPC_FC_POINTER:
1451       NdrPointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer);
1452       pPointer += 4;
1453       pMemory += 4;
1454       break;
1455     case RPC_FC_ALIGNM4:
1456       ALIGN_POINTER(pMemory, 3);
1457       break;
1458     case RPC_FC_ALIGNM8:
1459       ALIGN_POINTER(pMemory, 7);
1460       break;
1461     case RPC_FC_EMBEDDED_COMPLEX:
1462       pMemory += pFormat[1];
1463       pFormat += 2;
1464       desc = pFormat + *(const SHORT*)pFormat;
1465       size = EmbeddedComplexSize(pStubMsg, desc);
1466       m = NdrBufferSizer[*desc & NDR_TABLE_MASK];
1467       if (m) m(pStubMsg, pMemory, desc);
1468       else FIXME("no buffersizer for embedded type %02x\n", *desc);
1469       pMemory += size;
1470       pFormat += 2;
1471       continue;
1472     case RPC_FC_PAD:
1473       break;
1474     default:
1475       FIXME("unhandled format %d\n", *pFormat);
1476     }
1477     pFormat++;
1478   }
1479
1480   return pMemory;
1481 }
1482
1483 unsigned char * WINAPI ComplexFree(PMIDL_STUB_MESSAGE pStubMsg,
1484                                    unsigned char *pMemory,
1485                                    PFORMAT_STRING pFormat,
1486                                    PFORMAT_STRING pPointer)
1487 {
1488   PFORMAT_STRING desc;
1489   NDR_FREE m;
1490   unsigned long size;
1491
1492   while (*pFormat != RPC_FC_END) {
1493     switch (*pFormat) {
1494     case RPC_FC_SHORT:
1495     case RPC_FC_USHORT:
1496       pMemory += 2;
1497       break;
1498     case RPC_FC_LONG:
1499     case RPC_FC_ULONG:
1500       pMemory += 4;
1501       break;
1502     case RPC_FC_POINTER:
1503       NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer);
1504       pPointer += 4;
1505       pMemory += 4;
1506       break;
1507     case RPC_FC_ALIGNM4:
1508       ALIGN_POINTER(pMemory, 3);
1509       break;
1510     case RPC_FC_ALIGNM8:
1511       ALIGN_POINTER(pMemory, 7);
1512       break;
1513     case RPC_FC_EMBEDDED_COMPLEX:
1514       pMemory += pFormat[1];
1515       pFormat += 2;
1516       desc = pFormat + *(const SHORT*)pFormat;
1517       size = EmbeddedComplexSize(pStubMsg, desc);
1518       m = NdrFreer[*desc & NDR_TABLE_MASK];
1519       if (m) m(pStubMsg, pMemory, desc);
1520       else FIXME("no freer for embedded type %02x\n", *desc);
1521       pMemory += size;
1522       pFormat += 2;
1523       continue;
1524     case RPC_FC_PAD:
1525       break;
1526     default:
1527       FIXME("unhandled format %d\n", *pFormat);
1528     }
1529     pFormat++;
1530   }
1531
1532   return pMemory;
1533 }
1534
1535 unsigned long WINAPI ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg,
1536                                        PFORMAT_STRING pFormat)
1537 {
1538   PFORMAT_STRING desc;
1539   unsigned long size = 0;
1540
1541   while (*pFormat != RPC_FC_END) {
1542     switch (*pFormat) {
1543     case RPC_FC_SHORT:
1544     case RPC_FC_USHORT:
1545       size += 2;
1546       break;
1547     case RPC_FC_LONG:
1548     case RPC_FC_ULONG:
1549       size += 4;
1550       break;
1551     case RPC_FC_POINTER:
1552       size += 4;
1553       break;
1554     case RPC_FC_ALIGNM4:
1555       ALIGN_LENGTH(size, 3);
1556       break;
1557     case RPC_FC_ALIGNM8:
1558       ALIGN_LENGTH(size, 7);
1559       break;
1560     case RPC_FC_EMBEDDED_COMPLEX:
1561       size += pFormat[1];
1562       pFormat += 2;
1563       desc = pFormat + *(const SHORT*)pFormat;
1564       size += EmbeddedComplexSize(pStubMsg, desc);
1565       pFormat += 2;
1566       continue;
1567     case RPC_FC_PAD:
1568       break;
1569     default:
1570       FIXME("unhandled format %d\n", *pFormat);
1571     }
1572     pFormat++;
1573   }
1574
1575   return size;
1576 }
1577
1578 /***********************************************************************
1579  *           NdrComplexStructMarshall [RPCRT4.@]
1580  */
1581 unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1582                                                 unsigned char *pMemory,
1583                                                 PFORMAT_STRING pFormat)
1584 {
1585   PFORMAT_STRING conf_array = NULL;
1586   PFORMAT_STRING pointer_desc = NULL;
1587   unsigned char *OldMemory = pStubMsg->Memory;
1588
1589   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1590
1591   pFormat += 4;
1592   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1593   pFormat += 2;
1594   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1595   pFormat += 2;
1596
1597   pStubMsg->Memory = pMemory;
1598
1599   ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc);
1600
1601   if (conf_array)
1602     NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array);
1603
1604   pStubMsg->Memory = OldMemory;
1605
1606   STD_OVERFLOW_CHECK(pStubMsg);
1607
1608   return NULL;
1609 }
1610
1611 /***********************************************************************
1612  *           NdrComplexStructUnmarshall [RPCRT4.@]
1613  */
1614 unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1615                                                   unsigned char **ppMemory,
1616                                                   PFORMAT_STRING pFormat,
1617                                                   unsigned char fMustAlloc)
1618 {
1619   unsigned size = *(const WORD*)(pFormat+2);
1620   PFORMAT_STRING conf_array = NULL;
1621   PFORMAT_STRING pointer_desc = NULL;
1622   unsigned char *pMemory;
1623
1624   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1625
1626   if (fMustAlloc || !*ppMemory)
1627     *ppMemory = NdrAllocate(pStubMsg, size);
1628
1629   pFormat += 4;
1630   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1631   pFormat += 2;
1632   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1633   pFormat += 2;
1634
1635   pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc, fMustAlloc);
1636
1637   if (conf_array)
1638     NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc);
1639
1640   return NULL;
1641 }
1642
1643 /***********************************************************************
1644  *           NdrComplexStructBufferSize [RPCRT4.@]
1645  */
1646 void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1647                                        unsigned char *pMemory,
1648                                        PFORMAT_STRING pFormat)
1649 {
1650   PFORMAT_STRING conf_array = NULL;
1651   PFORMAT_STRING pointer_desc = NULL;
1652   unsigned char *OldMemory = pStubMsg->Memory;
1653
1654   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1655
1656   pFormat += 4;
1657   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1658   pFormat += 2;
1659   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1660   pFormat += 2;
1661
1662   pStubMsg->Memory = pMemory;
1663
1664   pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc);
1665
1666   if (conf_array)
1667     NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array);
1668
1669   pStubMsg->Memory = OldMemory;
1670 }
1671
1672 /***********************************************************************
1673  *           NdrComplexStructMemorySize [RPCRT4.@]
1674  */
1675 unsigned long WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1676                                                 PFORMAT_STRING pFormat)
1677 {
1678   /* unsigned size = *(LPWORD)(pFormat+2); */
1679   PFORMAT_STRING conf_array = NULL;
1680   PFORMAT_STRING pointer_desc = NULL;
1681
1682   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1683
1684   pFormat += 4;
1685   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1686   pFormat += 2;
1687   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1688   pFormat += 2;
1689
1690   return 0;
1691 }
1692
1693 /***********************************************************************
1694  *           NdrComplexStructFree [RPCRT4.@]
1695  */
1696 void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg,
1697                                  unsigned char *pMemory,
1698                                  PFORMAT_STRING pFormat)
1699 {
1700   PFORMAT_STRING conf_array = NULL;
1701   PFORMAT_STRING pointer_desc = NULL;
1702   unsigned char *OldMemory = pStubMsg->Memory;
1703
1704   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1705
1706   pFormat += 4;
1707   if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat;
1708   pFormat += 2;
1709   if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat;
1710   pFormat += 2;
1711
1712   pStubMsg->Memory = pMemory;
1713
1714   pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc);
1715
1716   if (conf_array)
1717     NdrConformantArrayFree(pStubMsg, pMemory, conf_array);
1718
1719   pStubMsg->Memory = OldMemory;
1720 }
1721
1722 /***********************************************************************
1723  *           NdrConformantArrayMarshall [RPCRT4.@]
1724  */
1725 unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1726                                                   unsigned char *pMemory,
1727                                                   PFORMAT_STRING pFormat)
1728 {
1729   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
1730   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1731   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1732
1733   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1734   size = pStubMsg->MaxCount;
1735
1736   NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, size);
1737   pStubMsg->Buffer += 4;
1738
1739   memcpy(pStubMsg->Buffer, pMemory, size*esize);
1740   pStubMsg->BufferMark = pStubMsg->Buffer;
1741   pStubMsg->Buffer += size*esize;
1742
1743   EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat);
1744
1745   STD_OVERFLOW_CHECK(pStubMsg);
1746
1747   return NULL;
1748 }
1749
1750 /***********************************************************************
1751  *           NdrConformantArrayUnmarshall [RPCRT4.@]
1752  */
1753 unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1754                                                     unsigned char **ppMemory,
1755                                                     PFORMAT_STRING pFormat,
1756                                                     unsigned char fMustAlloc)
1757 {
1758   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
1759   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1760   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1761
1762   pFormat = ReadConformance(pStubMsg, pFormat+4);
1763   size = pStubMsg->MaxCount;
1764
1765   if (fMustAlloc) {
1766     *ppMemory = NdrAllocate(pStubMsg, size*esize);
1767     memcpy(*ppMemory, pStubMsg->Buffer, size*esize);
1768   } else {
1769     if (pStubMsg->ReuseBuffer && !*ppMemory)
1770       /* for servers, we may just point straight into the RPC buffer, I think
1771        * (I guess that's what MS does since MIDL code doesn't try to free) */
1772       *ppMemory = pStubMsg->Buffer;
1773     else
1774       /* for clients, memory should be provided by caller */
1775       memcpy(*ppMemory, pStubMsg->Buffer, size*esize);
1776   }
1777
1778   pStubMsg->BufferMark = pStubMsg->Buffer;
1779   pStubMsg->Buffer += size*esize;
1780
1781   EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc);
1782
1783   return NULL;
1784 }
1785
1786 /***********************************************************************
1787  *           NdrConformantArrayBufferSize [RPCRT4.@]
1788  */
1789 void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1790                                          unsigned char *pMemory,
1791                                          PFORMAT_STRING pFormat)
1792 {
1793   DWORD size = 0, esize = *(const WORD*)(pFormat+2);
1794   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1795   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1796
1797   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0);
1798   size = pStubMsg->MaxCount;
1799
1800   pStubMsg->BufferLength += size*esize;
1801
1802   EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat);
1803 }
1804
1805 /***********************************************************************
1806  *           NdrConformantArrayMemorySize [RPCRT4.@]
1807  */
1808 unsigned long WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1809                                                   PFORMAT_STRING pFormat)
1810 {
1811   DWORD size = 0;
1812   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1813   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1814
1815   pFormat = ReadConformance(pStubMsg, pFormat+4);
1816   size = pStubMsg->MaxCount;
1817
1818   EmbeddedPointerMemorySize(pStubMsg, pFormat);
1819
1820   return 0;
1821 }
1822
1823 /***********************************************************************
1824  *           NdrConformantArrayFree [RPCRT4.@]
1825  */
1826 void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
1827                                    unsigned char *pMemory,
1828                                    PFORMAT_STRING pFormat)
1829 {
1830   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1831   if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]);
1832
1833   EmbeddedPointerFree(pStubMsg, pMemory, pFormat);
1834 }
1835
1836
1837 /***********************************************************************
1838  *           NdrConformantVaryingArrayMarshall  [RPCRT4.@]
1839  */
1840 unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg,
1841                                                          unsigned char* pMemory,
1842                                                          PFORMAT_STRING pFormat )
1843 {
1844     FIXME( "stub\n" );
1845     return NULL;
1846 }
1847
1848
1849 /***********************************************************************
1850  *           NdrConformantVaryingArrayUnmarshall  [RPCRT4.@]
1851  */
1852 unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg,
1853                                                            unsigned char** ppMemory,
1854                                                            PFORMAT_STRING pFormat,
1855                                                            unsigned char fMustAlloc )
1856 {
1857     FIXME( "stub\n" );
1858     return NULL;
1859 }
1860
1861
1862 /***********************************************************************
1863  *           NdrConformantVaryingArrayFree  [RPCRT4.@]
1864  */
1865 void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg,
1866                                            unsigned char* pMemory,
1867                                            PFORMAT_STRING pFormat )
1868 {
1869     FIXME( "stub\n" );
1870 }
1871
1872
1873 /***********************************************************************
1874  *           NdrConformantVaryingArrayBufferSize  [RPCRT4.@]
1875  */
1876 void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg,
1877                                                  unsigned char* pMemory, PFORMAT_STRING pFormat )
1878 {
1879     FIXME( "stub\n" );
1880 }
1881
1882
1883 /***********************************************************************
1884  *           NdrConformantVaryingArrayMemorySize  [RPCRT4.@]
1885  */
1886 unsigned long WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg,
1887                                                           PFORMAT_STRING pFormat )
1888 {
1889     FIXME( "stub\n" );
1890     return 0;
1891 }
1892
1893
1894 /***********************************************************************
1895  *           NdrComplexArrayMarshall [RPCRT4.@]
1896  */
1897 unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg,
1898                                                unsigned char *pMemory,
1899                                                PFORMAT_STRING pFormat)
1900 {
1901   DWORD size = 0, count, def;
1902   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1903
1904   def = *(const WORD*)&pFormat[2];
1905   pFormat += 4;
1906
1907   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
1908   size = pStubMsg->MaxCount;
1909   TRACE("conformance=%ld\n", size);
1910
1911   if (*(const DWORD*)pFormat != 0xffffffff)
1912     FIXME("compute variance\n");
1913   pFormat += 4;
1914
1915   NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, size);
1916   pStubMsg->Buffer += 4;
1917
1918   for (count=0; count<size; count++)
1919     pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL);
1920
1921   STD_OVERFLOW_CHECK(pStubMsg);
1922
1923   return NULL;
1924 }
1925
1926 /***********************************************************************
1927  *           NdrComplexArrayUnmarshall [RPCRT4.@]
1928  */
1929 unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
1930                                                  unsigned char **ppMemory,
1931                                                  PFORMAT_STRING pFormat,
1932                                                  unsigned char fMustAlloc)
1933 {
1934   DWORD size = 0, count, esize;
1935   unsigned char *pMemory;
1936   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
1937
1938   pFormat += 4;
1939
1940   pFormat = ReadConformance(pStubMsg, pFormat);
1941   size = pStubMsg->MaxCount;
1942   TRACE("conformance=%ld\n", size);
1943
1944   pFormat += 4;
1945
1946   esize = ComplexStructSize(pStubMsg, pFormat);
1947
1948   if (fMustAlloc || !*ppMemory)
1949     *ppMemory = NdrAllocate(pStubMsg, size*esize);
1950
1951   pMemory = *ppMemory;
1952   for (count=0; count<size; count++)
1953     pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc);
1954
1955   return NULL;
1956 }
1957
1958 /***********************************************************************
1959  *           NdrComplexArrayBufferSize [RPCRT4.@]
1960  */
1961 void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
1962                                       unsigned char *pMemory,
1963                                       PFORMAT_STRING pFormat)
1964 {
1965   DWORD size = 0, count, def;
1966   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
1967
1968   def = *(const WORD*)&pFormat[2];
1969   pFormat += 4;
1970
1971   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
1972   size = pStubMsg->MaxCount;
1973   TRACE("conformance=%ld\n", size);
1974
1975   if (*(const DWORD*)pFormat != 0xffffffff)
1976     FIXME("compute variance\n");
1977   pFormat += 4;
1978
1979   for (count=0; count<size; count++)
1980     pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL);
1981 }
1982
1983 /***********************************************************************
1984  *           NdrComplexArrayMemorySize [RPCRT4.@]
1985  */
1986 unsigned long WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
1987                                                PFORMAT_STRING pFormat)
1988 {
1989   DWORD size = 0;
1990   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
1991
1992   pFormat += 4;
1993
1994   pFormat = ReadConformance(pStubMsg, pFormat);
1995   size = pStubMsg->MaxCount;
1996   TRACE("conformance=%ld\n", size);
1997
1998   pFormat += 4;
1999
2000   return 0;
2001 }
2002
2003 /***********************************************************************
2004  *           NdrComplexArrayFree [RPCRT4.@]
2005  */
2006 void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg,
2007                                 unsigned char *pMemory,
2008                                 PFORMAT_STRING pFormat)
2009 {
2010   DWORD size = 0, count, def;
2011   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2012
2013   def = *(const WORD*)&pFormat[2];
2014   pFormat += 4;
2015
2016   pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def);
2017   size = pStubMsg->MaxCount;
2018   TRACE("conformance=%ld\n", size);
2019
2020   if (*(const DWORD*)pFormat != 0xffffffff)
2021     FIXME("compute variance\n");
2022   pFormat += 4;
2023
2024   for (count=0; count<size; count++)
2025     pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL);
2026 }
2027
2028 unsigned long UserMarshalFlags(PMIDL_STUB_MESSAGE pStubMsg)
2029 {
2030   return MAKELONG(pStubMsg->dwDestContext,
2031                   pStubMsg->RpcMsg->DataRepresentation);
2032 }
2033
2034 /***********************************************************************
2035  *           NdrUserMarshalMarshall [RPCRT4.@]
2036  */
2037 unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg,
2038                                               unsigned char *pMemory,
2039                                               PFORMAT_STRING pFormat)
2040 {
2041 /*  unsigned flags = pFormat[1]; */
2042   unsigned index = *(const WORD*)&pFormat[2];
2043   unsigned long uflag = UserMarshalFlags(pStubMsg);
2044   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2045   TRACE("index=%d\n", index);
2046
2047   pStubMsg->Buffer =
2048     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall(
2049       &uflag, pStubMsg->Buffer, pMemory);
2050
2051   STD_OVERFLOW_CHECK(pStubMsg);
2052
2053   return NULL;
2054 }
2055
2056 /***********************************************************************
2057  *           NdrUserMarshalUnmarshall [RPCRT4.@]
2058  */
2059 unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
2060                                                  unsigned char **ppMemory,
2061                                                  PFORMAT_STRING pFormat,
2062                                                  unsigned char fMustAlloc)
2063 {
2064 /*  unsigned flags = pFormat[1];*/
2065   unsigned index = *(const WORD*)&pFormat[2];
2066   DWORD memsize = *(const WORD*)&pFormat[4];
2067   unsigned long uflag = UserMarshalFlags(pStubMsg);
2068   TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc);
2069   TRACE("index=%d\n", index);
2070
2071   if (fMustAlloc || !*ppMemory)
2072     *ppMemory = NdrAllocate(pStubMsg, memsize);
2073
2074   pStubMsg->Buffer =
2075     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall(
2076       &uflag, pStubMsg->Buffer, *ppMemory);
2077
2078   return NULL;
2079 }
2080
2081 /***********************************************************************
2082  *           NdrUserMarshalBufferSize [RPCRT4.@]
2083  */
2084 void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
2085                                       unsigned char *pMemory,
2086                                       PFORMAT_STRING pFormat)
2087 {
2088 /*  unsigned flags = pFormat[1];*/
2089   unsigned index = *(const WORD*)&pFormat[2];
2090   DWORD bufsize = *(const WORD*)&pFormat[6];
2091   unsigned long uflag = UserMarshalFlags(pStubMsg);
2092   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2093   TRACE("index=%d\n", index);
2094
2095   if (bufsize) {
2096     TRACE("size=%ld\n", bufsize);
2097     pStubMsg->BufferLength += bufsize;
2098     return;
2099   }
2100
2101   pStubMsg->BufferLength =
2102     pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize(
2103       &uflag, pStubMsg->BufferLength, pMemory);
2104 }
2105
2106 /***********************************************************************
2107  *           NdrUserMarshalMemorySize [RPCRT4.@]
2108  */
2109 unsigned long WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
2110                                               PFORMAT_STRING pFormat)
2111 {
2112   unsigned index = *(const WORD*)&pFormat[2];
2113 /*  DWORD memsize = *(const WORD*)&pFormat[4]; */
2114   FIXME("(%p,%p): stub\n", pStubMsg, pFormat);
2115   TRACE("index=%d\n", index);
2116
2117   return 0;
2118 }
2119
2120 /***********************************************************************
2121  *           NdrUserMarshalFree [RPCRT4.@]
2122  */
2123 void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg,
2124                                 unsigned char *pMemory,
2125                                 PFORMAT_STRING pFormat)
2126 {
2127 /*  unsigned flags = pFormat[1]; */
2128   unsigned index = *(const WORD*)&pFormat[2];
2129   unsigned long uflag = UserMarshalFlags(pStubMsg);
2130   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
2131   TRACE("index=%d\n", index);
2132
2133   pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree(
2134     &uflag, pMemory);
2135 }
2136
2137 /***********************************************************************
2138  *           NdrClearOutParameters [RPCRT4.@]
2139  */
2140 void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg,
2141                                   PFORMAT_STRING pFormat,
2142                                   void *ArgAddr)
2143 {
2144   FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr);
2145 }
2146
2147 /***********************************************************************
2148  *           NdrConvert [RPCRT4.@]
2149  */
2150 void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat )
2151 {
2152   FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat);
2153   /* FIXME: since this stub doesn't do any converting, the proper behavior
2154      is to raise an exception */
2155 }
2156
2157 /***********************************************************************
2158  *           NdrConvert2 [RPCRT4.@]
2159  */
2160 void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, long NumberParams )
2161 {
2162   FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %ld): stub.\n",
2163     pStubMsg, pFormat, NumberParams);
2164   /* FIXME: since this stub doesn't do any converting, the proper behavior
2165      is to raise an exception */
2166 }