[BRANCHES]
[reactos.git] / rostests / winetests / rpcrt4 / ndr_marshall.c
1 /*
2 * Unit test suite for ndr marshalling functions
3 *
4 * Copyright 2006 Huw Davies
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define _WIN32_WINNT 0x0500
22 #define NTDDI_WIN2K 0x05000000
23 #define NTDDI_VERSION NTDDI_WIN2K /* for some MIDL_STUB_MESSAGE fields */
24
25 #include <stdarg.h>
26
27 #include "wine/test.h"
28 #include <windef.h>
29 #include <winbase.h>
30 #include <winnt.h>
31 #include <winerror.h>
32
33 #include "rpc.h"
34 #include "rpcdce.h"
35 #include "rpcproxy.h"
36
37
38 static int my_alloc_called;
39 static int my_free_called;
40 static void * CALLBACK my_alloc(SIZE_T size)
41 {
42 my_alloc_called++;
43 return NdrOleAllocate(size);
44 }
45
46 static void CALLBACK my_free(void *ptr)
47 {
48 my_free_called++;
49 NdrOleFree(ptr);
50 }
51
52 static const MIDL_STUB_DESC Object_StubDesc =
53 {
54 NULL,
55 my_alloc,
56 my_free,
57 { 0 },
58 0,
59 0,
60 0,
61 0,
62 NULL, /* format string, filled in by tests */
63 1, /* -error bounds_check flag */
64 0x20000, /* Ndr library version */
65 0,
66 0x50100a4, /* MIDL Version 5.1.164 */
67 0,
68 NULL,
69 0, /* notify & notify_flag routine table */
70 1, /* Flags */
71 0, /* Reserved3 */
72 0, /* Reserved4 */
73 0 /* Reserved5 */
74 };
75
76 static RPC_DISPATCH_FUNCTION IFoo_table[] =
77 {
78 0
79 };
80
81 static RPC_DISPATCH_TABLE IFoo_v0_0_DispatchTable =
82 {
83 0,
84 IFoo_table
85 };
86
87 static const RPC_SERVER_INTERFACE IFoo___RpcServerInterface =
88 {
89 sizeof(RPC_SERVER_INTERFACE),
90 {{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x34}},{0,0}},
91 {{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},
92 &IFoo_v0_0_DispatchTable,
93 0,
94 0,
95 0,
96 0,
97 0,
98 };
99
100 static RPC_IF_HANDLE IFoo_v0_0_s_ifspec = (RPC_IF_HANDLE)& IFoo___RpcServerInterface;
101 static BOOL use_pointer_ids = FALSE;
102
103 static void determine_pointer_marshalling_style(void)
104 {
105 RPC_MESSAGE RpcMessage;
106 MIDL_STUB_MESSAGE StubMsg;
107 MIDL_STUB_DESC StubDesc;
108 char ch = 0xde;
109
110 static const unsigned char fmtstr_up_char[] =
111 {
112 0x12, 0x8, /* FC_UP [simple_pointer] */
113 0x2, /* FC_CHAR */
114 0x5c, /* FC_PAD */
115 };
116
117 StubDesc = Object_StubDesc;
118 StubDesc.pFormatTypes = NULL;
119
120 NdrClientInitializeNew(
121 &RpcMessage,
122 &StubMsg,
123 &StubDesc,
124 0);
125
126 StubMsg.BufferLength = 8;
127 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
128 NdrPointerMarshall(&StubMsg, (unsigned char*)&ch, fmtstr_up_char);
129 ok(StubMsg.Buffer == StubMsg.BufferStart + 5, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart);
130
131 use_pointer_ids = (*(unsigned int *)StubMsg.BufferStart != (UINT_PTR)&ch);
132 trace("Pointer marshalling using %s\n", use_pointer_ids ? "pointer ids" : "pointer value");
133
134 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
135 }
136
137 static void test_ndr_simple_type(void)
138 {
139 RPC_MESSAGE RpcMessage;
140 MIDL_STUB_MESSAGE StubMsg;
141 MIDL_STUB_DESC StubDesc;
142 LONG l, l2 = 0;
143
144 StubDesc = Object_StubDesc;
145 StubDesc.pFormatTypes = NULL;
146
147 NdrClientInitializeNew(
148 &RpcMessage,
149 &StubMsg,
150 &StubDesc,
151 0);
152
153 StubMsg.BufferLength = 16;
154 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
155 l = 0xcafebabe;
156 NdrSimpleTypeMarshall(&StubMsg, (unsigned char*)&l, 8 /* FC_LONG */);
157 ok(StubMsg.Buffer == StubMsg.BufferStart + 4, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart);
158 ok(*(LONG*)StubMsg.BufferStart == l, "%d\n", *(LONG*)StubMsg.BufferStart);
159
160 StubMsg.Buffer = StubMsg.BufferStart + 1;
161 NdrSimpleTypeMarshall(&StubMsg, (unsigned char*)&l, 8 /* FC_LONG */);
162 ok(StubMsg.Buffer == StubMsg.BufferStart + 8, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart);
163 ok(*(LONG*)(StubMsg.BufferStart + 4) == l, "%d\n", *(LONG*)StubMsg.BufferStart);
164
165 StubMsg.Buffer = StubMsg.BufferStart + 1;
166 NdrSimpleTypeUnmarshall(&StubMsg, (unsigned char*)&l2, 8 /* FC_LONG */);
167 ok(StubMsg.Buffer == StubMsg.BufferStart + 8, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart);
168 ok(l2 == l, "%d\n", l2);
169
170 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
171 }
172
173 static void test_pointer_marshal(const unsigned char *formattypes,
174 void *memsrc, DWORD srcsize,
175 const void *wiredata,
176 ULONG wiredatalen,
177 int(*cmp)(const void*,const void*,size_t),
178 int num_additional_allocs,
179 const char *msgpfx)
180 {
181 RPC_MESSAGE RpcMessage;
182 MIDL_STUB_MESSAGE StubMsg;
183 MIDL_STUB_DESC StubDesc;
184 DWORD size;
185 void *ptr;
186 unsigned char *mem, *mem_orig;
187
188 my_alloc_called = my_free_called = 0;
189 if(!cmp)
190 cmp = memcmp;
191
192 StubDesc = Object_StubDesc;
193 StubDesc.pFormatTypes = formattypes;
194
195 NdrClientInitializeNew(
196 &RpcMessage,
197 &StubMsg,
198 &StubDesc,
199 0);
200
201 StubMsg.BufferLength = 0;
202 NdrPointerBufferSize( &StubMsg,
203 memsrc,
204 formattypes );
205 ok(StubMsg.BufferLength >= wiredatalen, "%s: length %d\n", msgpfx, StubMsg.BufferLength);
206
207 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
208 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
209 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
210
211 memset(StubMsg.BufferStart, 0x0, StubMsg.BufferLength); /* This is a hack to clear the padding between the ptr and longlong/double */
212
213 ptr = NdrPointerMarshall( &StubMsg, memsrc, formattypes );
214 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
215 if (srcsize == 8 && wiredatalen == 16 && StubMsg.Buffer - StubMsg.BufferStart == 12)
216 {
217 /* win9x doesn't align 8-byte types properly */
218 wiredatalen = 12;
219 }
220 else
221 {
222 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
223 ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled\n", msgpfx);
224 }
225
226 StubMsg.Buffer = StubMsg.BufferStart;
227 StubMsg.MemorySize = 0;
228
229 size = NdrPointerMemorySize( &StubMsg, formattypes );
230 ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size);
231 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
232 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
233 ok(size == srcsize + sizeof(void *), "%s: mem size %u\n", msgpfx, size);
234 else
235 ok(size == srcsize, "%s: mem size %u\n", msgpfx, size);
236
237 StubMsg.Buffer = StubMsg.BufferStart;
238 StubMsg.MemorySize = 16;
239 size = NdrPointerMemorySize( &StubMsg, formattypes );
240 ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size);
241 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
242 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
243 ok(size == srcsize + sizeof(void *) + 16, "%s: mem size %u\n", msgpfx, size);
244 else
245 ok(size == srcsize + 16, "%s: mem size %u\n", msgpfx, size);
246
247 StubMsg.Buffer = StubMsg.BufferStart;
248 StubMsg.MemorySize = 1;
249 size = NdrPointerMemorySize( &StubMsg, formattypes );
250 ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size);
251 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
252 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
253 ok(size == srcsize + sizeof(void *) + (srcsize == 8 ? 8 : sizeof(void *)), "%s: mem size %u\n", msgpfx, size);
254 else
255 ok(size == srcsize + (srcsize == 8 ? 8 : sizeof(void *)), "%s: mem size %u\n", msgpfx, size);
256
257 size = srcsize;
258 if(formattypes[1] & 0x10) size += 4;
259
260 StubMsg.Buffer = StubMsg.BufferStart;
261 StubMsg.MemorySize = 0;
262 mem_orig = mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
263
264 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
265 *(void**)mem = NULL;
266 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 );
267 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
268 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
269 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
270 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
271 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
272 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
273 my_alloc_called = 0;
274
275 /* reset the buffer and call with must alloc */
276 StubMsg.Buffer = StubMsg.BufferStart;
277 if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */)
278 *(void**)mem = NULL;
279 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 1 );
280 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
281 /* doesn't allocate mem in this case */
282 todo_wine {
283 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
284 }
285 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
286 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
287 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
288
289 todo_wine {
290 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
291 }
292 my_alloc_called = 0;
293 if(formattypes[0] != 0x11 /* FC_RP */)
294 {
295 /* now pass the address of a NULL ptr */
296 mem = NULL;
297 StubMsg.Buffer = StubMsg.BufferStart;
298 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 );
299 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
300 ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
301 ok(!cmp(mem, memsrc, size), "%s: incorrectly unmarshaled\n", msgpfx);
302 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
303 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
304 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
305 my_alloc_called = 0;
306 NdrPointerFree(&StubMsg, mem, formattypes);
307
308 /* again pass address of NULL ptr, but pretend we're a server */
309 if (0) /* crashes on Win9x and NT4 */
310 {
311 mem = NULL;
312 StubMsg.Buffer = StubMsg.BufferStart;
313 StubMsg.IsClient = 0;
314 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 );
315 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
316 if (formattypes[2] == 0xd /* FC_ENUM16 */)
317 ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
318 else
319 ok(mem == StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem doesn't point to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart);
320 ok(!cmp(mem, memsrc, size), "%s: incorrectly unmarshaled\n", msgpfx);
321 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
322 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
323 if (formattypes[2] != 0xd /* FC_ENUM16 */) {
324 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
325 my_alloc_called = 0;
326 }
327 }
328 }
329 HeapFree(GetProcessHeap(), 0, mem_orig);
330 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
331 }
332
333 static int deref_cmp(const void *s1, const void *s2, size_t num)
334 {
335 return memcmp(*(const void *const *)s1, *(const void *const *)s2, num);
336 }
337
338
339 static void test_simple_types(void)
340 {
341 unsigned char wiredata[16];
342 unsigned char ch;
343 unsigned char *ch_ptr;
344 unsigned short s;
345 unsigned int i;
346 ULONG l;
347 ULONGLONG ll;
348 float f;
349 double d;
350
351 static const unsigned char fmtstr_up_char[] =
352 {
353 0x12, 0x8, /* FC_UP [simple_pointer] */
354 0x2, /* FC_CHAR */
355 0x5c, /* FC_PAD */
356 };
357 static const unsigned char fmtstr_up_byte[] =
358 {
359 0x12, 0x8, /* FC_UP [simple_pointer] */
360 0x1, /* FC_BYTE */
361 0x5c, /* FC_PAD */
362 };
363 static const unsigned char fmtstr_up_small[] =
364 {
365 0x12, 0x8, /* FC_UP [simple_pointer] */
366 0x3, /* FC_SMALL */
367 0x5c, /* FC_PAD */
368 };
369 static const unsigned char fmtstr_up_usmall[] =
370 {
371 0x12, 0x8, /* FC_UP [simple_pointer] */
372 0x4, /* FC_USMALL */
373 0x5c, /* FC_PAD */
374 };
375 static const unsigned char fmtstr_rp_char[] =
376 {
377 0x11, 0x8, /* FC_RP [simple_pointer] */
378 0x2, /* FC_CHAR */
379 0x5c, /* FC_PAD */
380 };
381 static const unsigned char fmtstr_rpup_char[] =
382 {
383 0x11, 0x14, /* FC_RP [alloced_on_stack] */
384 NdrFcShort( 0x2 ), /* Offset= 2 (4) */
385 0x12, 0x8, /* FC_UP [simple_pointer] */
386 0x2, /* FC_CHAR */
387 0x5c, /* FC_PAD */
388 };
389 static const unsigned char fmtstr_rpup_char2[] =
390 {
391 0x11, 0x04, /* FC_RP [alloced_on_stack] */
392 NdrFcShort( 0x2 ), /* Offset= 2 (4) */
393 0x12, 0x8, /* FC_UP [simple_pointer] */
394 0x2, /* FC_CHAR */
395 0x5c, /* FC_PAD */
396 };
397
398 static const unsigned char fmtstr_up_wchar[] =
399 {
400 0x12, 0x8, /* FC_UP [simple_pointer] */
401 0x5, /* FC_WCHAR */
402 0x5c, /* FC_PAD */
403 };
404 static const unsigned char fmtstr_up_short[] =
405 {
406 0x12, 0x8, /* FC_UP [simple_pointer] */
407 0x6, /* FC_SHORT */
408 0x5c, /* FC_PAD */
409 };
410 static const unsigned char fmtstr_up_ushort[] =
411 {
412 0x12, 0x8, /* FC_UP [simple_pointer] */
413 0x7, /* FC_USHORT */
414 0x5c, /* FC_PAD */
415 };
416 static const unsigned char fmtstr_up_enum16[] =
417 {
418 0x12, 0x8, /* FC_UP [simple_pointer] */
419 0xd, /* FC_ENUM16 */
420 0x5c, /* FC_PAD */
421 };
422 static const unsigned char fmtstr_up_long[] =
423 {
424 0x12, 0x8, /* FC_UP [simple_pointer] */
425 0x8, /* FC_LONG */
426 0x5c, /* FC_PAD */
427 };
428 static const unsigned char fmtstr_up_ulong[] =
429 {
430 0x12, 0x8, /* FC_UP [simple_pointer] */
431 0x9, /* FC_ULONG */
432 0x5c, /* FC_PAD */
433 };
434 static const unsigned char fmtstr_up_enum32[] =
435 {
436 0x12, 0x8, /* FC_UP [simple_pointer] */
437 0xe, /* FC_ENUM32 */
438 0x5c, /* FC_PAD */
439 };
440 static const unsigned char fmtstr_up_errorstatus[] =
441 {
442 0x12, 0x8, /* FC_UP [simple_pointer] */
443 0x10, /* FC_ERROR_STATUS_T */
444 0x5c, /* FC_PAD */
445 };
446
447 static const unsigned char fmtstr_up_longlong[] =
448 {
449 0x12, 0x8, /* FC_UP [simple_pointer] */
450 0xb, /* FC_HYPER */
451 0x5c, /* FC_PAD */
452 };
453 static const unsigned char fmtstr_up_float[] =
454 {
455 0x12, 0x8, /* FC_UP [simple_pointer] */
456 0xa, /* FC_FLOAT */
457 0x5c, /* FC_PAD */
458 };
459 static const unsigned char fmtstr_up_double[] =
460 {
461 0x12, 0x8, /* FC_UP [simple_pointer] */
462 0xc, /* FC_DOUBLE */
463 0x5c, /* FC_PAD */
464 };
465
466 ch = 0xa5;
467 ch_ptr = &ch;
468 if (use_pointer_ids)
469 *(unsigned int *)wiredata = 0x20000;
470 else
471 *(unsigned int *)wiredata = (UINT_PTR)ch_ptr;
472 wiredata[4] = ch;
473
474 test_pointer_marshal(fmtstr_up_char, ch_ptr, 1, wiredata, 5, NULL, 0, "up_char");
475 test_pointer_marshal(fmtstr_up_byte, ch_ptr, 1, wiredata, 5, NULL, 0, "up_byte");
476 test_pointer_marshal(fmtstr_up_small, ch_ptr, 1, wiredata, 5, NULL, 0, "up_small");
477 test_pointer_marshal(fmtstr_up_usmall, ch_ptr, 1, wiredata, 5, NULL, 0, "up_usmall");
478
479 test_pointer_marshal(fmtstr_rp_char, ch_ptr, 1, &ch, 1, NULL, 0, "rp_char");
480
481 test_pointer_marshal(fmtstr_rpup_char, &ch_ptr, 1, wiredata, 5, deref_cmp, 1, "rpup_char");
482 test_pointer_marshal(fmtstr_rpup_char2, ch_ptr, 1, wiredata, 5, NULL, 0, "rpup_char2");
483
484 s = 0xa597;
485 if (use_pointer_ids)
486 *(unsigned int *)wiredata = 0x20000;
487 else
488 *(unsigned int *)wiredata = (UINT_PTR)&s;
489 *(unsigned short*)(wiredata + 4) = s;
490
491 test_pointer_marshal(fmtstr_up_wchar, &s, 2, wiredata, 6, NULL, 0, "up_wchar");
492 test_pointer_marshal(fmtstr_up_short, &s, 2, wiredata, 6, NULL, 0, "up_short");
493 test_pointer_marshal(fmtstr_up_ushort, &s, 2, wiredata, 6, NULL, 0, "up_ushort");
494
495 i = 0x7fff;
496 if (use_pointer_ids)
497 *(unsigned int *)wiredata = 0x20000;
498 else
499 *(unsigned int *)wiredata = (UINT_PTR)&i;
500 *(unsigned short*)(wiredata + 4) = i;
501 test_pointer_marshal(fmtstr_up_enum16, &i, 4, wiredata, 6, NULL, 0, "up_enum16");
502
503 l = 0xcafebabe;
504 if (use_pointer_ids)
505 *(unsigned int *)wiredata = 0x20000;
506 else
507 *(unsigned int *)wiredata = (UINT_PTR)&l;
508 *(ULONG*)(wiredata + 4) = l;
509
510 test_pointer_marshal(fmtstr_up_long, &l, 4, wiredata, 8, NULL, 0, "up_long");
511 test_pointer_marshal(fmtstr_up_ulong, &l, 4, wiredata, 8, NULL, 0, "up_ulong");
512 test_pointer_marshal(fmtstr_up_enum32, &l, 4, wiredata, 8, NULL, 0, "up_emun32");
513 test_pointer_marshal(fmtstr_up_errorstatus, &l, 4, wiredata, 8, NULL, 0, "up_errorstatus");
514
515 ll = ((ULONGLONG)0xcafebabe) << 32 | 0xdeadbeef;
516 if (use_pointer_ids)
517 *(unsigned int *)wiredata = 0x20000;
518 else
519 *(unsigned int *)wiredata = (UINT_PTR)&ll;
520 *(unsigned int *)(wiredata + 4) = 0;
521 *(ULONGLONG*)(wiredata + 8) = ll;
522 test_pointer_marshal(fmtstr_up_longlong, &ll, 8, wiredata, 16, NULL, 0, "up_longlong");
523
524 f = 3.1415f;
525 if (use_pointer_ids)
526 *(unsigned int *)wiredata = 0x20000;
527 else
528 *(unsigned int *)wiredata = (UINT_PTR)&f;
529 *(float*)(wiredata + 4) = f;
530 test_pointer_marshal(fmtstr_up_float, &f, 4, wiredata, 8, NULL, 0, "up_float");
531
532 d = 3.1415;
533 if (use_pointer_ids)
534 *(unsigned int *)wiredata = 0x20000;
535 else
536 *(unsigned int *)wiredata = (UINT_PTR)&d;
537 *(unsigned int *)(wiredata + 4) = 0;
538 *(double*)(wiredata + 8) = d;
539 test_pointer_marshal(fmtstr_up_double, &d, 8, wiredata, 16, NULL, 0, "up_double");
540
541 }
542
543 static void test_nontrivial_pointer_types(void)
544 {
545 RPC_MESSAGE RpcMessage;
546 MIDL_STUB_MESSAGE StubMsg;
547 MIDL_STUB_DESC StubDesc;
548 DWORD size;
549 void *ptr;
550 char **p1;
551 char *p2;
552 char ch;
553 unsigned char *mem, *mem_orig;
554
555 static const unsigned char fmtstr_ref_unique_out[] =
556 {
557 0x12, 0x8, /* FC_UP [simple_pointer] */
558 0x2, /* FC_CHAR */
559 0x5c, /* FC_PAD */
560 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */
561 NdrFcShort( 0xfffffffa ), /* Offset= -6 (0) */
562 };
563
564 p1 = &p2;
565 p2 = &ch;
566 ch = 0x22;
567
568 StubDesc = Object_StubDesc;
569 StubDesc.pFormatTypes = fmtstr_ref_unique_out;
570
571 NdrClientInitializeNew(
572 &RpcMessage,
573 &StubMsg,
574 &StubDesc,
575 0);
576
577 StubMsg.BufferLength = 0;
578 NdrPointerBufferSize( &StubMsg,
579 (unsigned char *)p1,
580 &fmtstr_ref_unique_out[4] );
581
582 /* Windows overestimates the buffer size */
583 ok(StubMsg.BufferLength >= 5, "length %d\n", StubMsg.BufferLength);
584
585 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
586 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
587 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
588
589 ptr = NdrPointerMarshall( &StubMsg, (unsigned char *)p1, &fmtstr_ref_unique_out[4] );
590 ok(ptr == NULL, "ret %p\n", ptr);
591 size = StubMsg.Buffer - StubMsg.BufferStart;
592 ok(size == 5, "Buffer %p Start %p len %d\n", StubMsg.Buffer, StubMsg.BufferStart, size);
593 ok(*(unsigned int *)StubMsg.BufferStart != 0, "pointer ID marshalled incorrectly\n");
594 ok(*(unsigned char *)(StubMsg.BufferStart + 4) == 0x22, "char data marshalled incorrectly: 0x%x\n",
595 *(unsigned char *)(StubMsg.BufferStart + 4));
596
597 StubMsg.Buffer = StubMsg.BufferStart;
598 StubMsg.MemorySize = 0;
599 mem = NULL;
600
601 /* Client */
602 my_alloc_called = 0;
603 StubMsg.Buffer = StubMsg.BufferStart;
604 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(void *));
605 *(void **)mem = NULL;
606 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
607 ok(mem == mem_orig, "mem alloced\n");
608 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
609
610 my_alloc_called = 0;
611 StubMsg.Buffer = StubMsg.BufferStart;
612 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
613 todo_wine {
614 ok(mem == mem_orig, "mem alloced\n");
615 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
616 }
617
618 my_free_called = 0;
619 StubMsg.Buffer = StubMsg.BufferStart;
620 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
621 ok(my_free_called == 1, "free called %d\n", my_free_called);
622
623 mem = my_alloc(sizeof(void *));
624 *(void **)mem = NULL;
625 my_free_called = 0;
626 StubMsg.Buffer = StubMsg.BufferStart;
627 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
628 ok(my_free_called == 0, "free called %d\n", my_free_called);
629 my_free(mem);
630
631 mem = my_alloc(sizeof(void *));
632 *(void **)mem = my_alloc(sizeof(char));
633 my_free_called = 0;
634 StubMsg.Buffer = StubMsg.BufferStart;
635 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
636 ok(my_free_called == 1, "free called %d\n", my_free_called);
637 my_free(mem);
638
639 /* Server */
640 my_alloc_called = 0;
641 StubMsg.IsClient = 0;
642 mem = NULL;
643 StubMsg.Buffer = StubMsg.BufferStart;
644 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
645 ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n");
646 todo_wine
647 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
648 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
649
650 my_alloc_called = 0;
651 mem = NULL;
652 StubMsg.Buffer = StubMsg.BufferStart;
653 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
654 ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n");
655 todo_wine
656 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
657 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
658
659 my_alloc_called = 0;
660 mem = mem_orig;
661 *(void **)mem = NULL;
662 StubMsg.Buffer = StubMsg.BufferStart;
663 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
664 todo_wine {
665 ok(mem == mem_orig, "mem alloced\n");
666 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
667 }
668
669 my_alloc_called = 0;
670 mem = mem_orig;
671 *(void **)mem = NULL;
672 StubMsg.Buffer = StubMsg.BufferStart;
673 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
674 todo_wine {
675 ok(mem == mem_orig, "mem alloced\n");
676 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
677 }
678
679 mem = my_alloc(sizeof(void *));
680 *(void **)mem = NULL;
681 my_free_called = 0;
682 StubMsg.Buffer = StubMsg.BufferStart;
683 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
684 ok(my_free_called == 0, "free called %d\n", my_free_called);
685 my_free(mem);
686
687 mem = my_alloc(sizeof(void *));
688 *(void **)mem = my_alloc(sizeof(char));
689 my_free_called = 0;
690 StubMsg.Buffer = StubMsg.BufferStart;
691 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
692 ok(my_free_called == 1, "free called %d\n", my_free_called);
693 my_free(mem);
694
695 HeapFree(GetProcessHeap(), 0, mem_orig);
696 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
697 }
698
699 static void test_simple_struct_marshal(const unsigned char *formattypes,
700 void *memsrc, DWORD srcsize,
701 const void *wiredata,
702 ULONG wiredatalen,
703 int(*cmp)(const void*,const void*,size_t),
704 int num_additional_allocs,
705 const char *msgpfx)
706 {
707 RPC_MESSAGE RpcMessage;
708 MIDL_STUB_MESSAGE StubMsg;
709 MIDL_STUB_DESC StubDesc;
710 DWORD size;
711 void *ptr;
712 unsigned char *mem, *mem_orig;
713
714 my_alloc_called = my_free_called = 0;
715 if(!cmp)
716 cmp = memcmp;
717
718 StubDesc = Object_StubDesc;
719 StubDesc.pFormatTypes = formattypes;
720
721 NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0);
722
723 StubMsg.BufferLength = 0;
724 NdrSimpleStructBufferSize( &StubMsg, memsrc, formattypes );
725 ok(StubMsg.BufferLength >= wiredatalen, "%s: length %d\n", msgpfx, StubMsg.BufferLength);
726 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
727 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
728 ptr = NdrSimpleStructMarshall( &StubMsg, memsrc, formattypes );
729 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
730 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
731 ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled %08x %08x %08x\n", msgpfx, *(DWORD*)StubMsg.BufferStart,*((DWORD*)StubMsg.BufferStart+1),*((DWORD*)StubMsg.BufferStart+2));
732
733 StubMsg.Buffer = StubMsg.BufferStart;
734 StubMsg.MemorySize = 0;
735 size = NdrSimpleStructMemorySize( &StubMsg, formattypes );
736 ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx);
737 ok(size == srcsize, "%s: mem size %u\n", msgpfx, size);
738 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
739
740 StubMsg.Buffer = StubMsg.BufferStart;
741 size = NdrSimpleStructMemorySize( &StubMsg, formattypes );
742 ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx);
743 ok(StubMsg.MemorySize == ((srcsize + 3) & ~3) + srcsize, "%s: mem size %u\n", msgpfx, size);
744 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
745 size = srcsize;
746 /*** Unmarshalling first with must_alloc false ***/
747
748 StubMsg.Buffer = StubMsg.BufferStart;
749 StubMsg.MemorySize = 0;
750 mem_orig = mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, srcsize);
751 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 );
752 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
753 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart);
754 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
755 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
756 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
757 my_alloc_called = 0;
758 ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
759
760 /* If we're a server we still use the supplied memory */
761 StubMsg.Buffer = StubMsg.BufferStart;
762 StubMsg.IsClient = 0;
763 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 );
764 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
765 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
766 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
767 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
768 my_alloc_called = 0;
769 ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
770
771 /* ...unless we pass a NULL ptr, then the buffer is used.
772 Passing a NULL ptr while we're a client && !must_alloc
773 crashes on Windows, so we won't do that. */
774
775 if (0) /* crashes on Win9x and NT4 */
776 {
777 mem = NULL;
778 StubMsg.IsClient = 0;
779 StubMsg.Buffer = StubMsg.BufferStart;
780 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, FALSE );
781 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
782 ok(mem == StubMsg.BufferStart, "%s: mem not equal buffer\n", msgpfx);
783 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
784 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
785 my_alloc_called = 0;
786 ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx);
787 }
788
789 /*** now must_alloc is true ***/
790
791 /* with must_alloc set we always allocate new memory whether or not we're
792 a server and also when passing NULL */
793 mem = mem_orig;
794 StubMsg.IsClient = 1;
795 StubMsg.Buffer = StubMsg.BufferStart;
796 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
797 ok(ptr == NULL, "ret %p\n", ptr);
798 ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig);
799 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
800 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
801 my_alloc_called = 0;
802 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
803
804 mem = NULL;
805 StubMsg.Buffer = StubMsg.BufferStart;
806 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
807 ok(ptr == NULL, "ret %p\n", ptr);
808 ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig);
809 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
810 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
811 my_alloc_called = 0;
812 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
813
814 mem = mem_orig;
815 StubMsg.Buffer = StubMsg.BufferStart;
816 StubMsg.IsClient = 0;
817 StubMsg.ReuseBuffer = 1;
818 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
819 ok(ptr == NULL, "ret %p\n", ptr);
820 ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig);
821 ok(mem != StubMsg.BufferStart, "mem is buffer mem\n");
822 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
823 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
824 my_alloc_called = 0;
825 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
826
827 mem = NULL;
828 StubMsg.Buffer = StubMsg.BufferStart;
829 StubMsg.IsClient = 0;
830 StubMsg.ReuseBuffer = 1;
831 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 );
832 ok(ptr == NULL, "ret %p\n", ptr);
833 ok(mem != StubMsg.BufferStart, "mem is buffer mem\n");
834 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n");
835 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
836 my_alloc_called = 0;
837 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n");
838
839 HeapFree(GetProcessHeap(), 0, mem_orig);
840 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
841 }
842
843 typedef struct
844 {
845 LONG l1;
846 LONG *pl1;
847 char *pc1;
848 } ps1_t;
849
850 static int ps1_cmp(const void *s1, const void *s2, size_t num)
851 {
852 const ps1_t *p1, *p2;
853
854 p1 = s1;
855 p2 = s2;
856
857 if(p1->l1 != p2->l1)
858 return 1;
859
860 if(p1->pl1 && p2->pl1)
861 {
862 if(*p1->pl1 != *p2->pl1)
863 return 1;
864 }
865 else if(p1->pl1 || p2->pl1)
866 return 1;
867
868 if(p1->pc1 && p2->pc1)
869 {
870 if(*p1->pc1 != *p2->pc1)
871 return 1;
872 }
873 else if(p1->pc1 || p2->pc1)
874 return 1;
875
876 return 0;
877 }
878
879 static void test_simple_struct(void)
880 {
881 unsigned char wiredata[28];
882 ULONG wiredatalen;
883 LONG l;
884 char c;
885 ps1_t ps1;
886
887 static const unsigned char fmtstr_simple_struct[] =
888 {
889 0x12, 0x0, /* FC_UP */
890 NdrFcShort( 0x2 ), /* Offset=2 */
891 0x15, 0x3, /* FC_STRUCT [align 4] */
892 NdrFcShort( 0x18 ), /* [size 24] */
893 0x6, /* FC_SHORT */
894 0x2, /* FC_CHAR */
895 0x38, /* FC_ALIGNM4 */
896 0x8, /* FC_LONG */
897 0x8, /* FC_LONG */
898 0x39, /* FC_ALIGNM8 */
899 0xb, /* FC_HYPER */
900 0x5b, /* FC_END */
901 };
902 struct {
903 short s;
904 char c;
905 LONG l1, l2;
906 LONGLONG ll;
907 } s1;
908
909 static const unsigned char fmtstr_pointer_struct[] =
910 {
911 0x12, 0x0, /* FC_UP */
912 NdrFcShort( 0x2 ), /* Offset=2 */
913 #ifdef _WIN64
914 0x1a, /* FC_BOGUS_STRUCT */
915 0x3, /* 3 */
916 NdrFcShort(0x18), /* [size 24] */
917 NdrFcShort(0x0),
918 NdrFcShort(0x8), /* Offset= 8 (266) */
919 0x08, /* FC_LONG */
920 0x39, /* FC_ALIGNM8 */
921 0x36, /* FC_POINTER */
922 0x36, /* FC_POINTER */
923 0x5c, /* FC_PAD */
924 0x5b, /* FC_END */
925 0x12, 0x8, /* FC_UP [simple_pointer] */
926 0x08, /* FC_LONG */
927 0x5c, /* FC_PAD */
928 0x12, 0x8, /* FC_UP [simple_pointer] */
929 0x02, /* FC_CHAR */
930 0x5c, /* FC_PAD */
931 #else
932 0x16, 0x3, /* FC_PSTRUCT [align 4] */
933 NdrFcShort( 0xc ), /* [size 12] */
934 0x4b, /* FC_PP */
935 0x5c, /* FC_PAD */
936 0x46, /* FC_NO_REPEAT */
937 0x5c, /* FC_PAD */
938 NdrFcShort( 0x4 ), /* 4 */
939 NdrFcShort( 0x4 ), /* 4 */
940 0x13, 0x8, /* FC_OP [simple_pointer] */
941 0x8, /* FC_LONG */
942 0x5c, /* FC_PAD */
943 0x46, /* FC_NO_REPEAT */
944 0x5c, /* FC_PAD */
945 NdrFcShort( 0x8 ), /* 8 */
946 NdrFcShort( 0x8 ), /* 8 */
947 0x13, 0x8, /* FC_OP [simple_pointer] */
948 0x2, /* FC_CHAR */
949 0x5c, /* FC_PAD */
950 0x5b, /* FC_END */
951 0x8, /* FC_LONG */
952 0x8, /* FC_LONG */
953 0x8, /* FC_LONG */
954 0x5c, /* FC_PAD */
955 0x5b, /* FC_END */
956 #endif
957 };
958
959 /* zero the entire structure, including the holes */
960 memset(&s1, 0, sizeof(s1));
961
962 /* FC_STRUCT */
963 s1.s = 0x1234;
964 s1.c = 0xa5;
965 s1.l1 = 0xdeadbeef;
966 s1.l2 = 0xcafebabe;
967 s1.ll = ((LONGLONG) 0xbadefeed << 32) | 0x2468ace0;
968
969 wiredatalen = 24;
970 memcpy(wiredata, &s1, wiredatalen);
971 test_simple_struct_marshal(fmtstr_simple_struct + 4, &s1, 24, wiredata, 24, NULL, 0, "struct");
972
973 if (use_pointer_ids)
974 *(unsigned int *)wiredata = 0x20000;
975 else
976 *(unsigned int *)wiredata = (UINT_PTR)&s1;
977 memcpy(wiredata + 4, &s1, wiredatalen);
978 test_pointer_marshal(fmtstr_simple_struct, &s1, 24, wiredata, 28, NULL, 0, "struct");
979
980 if (sizeof(void *) == 8) return; /* it cannot be represented as a simple struct on Win64 */
981
982 /* zero the entire structure, including the hole */
983 memset(&ps1, 0, sizeof(ps1));
984
985 /* FC_PSTRUCT */
986 ps1.l1 = 0xdeadbeef;
987 l = 0xcafebabe;
988 ps1.pl1 = &l;
989 c = 'a';
990 ps1.pc1 = &c;
991 *(unsigned int *)(wiredata + 4) = 0xdeadbeef;
992 if (use_pointer_ids)
993 {
994 *(unsigned int *)(wiredata + 8) = 0x20000;
995 *(unsigned int *)(wiredata + 12) = 0x20004;
996 }
997 else
998 {
999 *(unsigned int *)(wiredata + 8) = (UINT_PTR)&l;
1000 *(unsigned int *)(wiredata + 12) = (UINT_PTR)&c;
1001 }
1002 memcpy(wiredata + 16, &l, 4);
1003 memcpy(wiredata + 20, &c, 1);
1004
1005 test_simple_struct_marshal(fmtstr_pointer_struct + 4, &ps1, 17, wiredata + 4, 17, ps1_cmp, 2, "pointer_struct");
1006 if (use_pointer_ids)
1007 {
1008 *(unsigned int *)wiredata = 0x20000;
1009 *(unsigned int *)(wiredata + 8) = 0x20004;
1010 *(unsigned int *)(wiredata + 12) = 0x20008;
1011 }
1012 else
1013 *(unsigned int *)wiredata = (UINT_PTR)&ps1;
1014 test_pointer_marshal(fmtstr_pointer_struct, &ps1, 17, wiredata, 21, ps1_cmp, 2, "pointer_struct");
1015 }
1016
1017 static void test_fullpointer_xlat(void)
1018 {
1019 PFULL_PTR_XLAT_TABLES pXlatTables;
1020 ULONG RefId;
1021 int ret;
1022 void *Pointer;
1023
1024 pXlatTables = NdrFullPointerXlatInit(2, XLAT_CLIENT);
1025
1026 /* "marshaling" phase */
1027
1028 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
1029 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1030 ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%x\n", RefId);
1031
1032 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId);
1033 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1034 ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%x\n", RefId);
1035
1036 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId);
1037 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1038 ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%x\n", RefId);
1039
1040 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId);
1041 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1042 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1043
1044 ret = NdrFullPointerQueryPointer(pXlatTables, NULL, 0, &RefId);
1045 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1046 ok(RefId == 0, "RefId should be 0 instead of 0x%x\n", RefId);
1047
1048 /* "unmarshaling" phase */
1049
1050 ret = NdrFullPointerQueryRefId(pXlatTables, 0x0, 0, &Pointer);
1051 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1052
1053 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer);
1054 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1055 ok(Pointer == (void *)0xcafebabe, "Pointer should be 0xcafebabe instead of %p\n", Pointer);
1056
1057 ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 0, &Pointer);
1058 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1059 ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer);
1060
1061 NdrFullPointerInsertRefId(pXlatTables, 0x4, (void *)0xdeadbabe);
1062
1063 ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 1, &Pointer);
1064 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1065 ok(Pointer == (void *)0xdeadbabe, "Pointer should be (void *)0xdeadbabe instead of %p\n", Pointer);
1066
1067 NdrFullPointerXlatFree(pXlatTables);
1068
1069 pXlatTables = NdrFullPointerXlatInit(2, XLAT_SERVER);
1070
1071 /* "unmarshaling" phase */
1072
1073 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer);
1074 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1075 ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer);
1076
1077 NdrFullPointerInsertRefId(pXlatTables, 0x2, (void *)0xcafebabe);
1078
1079 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer);
1080 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1081 ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer);
1082
1083 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer);
1084 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1085 ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer);
1086
1087 /* "marshaling" phase */
1088
1089 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
1090 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1091 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1092
1093 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
1094 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1095 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1096
1097 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId);
1098 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1099 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1100
1101 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId);
1102 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1103 ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%x\n", RefId);
1104
1105 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId);
1106 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1107 ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId);
1108
1109 /* "freeing" phase */
1110
1111 ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebeef);
1112 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1113
1114 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0x20, &RefId);
1115 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1116 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1117
1118 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId);
1119 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1120 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId);
1121
1122 ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebabe);
1123 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1124
1125 ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef);
1126 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1127
1128 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0x20, &RefId);
1129 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1130 ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId);
1131
1132 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 1, &RefId);
1133 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1134 ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId);
1135
1136 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 1, &RefId);
1137 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret);
1138 ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId);
1139
1140 ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef);
1141 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret);
1142
1143 NdrFullPointerXlatFree(pXlatTables);
1144 }
1145
1146 /* verify stub data that is identical between client and server */
1147 static void test_common_stub_data( const char *prefix, const MIDL_STUB_MESSAGE *stubMsg )
1148 {
1149 void *unset_ptr;
1150
1151 memset(&unset_ptr, 0xcc, sizeof(unset_ptr));
1152
1153 #define TEST_ZERO(field, fmt) ok(stubMsg->field == 0, "%s: " #field " should have been set to zero instead of " fmt "\n", prefix, stubMsg->field)
1154 #define TEST_POINTER_UNSET(field) ok(stubMsg->field == unset_ptr, "%s: " #field " should have been unset instead of %p\n", prefix, stubMsg->field)
1155 #define TEST_ULONG_UNSET(field) ok(stubMsg->field == 0xcccccccc, "%s: " #field " should have been unset instead of 0x%x\n", prefix, stubMsg->field)
1156 #define TEST_ULONG_PTR_UNSET(field) ok(stubMsg->field == (ULONG_PTR)unset_ptr, "%s: " #field " should have been unset instead of 0x%lx\n", prefix, stubMsg->field)
1157
1158 TEST_POINTER_UNSET(BufferMark);
1159 TEST_ULONG_UNSET(MemorySize);
1160 TEST_POINTER_UNSET(Memory);
1161 TEST_ZERO(pAllocAllNodesContext, "%p");
1162 ok(stubMsg->pPointerQueueState == 0 ||
1163 broken(stubMsg->pPointerQueueState == unset_ptr), /* win2k */
1164 "%s: pPointerQueueState should have been unset instead of %p\n",
1165 prefix, stubMsg->pPointerQueueState);
1166 TEST_ZERO(IgnoreEmbeddedPointers, "%d");
1167 TEST_ZERO(PointerBufferMark, "%p");
1168 ok( stubMsg->uFlags == 0 ||
1169 broken(stubMsg->uFlags == 0xcc), /* win9x */
1170 "%s: uFlags should have been set to zero instead of 0x%x\n", prefix, stubMsg->uFlags );
1171 /* FIXME: UniquePtrCount */
1172 TEST_ULONG_PTR_UNSET(MaxCount);
1173 TEST_ULONG_UNSET(Offset);
1174 TEST_ULONG_UNSET(ActualCount);
1175 ok(stubMsg->pfnAllocate == my_alloc, "%s: pfnAllocate should have been %p instead of %p\n",
1176 prefix, my_alloc, stubMsg->pfnAllocate);
1177 ok(stubMsg->pfnFree == my_free, "%s: pfnFree should have been %p instead of %p\n",
1178 prefix, my_free, stubMsg->pfnFree);
1179 TEST_ZERO(StackTop, "%p");
1180 TEST_POINTER_UNSET(pPresentedType);
1181 TEST_POINTER_UNSET(pTransmitType);
1182 TEST_POINTER_UNSET(SavedHandle);
1183 ok(stubMsg->StubDesc == &Object_StubDesc, "%s: StubDesc should have been %p instead of %p\n",
1184 prefix, &Object_StubDesc, stubMsg->StubDesc);
1185 TEST_ZERO(FullPtrRefId, "%d");
1186 ok( stubMsg->PointerLength == 0 ||
1187 broken(stubMsg->PointerLength == 1), /* win9x, nt4 */
1188 "%s: pAsyncMsg should have been set to zero instead of %d\n", prefix, stubMsg->PointerLength );
1189 TEST_ZERO(fInDontFree, "%d");
1190 TEST_ZERO(fDontCallFreeInst, "%d");
1191 ok( stubMsg->fHasReturn == 0 || broken(stubMsg->fHasReturn), /* win9x, nt4 */
1192 "%s: fHasReturn should have been set to zero instead of %d\n", prefix, stubMsg->fHasReturn );
1193 TEST_ZERO(fHasExtensions, "%d");
1194 TEST_ZERO(fHasNewCorrDesc, "%d");
1195 ok(stubMsg->fIsIn == 0 || broken(stubMsg->fIsIn), /* win9x, nt4 */
1196 "%s: fIsIn should have been set to 0 instead of %d\n", prefix, stubMsg->fIsIn);
1197 TEST_ZERO(fIsOicf, "%d");
1198 ok(stubMsg->fBufferValid == 0,
1199 "%s: fBufferValid should have been set to 0 instead of %d\n", prefix, stubMsg->fBufferValid);
1200 TEST_ZERO(fNeedMCCP, "%d");
1201 ok(stubMsg->fUnused == 0 ||
1202 stubMsg->fUnused == -2, /* Vista */
1203 "%s: fUnused should have been set to 0 or -2 instead of %d\n", prefix, stubMsg->fUnused);
1204 ok(stubMsg->fUnused2 == 0xffffcccc, "%s: fUnused2 should have been 0xffffcccc instead of 0x%x\n",
1205 prefix, stubMsg->fUnused2);
1206 ok(stubMsg->dwDestContext == MSHCTX_DIFFERENTMACHINE,
1207 "%s: dwDestContext should have been MSHCTX_DIFFERENTMACHINE instead of %d\n",
1208 prefix, stubMsg->dwDestContext);
1209 TEST_ZERO(pvDestContext, "%p");
1210 TEST_POINTER_UNSET(SavedContextHandles);
1211 TEST_ULONG_UNSET(ParamNumber);
1212 TEST_ZERO(pRpcChannelBuffer, "%p");
1213 TEST_ZERO(pArrayInfo, "%p");
1214 TEST_POINTER_UNSET(SizePtrCountArray);
1215 TEST_POINTER_UNSET(SizePtrOffsetArray);
1216 TEST_POINTER_UNSET(SizePtrLengthArray);
1217 TEST_POINTER_UNSET(pArgQueue);
1218 TEST_ZERO(dwStubPhase, "%d");
1219 /* FIXME: where does this value come from? */
1220 trace("%s: LowStackMark is %p\n", prefix, stubMsg->LowStackMark);
1221 ok( stubMsg->pAsyncMsg == 0 || broken(stubMsg->pAsyncMsg == unset_ptr), /* win9x, nt4 */
1222 "%s: pAsyncMsg should have been set to zero instead of %p\n", prefix, stubMsg->pAsyncMsg );
1223 ok( stubMsg->pCorrInfo == 0 || broken(stubMsg->pCorrInfo == unset_ptr), /* win9x, nt4 */
1224 "%s: pCorrInfo should have been set to zero instead of %p\n", prefix, stubMsg->pCorrInfo );
1225 ok( stubMsg->pCorrMemory == 0 || broken(stubMsg->pCorrMemory == unset_ptr), /* win9x, nt4 */
1226 "%s: pCorrMemory should have been set to zero instead of %p\n", prefix, stubMsg->pCorrMemory );
1227 ok( stubMsg->pMemoryList == 0 || broken(stubMsg->pMemoryList == unset_ptr), /* win9x, nt4 */
1228 "%s: pMemoryList should have been set to zero instead of %p\n", prefix, stubMsg->pMemoryList );
1229 TEST_POINTER_UNSET(pCSInfo);
1230 TEST_POINTER_UNSET(ConformanceMark);
1231 TEST_POINTER_UNSET(VarianceMark);
1232 ok(stubMsg->Unused == (ULONG_PTR)unset_ptr, "%s: Unused should have be unset instead of 0x%lx\n",
1233 prefix, stubMsg->Unused);
1234 TEST_POINTER_UNSET(pContext);
1235 TEST_POINTER_UNSET(ContextHandleHash);
1236 TEST_POINTER_UNSET(pUserMarshalList);
1237 TEST_ULONG_PTR_UNSET(Reserved51_3);
1238 TEST_ULONG_PTR_UNSET(Reserved51_4);
1239 TEST_ULONG_PTR_UNSET(Reserved51_5);
1240
1241 #undef TEST_ULONG_PTR_UNSET
1242 #undef TEST_ULONG_UNSET
1243 #undef TEST_POINTER_UNSET
1244 #undef TEST_ZERO
1245 }
1246
1247 static void test_client_init(void)
1248 {
1249 MIDL_STUB_MESSAGE stubMsg;
1250 RPC_MESSAGE rpcMsg;
1251 void *unset_ptr;
1252
1253 memset(&rpcMsg, 0xcc, sizeof(rpcMsg));
1254 memset(&stubMsg, 0xcc, sizeof(stubMsg));
1255 memset(&unset_ptr, 0xcc, sizeof(unset_ptr));
1256
1257 NdrClientInitializeNew(&rpcMsg, &stubMsg, &Object_StubDesc, 1);
1258
1259 test_common_stub_data( "NdrClientInitializeNew", &stubMsg );
1260
1261 ok(stubMsg.RpcMsg == &rpcMsg, "stubMsg.RpcMsg should have been %p instead of %p\n", &rpcMsg, stubMsg.RpcMsg);
1262 ok(rpcMsg.Handle == NULL, "rpcMsg.Handle should have been NULL instead of %p\n", rpcMsg.Handle);
1263 ok(rpcMsg.Buffer == unset_ptr, "rpcMsg.Buffer should have been unset instead of %p\n",
1264 rpcMsg.Buffer);
1265 ok(rpcMsg.BufferLength == 0xcccccccc, "rpcMsg.BufferLength should have been unset instead of %d\n", rpcMsg.BufferLength);
1266 ok(rpcMsg.ProcNum == 0x8001, "rpcMsg.ProcNum should have been 0x8001 instead of 0x%x\n", rpcMsg.ProcNum);
1267 ok(rpcMsg.TransferSyntax == unset_ptr, "rpcMsg.TransferSyntax should have been unset instead of %p\n", rpcMsg.TransferSyntax);
1268 ok(rpcMsg.RpcInterfaceInformation == Object_StubDesc.RpcInterfaceInformation,
1269 "rpcMsg.RpcInterfaceInformation should have been %p instead of %p\n",
1270 Object_StubDesc.RpcInterfaceInformation, rpcMsg.RpcInterfaceInformation);
1271 /* Note: ReservedForRuntime not tested */
1272 ok(rpcMsg.ManagerEpv == unset_ptr, "rpcMsg.ManagerEpv should have been unset instead of %p\n", rpcMsg.ManagerEpv);
1273 ok(rpcMsg.ImportContext == unset_ptr, "rpcMsg.ImportContext should have been unset instead of %p\n", rpcMsg.ImportContext);
1274 ok(rpcMsg.RpcFlags == 0, "rpcMsg.RpcFlags should have been 0 instead of 0x%x\n", rpcMsg.RpcFlags);
1275
1276 ok(stubMsg.Buffer == unset_ptr, "stubMsg.Buffer should have been unset instead of %p\n",
1277 stubMsg.Buffer);
1278 ok(stubMsg.BufferStart == NULL, "stubMsg.BufferStart should have been NULL instead of %p\n",
1279 stubMsg.BufferStart);
1280 ok(stubMsg.BufferEnd == NULL, "stubMsg.BufferEnd should have been NULL instead of %p\n",
1281 stubMsg.BufferEnd);
1282 ok(stubMsg.BufferLength == 0, "stubMsg.BufferLength should have been 0 instead of %u\n",
1283 stubMsg.BufferLength);
1284 ok(stubMsg.IsClient == 1, "stubMsg.IsClient should have been 1 instead of %u\n", stubMsg.IsClient);
1285 ok(stubMsg.ReuseBuffer == 0, "stubMsg.ReuseBuffer should have been 0 instead of %d\n",
1286 stubMsg.ReuseBuffer);
1287 ok(stubMsg.CorrDespIncrement == 0, "stubMsg.CorrDespIncrement should have been 0 instead of %d\n",
1288 stubMsg.CorrDespIncrement);
1289 ok(stubMsg.FullPtrXlatTables == unset_ptr, "stubMsg.FullPtrXlatTables should have been unset instead of %p\n",
1290 stubMsg.FullPtrXlatTables);
1291 }
1292
1293 static void test_server_init(void)
1294 {
1295 MIDL_STUB_MESSAGE stubMsg;
1296 RPC_MESSAGE rpcMsg;
1297 unsigned char *ret;
1298 unsigned char buffer[256];
1299
1300 memset(&rpcMsg, 0, sizeof(rpcMsg));
1301 rpcMsg.Buffer = buffer;
1302 rpcMsg.BufferLength = sizeof(buffer);
1303 rpcMsg.RpcFlags = RPC_BUFFER_COMPLETE;
1304
1305 memset(&stubMsg, 0xcc, sizeof(stubMsg));
1306
1307 ret = NdrServerInitializeNew(&rpcMsg, &stubMsg, &Object_StubDesc);
1308 ok(ret == NULL, "NdrServerInitializeNew should have returned NULL instead of %p\n", ret);
1309
1310 test_common_stub_data( "NdrServerInitializeNew", &stubMsg );
1311
1312 ok(stubMsg.RpcMsg == &rpcMsg, "stubMsg.RpcMsg should have been %p instead of %p\n", &rpcMsg, stubMsg.RpcMsg);
1313 ok(stubMsg.Buffer == buffer, "stubMsg.Buffer should have been %p instead of %p\n", buffer, stubMsg.Buffer);
1314 ok(stubMsg.BufferStart == buffer, "stubMsg.BufferStart should have been %p instead of %p\n", buffer, stubMsg.BufferStart);
1315 ok(stubMsg.BufferEnd == buffer + sizeof(buffer), "stubMsg.BufferEnd should have been %p instead of %p\n", buffer + sizeof(buffer), stubMsg.BufferEnd);
1316 todo_wine
1317 ok(stubMsg.BufferLength == 0, "stubMsg.BufferLength should have been 0 instead of %u\n", stubMsg.BufferLength);
1318 ok(stubMsg.IsClient == 0, "stubMsg.IsClient should have been 0 instead of %u\n", stubMsg.IsClient);
1319 ok(stubMsg.ReuseBuffer == 0 ||
1320 broken(stubMsg.ReuseBuffer == 1), /* win2k */
1321 "stubMsg.ReuseBuffer should have been set to zero instead of %d\n", stubMsg.ReuseBuffer);
1322 ok(stubMsg.CorrDespIncrement == 0xcc ||
1323 stubMsg.CorrDespIncrement == 0,
1324 "CorrDespIncrement should have been unset instead of 0x%x\n", stubMsg.CorrDespIncrement);
1325 ok(stubMsg.FullPtrXlatTables == 0, "stubMsg.BufferLength should have been 0 instead of %p\n", stubMsg.FullPtrXlatTables);
1326 }
1327
1328 static void test_ndr_allocate(void)
1329 {
1330 RPC_MESSAGE RpcMessage;
1331 MIDL_STUB_MESSAGE StubMsg;
1332 MIDL_STUB_DESC StubDesc;
1333 void *p1, *p2;
1334 struct tag_mem_list_v2_t
1335 {
1336 DWORD magic;
1337 DWORD size;
1338 DWORD unknown;
1339 struct tag_mem_list_v2_t *next;
1340 } *mem_list_v2;
1341 const DWORD magic_MEML = 'M' << 24 | 'E' << 16 | 'M' << 8 | 'L';
1342
1343 StubDesc = Object_StubDesc;
1344 NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0);
1345
1346 my_alloc_called = my_free_called = 0;
1347 p1 = NdrAllocate(&StubMsg, 10);
1348 p2 = NdrAllocate(&StubMsg, 24);
1349 ok(my_alloc_called == 2, "alloc called %d\n", my_alloc_called);
1350 ok(StubMsg.pMemoryList != NULL, "StubMsg.pMemoryList NULL\n");
1351 if(StubMsg.pMemoryList)
1352 {
1353 mem_list_v2 = StubMsg.pMemoryList;
1354 if (mem_list_v2->size == 24)
1355 {
1356 trace("v2 mem list format\n");
1357 ok((char *)mem_list_v2 == (char *)p2 + 24, "expected mem_list_v2 pointer %p, but got %p\n", (char *)p2 + 24, mem_list_v2);
1358 ok(mem_list_v2->magic == magic_MEML, "magic %08x\n", mem_list_v2->magic);
1359 ok(mem_list_v2->size == 24, "wrong size for p2 %d\n", mem_list_v2->size);
1360 ok(mem_list_v2->unknown == 0, "wrong unknown for p2 0x%x\n", mem_list_v2->unknown);
1361 ok(mem_list_v2->next != NULL, "next NULL\n");
1362 mem_list_v2 = mem_list_v2->next;
1363 if(mem_list_v2)
1364 {
1365 ok((char *)mem_list_v2 == (char *)p1 + 16, "expected mem_list_v2 pointer %p, but got %p\n", (char *)p1 + 16, mem_list_v2);
1366 ok(mem_list_v2->magic == magic_MEML, "magic %08x\n", mem_list_v2->magic);
1367 ok(mem_list_v2->size == 16, "wrong size for p1 %d\n", mem_list_v2->size);
1368 ok(mem_list_v2->unknown == 0, "wrong unknown for p1 0x%x\n", mem_list_v2->unknown);
1369 ok(mem_list_v2->next == NULL, "next %p\n", mem_list_v2->next);
1370 }
1371 }
1372 else win_skip("v1 mem list format\n");
1373 }
1374 /* NdrFree isn't exported so we can't test free'ing */
1375 }
1376
1377 static void test_conformant_array(void)
1378 {
1379 RPC_MESSAGE RpcMessage;
1380 MIDL_STUB_MESSAGE StubMsg;
1381 MIDL_STUB_DESC StubDesc;
1382 void *ptr;
1383 unsigned char *mem, *mem_orig;
1384 unsigned char memsrc[20];
1385 unsigned int i;
1386
1387 static const unsigned char fmtstr_conf_array[] =
1388 {
1389 0x1b, /* FC_CARRAY */
1390 0x0, /* align */
1391 NdrFcShort( 0x1 ), /* elem size */
1392 0x40, /* Corr desc: const */
1393 0x0,
1394 NdrFcShort(0x10), /* const = 0x10 */
1395 0x1, /* FC_BYTE */
1396 0x5b /* FC_END */
1397 };
1398
1399 for (i = 0; i < sizeof(memsrc); i++)
1400 memsrc[i] = i * i;
1401
1402 StubDesc = Object_StubDesc;
1403 StubDesc.pFormatTypes = fmtstr_conf_array;
1404
1405 NdrClientInitializeNew(
1406 &RpcMessage,
1407 &StubMsg,
1408 &StubDesc,
1409 0);
1410
1411 StubMsg.BufferLength = 0;
1412 NdrConformantArrayBufferSize( &StubMsg,
1413 memsrc,
1414 fmtstr_conf_array );
1415 ok(StubMsg.BufferLength >= 20, "length %d\n", StubMsg.BufferLength);
1416
1417 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1418 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1419 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1420
1421 ptr = NdrConformantArrayMarshall( &StubMsg, memsrc, fmtstr_conf_array );
1422 ok(ptr == NULL, "ret %p\n", ptr);
1423 ok(StubMsg.Buffer - StubMsg.BufferStart == 20, "Buffer %p Start %p len %d\n", StubMsg.Buffer, StubMsg.BufferStart, 20);
1424 ok(!memcmp(StubMsg.BufferStart + 4, memsrc, 16), "incorrectly marshaled\n");
1425
1426 StubMsg.Buffer = StubMsg.BufferStart;
1427 StubMsg.MemorySize = 0;
1428 mem = NULL;
1429
1430 /* Client */
1431 my_alloc_called = 0;
1432 /* passing mem == NULL with must_alloc == 0 crashes under Windows */
1433 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1);
1434 ok(mem != NULL, "mem not alloced\n");
1435 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1436 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1437
1438 my_alloc_called = 0;
1439 StubMsg.Buffer = StubMsg.BufferStart;
1440 mem_orig = mem;
1441 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0);
1442 ok(mem == mem_orig, "mem alloced\n");
1443 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1444 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1445
1446 my_alloc_called = 0;
1447 StubMsg.Buffer = StubMsg.BufferStart;
1448 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1);
1449 ok(mem != mem_orig, "mem not alloced\n");
1450 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1451 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1452
1453 my_free_called = 0;
1454 StubMsg.Buffer = StubMsg.BufferStart;
1455 NdrConformantArrayFree( &StubMsg, mem, fmtstr_conf_array );
1456 ok(my_free_called == 0, "free called %d\n", my_free_called);
1457 StubMsg.pfnFree(mem);
1458
1459 /* Server */
1460 my_alloc_called = 0;
1461 StubMsg.IsClient = 0;
1462 mem = NULL;
1463 StubMsg.Buffer = StubMsg.BufferStart;
1464 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0);
1465 ok(mem == StubMsg.BufferStart + 4 || broken(!mem), /* win9x, nt4 */
1466 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 4);
1467 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1468 my_alloc_called = 0;
1469 mem = NULL;
1470 StubMsg.Buffer = StubMsg.BufferStart;
1471 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1);
1472 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1473 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1474 StubMsg.pfnFree(mem);
1475
1476 my_alloc_called = 0;
1477 mem = mem_orig;
1478 StubMsg.Buffer = StubMsg.BufferStart;
1479 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0);
1480 ok(mem == mem_orig, "mem alloced\n");
1481 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1482
1483 my_alloc_called = 0;
1484 mem = mem_orig;
1485 StubMsg.Buffer = StubMsg.BufferStart;
1486 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1);
1487 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n");
1488 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1489 StubMsg.pfnFree(mem);
1490 StubMsg.pfnFree(mem_orig);
1491
1492 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1493 }
1494
1495 static void test_conformant_string(void)
1496 {
1497 RPC_MESSAGE RpcMessage;
1498 MIDL_STUB_MESSAGE StubMsg;
1499 MIDL_STUB_DESC StubDesc;
1500 DWORD size;
1501 void *ptr;
1502 unsigned char *mem, *mem_orig;
1503 char memsrc[] = "This is a test string";
1504
1505 static const unsigned char fmtstr_conf_str[] =
1506 {
1507 0x11, 0x8, /* FC_RP [simple_pointer] */
1508 0x22, /* FC_C_CSTRING */
1509 0x5c, /* FC_PAD */
1510 };
1511
1512 StubDesc = Object_StubDesc;
1513 StubDesc.pFormatTypes = fmtstr_conf_str;
1514
1515 memset( &StubMsg, 0, sizeof(StubMsg) ); /* needed on win9x and nt4 */
1516 NdrClientInitializeNew(
1517 &RpcMessage,
1518 &StubMsg,
1519 &StubDesc,
1520 0);
1521
1522 StubMsg.BufferLength = 0;
1523 NdrPointerBufferSize( &StubMsg,
1524 (unsigned char *)memsrc,
1525 fmtstr_conf_str );
1526 ok(StubMsg.BufferLength >= sizeof(memsrc) + 12, "length %d\n", StubMsg.BufferLength);
1527
1528 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1529 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1530 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1531
1532 ptr = NdrPointerMarshall( &StubMsg, (unsigned char *)memsrc, fmtstr_conf_str );
1533 ok(ptr == NULL, "ret %p\n", ptr);
1534 size = StubMsg.Buffer - StubMsg.BufferStart;
1535 ok(size == sizeof(memsrc) + 12, "Buffer %p Start %p len %d\n",
1536 StubMsg.Buffer, StubMsg.BufferStart, size);
1537 ok(!memcmp(StubMsg.BufferStart + 12, memsrc, sizeof(memsrc)), "incorrectly marshaled\n");
1538
1539 StubMsg.Buffer = StubMsg.BufferStart;
1540 StubMsg.MemorySize = 0;
1541 mem = NULL;
1542
1543 /* Client */
1544 my_alloc_called = 0;
1545 StubMsg.Buffer = StubMsg.BufferStart;
1546 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc));
1547 /* Windows apparently checks string length on the output buffer to determine its size... */
1548 memset( mem, 'x', sizeof(memsrc) - 1 );
1549 mem[sizeof(memsrc) - 1] = 0;
1550 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0);
1551 ok(mem == mem_orig, "mem not alloced\n");
1552 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1553
1554 my_alloc_called = 0;
1555 StubMsg.Buffer = StubMsg.BufferStart;
1556 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1);
1557 todo_wine {
1558 ok(mem == mem_orig, "mem not alloced\n");
1559 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1560 }
1561
1562 my_free_called = 0;
1563 StubMsg.Buffer = StubMsg.BufferStart;
1564 NdrPointerFree( &StubMsg, mem, fmtstr_conf_str );
1565 ok(my_free_called == 1, "free called %d\n", my_free_called);
1566
1567 mem = my_alloc(10);
1568 my_free_called = 0;
1569 StubMsg.Buffer = StubMsg.BufferStart;
1570 NdrPointerFree( &StubMsg, mem, fmtstr_conf_str );
1571 ok(my_free_called == 1, "free called %d\n", my_free_called);
1572
1573 /* Server */
1574 my_alloc_called = 0;
1575 StubMsg.IsClient = 0;
1576 mem = NULL;
1577 StubMsg.Buffer = StubMsg.BufferStart;
1578 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0);
1579 ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
1580 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
1581 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1582
1583 my_alloc_called = 0;
1584 mem = NULL;
1585 StubMsg.Buffer = StubMsg.BufferStart;
1586 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1);
1587 todo_wine {
1588 ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
1589 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
1590 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1591 }
1592
1593 my_alloc_called = 0;
1594 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc));
1595 StubMsg.Buffer = StubMsg.BufferStart;
1596 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0);
1597 ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
1598 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
1599 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1600
1601 my_alloc_called = 0;
1602 mem = mem_orig;
1603 StubMsg.Buffer = StubMsg.BufferStart;
1604 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1);
1605 todo_wine {
1606 ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
1607 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
1608 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1609 }
1610
1611 mem = my_alloc(10);
1612 my_free_called = 0;
1613 StubMsg.Buffer = StubMsg.BufferStart;
1614 NdrPointerFree( &StubMsg, mem, fmtstr_conf_str );
1615 ok(my_free_called == 1, "free called %d\n", my_free_called);
1616
1617 HeapFree(GetProcessHeap(), 0, mem_orig);
1618 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1619 }
1620
1621 static void test_nonconformant_string(void)
1622 {
1623 RPC_MESSAGE RpcMessage;
1624 MIDL_STUB_MESSAGE StubMsg;
1625 MIDL_STUB_DESC StubDesc;
1626 DWORD size;
1627 void *ptr;
1628 unsigned char *mem, *mem_orig;
1629 unsigned char memsrc[10] = "This is";
1630 unsigned char memsrc2[10] = "This is a";
1631
1632 static const unsigned char fmtstr_nonconf_str[] =
1633 {
1634 0x26, /* FC_CSTRING */
1635 0x5c, /* FC_PAD */
1636 NdrFcShort( 0xa ), /* 10 */
1637 };
1638
1639 StubDesc = Object_StubDesc;
1640 StubDesc.pFormatTypes = fmtstr_nonconf_str;
1641
1642 /* length < size */
1643 NdrClientInitializeNew(
1644 &RpcMessage,
1645 &StubMsg,
1646 &StubDesc,
1647 0);
1648
1649 StubMsg.BufferLength = 0;
1650
1651 NdrNonConformantStringBufferSize( &StubMsg, memsrc, fmtstr_nonconf_str );
1652 ok(StubMsg.BufferLength >= strlen((char *)memsrc) + 1 + 8, "length %d\n", StubMsg.BufferLength);
1653
1654 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1655 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1656 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1657
1658 ptr = NdrNonConformantStringMarshall( &StubMsg, memsrc, fmtstr_nonconf_str );
1659 ok(ptr == NULL, "ret %p\n", ptr);
1660 size = StubMsg.Buffer - StubMsg.BufferStart;
1661 ok(size == strlen((char *)memsrc) + 1 + 8, "Buffer %p Start %p len %d\n",
1662 StubMsg.Buffer, StubMsg.BufferStart, size);
1663 ok(!memcmp(StubMsg.BufferStart + 8, memsrc, strlen((char *)memsrc) + 1), "incorrectly marshaled\n");
1664
1665 StubMsg.Buffer = StubMsg.BufferStart;
1666 StubMsg.MemorySize = 0;
1667 mem = NULL;
1668
1669 /* Client */
1670 my_alloc_called = 0;
1671 StubMsg.Buffer = StubMsg.BufferStart;
1672 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc));
1673 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1674 ok(mem == mem_orig, "mem alloced\n");
1675 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1676
1677 my_alloc_called = 0;
1678 StubMsg.Buffer = StubMsg.BufferStart;
1679 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1);
1680 todo_wine
1681 ok(mem == mem_orig, "mem alloced\n");
1682 todo_wine
1683 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1684
1685 /* Server */
1686 my_alloc_called = 0;
1687 StubMsg.IsClient = 0;
1688 mem = NULL;
1689 StubMsg.Buffer = StubMsg.BufferStart;
1690 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1691 ok(mem != mem_orig, "mem not alloced\n");
1692 ok(mem != StubMsg.BufferStart + 8, "mem pointing at buffer\n");
1693 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1694 NdrOleFree(mem);
1695
1696 my_alloc_called = 0;
1697 mem = mem_orig;
1698 StubMsg.Buffer = StubMsg.BufferStart;
1699 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1700 ok(mem == mem_orig, "mem alloced\n");
1701 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1702
1703 my_alloc_called = 0;
1704 mem = mem_orig;
1705 StubMsg.Buffer = StubMsg.BufferStart;
1706 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1);
1707 todo_wine
1708 ok(mem == mem_orig, "mem alloced\n");
1709 todo_wine
1710 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1711
1712 HeapFree(GetProcessHeap(), 0, mem_orig);
1713 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1714
1715 /* length = size */
1716 NdrClientInitializeNew(
1717 &RpcMessage,
1718 &StubMsg,
1719 &StubDesc,
1720 0);
1721
1722 StubMsg.BufferLength = 0;
1723
1724 NdrNonConformantStringBufferSize( &StubMsg, memsrc2, fmtstr_nonconf_str );
1725 ok(StubMsg.BufferLength >= strlen((char *)memsrc2) + 1 + 8, "length %d\n", StubMsg.BufferLength);
1726
1727 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1728 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1729 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1730
1731 ptr = NdrNonConformantStringMarshall( &StubMsg, memsrc2, fmtstr_nonconf_str );
1732 ok(ptr == NULL, "ret %p\n", ptr);
1733 size = StubMsg.Buffer - StubMsg.BufferStart;
1734 ok(size == strlen((char *)memsrc2) + 1 + 8, "Buffer %p Start %p len %d\n",
1735 StubMsg.Buffer, StubMsg.BufferStart, size);
1736 ok(!memcmp(StubMsg.BufferStart + 8, memsrc2, strlen((char *)memsrc2) + 1), "incorrectly marshaled\n");
1737
1738 StubMsg.Buffer = StubMsg.BufferStart;
1739 StubMsg.MemorySize = 0;
1740 mem = NULL;
1741
1742 /* Client */
1743 my_alloc_called = 0;
1744 StubMsg.Buffer = StubMsg.BufferStart;
1745 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc));
1746 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1747 ok(mem == mem_orig, "mem alloced\n");
1748 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1749
1750 my_alloc_called = 0;
1751 StubMsg.Buffer = StubMsg.BufferStart;
1752 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1);
1753 todo_wine
1754 ok(mem == mem_orig, "mem alloced\n");
1755 todo_wine
1756 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1757
1758 /* Server */
1759 my_alloc_called = 0;
1760 StubMsg.IsClient = 0;
1761 mem = NULL;
1762 StubMsg.Buffer = StubMsg.BufferStart;
1763 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1764 ok(mem != mem_orig, "mem not alloced\n");
1765 ok(mem != StubMsg.BufferStart + 8, "mem pointing at buffer\n");
1766 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
1767 NdrOleFree(mem);
1768
1769 my_alloc_called = 0;
1770 mem = mem_orig;
1771 StubMsg.Buffer = StubMsg.BufferStart;
1772 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0);
1773 ok(mem == mem_orig, "mem alloced\n");
1774 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1775
1776 my_alloc_called = 0;
1777 mem = mem_orig;
1778 StubMsg.Buffer = StubMsg.BufferStart;
1779 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1);
1780 todo_wine
1781 ok(mem == mem_orig, "mem alloced\n");
1782 todo_wine
1783 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
1784
1785 HeapFree(GetProcessHeap(), 0, mem_orig);
1786 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1787 }
1788
1789 static void test_conf_complex_struct(void)
1790 {
1791 RPC_MESSAGE RpcMessage;
1792 MIDL_STUB_MESSAGE StubMsg;
1793 MIDL_STUB_DESC StubDesc;
1794 void *ptr;
1795 unsigned int i;
1796 struct conf_complex
1797 {
1798 unsigned int size;
1799 unsigned int *array[1];
1800 };
1801 struct conf_complex *memsrc;
1802 struct conf_complex *mem;
1803
1804 static const unsigned char fmtstr_complex_struct[] =
1805 {
1806 /* 0 */
1807 0x1b, /* FC_CARRAY */
1808 0x3, /* 3 */
1809 /* 2 */ NdrFcShort( 0x4 ), /* 4 */
1810 /* 4 */ 0x8, /* Corr desc: FC_LONG */
1811 0x0, /* */
1812 /* 6 */ NdrFcShort( 0xfffc ), /* -4 */
1813 /* 8 */
1814 0x4b, /* FC_PP */
1815 0x5c, /* FC_PAD */
1816 /* 10 */
1817 0x48, /* FC_VARIABLE_REPEAT */
1818 0x49, /* FC_FIXED_OFFSET */
1819 /* 12 */ NdrFcShort( 0x4 ), /* 4 */
1820 /* 14 */ NdrFcShort( 0x0 ), /* 0 */
1821 /* 16 */ NdrFcShort( 0x1 ), /* 1 */
1822 /* 18 */ NdrFcShort( 0x0 ), /* 0 */
1823 /* 20 */ NdrFcShort( 0x0 ), /* 0 */
1824 /* 22 */ 0x12, 0x8, /* FC_UP [simple_pointer] */
1825 /* 24 */ 0x8, /* FC_LONG */
1826 0x5c, /* FC_PAD */
1827 /* 26 */
1828 0x5b, /* FC_END */
1829
1830 0x8, /* FC_LONG */
1831 /* 28 */ 0x5c, /* FC_PAD */
1832 0x5b, /* FC_END */
1833 /* 30 */
1834 0x1a, /* FC_BOGUS_STRUCT */
1835 0x3, /* 3 */
1836 /* 32 */ NdrFcShort( 0x4 ), /* 4 */
1837 /* 34 */ NdrFcShort( 0xffffffde ), /* Offset= -34 (0) */
1838 /* 36 */ NdrFcShort( 0x0 ), /* Offset= 0 (36) */
1839 /* 38 */ 0x8, /* FC_LONG */
1840 0x5b, /* FC_END */
1841 };
1842
1843 memsrc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1844 FIELD_OFFSET(struct conf_complex, array[20]));
1845 memsrc->size = 20;
1846
1847 StubDesc = Object_StubDesc;
1848 StubDesc.pFormatTypes = fmtstr_complex_struct;
1849
1850 NdrClientInitializeNew(
1851 &RpcMessage,
1852 &StubMsg,
1853 &StubDesc,
1854 0);
1855
1856 StubMsg.BufferLength = 0;
1857 NdrComplexStructBufferSize( &StubMsg,
1858 (unsigned char *)memsrc,
1859 &fmtstr_complex_struct[30] );
1860 ok(StubMsg.BufferLength >= 28, "length %d\n", StubMsg.BufferLength);
1861
1862 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
1863 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
1864 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
1865
1866 ptr = NdrComplexStructMarshall( &StubMsg, (unsigned char *)memsrc,
1867 &fmtstr_complex_struct[30] );
1868 ok(ptr == NULL, "ret %p\n", ptr);
1869 ok(*(unsigned int *)StubMsg.BufferStart == 20, "Conformance should have been 20 instead of %d\n", *(unsigned int *)StubMsg.BufferStart);
1870 ok(*(unsigned int *)(StubMsg.BufferStart + 4) == 20, "conf_complex.size should have been 20 instead of %d\n", *(unsigned int *)(StubMsg.BufferStart + 4));
1871 for (i = 0; i < 20; i++)
1872 ok(*(unsigned int *)(StubMsg.BufferStart + 8 + i * 4) == 0, "pointer id for conf_complex.array[%d] should have been 0 instead of 0x%x\n", i, *(unsigned int *)(StubMsg.BufferStart + 8 + i * 4));
1873
1874 /* Server */
1875 my_alloc_called = 0;
1876 StubMsg.IsClient = 0;
1877 mem = NULL;
1878 StubMsg.Buffer = StubMsg.BufferStart;
1879 ptr = NdrComplexStructUnmarshall( &StubMsg, (unsigned char **)&mem, &fmtstr_complex_struct[30], 0);
1880 ok(ptr == NULL, "ret %p\n", ptr);
1881 ok(mem->size == 20, "mem->size wasn't unmarshalled correctly (%d)\n", mem->size);
1882 ok(mem->array[0] == NULL, "mem->array[0] wasn't unmarshalled correctly (%p)\n", mem->array[0]);
1883 StubMsg.pfnFree(mem);
1884
1885 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
1886 HeapFree(GetProcessHeap(), 0, memsrc);
1887 }
1888
1889
1890 static void test_conf_complex_array(void)
1891 {
1892 RPC_MESSAGE RpcMessage;
1893 MIDL_STUB_MESSAGE StubMsg;
1894 MIDL_STUB_DESC StubDesc;
1895 void *ptr;
1896 unsigned int i, j;
1897 struct conf_complex
1898 {
1899 unsigned int dim1, dim2;
1900 DWORD **array;
1901 };
1902 struct conf_complex memsrc;
1903 struct conf_complex *mem;
1904 DWORD *buf, expected_length;
1905
1906 static const unsigned char fmtstr_complex_array[] =
1907 {
1908
1909 /* 0 */ 0x21, /* FC_BOGUS_ARRAY */
1910 0x3, /* 3 */
1911 /* 2 */ NdrFcShort( 0x0 ), /* 0 */
1912 /* 4 */ 0x19, 0x0, /* Corr desc: field pointer, FC_ULONG */
1913 /* 6 */ NdrFcShort( 0x4 ), /* 4 */
1914 /* 8 */ NdrFcLong( 0xffffffff ), /* -1 */
1915 /* 12 */ 0x8, /* FC_LONG */
1916 0x5b, /* FC_END */
1917 /* 14 */
1918 0x21, /* FC_BOGUS_ARRAY */
1919 0x3, /* 3 */
1920 /* 16 */ NdrFcShort( 0x0 ), /* 0 */
1921 /* 18 */ 0x19, /* Corr desc: field pointer, FC_ULONG */
1922 0x0, /* */
1923 /* 20 */ NdrFcShort( 0x0 ), /* 0 */
1924 /* 22 */ NdrFcLong( 0xffffffff ), /* -1 */
1925 /* 26 */ 0x12, 0x0, /* FC_UP */
1926 /* 28 */ NdrFcShort( 0xffe4 ), /* Offset= -28 (0) */
1927 /* 30 */ 0x5c, /* FC_PAD */
1928 0x5b, /* FC_END */
1929
1930 #ifdef _WIN64
1931 /* 32 */ 0x1a, /* FC_BOGUS_STRUCT */
1932 0x3, /* 3 */
1933 /* 34 */ NdrFcShort( 0x10 ), /* 16 */
1934 /* 36 */ NdrFcShort( 0x0 ), /* 0 */
1935 /* 38 */ NdrFcShort( 0x6 ), /* Offset= 6 (44) */
1936 /* 40 */ 0x8, /* FC_LONG */
1937 0x8, /* FC_LONG */
1938 /* 42 */ 0x36, /* FC_POINTER */
1939 0x5b, /* FC_END */
1940 /* 44 */
1941 0x12, 0x0, /* FC_UP */
1942 /* 46 */ NdrFcShort( 0xffe0 ), /* Offset= -32 (14) */
1943 #else
1944 /* 32 */
1945 0x16, /* FC_PSTRUCT */
1946 0x3, /* 3 */
1947 /* 34 */ NdrFcShort( 0xc ), /* 12 */
1948 /* 36 */ 0x4b, /* FC_PP */
1949 0x5c, /* FC_PAD */
1950 /* 38 */ 0x46, /* FC_NO_REPEAT */
1951 0x5c, /* FC_PAD */
1952 /* 40 */ NdrFcShort( 0x8 ), /* 8 */
1953 /* 42 */ NdrFcShort( 0x8 ), /* 8 */
1954 /* 44 */ 0x12, 0x0, /* FC_UP */
1955 /* 46 */ NdrFcShort( 0xffe0 ), /* Offset= -32 (14) */
1956 /* 48 */ 0x5b, /* FC_END */
1957 0x8, /* FC_LONG */
1958 /* 50 */ 0x8, /* FC_LONG */
1959 0x8, /* FC_LONG */
1960 /* 52 */ 0x5c, /* FC_PAD */
1961 0x5b, /* FC_END */
1962 #endif
1963 };
1964
1965 memsrc.dim1 = 5;
1966 memsrc.dim2 = 3;
1967
1968 memsrc.array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, memsrc.dim1 * sizeof(DWORD*));
1969
1970 for(i = 0; i < memsrc.dim1; i++)
1971 {
1972 memsrc.array[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, memsrc.dim2 * sizeof(DWORD));
1973 for(j = 0; j < memsrc.dim2; j++)
1974 memsrc.array[i][j] = i * memsrc.dim2 + j;
1975 }
1976
1977 StubDesc = Object_StubDesc;
1978 StubDesc.pFormatTypes = fmtstr_complex_array;
1979
1980 NdrClientInitializeNew(
1981 &RpcMessage,
1982 &StubMsg,
1983 &StubDesc,
1984 0);
1985
1986 StubMsg.BufferLength = 0;
1987
1988 #ifdef _WIN64
1989 NdrComplexStructBufferSize( &StubMsg,
1990 (unsigned char *)&memsrc,
1991 &fmtstr_complex_array[32] );
1992 #else
1993 NdrSimpleStructBufferSize( &StubMsg,
1994 (unsigned char *)&memsrc,
1995 &fmtstr_complex_array[32] );
1996 #endif
1997
1998 expected_length = (4 + memsrc.dim1 * (2 + memsrc.dim2)) * 4;
1999 if (StubMsg.BufferLength == 96)
2000 {
2001 win_skip("Tests crash on Win9x, WinMe and NT4\n");
2002 goto cleanup;
2003 }
2004 ok(StubMsg.BufferLength >= expected_length, "length %d\n", StubMsg.BufferLength);
2005
2006 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/
2007 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
2008 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
2009
2010 #ifdef _WIN64
2011 ptr = NdrComplexStructMarshall( &StubMsg, (unsigned char *)&memsrc,
2012 &fmtstr_complex_array[32] );
2013 #else
2014 ptr = NdrSimpleStructMarshall( &StubMsg, (unsigned char *)&memsrc,
2015 &fmtstr_complex_array[32] );
2016 #endif
2017
2018 ok(ptr == NULL, "ret %p\n", ptr);
2019 ok((char*)StubMsg.Buffer == (char*)StubMsg.BufferStart + expected_length, "not at expected length\n");
2020
2021 buf = (DWORD *)StubMsg.BufferStart;
2022
2023 ok(*buf == memsrc.dim1, "dim1 should have been %d instead of %08x\n", memsrc.dim1, *buf);
2024 buf++;
2025 ok(*buf == memsrc.dim2, "dim2 should have been %d instead of %08x\n", memsrc.dim2, *buf);
2026 buf++;
2027 ok(*buf != 0, "pointer id should be non-zero\n");
2028 buf++;
2029 ok(*buf == memsrc.dim1, "Conformance should have been %d instead of %08x\n", memsrc.dim1, *buf);
2030 buf++;
2031 for(i = 0; i < memsrc.dim1; i++)
2032 {
2033 ok(*buf != 0, "pointer id[%d] should be non-zero\n", i);
2034 buf++;
2035 }
2036 for(i = 0; i < memsrc.dim1; i++)
2037 {
2038 ok(*buf == memsrc.dim2, "Conformance should have been %d instead of %08x\n", memsrc.dim2, *buf);
2039 buf++;
2040 for(j = 0; j < memsrc.dim2; j++)
2041 {
2042 ok(*buf == i * memsrc.dim2 + j, "got %08x\n", *buf);
2043 buf++;
2044 }
2045 }
2046
2047 ok((void*)buf == StubMsg.Buffer, "not at end of buffer\n");
2048
2049 /* Server */
2050 my_alloc_called = 0;
2051 StubMsg.IsClient = 0;
2052 mem = NULL;
2053 StubMsg.Buffer = StubMsg.BufferStart;
2054 #ifdef _WIN64
2055 ptr = NdrComplexStructUnmarshall( &StubMsg, (unsigned char **)&mem, &fmtstr_complex_array[32], 0);
2056 #else
2057 ptr = NdrSimpleStructUnmarshall( &StubMsg, (unsigned char **)&mem, &fmtstr_complex_array[32], 0);
2058 #endif
2059 ok(ptr == NULL, "ret %p\n", ptr);
2060 ok(mem->dim1 == memsrc.dim1, "mem->dim1 wasn't unmarshalled correctly (%d)\n", mem->dim1);
2061 ok(mem->dim2 == memsrc.dim2, "mem->dim2 wasn't unmarshalled correctly (%d)\n", mem->dim2);
2062 ok(mem->array[1][0] == memsrc.dim2, "mem->array[1][0] wasn't unmarshalled correctly (%d)\n", mem->array[1][0]);
2063
2064 StubMsg.Buffer = StubMsg.BufferStart;
2065 #ifdef _WIN64
2066 NdrComplexStructFree( &StubMsg, (unsigned char*)mem, &fmtstr_complex_array[32]);
2067 #else
2068 NdrSimpleStructFree( &StubMsg, (unsigned char*)mem, &fmtstr_complex_array[32]);
2069 #endif
2070
2071 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer);
2072
2073 cleanup:
2074 for(i = 0; i < memsrc.dim1; i++)
2075 HeapFree(GetProcessHeap(), 0, memsrc.array[i]);
2076 HeapFree(GetProcessHeap(), 0, memsrc.array);
2077 }
2078
2079 static void test_ndr_buffer(void)
2080 {
2081 static unsigned char ncalrpc[] = "ncalrpc";
2082 static unsigned char endpoint[] = "winetest:test_ndr_buffer";
2083 RPC_MESSAGE RpcMessage;
2084 MIDL_STUB_MESSAGE StubMsg;
2085 MIDL_STUB_DESC StubDesc = Object_StubDesc;
2086 unsigned char *ret;
2087 unsigned char *binding;
2088 RPC_BINDING_HANDLE Handle;
2089 RPC_STATUS status;
2090 ULONG prev_buffer_length;
2091 BOOL old_buffer_valid_location;
2092
2093 StubDesc.RpcInterfaceInformation = (void *)&IFoo___RpcServerInterface;
2094
2095 status = RpcServerUseProtseqEpA(ncalrpc, 20, endpoint, NULL);
2096 ok(RPC_S_OK == status, "RpcServerUseProtseqEp failed with status %u\n", status);
2097 status = RpcServerRegisterIf(IFoo_v0_0_s_ifspec, NULL, NULL);
2098 ok(RPC_S_OK == status, "RpcServerRegisterIf failed with status %u\n", status);
2099 status = RpcServerListen(1, 20, TRUE);
2100 ok(RPC_S_OK == status, "RpcServerListen failed with status %u\n", status);
2101 if (status != RPC_S_OK)
2102 {
2103 /* Failed to create a server, running client tests is useless */
2104 return;
2105 }
2106
2107 status = RpcStringBindingComposeA(NULL, ncalrpc, NULL, endpoint, NULL, &binding);
2108 ok(status == RPC_S_OK, "RpcStringBindingCompose failed (%u)\n", status);
2109
2110 status = RpcBindingFromStringBindingA(binding, &Handle);
2111 ok(status == RPC_S_OK, "RpcBindingFromStringBinding failed (%u)\n", status);
2112 RpcStringFreeA(&binding);
2113
2114 NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 5);
2115
2116 ret = NdrGetBuffer(&StubMsg, 10, Handle);
2117 ok(ret == StubMsg.Buffer, "NdrGetBuffer should have returned the same value as StubMsg.Buffer instead of %p\n", ret);
2118 ok(RpcMessage.Handle != NULL, "RpcMessage.Handle should not have been NULL\n");
2119 ok(RpcMessage.Buffer != NULL, "RpcMessage.Buffer should not have been NULL\n");
2120 ok(RpcMessage.BufferLength == 10 ||
2121 broken(RpcMessage.BufferLength == 12), /* win2k */
2122 "RpcMessage.BufferLength should have been 10 instead of %d\n", RpcMessage.BufferLength);
2123 ok(RpcMessage.RpcFlags == 0, "RpcMessage.RpcFlags should have been 0x0 instead of 0x%x\n", RpcMessage.RpcFlags);
2124 ok(StubMsg.Buffer != NULL, "Buffer should not have been NULL\n");
2125 ok(!StubMsg.BufferStart, "BufferStart should have been NULL instead of %p\n", StubMsg.BufferStart);
2126 ok(!StubMsg.BufferEnd, "BufferEnd should have been NULL instead of %p\n", StubMsg.BufferEnd);
2127 todo_wine
2128 ok(StubMsg.BufferLength == 0, "BufferLength should have left as 0 instead of being set to %d\n", StubMsg.BufferLength);
2129 old_buffer_valid_location = !StubMsg.fBufferValid;
2130 if (old_buffer_valid_location)
2131 ok(broken(StubMsg.CorrDespIncrement == TRUE), "fBufferValid should have been TRUE instead of 0x%x\n", StubMsg.CorrDespIncrement);
2132 else
2133 ok(StubMsg.fBufferValid, "fBufferValid should have been non-zero instead of 0x%x\n", StubMsg.fBufferValid);
2134
2135 prev_buffer_length = RpcMessage.BufferLength;
2136 StubMsg.BufferLength = 1;
2137 NdrFreeBuffer(&StubMsg);
2138 ok(RpcMessage.Handle != NULL, "RpcMessage.Handle should not have been NULL\n");
2139 ok(RpcMessage.Buffer != NULL, "RpcMessage.Buffer should not have been NULL\n");
2140 ok(RpcMessage.BufferLength == prev_buffer_length, "RpcMessage.BufferLength should have been left as %d instead of %d\n", prev_buffer_length, RpcMessage.BufferLength);
2141 ok(StubMsg.Buffer != NULL, "Buffer should not have been NULL\n");
2142 ok(StubMsg.BufferLength == 1, "BufferLength should have left as 1 instead of being set to %d\n", StubMsg.BufferLength);
2143 if (old_buffer_valid_location)
2144 ok(broken(StubMsg.CorrDespIncrement == FALSE), "fBufferValid should have been FALSE instead of 0x%x\n", StubMsg.CorrDespIncrement);
2145 else
2146 ok(!StubMsg.fBufferValid, "fBufferValid should have been FALSE instead of %d\n", StubMsg.fBufferValid);
2147
2148 /* attempt double-free */
2149 NdrFreeBuffer(&StubMsg);
2150
2151 RpcBindingFree(&Handle);
2152
2153 status = RpcServerUnregisterIf(NULL, NULL, FALSE);
2154 ok(status == RPC_S_OK, "RpcServerUnregisterIf failed (%u)\n", status);
2155 }
2156
2157 static void test_NdrMapCommAndFaultStatus(void)
2158 {
2159 RPC_STATUS rpc_status;
2160 MIDL_STUB_MESSAGE StubMsg;
2161 RPC_MESSAGE RpcMessage;
2162
2163 NdrClientInitializeNew(&RpcMessage, &StubMsg, &Object_StubDesc, 5);
2164
2165 for (rpc_status = 0; rpc_status < 10000; rpc_status++)
2166 {
2167 RPC_STATUS status;
2168 ULONG comm_status = 0;
2169 ULONG fault_status = 0;
2170 ULONG expected_comm_status = 0;
2171 ULONG expected_fault_status = 0;
2172 status = NdrMapCommAndFaultStatus(&StubMsg, &comm_status, &fault_status, rpc_status);
2173 ok(status == RPC_S_OK, "NdrMapCommAndFaultStatus failed with error %d\n", status);
2174 switch (rpc_status)
2175 {
2176 case ERROR_INVALID_HANDLE:
2177 case RPC_S_INVALID_BINDING:
2178 case RPC_S_UNKNOWN_IF:
2179 case RPC_S_SERVER_UNAVAILABLE:
2180 case RPC_S_SERVER_TOO_BUSY:
2181 case RPC_S_CALL_FAILED_DNE:
2182 case RPC_S_PROTOCOL_ERROR:
2183 case RPC_S_UNSUPPORTED_TRANS_SYN:
2184 case RPC_S_UNSUPPORTED_TYPE:
2185 case RPC_S_PROCNUM_OUT_OF_RANGE:
2186 case EPT_S_NOT_REGISTERED:
2187 case RPC_S_COMM_FAILURE:
2188 expected_comm_status = rpc_status;
2189 break;
2190 default:
2191 expected_fault_status = rpc_status;
2192 }
2193 ok(comm_status == expected_comm_status, "NdrMapCommAndFaultStatus should have mapped %d to comm status %d instead of %d\n",
2194 rpc_status, expected_comm_status, comm_status);
2195 ok(fault_status == expected_fault_status, "NdrMapCommAndFaultStatus should have mapped %d to fault status %d instead of %d\n",
2196 rpc_status, expected_fault_status, fault_status);
2197 }
2198 }
2199
2200 static void test_NdrGetUserMarshalInfo(void)
2201 {
2202 RPC_STATUS status;
2203 MIDL_STUB_MESSAGE stubmsg;
2204 USER_MARSHAL_CB umcb;
2205 NDR_USER_MARSHAL_INFO umi;
2206 unsigned char buffer[16];
2207 void *rpc_channel_buffer = (void *)(ULONG_PTR)0xcafebabe;
2208 RPC_MESSAGE rpc_msg;
2209 RPC_STATUS (RPC_ENTRY *pNdrGetUserMarshalInfo)(ULONG *,ULONG,NDR_USER_MARSHAL_INFO *);
2210
2211 pNdrGetUserMarshalInfo = (void *)GetProcAddress(GetModuleHandleA("rpcrt4.dll"), "NdrGetUserMarshalInfo");
2212 if (!pNdrGetUserMarshalInfo)
2213 {
2214 skip("NdrGetUserMarshalInfo not exported\n");
2215 return;
2216 }
2217
2218 /* unmarshall */
2219
2220 memset(&rpc_msg, 0xcc, sizeof(rpc_msg));
2221 rpc_msg.Buffer = buffer;
2222 rpc_msg.BufferLength = 16;
2223
2224 memset(&stubmsg, 0xcc, sizeof(stubmsg));
2225 stubmsg.RpcMsg = &rpc_msg;
2226 stubmsg.dwDestContext = MSHCTX_INPROC;
2227 stubmsg.pvDestContext = NULL;
2228 stubmsg.Buffer = buffer + 15;
2229 stubmsg.BufferLength = 0;
2230 stubmsg.BufferEnd = NULL;
2231 stubmsg.pRpcChannelBuffer = rpc_channel_buffer;
2232 stubmsg.StubDesc = NULL;
2233 stubmsg.pfnAllocate = my_alloc;
2234 stubmsg.pfnFree = my_free;
2235
2236 memset(&umcb, 0xcc, sizeof(umcb));
2237 umcb.Flags = MAKELONG(MSHCTX_INPROC, NDR_LOCAL_DATA_REPRESENTATION);
2238 umcb.pStubMsg = &stubmsg;
2239 umcb.Signature = USER_MARSHAL_CB_SIGNATURE;
2240 umcb.CBType = USER_MARSHAL_CB_UNMARSHALL;
2241
2242 memset(&umi, 0xaa, sizeof(umi));
2243
2244 status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2245 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2246 ok( umi.InformationLevel == 1,
2247 "umi.InformationLevel was %u instead of 1\n",
2248 umi.InformationLevel);
2249 ok( U1(umi).Level1.Buffer == buffer + 15,
2250 "umi.Level1.Buffer was %p instead of %p\n",
2251 U1(umi).Level1.Buffer, buffer);
2252 ok( U1(umi).Level1.BufferSize == 1,
2253 "umi.Level1.BufferSize was %u instead of 1\n",
2254 U1(umi).Level1.BufferSize);
2255 ok( U1(umi).Level1.pfnAllocate == my_alloc,
2256 "umi.Level1.pfnAllocate was %p instead of %p\n",
2257 U1(umi).Level1.pfnAllocate, my_alloc);
2258 ok( U1(umi).Level1.pfnFree == my_free,
2259 "umi.Level1.pfnFree was %p instead of %p\n",
2260 U1(umi).Level1.pfnFree, my_free);
2261 ok( U1(umi).Level1.pRpcChannelBuffer == rpc_channel_buffer,
2262 "umi.Level1.pRpcChannelBuffer was %p instead of %p\n",
2263 U1(umi).Level1.pRpcChannelBuffer, rpc_channel_buffer);
2264
2265 /* buffer size */
2266
2267 rpc_msg.Buffer = buffer;
2268 rpc_msg.BufferLength = 16;
2269
2270 stubmsg.Buffer = buffer;
2271 stubmsg.BufferLength = 16;
2272 stubmsg.BufferEnd = NULL;
2273
2274 umcb.CBType = USER_MARSHAL_CB_BUFFER_SIZE;
2275
2276 memset(&umi, 0xaa, sizeof(umi));
2277
2278 status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2279 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2280 ok( umi.InformationLevel == 1,
2281 "umi.InformationLevel was %u instead of 1\n",
2282 umi.InformationLevel);
2283 ok( U1(umi).Level1.Buffer == NULL,
2284 "umi.Level1.Buffer was %p instead of NULL\n",
2285 U1(umi).Level1.Buffer);
2286 ok( U1(umi).Level1.BufferSize == 0,
2287 "umi.Level1.BufferSize was %u instead of 0\n",
2288 U1(umi).Level1.BufferSize);
2289 ok( U1(umi).Level1.pfnAllocate == my_alloc,
2290 "umi.Level1.pfnAllocate was %p instead of %p\n",
2291 U1(umi).Level1.pfnAllocate, my_alloc);
2292 ok( U1(umi).Level1.pfnFree == my_free,
2293 "umi.Level1.pfnFree was %p instead of %p\n",
2294 U1(umi).Level1.pfnFree, my_free);
2295 ok( U1(umi).Level1.pRpcChannelBuffer == rpc_channel_buffer,
2296 "umi.Level1.pRpcChannelBuffer was %p instead of %p\n",
2297 U1(umi).Level1.pRpcChannelBuffer, rpc_channel_buffer);
2298
2299 /* marshall */
2300
2301 rpc_msg.Buffer = buffer;
2302 rpc_msg.BufferLength = 16;
2303
2304 stubmsg.Buffer = buffer + 15;
2305 stubmsg.BufferLength = 0;
2306 stubmsg.BufferEnd = NULL;
2307
2308 umcb.CBType = USER_MARSHAL_CB_MARSHALL;
2309
2310 memset(&umi, 0xaa, sizeof(umi));
2311
2312 status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2313 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2314 ok( umi.InformationLevel == 1,
2315 "umi.InformationLevel was %u instead of 1\n",
2316 umi.InformationLevel);
2317 ok( U1(umi).Level1.Buffer == buffer + 15,
2318 "umi.Level1.Buffer was %p instead of %p\n",
2319 U1(umi).Level1.Buffer, buffer);
2320 ok( U1(umi).Level1.BufferSize == 1,
2321 "umi.Level1.BufferSize was %u instead of 1\n",
2322 U1(umi).Level1.BufferSize);
2323 ok( U1(umi).Level1.pfnAllocate == my_alloc,
2324 "umi.Level1.pfnAllocate was %p instead of %p\n",
2325 U1(umi).Level1.pfnAllocate, my_alloc);
2326 ok( U1(umi).Level1.pfnFree == my_free,
2327 "umi.Level1.pfnFree was %p instead of %p\n",
2328 U1(umi).Level1.pfnFree, my_free);
2329 ok( U1(umi).Level1.pRpcChannelBuffer == rpc_channel_buffer,
2330 "umi.Level1.pRpcChannelBuffer was %p instead of %p\n",
2331 U1(umi).Level1.pRpcChannelBuffer, rpc_channel_buffer);
2332
2333 /* free */
2334
2335 rpc_msg.Buffer = buffer;
2336 rpc_msg.BufferLength = 16;
2337
2338 stubmsg.Buffer = buffer;
2339 stubmsg.BufferLength = 16;
2340 stubmsg.BufferEnd = NULL;
2341
2342 umcb.CBType = USER_MARSHAL_CB_FREE;
2343
2344 memset(&umi, 0xaa, sizeof(umi));
2345
2346 status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2347 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2348 ok( umi.InformationLevel == 1,
2349 "umi.InformationLevel was %u instead of 1\n",
2350 umi.InformationLevel);
2351 ok( U1(umi).Level1.Buffer == NULL,
2352 "umi.Level1.Buffer was %p instead of NULL\n",
2353 U1(umi).Level1.Buffer);
2354 ok( U1(umi).Level1.BufferSize == 0,
2355 "umi.Level1.BufferSize was %u instead of 0\n",
2356 U1(umi).Level1.BufferSize);
2357 ok( U1(umi).Level1.pfnAllocate == my_alloc,
2358 "umi.Level1.pfnAllocate was %p instead of %p\n",
2359 U1(umi).Level1.pfnAllocate, my_alloc);
2360 ok( U1(umi).Level1.pfnFree == my_free,
2361 "umi.Level1.pfnFree was %p instead of %p\n",
2362 U1(umi).Level1.pfnFree, my_free);
2363 ok( U1(umi).Level1.pRpcChannelBuffer == rpc_channel_buffer,
2364 "umi.Level1.pRpcChannelBuffer was %p instead of %p\n",
2365 U1(umi).Level1.pRpcChannelBuffer, rpc_channel_buffer);
2366
2367 /* boundary test */
2368
2369 rpc_msg.Buffer = buffer;
2370 rpc_msg.BufferLength = 15;
2371
2372 stubmsg.Buffer = buffer + 15;
2373 stubmsg.BufferLength = 0;
2374 stubmsg.BufferEnd = NULL;
2375
2376 umcb.CBType = USER_MARSHAL_CB_MARSHALL;
2377
2378 status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2379 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2380 ok( U1(umi).Level1.BufferSize == 0,
2381 "umi.Level1.BufferSize was %u instead of 0\n",
2382 U1(umi).Level1.BufferSize);
2383
2384 /* error conditions */
2385
2386 rpc_msg.BufferLength = 14;
2387 status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2388 ok(status == ERROR_INVALID_USER_BUFFER,
2389 "NdrGetUserMarshalInfo should have failed with ERROR_INVALID_USER_BUFFER instead of %d\n", status);
2390
2391 rpc_msg.BufferLength = 15;
2392 status = pNdrGetUserMarshalInfo(&umcb.Flags, 9999, &umi);
2393 ok(status == RPC_S_INVALID_ARG,
2394 "NdrGetUserMarshalInfo should have failed with RPC_S_INVALID_ARG instead of %d\n", status);
2395
2396 umcb.CBType = 9999;
2397 status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2398 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status);
2399
2400 umcb.CBType = USER_MARSHAL_CB_MARSHALL;
2401 umcb.Signature = 0;
2402 status = pNdrGetUserMarshalInfo(&umcb.Flags, 1, &umi);
2403 ok(status == RPC_S_INVALID_ARG,
2404 "NdrGetUserMarshalInfo should have failed with RPC_S_INVALID_ARG instead of %d\n", status);
2405 }
2406
2407 START_TEST( ndr_marshall )
2408 {
2409 determine_pointer_marshalling_style();
2410
2411 test_ndr_simple_type();
2412 test_simple_types();
2413 test_nontrivial_pointer_types();
2414 test_simple_struct();
2415 test_fullpointer_xlat();
2416 test_client_init();
2417 test_server_init();
2418 test_ndr_allocate();
2419 test_conformant_array();
2420 test_conformant_string();
2421 test_nonconformant_string();
2422 test_conf_complex_struct();
2423 test_conf_complex_array();
2424 test_ndr_buffer();
2425 test_NdrMapCommAndFaultStatus();
2426 test_NdrGetUserMarshalInfo();
2427 }