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