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 #define COBJMACROS 25 26 #include <stdarg.h> 27 28 #include <windef.h> 29 #include <winbase.h> 30 #include <winnt.h> 31 #include <winerror.h> 32 #include <ole2.h> 33 34 #include "rpc.h" 35 #include "rpcdce.h" 36 #include "rpcproxy.h" 37 #include "midles.h" 38 #include "ndrtypes.h" 39 40 #include "wine/heap.h" 41 #include "wine/test.h" 42 43 static int my_alloc_called; 44 static int my_free_called; 45 static void * CALLBACK my_alloc(SIZE_T size) 46 { 47 my_alloc_called++; 48 return NdrOleAllocate(size); 49 } 50 51 static void CALLBACK my_free(void *ptr) 52 { 53 my_free_called++; 54 NdrOleFree(ptr); 55 } 56 57 static const MIDL_STUB_DESC Object_StubDesc = 58 { 59 NULL, 60 my_alloc, 61 my_free, 62 { 0 }, 63 0, 64 0, 65 0, 66 0, 67 NULL, /* format string, filled in by tests */ 68 1, /* -error bounds_check flag */ 69 0x20000, /* Ndr library version */ 70 0, 71 0x50100a4, /* MIDL Version 5.1.164 */ 72 0, 73 NULL, 74 0, /* notify & notify_flag routine table */ 75 1, /* Flags */ 76 0, /* Reserved3 */ 77 0, /* Reserved4 */ 78 0 /* Reserved5 */ 79 }; 80 81 static RPC_DISPATCH_FUNCTION IFoo_table[] = 82 { 83 0 84 }; 85 86 static RPC_DISPATCH_TABLE IFoo_v0_0_DispatchTable = 87 { 88 0, 89 IFoo_table 90 }; 91 92 static const RPC_SERVER_INTERFACE IFoo___RpcServerInterface = 93 { 94 sizeof(RPC_SERVER_INTERFACE), 95 {{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x34}},{0,0}}, 96 {{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}}, 97 &IFoo_v0_0_DispatchTable, 98 0, 99 0, 100 0, 101 0, 102 0, 103 }; 104 105 static RPC_IF_HANDLE IFoo_v0_0_s_ifspec = (RPC_IF_HANDLE)& IFoo___RpcServerInterface; 106 static BOOL use_pointer_ids = FALSE; 107 108 static void determine_pointer_marshalling_style(void) 109 { 110 RPC_MESSAGE RpcMessage; 111 MIDL_STUB_MESSAGE StubMsg; 112 MIDL_STUB_DESC StubDesc; 113 char ch = 0xde; 114 115 static const unsigned char fmtstr_up_char[] = 116 { 117 0x12, 0x8, /* FC_UP [simple_pointer] */ 118 0x2, /* FC_CHAR */ 119 0x5c, /* FC_PAD */ 120 }; 121 122 StubDesc = Object_StubDesc; 123 StubDesc.pFormatTypes = NULL; 124 125 NdrClientInitializeNew( 126 &RpcMessage, 127 &StubMsg, 128 &StubDesc, 129 0); 130 131 StubMsg.BufferLength = 8; 132 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 133 NdrPointerMarshall(&StubMsg, (unsigned char*)&ch, fmtstr_up_char); 134 ok(StubMsg.Buffer == StubMsg.BufferStart + 5, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart); 135 136 use_pointer_ids = (*(unsigned int *)StubMsg.BufferStart != (UINT_PTR)&ch); 137 trace("Pointer marshalling using %s\n", use_pointer_ids ? "pointer ids" : "pointer value"); 138 139 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart); 140 } 141 142 static void test_ndr_simple_type(void) 143 { 144 RPC_MESSAGE RpcMessage; 145 MIDL_STUB_MESSAGE StubMsg; 146 MIDL_STUB_DESC StubDesc; 147 LONG l, l2 = 0; 148 149 StubDesc = Object_StubDesc; 150 StubDesc.pFormatTypes = NULL; 151 152 NdrClientInitializeNew( 153 &RpcMessage, 154 &StubMsg, 155 &StubDesc, 156 0); 157 158 StubMsg.BufferLength = 16; 159 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 160 l = 0xcafebabe; 161 NdrSimpleTypeMarshall(&StubMsg, (unsigned char*)&l, FC_LONG); 162 ok(StubMsg.Buffer == StubMsg.BufferStart + 4, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart); 163 ok(*(LONG*)StubMsg.BufferStart == l, "%d\n", *(LONG*)StubMsg.BufferStart); 164 165 StubMsg.Buffer = StubMsg.BufferStart + 1; 166 NdrSimpleTypeMarshall(&StubMsg, (unsigned char*)&l, FC_LONG); 167 ok(StubMsg.Buffer == StubMsg.BufferStart + 8, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart); 168 ok(*(LONG*)(StubMsg.BufferStart + 4) == l, "%d\n", *(LONG*)StubMsg.BufferStart); 169 170 StubMsg.Buffer = StubMsg.BufferStart + 1; 171 NdrSimpleTypeUnmarshall(&StubMsg, (unsigned char*)&l2, FC_LONG); 172 ok(StubMsg.Buffer == StubMsg.BufferStart + 8, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart); 173 ok(l2 == l, "%d\n", l2); 174 175 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart); 176 } 177 178 static void test_pointer_marshal(const unsigned char *formattypes, 179 void *memsrc, DWORD srcsize, 180 const void *wiredata, 181 ULONG wiredatalen, 182 int(*cmp)(const void*,const void*,size_t), 183 int num_additional_allocs, 184 const char *msgpfx) 185 { 186 RPC_MESSAGE RpcMessage; 187 MIDL_STUB_MESSAGE StubMsg; 188 MIDL_STUB_DESC StubDesc; 189 DWORD size; 190 void *ptr; 191 unsigned char *mem, *mem_orig; 192 193 if(!cmp) 194 cmp = memcmp; 195 196 StubDesc = Object_StubDesc; 197 StubDesc.pFormatTypes = formattypes; 198 199 NdrClientInitializeNew( 200 &RpcMessage, 201 &StubMsg, 202 &StubDesc, 203 0); 204 205 StubMsg.BufferLength = 0; 206 NdrPointerBufferSize( &StubMsg, 207 memsrc, 208 formattypes ); 209 ok(StubMsg.BufferLength >= wiredatalen, "%s: length %d\n", msgpfx, StubMsg.BufferLength); 210 211 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ 212 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 213 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 214 215 memset(StubMsg.BufferStart, 0x0, StubMsg.BufferLength); /* This is a hack to clear the padding between the ptr and longlong/double */ 216 217 ptr = NdrPointerMarshall( &StubMsg, memsrc, formattypes ); 218 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 219 if (srcsize == 8 && wiredatalen == 16 && StubMsg.Buffer - StubMsg.BufferStart == 12) 220 { 221 /* win9x doesn't align 8-byte types properly */ 222 wiredatalen = 12; 223 } 224 else 225 { 226 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 227 ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled\n", msgpfx); 228 } 229 230 StubMsg.Buffer = StubMsg.BufferStart; 231 StubMsg.MemorySize = 0; 232 233 size = NdrPointerMemorySize( &StubMsg, formattypes ); 234 ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size); 235 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 236 if (formattypes[1] & FC_POINTER_DEREF) 237 ok(size == srcsize + sizeof(void *), "%s: mem size %u\n", msgpfx, size); 238 else 239 ok(size == srcsize, "%s: mem size %u\n", msgpfx, size); 240 241 StubMsg.Buffer = StubMsg.BufferStart; 242 StubMsg.MemorySize = 16; 243 size = NdrPointerMemorySize( &StubMsg, formattypes ); 244 ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size); 245 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 246 if (formattypes[1] & FC_POINTER_DEREF) 247 ok(size == srcsize + sizeof(void *) + 16, "%s: mem size %u\n", msgpfx, size); 248 else 249 ok(size == srcsize + 16, "%s: mem size %u\n", msgpfx, size); 250 251 StubMsg.Buffer = StubMsg.BufferStart; 252 StubMsg.MemorySize = 1; 253 size = NdrPointerMemorySize( &StubMsg, formattypes ); 254 ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size); 255 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 256 if (formattypes[1] & FC_POINTER_DEREF) 257 ok(size == srcsize + sizeof(void *) + (srcsize == 8 ? 8 : sizeof(void *)), "%s: mem size %u\n", msgpfx, size); 258 else 259 ok(size == srcsize + (srcsize == 8 ? 8 : sizeof(void *)), "%s: mem size %u\n", msgpfx, size); 260 261 size = srcsize; 262 if (formattypes[1] & FC_POINTER_DEREF) size += 4; 263 264 StubMsg.Buffer = StubMsg.BufferStart; 265 StubMsg.MemorySize = 0; 266 /* Using my_alloc() here is necessary to prevent a crash in Windows 7+. */ 267 mem_orig = mem = my_alloc(size); 268 memset(mem, 0, size); 269 my_alloc_called = my_free_called = 0; 270 if (formattypes[1] & FC_POINTER_DEREF) 271 *(void**)mem = NULL; 272 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 ); 273 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 274 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); 275 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 276 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 277 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); 278 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 279 /* On Windows 7+ unmarshalling may involve calls to NdrFree, for unclear reasons. */ 280 my_free_called = 0; 281 282 NdrPointerFree(&StubMsg, mem, formattypes); 283 if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 284 { 285 /* In this case the top-level pointer is not freed. */ 286 ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called); 287 HeapFree(GetProcessHeap(), 0, mem); 288 } 289 else 290 ok(my_free_called == 1 + num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called); 291 292 /* reset the buffer and call with must alloc */ 293 my_alloc_called = my_free_called = 0; 294 StubMsg.Buffer = StubMsg.BufferStart; 295 mem_orig = mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 296 if (formattypes[1] & FC_POINTER_DEREF) 297 *(void**)mem = NULL; 298 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 1 ); 299 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 300 /* doesn't allocate mem in this case */ 301 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); 302 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 303 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 304 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); 305 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 306 ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called); 307 308 NdrPointerFree(&StubMsg, mem, formattypes); 309 if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 310 { 311 /* In this case the top-level pointer is not freed. */ 312 ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called); 313 HeapFree(GetProcessHeap(), 0, mem); 314 } 315 else 316 ok(my_free_called == 1 + num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called); 317 318 if (formattypes[0] != FC_RP) 319 { 320 /* now pass the address of a NULL ptr */ 321 mem = NULL; 322 my_alloc_called = my_free_called = 0; 323 StubMsg.Buffer = StubMsg.BufferStart; 324 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 ); 325 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 326 ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart); 327 ok(!cmp(mem, memsrc, size), "%s: incorrectly unmarshaled\n", msgpfx); 328 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 329 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); 330 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 331 my_alloc_called = 0; 332 NdrPointerFree(&StubMsg, mem, formattypes); 333 334 /* again pass address of NULL ptr, but pretend we're a server */ 335 if (0) /* crashes on Win9x and NT4 */ 336 { 337 mem = NULL; 338 StubMsg.Buffer = StubMsg.BufferStart; 339 StubMsg.IsClient = 0; 340 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 ); 341 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 342 if (formattypes[2] == FC_ENUM16) 343 ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart); 344 else 345 ok(mem == StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem doesn't point to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart); 346 ok(!cmp(mem, memsrc, size), "%s: incorrectly unmarshaled\n", msgpfx); 347 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 348 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); 349 if (formattypes[2] != FC_ENUM16) 350 { 351 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 352 my_alloc_called = 0; 353 } 354 } 355 } 356 357 /* Server */ 358 StubMsg.IsClient = 0; 359 360 /* For most basetypes (but not enum16), memory will not be allocated but 361 * instead point directly to the buffer. */ 362 my_alloc_called = my_free_called = 0; 363 StubMsg.Buffer = StubMsg.BufferStart; 364 mem = NULL; 365 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 ); 366 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 367 ok(!!mem, "%s: mem was not allocated\n", msgpfx); 368 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 369 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 370 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); 371 if (formattypes[2] == FC_ENUM16) 372 ok(my_alloc_called == 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 373 else 374 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 375 ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called); 376 377 NdrPointerFree(&StubMsg, mem, formattypes); 378 if (formattypes[2] == FC_ENUM16) 379 ok(my_free_called == 1, "%s: my_free got called %d times\n", msgpfx, my_free_called); 380 else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 381 { 382 /* In theory this should be freed to correspond with the allocation, but 383 * FC_ALLOCED_ON_STACK is set, and NdrPointerFree() has no way of 384 * knowing that the memory allocated by NdrPointerUnmarshall() isn't 385 * stack memory. In practice it always *is* stack memory if ON_STACK is 386 * set, so this leak isn't a concern. */ 387 ok(my_free_called == 0, "%s: my_free got called %d times\n", msgpfx, my_free_called); 388 HeapFree(GetProcessHeap(), 0, mem); 389 } 390 else 391 ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called); 392 393 /* reset the buffer and call with must alloc */ 394 my_alloc_called = my_free_called = 0; 395 StubMsg.Buffer = StubMsg.BufferStart; 396 mem = NULL; 397 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 1 ); 398 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 399 ok(!!mem, "%s: mem was not allocated\n", msgpfx); 400 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 401 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 402 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); 403 if (formattypes[2] == FC_ENUM16) 404 ok(my_alloc_called == 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 405 else 406 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 407 ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called); 408 409 NdrPointerFree(&StubMsg, mem, formattypes); 410 if (formattypes[2] == FC_ENUM16) 411 ok(my_free_called == 1, "%s: my_free got called %d times\n", msgpfx, my_free_called); 412 else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 413 { 414 ok(my_free_called == 0, "%s: my_free got called %d times\n", msgpfx, my_free_called); 415 HeapFree(GetProcessHeap(), 0, mem); 416 } 417 else 418 ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called); 419 420 /* Τest with an existing pointer. Unless it's a stack pointer (and deref'd) 421 * a new pointer will be allocated anyway (in fact, an invalid pointer works 422 * in every such case). */ 423 424 my_alloc_called = my_free_called = 0; 425 StubMsg.Buffer = StubMsg.BufferStart; 426 mem_orig = mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 427 if (formattypes[1] & FC_POINTER_DEREF) 428 *(void**)mem = NULL; 429 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 ); 430 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 431 if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 432 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); 433 else 434 { 435 ok(mem != mem_orig, "%s: mem has not changed\n", msgpfx); 436 HeapFree(GetProcessHeap(), 0, mem_orig); 437 } 438 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 439 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 440 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); 441 if (formattypes[2] == FC_ENUM16) 442 ok(my_alloc_called == 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 443 else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 444 ok(my_alloc_called == 0, "%s: my_alloc got called %d times\n", msgpfx, my_free_called); 445 else 446 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 447 ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called); 448 449 NdrPointerFree(&StubMsg, mem, formattypes); 450 if (formattypes[2] == FC_ENUM16) 451 ok(my_free_called == 1, "%s: my_free got called %d times\n", msgpfx, my_free_called); 452 else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 453 { 454 ok(my_free_called == 0, "%s: my_free got called %d times\n", msgpfx, my_free_called); 455 HeapFree(GetProcessHeap(), 0, mem); 456 } 457 else 458 ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called); 459 460 /* reset the buffer and call with must alloc */ 461 my_alloc_called = my_free_called = 0; 462 StubMsg.Buffer = StubMsg.BufferStart; 463 mem_orig = mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 464 if (formattypes[1] & FC_POINTER_DEREF) 465 *(void**)mem = NULL; 466 ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 1 ); 467 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 468 if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 469 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); 470 else 471 { 472 ok(mem != mem_orig, "%s: mem has not changed\n", msgpfx); 473 HeapFree(GetProcessHeap(), 0, mem_orig); 474 } 475 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 476 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); 477 ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); 478 if (formattypes[2] == FC_ENUM16) 479 ok(my_alloc_called == 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 480 else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 481 ok(my_alloc_called == 0, "%s: my_alloc got called %d times\n", msgpfx, my_free_called); 482 else 483 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 484 ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called); 485 486 NdrPointerFree(&StubMsg, mem, formattypes); 487 if (formattypes[2] == FC_ENUM16) 488 ok(my_free_called == 1, "%s: my_free got called %d times\n", msgpfx, my_free_called); 489 else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF)) 490 { 491 ok(my_free_called == 0, "%s: my_free got called %d times\n", msgpfx, my_free_called); 492 HeapFree(GetProcessHeap(), 0, mem); 493 } 494 else 495 ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called); 496 497 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart); 498 } 499 500 static int deref_cmp(const void *s1, const void *s2, size_t num) 501 { 502 return memcmp(*(const void *const *)s1, *(const void *const *)s2, num); 503 } 504 505 506 static void test_simple_types(void) 507 { 508 unsigned char wiredata[16]; 509 unsigned char ch; 510 unsigned char *ch_ptr; 511 unsigned short s; 512 unsigned int i; 513 ULONG l; 514 ULONGLONG ll; 515 float f; 516 double d; 517 518 static const unsigned char fmtstr_up_char[] = 519 { 520 0x12, 0x8, /* FC_UP [simple_pointer] */ 521 0x2, /* FC_CHAR */ 522 0x5c, /* FC_PAD */ 523 }; 524 static const unsigned char fmtstr_up_byte[] = 525 { 526 0x12, 0x8, /* FC_UP [simple_pointer] */ 527 0x1, /* FC_BYTE */ 528 0x5c, /* FC_PAD */ 529 }; 530 static const unsigned char fmtstr_up_small[] = 531 { 532 0x12, 0x8, /* FC_UP [simple_pointer] */ 533 0x3, /* FC_SMALL */ 534 0x5c, /* FC_PAD */ 535 }; 536 static const unsigned char fmtstr_up_usmall[] = 537 { 538 0x12, 0x8, /* FC_UP [simple_pointer] */ 539 0x4, /* FC_USMALL */ 540 0x5c, /* FC_PAD */ 541 }; 542 static const unsigned char fmtstr_rp_char[] = 543 { 544 0x11, 0x8, /* FC_RP [simple_pointer] */ 545 0x2, /* FC_CHAR */ 546 0x5c, /* FC_PAD */ 547 }; 548 static const unsigned char fmtstr_rpup_char_onstack_deref[] = 549 { 550 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */ 551 NdrFcShort( 0x2 ), /* Offset= 2 (4) */ 552 0x12, 0x8, /* FC_UP [simple_pointer] */ 553 0x2, /* FC_CHAR */ 554 0x5c, /* FC_PAD */ 555 }; 556 static const unsigned char fmtstr_rpup_char_onstack[] = 557 { 558 0x11, 0x04, /* FC_RP [alloced_on_stack] */ 559 NdrFcShort( 0x2 ), /* Offset= 2 (4) */ 560 0x12, 0x8, /* FC_UP [simple_pointer] */ 561 0x2, /* FC_CHAR */ 562 0x5c, /* FC_PAD */ 563 }; 564 static const unsigned char fmtstr_rpup_char_deref[] = 565 { 566 0x11, 0x10, /* FC_RP [pointer_deref] */ 567 NdrFcShort( 0x2 ), /* Offset= 2 (4) */ 568 0x12, 0x8, /* FC_UP [simple_pointer] */ 569 0x2, /* FC_CHAR */ 570 0x5c, /* FC_PAD */ 571 }; 572 573 static const unsigned char fmtstr_up_wchar[] = 574 { 575 0x12, 0x8, /* FC_UP [simple_pointer] */ 576 0x5, /* FC_WCHAR */ 577 0x5c, /* FC_PAD */ 578 }; 579 static const unsigned char fmtstr_up_short[] = 580 { 581 0x12, 0x8, /* FC_UP [simple_pointer] */ 582 0x6, /* FC_SHORT */ 583 0x5c, /* FC_PAD */ 584 }; 585 static const unsigned char fmtstr_up_ushort[] = 586 { 587 0x12, 0x8, /* FC_UP [simple_pointer] */ 588 0x7, /* FC_USHORT */ 589 0x5c, /* FC_PAD */ 590 }; 591 static const unsigned char fmtstr_up_enum16[] = 592 { 593 0x12, 0x8, /* FC_UP [simple_pointer] */ 594 0xd, /* FC_ENUM16 */ 595 0x5c, /* FC_PAD */ 596 }; 597 static const unsigned char fmtstr_up_long[] = 598 { 599 0x12, 0x8, /* FC_UP [simple_pointer] */ 600 0x8, /* FC_LONG */ 601 0x5c, /* FC_PAD */ 602 }; 603 static const unsigned char fmtstr_up_ulong[] = 604 { 605 0x12, 0x8, /* FC_UP [simple_pointer] */ 606 0x9, /* FC_ULONG */ 607 0x5c, /* FC_PAD */ 608 }; 609 static const unsigned char fmtstr_up_enum32[] = 610 { 611 0x12, 0x8, /* FC_UP [simple_pointer] */ 612 0xe, /* FC_ENUM32 */ 613 0x5c, /* FC_PAD */ 614 }; 615 static const unsigned char fmtstr_up_errorstatus[] = 616 { 617 0x12, 0x8, /* FC_UP [simple_pointer] */ 618 0x10, /* FC_ERROR_STATUS_T */ 619 0x5c, /* FC_PAD */ 620 }; 621 622 static const unsigned char fmtstr_up_longlong[] = 623 { 624 0x12, 0x8, /* FC_UP [simple_pointer] */ 625 0xb, /* FC_HYPER */ 626 0x5c, /* FC_PAD */ 627 }; 628 static const unsigned char fmtstr_up_float[] = 629 { 630 0x12, 0x8, /* FC_UP [simple_pointer] */ 631 0xa, /* FC_FLOAT */ 632 0x5c, /* FC_PAD */ 633 }; 634 static const unsigned char fmtstr_up_double[] = 635 { 636 0x12, 0x8, /* FC_UP [simple_pointer] */ 637 0xc, /* FC_DOUBLE */ 638 0x5c, /* FC_PAD */ 639 }; 640 641 ch = 0xa5; 642 ch_ptr = &ch; 643 if (use_pointer_ids) 644 *(unsigned int *)wiredata = 0x20000; 645 else 646 *(unsigned int *)wiredata = (UINT_PTR)ch_ptr; 647 wiredata[4] = ch; 648 649 test_pointer_marshal(fmtstr_up_char, ch_ptr, 1, wiredata, 5, NULL, 0, "up_char"); 650 test_pointer_marshal(fmtstr_up_byte, ch_ptr, 1, wiredata, 5, NULL, 0, "up_byte"); 651 test_pointer_marshal(fmtstr_up_small, ch_ptr, 1, wiredata, 5, NULL, 0, "up_small"); 652 test_pointer_marshal(fmtstr_up_usmall, ch_ptr, 1, wiredata, 5, NULL, 0, "up_usmall"); 653 654 test_pointer_marshal(fmtstr_rp_char, ch_ptr, 1, &ch, 1, NULL, 0, "rp_char"); 655 656 test_pointer_marshal(fmtstr_rpup_char_onstack_deref, &ch_ptr, 1, wiredata, 5, deref_cmp, 1, "rpup_char_onstack_deref"); 657 test_pointer_marshal(fmtstr_rpup_char_onstack, ch_ptr, 1, wiredata, 5, NULL, 0, "rpup_char_onstack"); 658 test_pointer_marshal(fmtstr_rpup_char_deref, &ch_ptr, 1, wiredata, 5, deref_cmp, 1, "rpup_char_deref"); 659 660 s = 0xa597; 661 if (use_pointer_ids) 662 *(unsigned int *)wiredata = 0x20000; 663 else 664 *(unsigned int *)wiredata = (UINT_PTR)&s; 665 *(unsigned short*)(wiredata + 4) = s; 666 667 test_pointer_marshal(fmtstr_up_wchar, &s, 2, wiredata, 6, NULL, 0, "up_wchar"); 668 test_pointer_marshal(fmtstr_up_short, &s, 2, wiredata, 6, NULL, 0, "up_short"); 669 test_pointer_marshal(fmtstr_up_ushort, &s, 2, wiredata, 6, NULL, 0, "up_ushort"); 670 671 i = 0x7fff; 672 if (use_pointer_ids) 673 *(unsigned int *)wiredata = 0x20000; 674 else 675 *(unsigned int *)wiredata = (UINT_PTR)&i; 676 *(unsigned short*)(wiredata + 4) = i; 677 test_pointer_marshal(fmtstr_up_enum16, &i, 4, wiredata, 6, NULL, 0, "up_enum16"); 678 679 l = 0xcafebabe; 680 if (use_pointer_ids) 681 *(unsigned int *)wiredata = 0x20000; 682 else 683 *(unsigned int *)wiredata = (UINT_PTR)&l; 684 *(ULONG*)(wiredata + 4) = l; 685 686 test_pointer_marshal(fmtstr_up_long, &l, 4, wiredata, 8, NULL, 0, "up_long"); 687 test_pointer_marshal(fmtstr_up_ulong, &l, 4, wiredata, 8, NULL, 0, "up_ulong"); 688 test_pointer_marshal(fmtstr_up_enum32, &l, 4, wiredata, 8, NULL, 0, "up_emun32"); 689 test_pointer_marshal(fmtstr_up_errorstatus, &l, 4, wiredata, 8, NULL, 0, "up_errorstatus"); 690 691 ll = ((ULONGLONG)0xcafebabe) << 32 | 0xdeadbeef; 692 if (use_pointer_ids) 693 *(unsigned int *)wiredata = 0x20000; 694 else 695 *(unsigned int *)wiredata = (UINT_PTR)≪ 696 *(unsigned int *)(wiredata + 4) = 0; 697 *(ULONGLONG*)(wiredata + 8) = ll; 698 test_pointer_marshal(fmtstr_up_longlong, &ll, 8, wiredata, 16, NULL, 0, "up_longlong"); 699 700 f = 3.1415f; 701 if (use_pointer_ids) 702 *(unsigned int *)wiredata = 0x20000; 703 else 704 *(unsigned int *)wiredata = (UINT_PTR)&f; 705 *(float*)(wiredata + 4) = f; 706 test_pointer_marshal(fmtstr_up_float, &f, 4, wiredata, 8, NULL, 0, "up_float"); 707 708 d = 3.1415; 709 if (use_pointer_ids) 710 *(unsigned int *)wiredata = 0x20000; 711 else 712 *(unsigned int *)wiredata = (UINT_PTR)&d; 713 *(unsigned int *)(wiredata + 4) = 0; 714 *(double*)(wiredata + 8) = d; 715 test_pointer_marshal(fmtstr_up_double, &d, 8, wiredata, 16, NULL, 0, "up_double"); 716 717 } 718 719 static void test_nontrivial_pointer_types(void) 720 { 721 RPC_MESSAGE RpcMessage; 722 MIDL_STUB_MESSAGE StubMsg; 723 MIDL_STUB_DESC StubDesc; 724 DWORD size; 725 void *ptr; 726 char **p1; 727 char *p2; 728 char ch; 729 unsigned char *mem, *mem_orig; 730 731 static const unsigned char fmtstr_ref_unique_out[] = 732 { 733 0x12, 0x8, /* FC_UP [simple_pointer] */ 734 0x2, /* FC_CHAR */ 735 0x5c, /* FC_PAD */ 736 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */ 737 NdrFcShort( 0xfffffffa ), /* Offset= -6 (0) */ 738 }; 739 740 p1 = &p2; 741 p2 = &ch; 742 ch = 0x22; 743 744 StubDesc = Object_StubDesc; 745 StubDesc.pFormatTypes = fmtstr_ref_unique_out; 746 747 NdrClientInitializeNew( 748 &RpcMessage, 749 &StubMsg, 750 &StubDesc, 751 0); 752 753 StubMsg.BufferLength = 0; 754 NdrPointerBufferSize( &StubMsg, 755 (unsigned char *)p1, 756 &fmtstr_ref_unique_out[4] ); 757 758 /* Windows overestimates the buffer size */ 759 ok(StubMsg.BufferLength >= 5, "length %d\n", StubMsg.BufferLength); 760 761 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ 762 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 763 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 764 765 ptr = NdrPointerMarshall( &StubMsg, (unsigned char *)p1, &fmtstr_ref_unique_out[4] ); 766 ok(ptr == NULL, "ret %p\n", ptr); 767 size = StubMsg.Buffer - StubMsg.BufferStart; 768 ok(size == 5, "Buffer %p Start %p len %d\n", StubMsg.Buffer, StubMsg.BufferStart, size); 769 ok(*(unsigned int *)StubMsg.BufferStart != 0, "pointer ID marshalled incorrectly\n"); 770 ok(*(unsigned char *)(StubMsg.BufferStart + 4) == 0x22, "char data marshalled incorrectly: 0x%x\n", 771 *(unsigned char *)(StubMsg.BufferStart + 4)); 772 773 StubMsg.Buffer = StubMsg.BufferStart; 774 StubMsg.MemorySize = 0; 775 mem = NULL; 776 777 /* Client */ 778 my_alloc_called = 0; 779 StubMsg.Buffer = StubMsg.BufferStart; 780 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(void *)); 781 *(void **)mem = NULL; 782 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0); 783 ok(mem == mem_orig, "mem alloced\n"); 784 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); 785 786 my_alloc_called = 0; 787 StubMsg.Buffer = StubMsg.BufferStart; 788 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1); 789 ok(mem == mem_orig, "mem alloced\n"); 790 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 791 792 my_free_called = 0; 793 StubMsg.Buffer = StubMsg.BufferStart; 794 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] ); 795 ok(my_free_called == 1, "free called %d\n", my_free_called); 796 797 mem = my_alloc(sizeof(void *)); 798 *(void **)mem = NULL; 799 my_free_called = 0; 800 StubMsg.Buffer = StubMsg.BufferStart; 801 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] ); 802 ok(my_free_called == 0, "free called %d\n", my_free_called); 803 my_free(mem); 804 805 mem = my_alloc(sizeof(void *)); 806 *(void **)mem = my_alloc(sizeof(char)); 807 my_free_called = 0; 808 StubMsg.Buffer = StubMsg.BufferStart; 809 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] ); 810 ok(my_free_called == 1, "free called %d\n", my_free_called); 811 my_free(mem); 812 813 /* Server */ 814 my_alloc_called = 0; 815 my_free_called = 0; 816 StubMsg.IsClient = 0; 817 mem = NULL; 818 StubMsg.Buffer = StubMsg.BufferStart; 819 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0); 820 ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n"); 821 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); 822 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] ); 823 ok(my_free_called == 0, "free called %d\n", my_free_called); 824 my_free(mem); 825 826 my_alloc_called = 0; 827 my_free_called = 0; 828 mem = NULL; 829 StubMsg.Buffer = StubMsg.BufferStart; 830 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1); 831 ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n"); 832 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); 833 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] ); 834 ok(my_free_called == 0, "free called %d\n", my_free_called); 835 my_free(mem); 836 837 my_alloc_called = 0; 838 mem = mem_orig; 839 *(void **)mem = NULL; 840 StubMsg.Buffer = StubMsg.BufferStart; 841 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0); 842 ok(mem == mem_orig, "mem alloced\n"); 843 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 844 845 my_alloc_called = 0; 846 mem = mem_orig; 847 *(void **)mem = NULL; 848 StubMsg.Buffer = StubMsg.BufferStart; 849 NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1); 850 ok(mem == mem_orig, "mem alloced\n"); 851 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 852 853 mem = my_alloc(sizeof(void *)); 854 *(void **)mem = NULL; 855 my_free_called = 0; 856 StubMsg.Buffer = StubMsg.BufferStart; 857 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] ); 858 ok(my_free_called == 0, "free called %d\n", my_free_called); 859 my_free(mem); 860 861 mem = my_alloc(sizeof(void *)); 862 *(void **)mem = my_alloc(sizeof(char)); 863 my_free_called = 0; 864 StubMsg.Buffer = StubMsg.BufferStart; 865 NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] ); 866 ok(my_free_called == 1, "free called %d\n", my_free_called); 867 my_free(mem); 868 869 HeapFree(GetProcessHeap(), 0, mem_orig); 870 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); 871 } 872 873 static void test_simple_struct_marshal(const unsigned char *formattypes, 874 void *memsrc, DWORD srcsize, 875 const void *wiredata, 876 ULONG wiredatalen, 877 int(*cmp)(const void*,const void*,size_t), 878 int num_additional_allocs, 879 const char *msgpfx) 880 { 881 RPC_MESSAGE RpcMessage; 882 MIDL_STUB_MESSAGE StubMsg; 883 MIDL_STUB_DESC StubDesc; 884 DWORD size; 885 void *ptr; 886 unsigned char *mem, *mem_orig; 887 888 my_alloc_called = my_free_called = 0; 889 if(!cmp) 890 cmp = memcmp; 891 892 StubDesc = Object_StubDesc; 893 StubDesc.pFormatTypes = formattypes; 894 895 NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0); 896 897 StubMsg.BufferLength = 0; 898 NdrSimpleStructBufferSize( &StubMsg, memsrc, formattypes ); 899 ok(StubMsg.BufferLength >= wiredatalen, "%s: length %d\n", msgpfx, StubMsg.BufferLength); 900 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 901 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 902 ptr = NdrSimpleStructMarshall( &StubMsg, memsrc, formattypes ); 903 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 904 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart); 905 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)); 906 907 StubMsg.Buffer = StubMsg.BufferStart; 908 StubMsg.MemorySize = 0; 909 size = NdrSimpleStructMemorySize( &StubMsg, formattypes ); 910 ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx); 911 ok(size == srcsize, "%s: mem size %u\n", msgpfx, size); 912 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart); 913 914 StubMsg.Buffer = StubMsg.BufferStart; 915 size = NdrSimpleStructMemorySize( &StubMsg, formattypes ); 916 ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx); 917 ok(StubMsg.MemorySize == ((srcsize + 3) & ~3) + srcsize, "%s: mem size %u\n", msgpfx, size); 918 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart); 919 size = srcsize; 920 /*** Unmarshalling first with must_alloc false ***/ 921 922 StubMsg.Buffer = StubMsg.BufferStart; 923 StubMsg.MemorySize = 0; 924 mem_orig = mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, srcsize); 925 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 ); 926 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 927 ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart); 928 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); 929 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 930 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 931 my_alloc_called = 0; 932 my_free_called = 0; 933 ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx); 934 NdrSimpleStructFree(&StubMsg, mem, formattypes ); 935 ok(my_free_called == num_additional_allocs, "free called %d\n", my_free_called); 936 937 /* If we're a server we still use the supplied memory */ 938 StubMsg.Buffer = StubMsg.BufferStart; 939 StubMsg.IsClient = 0; 940 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 ); 941 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 942 ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); 943 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 944 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 945 my_alloc_called = 0; 946 my_free_called = 0; 947 ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx); 948 NdrSimpleStructFree(&StubMsg, mem, formattypes ); 949 ok(my_free_called == num_additional_allocs, "free called %d\n", my_free_called); 950 951 /* ...unless we pass a NULL ptr, then the buffer is used. 952 Passing a NULL ptr while we're a client && !must_alloc 953 crashes on Windows, so we won't do that. */ 954 955 if (0) /* crashes on Win9x and NT4 */ 956 { 957 mem = NULL; 958 StubMsg.IsClient = 0; 959 StubMsg.Buffer = StubMsg.BufferStart; 960 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, FALSE ); 961 ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); 962 ok(mem == StubMsg.BufferStart, "%s: mem not equal buffer\n", msgpfx); 963 ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); 964 ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 965 my_alloc_called = 0; 966 ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx); 967 NdrSimpleStructFree(&StubMsg, mem, formattypes ); 968 ok(my_free_called == num_additional_allocs, "free called %d\n", my_free_called); 969 } 970 971 /*** now must_alloc is true ***/ 972 973 /* with must_alloc set we always allocate new memory whether or not we're 974 a server and also when passing NULL */ 975 mem = mem_orig; 976 StubMsg.IsClient = 1; 977 StubMsg.Buffer = StubMsg.BufferStart; 978 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 ); 979 ok(ptr == NULL, "ret %p\n", ptr); 980 ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig); 981 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n"); 982 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 983 my_alloc_called = 0; 984 my_free_called = 0; 985 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n"); 986 NdrSimpleStructFree(&StubMsg, mem, formattypes ); 987 ok(my_free_called == num_additional_allocs, "free called %d\n", my_free_called); 988 my_free(mem); 989 990 mem = NULL; 991 StubMsg.Buffer = StubMsg.BufferStart; 992 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 ); 993 ok(ptr == NULL, "ret %p\n", ptr); 994 ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig); 995 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n"); 996 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 997 my_alloc_called = 0; 998 my_free_called = 0; 999 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n"); 1000 NdrSimpleStructFree(&StubMsg, mem, formattypes ); 1001 ok(my_free_called == num_additional_allocs, "free called %d\n", my_free_called); 1002 my_free(mem); 1003 1004 mem = mem_orig; 1005 StubMsg.Buffer = StubMsg.BufferStart; 1006 StubMsg.IsClient = 0; 1007 StubMsg.ReuseBuffer = 1; 1008 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 ); 1009 ok(ptr == NULL, "ret %p\n", ptr); 1010 ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig); 1011 ok(mem != StubMsg.BufferStart, "mem is buffer mem\n"); 1012 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n"); 1013 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 1014 my_alloc_called = 0; 1015 my_free_called = 0; 1016 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n"); 1017 NdrSimpleStructFree(&StubMsg, mem, formattypes ); 1018 ok(my_free_called == num_additional_allocs, "free called %d\n", my_free_called); 1019 my_free(mem); 1020 1021 mem = NULL; 1022 StubMsg.Buffer = StubMsg.BufferStart; 1023 StubMsg.IsClient = 0; 1024 StubMsg.ReuseBuffer = 1; 1025 ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 ); 1026 ok(ptr == NULL, "ret %p\n", ptr); 1027 ok(mem != StubMsg.BufferStart, "mem is buffer mem\n"); 1028 ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n"); 1029 ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); 1030 my_alloc_called = 0; 1031 my_free_called = 0; 1032 ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n"); 1033 NdrSimpleStructFree(&StubMsg, mem, formattypes ); 1034 ok(my_free_called == num_additional_allocs, "free called %d\n", my_free_called); 1035 my_free(mem); 1036 1037 HeapFree(GetProcessHeap(), 0, mem_orig); 1038 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart); 1039 } 1040 1041 typedef struct 1042 { 1043 LONG l1; 1044 LONG *pl1; 1045 char *pc1; 1046 } ps1_t; 1047 1048 static int ps1_cmp(const void *s1, const void *s2, size_t num) 1049 { 1050 const ps1_t *p1, *p2; 1051 1052 p1 = s1; 1053 p2 = s2; 1054 1055 if(p1->l1 != p2->l1) 1056 return 1; 1057 1058 if(p1->pl1 && p2->pl1) 1059 { 1060 if(*p1->pl1 != *p2->pl1) 1061 return 1; 1062 } 1063 else if(p1->pl1 || p2->pl1) 1064 return 1; 1065 1066 if(p1->pc1 && p2->pc1) 1067 { 1068 if(*p1->pc1 != *p2->pc1) 1069 return 1; 1070 } 1071 else if(p1->pc1 || p2->pc1) 1072 return 1; 1073 1074 return 0; 1075 } 1076 1077 static void test_simple_struct(void) 1078 { 1079 unsigned char wiredata[28]; 1080 ULONG wiredatalen; 1081 LONG l; 1082 char c; 1083 ps1_t ps1; 1084 1085 static const unsigned char fmtstr_simple_struct[] = 1086 { 1087 0x12, 0x0, /* FC_UP */ 1088 NdrFcShort( 0x2 ), /* Offset=2 */ 1089 0x15, 0x3, /* FC_STRUCT [align 4] */ 1090 NdrFcShort( 0x18 ), /* [size 24] */ 1091 0x6, /* FC_SHORT */ 1092 0x2, /* FC_CHAR */ 1093 0x38, /* FC_ALIGNM4 */ 1094 0x8, /* FC_LONG */ 1095 0x8, /* FC_LONG */ 1096 0x39, /* FC_ALIGNM8 */ 1097 0xb, /* FC_HYPER */ 1098 0x5b, /* FC_END */ 1099 }; 1100 struct { 1101 short s; 1102 char c; 1103 LONG l1, l2; 1104 LONGLONG ll; 1105 } s1; 1106 1107 static const unsigned char fmtstr_pointer_struct[] = 1108 { 1109 0x12, 0x0, /* FC_UP */ 1110 NdrFcShort( 0x2 ), /* Offset=2 */ 1111 #ifdef _WIN64 1112 0x1a, /* FC_BOGUS_STRUCT */ 1113 0x3, /* 3 */ 1114 NdrFcShort(0x18), /* [size 24] */ 1115 NdrFcShort(0x0), 1116 NdrFcShort(0x8), /* Offset= 8 (266) */ 1117 0x08, /* FC_LONG */ 1118 0x39, /* FC_ALIGNM8 */ 1119 0x36, /* FC_POINTER */ 1120 0x36, /* FC_POINTER */ 1121 0x5c, /* FC_PAD */ 1122 0x5b, /* FC_END */ 1123 0x12, 0x8, /* FC_UP [simple_pointer] */ 1124 0x08, /* FC_LONG */ 1125 0x5c, /* FC_PAD */ 1126 0x12, 0x8, /* FC_UP [simple_pointer] */ 1127 0x02, /* FC_CHAR */ 1128 0x5c, /* FC_PAD */ 1129 #else 1130 0x16, 0x3, /* FC_PSTRUCT [align 4] */ 1131 NdrFcShort( 0xc ), /* [size 12] */ 1132 0x4b, /* FC_PP */ 1133 0x5c, /* FC_PAD */ 1134 0x46, /* FC_NO_REPEAT */ 1135 0x5c, /* FC_PAD */ 1136 NdrFcShort( 0x4 ), /* 4 */ 1137 NdrFcShort( 0x4 ), /* 4 */ 1138 0x13, 0x8, /* FC_OP [simple_pointer] */ 1139 0x8, /* FC_LONG */ 1140 0x5c, /* FC_PAD */ 1141 0x46, /* FC_NO_REPEAT */ 1142 0x5c, /* FC_PAD */ 1143 NdrFcShort( 0x8 ), /* 8 */ 1144 NdrFcShort( 0x8 ), /* 8 */ 1145 0x13, 0x8, /* FC_OP [simple_pointer] */ 1146 0x2, /* FC_CHAR */ 1147 0x5c, /* FC_PAD */ 1148 0x5b, /* FC_END */ 1149 0x8, /* FC_LONG */ 1150 0x8, /* FC_LONG */ 1151 0x8, /* FC_LONG */ 1152 0x5c, /* FC_PAD */ 1153 0x5b, /* FC_END */ 1154 #endif 1155 }; 1156 1157 /* zero the entire structure, including the holes */ 1158 memset(&s1, 0, sizeof(s1)); 1159 1160 /* FC_STRUCT */ 1161 s1.s = 0x1234; 1162 s1.c = 0xa5; 1163 s1.l1 = 0xdeadbeef; 1164 s1.l2 = 0xcafebabe; 1165 s1.ll = ((ULONGLONG) 0xbadefeed << 32) | 0x2468ace0; 1166 1167 wiredatalen = 24; 1168 memcpy(wiredata, &s1, wiredatalen); 1169 test_simple_struct_marshal(fmtstr_simple_struct + 4, &s1, 24, wiredata, 24, NULL, 0, "struct"); 1170 1171 if (use_pointer_ids) 1172 *(unsigned int *)wiredata = 0x20000; 1173 else 1174 *(unsigned int *)wiredata = (UINT_PTR)&s1; 1175 memcpy(wiredata + 4, &s1, wiredatalen); 1176 test_pointer_marshal(fmtstr_simple_struct, &s1, 24, wiredata, 28, NULL, 0, "struct"); 1177 1178 if (sizeof(void *) == 8) return; /* it cannot be represented as a simple struct on Win64 */ 1179 1180 /* zero the entire structure, including the hole */ 1181 memset(&ps1, 0, sizeof(ps1)); 1182 1183 /* FC_PSTRUCT */ 1184 ps1.l1 = 0xdeadbeef; 1185 l = 0xcafebabe; 1186 ps1.pl1 = &l; 1187 c = 'a'; 1188 ps1.pc1 = &c; 1189 *(unsigned int *)(wiredata + 4) = 0xdeadbeef; 1190 if (use_pointer_ids) 1191 { 1192 *(unsigned int *)(wiredata + 8) = 0x20000; 1193 *(unsigned int *)(wiredata + 12) = 0x20004; 1194 } 1195 else 1196 { 1197 *(unsigned int *)(wiredata + 8) = (UINT_PTR)&l; 1198 *(unsigned int *)(wiredata + 12) = (UINT_PTR)&c; 1199 } 1200 memcpy(wiredata + 16, &l, 4); 1201 memcpy(wiredata + 20, &c, 1); 1202 1203 test_simple_struct_marshal(fmtstr_pointer_struct + 4, &ps1, 17, wiredata + 4, 17, ps1_cmp, 2, "pointer_struct"); 1204 if (use_pointer_ids) 1205 { 1206 *(unsigned int *)wiredata = 0x20000; 1207 *(unsigned int *)(wiredata + 8) = 0x20004; 1208 *(unsigned int *)(wiredata + 12) = 0x20008; 1209 } 1210 else 1211 *(unsigned int *)wiredata = (UINT_PTR)&ps1; 1212 test_pointer_marshal(fmtstr_pointer_struct, &ps1, 17, wiredata, 21, ps1_cmp, 2, "pointer_struct"); 1213 } 1214 1215 struct aligned 1216 { 1217 int a; 1218 LONGLONG b; 1219 }; 1220 1221 static void test_struct_align(void) 1222 { 1223 RPC_MESSAGE RpcMessage; 1224 MIDL_STUB_MESSAGE StubMsg; 1225 MIDL_STUB_DESC StubDesc; 1226 void *ptr; 1227 struct aligned *memsrc_orig, *memsrc, *mem; 1228 1229 /* force bogus struct so that members are marshalled individually */ 1230 static const unsigned char fmtstr[] = 1231 { 1232 0x1a, /* FC_BOGUS_STRUCT */ 1233 0x7, /* alignment 8 */ 1234 NdrFcShort(0x10), /* memory size 16 */ 1235 NdrFcShort(0x0), 1236 NdrFcShort(0x0), 1237 0x08, /* FC_LONG */ 1238 0x39, /* FC_ALIGNM8 */ 1239 0x0b, /* FC_HYPER */ 1240 0x5b, /* FC_END */ 1241 }; 1242 1243 memsrc_orig = heap_alloc_zero(sizeof(struct aligned) + 8); 1244 /* intentionally mis-align memsrc */ 1245 memsrc = (struct aligned *)((((ULONG_PTR)memsrc_orig + 7) & ~7) + 4); 1246 1247 memsrc->a = 0xdeadbeef; 1248 memsrc->b = ((ULONGLONG) 0xbadefeed << 32) | 0x2468ace0; 1249 1250 StubDesc = Object_StubDesc; 1251 StubDesc.pFormatTypes = fmtstr; 1252 NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0); 1253 1254 StubMsg.BufferLength = 0; 1255 NdrComplexStructBufferSize(&StubMsg, (unsigned char *)memsrc, fmtstr); 1256 1257 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = heap_alloc(StubMsg.BufferLength); 1258 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 1259 1260 ptr = NdrComplexStructMarshall(&StubMsg, (unsigned char *)memsrc, fmtstr); 1261 ok(ptr == NULL, "ret %p\n", ptr); 1262 1263 /* Server */ 1264 StubMsg.IsClient = 0; 1265 mem = NULL; 1266 StubMsg.Buffer = StubMsg.BufferStart; 1267 ptr = NdrComplexStructUnmarshall(&StubMsg, (unsigned char **)&mem, fmtstr, 0); 1268 ok(ptr == NULL, "ret %p\n", ptr); 1269 ok(!memcmp(mem, memsrc, sizeof(*memsrc)), "struct wasn't unmarshalled correctly\n"); 1270 StubMsg.pfnFree(mem); 1271 1272 heap_free(StubMsg.RpcMsg->Buffer); 1273 heap_free(memsrc_orig); 1274 } 1275 1276 struct testiface 1277 { 1278 IPersist IPersist_iface; 1279 LONG ref; 1280 }; 1281 1282 static struct testiface *impl_from_IPersist(IPersist *iface) 1283 { 1284 return CONTAINING_RECORD(iface, struct testiface, IPersist_iface); 1285 } 1286 1287 static HRESULT WINAPI test_persist_QueryInterface(IPersist *iface, REFIID iid, void **out) 1288 { 1289 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IPersist)) 1290 { 1291 *out = iface; 1292 IPersist_AddRef(iface); 1293 return S_OK; 1294 } 1295 1296 *out = NULL; 1297 return E_NOINTERFACE; 1298 } 1299 1300 static ULONG WINAPI test_persist_AddRef(IPersist *iface) 1301 { 1302 struct testiface *unk = impl_from_IPersist(iface); 1303 return ++unk->ref; 1304 } 1305 1306 static ULONG WINAPI test_persist_Release(IPersist *iface) 1307 { 1308 struct testiface *unk = impl_from_IPersist(iface); 1309 return --unk->ref; 1310 } 1311 1312 static HRESULT WINAPI test_persist_GetClassId(IPersist *iface, GUID *clsid) 1313 { 1314 *clsid = IID_IPersist; 1315 return S_OK; 1316 } 1317 1318 static IPersistVtbl testiface_vtbl = { 1319 test_persist_QueryInterface, 1320 test_persist_AddRef, 1321 test_persist_Release, 1322 test_persist_GetClassId, 1323 }; 1324 1325 static void test_iface_ptr(void) 1326 { 1327 struct testiface server_obj = {{&testiface_vtbl}, 1}; 1328 struct testiface client_obj = {{&testiface_vtbl}, 1}; 1329 1330 MIDL_STUB_MESSAGE StubMsg; 1331 MIDL_STUB_DESC StubDesc; 1332 RPC_MESSAGE RpcMessage; 1333 IPersist *proxy; 1334 HRESULT hr; 1335 GUID clsid; 1336 void *ptr; 1337 LONG ref; 1338 1339 static const unsigned char fmtstr_ip[] = 1340 { 1341 FC_IP, 1342 FC_CONSTANT_IID, 1343 NdrFcLong(0x0000010c), 1344 NdrFcShort(0x0000), 1345 NdrFcShort(0x0000), 1346 0xc0, 1347 0x00, 1348 0x00, 1349 0x00, 1350 0x00, 1351 0x00, 1352 0x00, 1353 0x46, 1354 }; 1355 1356 CoInitialize(NULL); 1357 1358 StubDesc = Object_StubDesc; 1359 StubDesc.pFormatTypes = fmtstr_ip; 1360 1361 NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0); 1362 StubMsg.BufferLength = 0; 1363 NdrInterfacePointerBufferSize(&StubMsg, (unsigned char *)&client_obj.IPersist_iface, fmtstr_ip); 1364 1365 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 1366 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 1367 1368 /* server -> client */ 1369 1370 StubMsg.IsClient = 0; 1371 my_alloc_called = my_free_called = 0; 1372 StubMsg.Buffer = StubMsg.BufferStart; 1373 IPersist_AddRef(&server_obj.IPersist_iface); 1374 ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&server_obj.IPersist_iface, fmtstr_ip); 1375 ok(!ptr, "ret %p\n", ptr); 1376 ok(server_obj.ref > 2, "got %d references\n", server_obj.ref); 1377 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1378 ok(!my_free_called, "free called %d\n", my_free_called); 1379 1380 NdrInterfacePointerFree(&StubMsg, (unsigned char *)&server_obj.IPersist_iface, fmtstr_ip); 1381 ok(server_obj.ref > 1, "got %d references\n", server_obj.ref); 1382 1383 StubMsg.IsClient = 1; 1384 my_alloc_called = my_free_called = 0; 1385 StubMsg.Buffer = StubMsg.BufferStart; 1386 proxy = NULL; 1387 ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0); 1388 ok(!ptr, "ret %p\n", ptr); 1389 ok(!!proxy, "mem not alloced\n"); 1390 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1391 ok(!my_free_called, "free called %d\n", my_free_called); 1392 ok(server_obj.ref > 1, "got %d references\n", server_obj.ref); 1393 1394 hr = IPersist_GetClassID(proxy, &clsid); 1395 ok(hr == S_OK, "got hr %#x\n", hr); 1396 ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid)); 1397 1398 ref = IPersist_Release(proxy); 1399 ok(ref == 1, "got %d references\n", ref); 1400 ok(server_obj.ref == 1, "got %d references\n", server_obj.ref); 1401 1402 /* An existing interface pointer is released; this is necessary so that an 1403 * [in, out] pointer which changes does not leak references. */ 1404 1405 StubMsg.IsClient = 0; 1406 my_alloc_called = my_free_called = 0; 1407 StubMsg.Buffer = StubMsg.BufferStart; 1408 IPersist_AddRef(&server_obj.IPersist_iface); 1409 ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&server_obj.IPersist_iface, fmtstr_ip); 1410 ok(!ptr, "ret %p\n", ptr); 1411 ok(server_obj.ref > 2, "got %d references\n", server_obj.ref); 1412 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1413 ok(!my_free_called, "free called %d\n", my_free_called); 1414 1415 NdrInterfacePointerFree(&StubMsg, (unsigned char *)&server_obj.IPersist_iface, fmtstr_ip); 1416 ok(server_obj.ref > 1, "got %d references\n", server_obj.ref); 1417 1418 StubMsg.IsClient = 1; 1419 my_alloc_called = my_free_called = 0; 1420 StubMsg.Buffer = StubMsg.BufferStart; 1421 proxy = &client_obj.IPersist_iface; 1422 IPersist_AddRef(proxy); 1423 ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0); 1424 ok(!ptr, "ret %p\n", ptr); 1425 ok(!!proxy && proxy != &client_obj.IPersist_iface, "mem not alloced\n"); 1426 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1427 ok(!my_free_called, "free called %d\n", my_free_called); 1428 ok(server_obj.ref > 1, "got %d references\n", server_obj.ref); 1429 ok(client_obj.ref == 1, "got %d references\n", client_obj.ref); 1430 1431 hr = IPersist_GetClassID(proxy, &clsid); 1432 ok(hr == S_OK, "got hr %#x\n", hr); 1433 ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid)); 1434 1435 ref = IPersist_Release(proxy); 1436 ok(ref == 1, "got %d references\n", ref); 1437 ok(server_obj.ref == 1, "got %d references\n", server_obj.ref); 1438 1439 /* client -> server */ 1440 1441 StubMsg.IsClient = 1; 1442 my_alloc_called = my_free_called = 0; 1443 StubMsg.Buffer = StubMsg.BufferStart; 1444 IPersist_AddRef(&client_obj.IPersist_iface); 1445 ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&client_obj.IPersist_iface, fmtstr_ip); 1446 ok(!ptr, "ret %p\n", ptr); 1447 ok(client_obj.ref > 2, "got %d references\n", client_obj.ref); 1448 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1449 ok(!my_free_called, "free called %d\n", my_free_called); 1450 1451 StubMsg.IsClient = 0; 1452 my_alloc_called = my_free_called = 0; 1453 StubMsg.Buffer = StubMsg.BufferStart; 1454 proxy = NULL; 1455 ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0); 1456 ok(!ptr, "ret %p\n", ptr); 1457 ok(!!proxy, "mem not alloced\n"); 1458 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1459 ok(!my_free_called, "free called %d\n", my_free_called); 1460 ok(client_obj.ref > 2, "got %d references\n", client_obj.ref); 1461 1462 hr = IPersist_GetClassID(proxy, &clsid); 1463 ok(hr == S_OK, "got hr %#x\n", hr); 1464 ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid)); 1465 1466 ref = IPersist_Release(proxy); 1467 ok(client_obj.ref > 1, "got %d references\n", client_obj.ref); 1468 ok(ref == client_obj.ref, "expected %d references, got %d\n", client_obj.ref, ref); 1469 1470 NdrInterfacePointerFree(&StubMsg, (unsigned char *)proxy, fmtstr_ip); 1471 ok(client_obj.ref == 1, "got %d references\n", client_obj.ref); 1472 1473 /* same, but free the interface after calling NdrInterfacePointerFree */ 1474 1475 StubMsg.IsClient = 1; 1476 my_alloc_called = my_free_called = 0; 1477 StubMsg.Buffer = StubMsg.BufferStart; 1478 IPersist_AddRef(&client_obj.IPersist_iface); 1479 ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&client_obj.IPersist_iface, fmtstr_ip); 1480 ok(!ptr, "ret %p\n", ptr); 1481 ok(client_obj.ref > 2, "got %d references\n", client_obj.ref); 1482 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1483 ok(!my_free_called, "free called %d\n", my_free_called); 1484 1485 StubMsg.IsClient = 0; 1486 my_alloc_called = my_free_called = 0; 1487 StubMsg.Buffer = StubMsg.BufferStart; 1488 proxy = NULL; 1489 ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0); 1490 ok(!ptr, "ret %p\n", ptr); 1491 ok(!!proxy, "mem not alloced\n"); 1492 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1493 ok(!my_free_called, "free called %d\n", my_free_called); 1494 ok(client_obj.ref > 2, "got %d references\n", client_obj.ref); 1495 1496 NdrInterfacePointerFree(&StubMsg, (unsigned char *)proxy, fmtstr_ip); 1497 ok(client_obj.ref > 1, "got %d references\n", client_obj.ref); 1498 1499 hr = IPersist_GetClassID(proxy, &clsid); 1500 ok(hr == S_OK, "got hr %#x\n", hr); 1501 ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid)); 1502 1503 ref = IPersist_Release(proxy); 1504 ok(ref == 1, "got %d references\n", ref); 1505 ok(client_obj.ref == 1, "got %d references\n", client_obj.ref); 1506 1507 /* An existing interface pointer is *not* released (in fact, it is ignored 1508 * and may be invalid). In practice it will always be NULL anyway. */ 1509 1510 StubMsg.IsClient = 1; 1511 my_alloc_called = my_free_called = 0; 1512 StubMsg.Buffer = StubMsg.BufferStart; 1513 IPersist_AddRef(&client_obj.IPersist_iface); 1514 ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&client_obj.IPersist_iface, fmtstr_ip); 1515 ok(!ptr, "ret %p\n", ptr); 1516 ok(client_obj.ref > 2, "got %d references\n", client_obj.ref); 1517 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1518 ok(!my_free_called, "free called %d\n", my_free_called); 1519 1520 StubMsg.IsClient = 0; 1521 my_alloc_called = my_free_called = 0; 1522 StubMsg.Buffer = StubMsg.BufferStart; 1523 proxy = &server_obj.IPersist_iface; 1524 IPersist_AddRef(proxy); 1525 ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0); 1526 ok(!ptr, "ret %p\n", ptr); 1527 ok(!!proxy && proxy != &server_obj.IPersist_iface, "mem not alloced\n"); 1528 ok(!my_alloc_called, "alloc called %d\n", my_alloc_called); 1529 ok(!my_free_called, "free called %d\n", my_free_called); 1530 ok(client_obj.ref > 2, "got %d references\n", client_obj.ref); 1531 ok(server_obj.ref == 2, "got %d references\n", server_obj.ref); 1532 IPersist_Release(&server_obj.IPersist_iface); 1533 1534 hr = IPersist_GetClassID(proxy, &clsid); 1535 ok(hr == S_OK, "got hr %#x\n", hr); 1536 ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid)); 1537 1538 ref = IPersist_Release(proxy); 1539 ok(client_obj.ref > 1, "got %d references\n", client_obj.ref); 1540 ok(ref == client_obj.ref, "expected %d references, got %d\n", client_obj.ref, ref); 1541 1542 NdrInterfacePointerFree(&StubMsg, (unsigned char *)proxy, fmtstr_ip); 1543 ok(client_obj.ref == 1, "got %d references\n", client_obj.ref); 1544 1545 HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart); 1546 1547 CoUninitialize(); 1548 } 1549 1550 static void test_fullpointer_xlat(void) 1551 { 1552 PFULL_PTR_XLAT_TABLES pXlatTables; 1553 ULONG RefId; 1554 int ret; 1555 void *Pointer; 1556 1557 pXlatTables = NdrFullPointerXlatInit(2, XLAT_CLIENT); 1558 1559 /* "marshaling" phase */ 1560 1561 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); 1562 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1563 ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%x\n", RefId); 1564 1565 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId); 1566 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1567 ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%x\n", RefId); 1568 1569 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId); 1570 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1571 ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%x\n", RefId); 1572 1573 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId); 1574 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1575 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); 1576 1577 ret = NdrFullPointerQueryPointer(pXlatTables, NULL, 0, &RefId); 1578 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1579 ok(RefId == 0, "RefId should be 0 instead of 0x%x\n", RefId); 1580 1581 /* "unmarshaling" phase */ 1582 1583 ret = NdrFullPointerQueryRefId(pXlatTables, 0x0, 0, &Pointer); 1584 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1585 1586 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer); 1587 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1588 ok(Pointer == (void *)0xcafebabe, "Pointer should be 0xcafebabe instead of %p\n", Pointer); 1589 1590 ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 0, &Pointer); 1591 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1592 ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer); 1593 1594 NdrFullPointerInsertRefId(pXlatTables, 0x4, (void *)0xdeadbabe); 1595 1596 ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 1, &Pointer); 1597 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1598 ok(Pointer == (void *)0xdeadbabe, "Pointer should be (void *)0xdeadbabe instead of %p\n", Pointer); 1599 1600 NdrFullPointerXlatFree(pXlatTables); 1601 1602 pXlatTables = NdrFullPointerXlatInit(2, XLAT_SERVER); 1603 1604 /* "unmarshaling" phase */ 1605 1606 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer); 1607 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1608 ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer); 1609 1610 NdrFullPointerInsertRefId(pXlatTables, 0x2, (void *)0xcafebabe); 1611 1612 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer); 1613 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1614 ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer); 1615 1616 ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer); 1617 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1618 ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer); 1619 1620 /* "marshaling" phase */ 1621 1622 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); 1623 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1624 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); 1625 1626 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); 1627 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1628 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); 1629 1630 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId); 1631 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1632 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); 1633 1634 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId); 1635 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1636 ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%x\n", RefId); 1637 1638 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId); 1639 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1640 ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId); 1641 1642 /* "freeing" phase */ 1643 1644 ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebeef); 1645 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1646 1647 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0x20, &RefId); 1648 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1649 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); 1650 1651 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); 1652 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1653 ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); 1654 1655 ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebabe); 1656 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1657 1658 ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef); 1659 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1660 1661 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0x20, &RefId); 1662 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1663 ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId); 1664 1665 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 1, &RefId); 1666 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1667 ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId); 1668 1669 ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 1, &RefId); 1670 ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); 1671 ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId); 1672 1673 ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef); 1674 ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); 1675 1676 NdrFullPointerXlatFree(pXlatTables); 1677 } 1678 1679 /* verify stub data that is identical between client and server */ 1680 static void test_common_stub_data( const char *prefix, const MIDL_STUB_MESSAGE *stubMsg ) 1681 { 1682 void *unset_ptr; 1683 1684 memset(&unset_ptr, 0xcc, sizeof(unset_ptr)); 1685 1686 #define TEST_ZERO(field, fmt) ok(stubMsg->field == 0, "%s: " #field " should have been set to zero instead of " fmt "\n", prefix, stubMsg->field) 1687 #define TEST_POINTER_UNSET(field) ok(stubMsg->field == unset_ptr, "%s: " #field " should have been unset instead of %p\n", prefix, stubMsg->field) 1688 #define TEST_ULONG_UNSET(field) ok(stubMsg->field == 0xcccccccc, "%s: " #field " should have been unset instead of 0x%x\n", prefix, stubMsg->field) 1689 #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) 1690 1691 TEST_POINTER_UNSET(BufferMark); 1692 TEST_ULONG_UNSET(MemorySize); 1693 TEST_POINTER_UNSET(Memory); 1694 TEST_ZERO(pAllocAllNodesContext, "%p"); 1695 ok(stubMsg->pPointerQueueState == 0 || 1696 broken(stubMsg->pPointerQueueState == unset_ptr), /* win2k */ 1697 "%s: pPointerQueueState should have been unset instead of %p\n", 1698 prefix, stubMsg->pPointerQueueState); 1699 TEST_ZERO(IgnoreEmbeddedPointers, "%d"); 1700 TEST_ZERO(PointerBufferMark, "%p"); 1701 ok( stubMsg->uFlags == 0 || 1702 broken(stubMsg->uFlags == 0xcc), /* win9x */ 1703 "%s: uFlags should have been set to zero instead of 0x%x\n", prefix, stubMsg->uFlags ); 1704 /* FIXME: UniquePtrCount */ 1705 TEST_ULONG_PTR_UNSET(MaxCount); 1706 TEST_ULONG_UNSET(Offset); 1707 TEST_ULONG_UNSET(ActualCount); 1708 ok(stubMsg->pfnAllocate == my_alloc, "%s: pfnAllocate should have been %p instead of %p\n", 1709 prefix, my_alloc, stubMsg->pfnAllocate); 1710 ok(stubMsg->pfnFree == my_free, "%s: pfnFree should have been %p instead of %p\n", 1711 prefix, my_free, stubMsg->pfnFree); 1712 TEST_ZERO(StackTop, "%p"); 1713 TEST_POINTER_UNSET(pPresentedType); 1714 TEST_POINTER_UNSET(pTransmitType); 1715 TEST_POINTER_UNSET(SavedHandle); 1716 ok(stubMsg->StubDesc == &Object_StubDesc, "%s: StubDesc should have been %p instead of %p\n", 1717 prefix, &Object_StubDesc, stubMsg->StubDesc); 1718 TEST_ZERO(FullPtrRefId, "%d"); 1719 ok( stubMsg->PointerLength == 0 || 1720 broken(stubMsg->PointerLength == 1), /* win9x, nt4 */ 1721 "%s: pAsyncMsg should have been set to zero instead of %d\n", prefix, stubMsg->PointerLength ); 1722 TEST_ZERO(fInDontFree, "%d"); 1723 TEST_ZERO(fDontCallFreeInst, "%d"); 1724 ok( stubMsg->fHasReturn == 0 || broken(stubMsg->fHasReturn), /* win9x, nt4 */ 1725 "%s: fHasReturn should have been set to zero instead of %d\n", prefix, stubMsg->fHasReturn ); 1726 TEST_ZERO(fHasExtensions, "%d"); 1727 TEST_ZERO(fHasNewCorrDesc, "%d"); 1728 ok(stubMsg->fIsIn == 0 || broken(stubMsg->fIsIn), /* win9x, nt4 */ 1729 "%s: fIsIn should have been set to 0 instead of %d\n", prefix, stubMsg->fIsIn); 1730 TEST_ZERO(fIsOicf, "%d"); 1731 ok(stubMsg->fBufferValid == 0, 1732 "%s: fBufferValid should have been set to 0 instead of %d\n", prefix, stubMsg->fBufferValid); 1733 TEST_ZERO(fNeedMCCP, "%d"); 1734 ok(stubMsg->fUnused == 0 || 1735 stubMsg->fUnused == -2, /* Vista */ 1736 "%s: fUnused should have been set to 0 or -2 instead of %d\n", prefix, stubMsg->fUnused); 1737 ok(stubMsg->fUnused2 == 0xffffcccc, "%s: fUnused2 should have been 0xffffcccc instead of 0x%x\n", 1738 prefix, stubMsg->fUnused2); 1739 ok(stubMsg->dwDestContext == MSHCTX_DIFFERENTMACHINE, 1740 "%s: dwDestContext should have been MSHCTX_DIFFERENTMACHINE instead of %d\n", 1741 prefix, stubMsg->dwDestContext); 1742 TEST_ZERO(pvDestContext, "%p"); 1743 TEST_POINTER_UNSET(SavedContextHandles); 1744 TEST_ULONG_UNSET(ParamNumber); 1745 TEST_ZERO(pRpcChannelBuffer, "%p"); 1746 TEST_ZERO(pArrayInfo, "%p"); 1747 TEST_POINTER_UNSET(SizePtrCountArray); 1748 TEST_POINTER_UNSET(SizePtrOffsetArray); 1749 TEST_POINTER_UNSET(SizePtrLengthArray); 1750 TEST_POINTER_UNSET(pArgQueue); 1751 TEST_ZERO(dwStubPhase, "%d"); 1752 /* FIXME: where does this value come from? */ 1753 trace("%s: LowStackMark is %p\n", prefix, stubMsg->LowStackMark); 1754 ok( stubMsg->pAsyncMsg == 0 || broken(stubMsg->pAsyncMsg == unset_ptr), /* win9x, nt4 */ 1755 "%s: pAsyncMsg should have been set to zero instead of %p\n", prefix, stubMsg->pAsyncMsg ); 1756 ok( stubMsg->pCorrInfo == 0 || broken(stubMsg->pCorrInfo == unset_ptr), /* win9x, nt4 */ 1757 "%s: pCorrInfo should have been set to zero instead of %p\n", prefix, stubMsg->pCorrInfo ); 1758 ok( stubMsg->pCorrMemory == 0 || broken(stubMsg->pCorrMemory == unset_ptr), /* win9x, nt4 */ 1759 "%s: pCorrMemory should have been set to zero instead of %p\n", prefix, stubMsg->pCorrMemory ); 1760 ok( stubMsg->pMemoryList == 0 || broken(stubMsg->pMemoryList == unset_ptr), /* win9x, nt4 */ 1761 "%s: pMemoryList should have been set to zero instead of %p\n", prefix, stubMsg->pMemoryList ); 1762 TEST_POINTER_UNSET(pCSInfo); 1763 TEST_POINTER_UNSET(ConformanceMark); 1764 TEST_POINTER_UNSET(VarianceMark); 1765 ok(stubMsg->Unused == (ULONG_PTR)unset_ptr, "%s: Unused should have be unset instead of 0x%lx\n", 1766 prefix, stubMsg->Unused); 1767 TEST_POINTER_UNSET(pContext); 1768 TEST_POINTER_UNSET(ContextHandleHash); 1769 TEST_POINTER_UNSET(pUserMarshalList); 1770 TEST_ULONG_PTR_UNSET(Reserved51_3); 1771 TEST_ULONG_PTR_UNSET(Reserved51_4); 1772 TEST_ULONG_PTR_UNSET(Reserved51_5); 1773 1774 #undef TEST_ULONG_PTR_UNSET 1775 #undef TEST_ULONG_UNSET 1776 #undef TEST_POINTER_UNSET 1777 #undef TEST_ZERO 1778 } 1779 1780 static void test_client_init(void) 1781 { 1782 MIDL_STUB_MESSAGE stubMsg; 1783 RPC_MESSAGE rpcMsg; 1784 void *unset_ptr; 1785 1786 memset(&rpcMsg, 0xcc, sizeof(rpcMsg)); 1787 memset(&stubMsg, 0xcc, sizeof(stubMsg)); 1788 memset(&unset_ptr, 0xcc, sizeof(unset_ptr)); 1789 1790 NdrClientInitializeNew(&rpcMsg, &stubMsg, &Object_StubDesc, 1); 1791 1792 test_common_stub_data( "NdrClientInitializeNew", &stubMsg ); 1793 1794 ok(stubMsg.RpcMsg == &rpcMsg, "stubMsg.RpcMsg should have been %p instead of %p\n", &rpcMsg, stubMsg.RpcMsg); 1795 ok(rpcMsg.Handle == NULL, "rpcMsg.Handle should have been NULL instead of %p\n", rpcMsg.Handle); 1796 ok(rpcMsg.Buffer == unset_ptr, "rpcMsg.Buffer should have been unset instead of %p\n", 1797 rpcMsg.Buffer); 1798 ok(rpcMsg.BufferLength == 0xcccccccc, "rpcMsg.BufferLength should have been unset instead of %d\n", rpcMsg.BufferLength); 1799 ok(rpcMsg.ProcNum == 0x8001, "rpcMsg.ProcNum should have been 0x8001 instead of 0x%x\n", rpcMsg.ProcNum); 1800 ok(rpcMsg.TransferSyntax == unset_ptr, "rpcMsg.TransferSyntax should have been unset instead of %p\n", rpcMsg.TransferSyntax); 1801 ok(rpcMsg.RpcInterfaceInformation == Object_StubDesc.RpcInterfaceInformation, 1802 "rpcMsg.RpcInterfaceInformation should have been %p instead of %p\n", 1803 Object_StubDesc.RpcInterfaceInformation, rpcMsg.RpcInterfaceInformation); 1804 /* Note: ReservedForRuntime not tested */ 1805 ok(rpcMsg.ManagerEpv == unset_ptr, "rpcMsg.ManagerEpv should have been unset instead of %p\n", rpcMsg.ManagerEpv); 1806 ok(rpcMsg.ImportContext == unset_ptr, "rpcMsg.ImportContext should have been unset instead of %p\n", rpcMsg.ImportContext); 1807 ok(rpcMsg.RpcFlags == 0, "rpcMsg.RpcFlags should have been 0 instead of 0x%x\n", rpcMsg.RpcFlags); 1808 1809 ok(stubMsg.Buffer == unset_ptr, "stubMsg.Buffer should have been unset instead of %p\n", 1810 stubMsg.Buffer); 1811 ok(stubMsg.BufferStart == NULL, "stubMsg.BufferStart should have been NULL instead of %p\n", 1812 stubMsg.BufferStart); 1813 ok(stubMsg.BufferEnd == NULL, "stubMsg.BufferEnd should have been NULL instead of %p\n", 1814 stubMsg.BufferEnd); 1815 ok(stubMsg.BufferLength == 0, "stubMsg.BufferLength should have been 0 instead of %u\n", 1816 stubMsg.BufferLength); 1817 ok(stubMsg.IsClient == 1, "stubMsg.IsClient should have been 1 instead of %u\n", stubMsg.IsClient); 1818 ok(stubMsg.ReuseBuffer == 0, "stubMsg.ReuseBuffer should have been 0 instead of %d\n", 1819 stubMsg.ReuseBuffer); 1820 ok(stubMsg.CorrDespIncrement == 0, "stubMsg.CorrDespIncrement should have been 0 instead of %d\n", 1821 stubMsg.CorrDespIncrement); 1822 ok(stubMsg.FullPtrXlatTables == unset_ptr, "stubMsg.FullPtrXlatTables should have been unset instead of %p\n", 1823 stubMsg.FullPtrXlatTables); 1824 } 1825 1826 static void test_server_init(void) 1827 { 1828 MIDL_STUB_MESSAGE stubMsg; 1829 RPC_MESSAGE rpcMsg; 1830 unsigned char *ret; 1831 unsigned char buffer[256]; 1832 1833 memset(&rpcMsg, 0, sizeof(rpcMsg)); 1834 rpcMsg.Buffer = buffer; 1835 rpcMsg.BufferLength = sizeof(buffer); 1836 rpcMsg.RpcFlags = RPC_BUFFER_COMPLETE; 1837 1838 memset(&stubMsg, 0xcc, sizeof(stubMsg)); 1839 1840 ret = NdrServerInitializeNew(&rpcMsg, &stubMsg, &Object_StubDesc); 1841 ok(ret == NULL, "NdrServerInitializeNew should have returned NULL instead of %p\n", ret); 1842 1843 test_common_stub_data( "NdrServerInitializeNew", &stubMsg ); 1844 1845 ok(stubMsg.RpcMsg == &rpcMsg, "stubMsg.RpcMsg should have been %p instead of %p\n", &rpcMsg, stubMsg.RpcMsg); 1846 ok(stubMsg.Buffer == buffer, "stubMsg.Buffer should have been %p instead of %p\n", buffer, stubMsg.Buffer); 1847 ok(stubMsg.BufferStart == buffer, "stubMsg.BufferStart should have been %p instead of %p\n", buffer, stubMsg.BufferStart); 1848 ok(stubMsg.BufferEnd == buffer + sizeof(buffer), "stubMsg.BufferEnd should have been %p instead of %p\n", buffer + sizeof(buffer), stubMsg.BufferEnd); 1849 todo_wine 1850 ok(stubMsg.BufferLength == 0, "stubMsg.BufferLength should have been 0 instead of %u\n", stubMsg.BufferLength); 1851 ok(stubMsg.IsClient == 0, "stubMsg.IsClient should have been 0 instead of %u\n", stubMsg.IsClient); 1852 ok(stubMsg.ReuseBuffer == 0 || 1853 broken(stubMsg.ReuseBuffer == 1), /* win2k */ 1854 "stubMsg.ReuseBuffer should have been set to zero instead of %d\n", stubMsg.ReuseBuffer); 1855 ok(stubMsg.CorrDespIncrement == 0 || 1856 broken(stubMsg.CorrDespIncrement == 0xcc), /* <= Win 2003 */ 1857 "CorrDespIncrement should have been set to zero instead of 0x%x\n", stubMsg.CorrDespIncrement); 1858 ok(stubMsg.FullPtrXlatTables == 0, "stubMsg.BufferLength should have been 0 instead of %p\n", stubMsg.FullPtrXlatTables); 1859 } 1860 1861 static void test_ndr_allocate(void) 1862 { 1863 RPC_MESSAGE RpcMessage; 1864 MIDL_STUB_MESSAGE StubMsg; 1865 MIDL_STUB_DESC StubDesc; 1866 void *p1, *p2; 1867 struct tag_mem_list_v2_t 1868 { 1869 DWORD magic; 1870 DWORD size; 1871 DWORD unknown; 1872 struct tag_mem_list_v2_t *next; 1873 } *mem_list_v2; 1874 const DWORD magic_MEML = 'M' << 24 | 'E' << 16 | 'M' << 8 | 'L'; 1875 1876 StubDesc = Object_StubDesc; 1877 NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0); 1878 1879 my_alloc_called = my_free_called = 0; 1880 p1 = NdrAllocate(&StubMsg, 10); 1881 p2 = NdrAllocate(&StubMsg, 24); 1882 ok(my_alloc_called == 2, "alloc called %d\n", my_alloc_called); 1883 ok(StubMsg.pMemoryList != NULL, "StubMsg.pMemoryList NULL\n"); 1884 if(StubMsg.pMemoryList) 1885 { 1886 mem_list_v2 = StubMsg.pMemoryList; 1887 if (mem_list_v2->size == 24) 1888 { 1889 trace("v2 mem list format\n"); 1890 ok((char *)mem_list_v2 == (char *)p2 + 24, "expected mem_list_v2 pointer %p, but got %p\n", (char *)p2 + 24, mem_list_v2); 1891 ok(mem_list_v2->magic == magic_MEML, "magic %08x\n", mem_list_v2->magic); 1892 ok(mem_list_v2->size == 24, "wrong size for p2 %d\n", mem_list_v2->size); 1893 ok(mem_list_v2->unknown == 0, "wrong unknown for p2 0x%x\n", mem_list_v2->unknown); 1894 ok(mem_list_v2->next != NULL, "next NULL\n"); 1895 mem_list_v2 = mem_list_v2->next; 1896 if(mem_list_v2) 1897 { 1898 ok((char *)mem_list_v2 == (char *)p1 + 16, "expected mem_list_v2 pointer %p, but got %p\n", (char *)p1 + 16, mem_list_v2); 1899 ok(mem_list_v2->magic == magic_MEML, "magic %08x\n", mem_list_v2->magic); 1900 ok(mem_list_v2->size == 16, "wrong size for p1 %d\n", mem_list_v2->size); 1901 ok(mem_list_v2->unknown == 0, "wrong unknown for p1 0x%x\n", mem_list_v2->unknown); 1902 ok(mem_list_v2->next == NULL, "next %p\n", mem_list_v2->next); 1903 } 1904 } 1905 else win_skip("v1 mem list format\n"); 1906 } 1907 /* NdrFree isn't exported so we can't test free'ing */ 1908 my_free(p1); 1909 my_free(p2); 1910 } 1911 1912 static void test_conformant_array(void) 1913 { 1914 RPC_MESSAGE RpcMessage; 1915 MIDL_STUB_MESSAGE StubMsg; 1916 MIDL_STUB_DESC StubDesc; 1917 void *ptr; 1918 unsigned char *mem, *mem_orig; 1919 unsigned char memsrc[20]; 1920 unsigned int i; 1921 1922 static const unsigned char fmtstr_conf_array[] = 1923 { 1924 0x1b, /* FC_CARRAY */ 1925 0x0, /* align */ 1926 NdrFcShort( 0x1 ), /* elem size */ 1927 0x40, /* Corr desc: const */ 1928 0x0, 1929 NdrFcShort(0x10), /* const = 0x10 */ 1930 0x1, /* FC_BYTE */ 1931 0x5b /* FC_END */ 1932 }; 1933 1934 for (i = 0; i < sizeof(memsrc); i++) 1935 memsrc[i] = i * i; 1936 1937 StubDesc = Object_StubDesc; 1938 StubDesc.pFormatTypes = fmtstr_conf_array; 1939 1940 NdrClientInitializeNew( 1941 &RpcMessage, 1942 &StubMsg, 1943 &StubDesc, 1944 0); 1945 1946 StubMsg.BufferLength = 0; 1947 NdrConformantArrayBufferSize( &StubMsg, 1948 memsrc, 1949 fmtstr_conf_array ); 1950 ok(StubMsg.BufferLength >= 20, "length %d\n", StubMsg.BufferLength); 1951 1952 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ 1953 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 1954 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 1955 1956 ptr = NdrConformantArrayMarshall( &StubMsg, memsrc, fmtstr_conf_array ); 1957 ok(ptr == NULL, "ret %p\n", ptr); 1958 ok(StubMsg.Buffer - StubMsg.BufferStart == 20, "Buffer %p Start %p len %d\n", StubMsg.Buffer, StubMsg.BufferStart, 20); 1959 ok(!memcmp(StubMsg.BufferStart + 4, memsrc, 16), "incorrectly marshaled\n"); 1960 1961 StubMsg.Buffer = StubMsg.BufferStart; 1962 StubMsg.MemorySize = 0; 1963 mem = NULL; 1964 1965 /* Client */ 1966 my_alloc_called = 0; 1967 /* passing mem == NULL with must_alloc == 0 crashes under Windows */ 1968 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1); 1969 ok(mem != NULL, "mem not alloced\n"); 1970 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); 1971 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); 1972 1973 my_alloc_called = 0; 1974 StubMsg.Buffer = StubMsg.BufferStart; 1975 mem_orig = mem; 1976 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0); 1977 ok(mem == mem_orig, "mem alloced\n"); 1978 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); 1979 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 1980 1981 my_alloc_called = 0; 1982 StubMsg.Buffer = StubMsg.BufferStart; 1983 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1); 1984 ok(mem != mem_orig, "mem not alloced\n"); 1985 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); 1986 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); 1987 1988 my_free_called = 0; 1989 StubMsg.Buffer = StubMsg.BufferStart; 1990 NdrConformantArrayFree( &StubMsg, mem, fmtstr_conf_array ); 1991 ok(my_free_called == 0, "free called %d\n", my_free_called); 1992 StubMsg.pfnFree(mem); 1993 1994 /* Server */ 1995 my_alloc_called = 0; 1996 StubMsg.IsClient = 0; 1997 mem = NULL; 1998 StubMsg.Buffer = StubMsg.BufferStart; 1999 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0); 2000 ok(mem == StubMsg.BufferStart + 4 || broken(!mem), /* win9x, nt4 */ 2001 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 4); 2002 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2003 my_alloc_called = 0; 2004 mem = NULL; 2005 StubMsg.Buffer = StubMsg.BufferStart; 2006 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1); 2007 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); 2008 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); 2009 StubMsg.pfnFree(mem); 2010 2011 my_alloc_called = 0; 2012 mem = mem_orig; 2013 StubMsg.Buffer = StubMsg.BufferStart; 2014 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0); 2015 ok(mem == mem_orig, "mem alloced\n"); 2016 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2017 2018 my_alloc_called = 0; 2019 mem = mem_orig; 2020 StubMsg.Buffer = StubMsg.BufferStart; 2021 NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1); 2022 ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); 2023 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); 2024 StubMsg.pfnFree(mem); 2025 StubMsg.pfnFree(mem_orig); 2026 2027 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); 2028 } 2029 2030 static void test_conformant_string(void) 2031 { 2032 RPC_MESSAGE RpcMessage; 2033 MIDL_STUB_MESSAGE StubMsg; 2034 MIDL_STUB_DESC StubDesc; 2035 DWORD size; 2036 void *ptr; 2037 unsigned char *mem, *mem_orig; 2038 char memsrc[] = "This is a test string"; 2039 2040 static const unsigned char fmtstr_conf_str[] = 2041 { 2042 0x11, 0x8, /* FC_RP [simple_pointer] */ 2043 0x22, /* FC_C_CSTRING */ 2044 0x5c, /* FC_PAD */ 2045 }; 2046 2047 StubDesc = Object_StubDesc; 2048 StubDesc.pFormatTypes = fmtstr_conf_str; 2049 2050 memset( &StubMsg, 0, sizeof(StubMsg) ); /* needed on win9x and nt4 */ 2051 NdrClientInitializeNew( 2052 &RpcMessage, 2053 &StubMsg, 2054 &StubDesc, 2055 0); 2056 2057 StubMsg.BufferLength = 0; 2058 NdrPointerBufferSize( &StubMsg, 2059 (unsigned char *)memsrc, 2060 fmtstr_conf_str ); 2061 ok(StubMsg.BufferLength >= sizeof(memsrc) + 12, "length %d\n", StubMsg.BufferLength); 2062 2063 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ 2064 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 2065 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 2066 2067 ptr = NdrPointerMarshall( &StubMsg, (unsigned char *)memsrc, fmtstr_conf_str ); 2068 ok(ptr == NULL, "ret %p\n", ptr); 2069 size = StubMsg.Buffer - StubMsg.BufferStart; 2070 ok(size == sizeof(memsrc) + 12, "Buffer %p Start %p len %d\n", 2071 StubMsg.Buffer, StubMsg.BufferStart, size); 2072 ok(!memcmp(StubMsg.BufferStart + 12, memsrc, sizeof(memsrc)), "incorrectly marshaled\n"); 2073 2074 StubMsg.Buffer = StubMsg.BufferStart; 2075 StubMsg.MemorySize = 0; 2076 mem = NULL; 2077 2078 /* Client */ 2079 my_alloc_called = 0; 2080 StubMsg.Buffer = StubMsg.BufferStart; 2081 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc)); 2082 /* Windows apparently checks string length on the output buffer to determine its size... */ 2083 memset( mem, 'x', sizeof(memsrc) - 1 ); 2084 mem[sizeof(memsrc) - 1] = 0; 2085 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0); 2086 ok(mem == mem_orig, "mem not alloced\n"); 2087 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2088 2089 my_alloc_called = 0; 2090 StubMsg.Buffer = StubMsg.BufferStart; 2091 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1); 2092 ok(mem == mem_orig, "mem not alloced\n"); 2093 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2094 2095 /* Prevent a memory leak when running with Wine. 2096 Remove once the todo_wine block above is fixed. */ 2097 if (mem != mem_orig) 2098 HeapFree(GetProcessHeap(), 0, mem_orig); 2099 2100 my_free_called = 0; 2101 StubMsg.Buffer = StubMsg.BufferStart; 2102 NdrPointerFree( &StubMsg, mem, fmtstr_conf_str ); 2103 ok(my_free_called == 1, "free called %d\n", my_free_called); 2104 2105 mem = my_alloc(10); 2106 my_free_called = 0; 2107 StubMsg.Buffer = StubMsg.BufferStart; 2108 NdrPointerFree( &StubMsg, mem, fmtstr_conf_str ); 2109 ok(my_free_called == 1, "free called %d\n", my_free_called); 2110 2111 /* Server */ 2112 my_alloc_called = 0; 2113 StubMsg.IsClient = 0; 2114 mem = NULL; 2115 StubMsg.Buffer = StubMsg.BufferStart; 2116 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0); 2117 ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */ 2118 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 ); 2119 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2120 2121 my_alloc_called = 0; 2122 mem = NULL; 2123 StubMsg.Buffer = StubMsg.BufferStart; 2124 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1); 2125 ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */ 2126 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 ); 2127 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2128 2129 my_alloc_called = 0; 2130 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc)); 2131 StubMsg.Buffer = StubMsg.BufferStart; 2132 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0); 2133 ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */ 2134 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 ); 2135 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2136 2137 my_alloc_called = 0; 2138 mem = mem_orig; 2139 StubMsg.Buffer = StubMsg.BufferStart; 2140 NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1); 2141 ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */ 2142 "mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 ); 2143 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2144 2145 mem = my_alloc(10); 2146 my_free_called = 0; 2147 StubMsg.Buffer = StubMsg.BufferStart; 2148 NdrPointerFree( &StubMsg, mem, fmtstr_conf_str ); 2149 ok(my_free_called == 1, "free called %d\n", my_free_called); 2150 2151 HeapFree(GetProcessHeap(), 0, mem_orig); 2152 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); 2153 } 2154 2155 static void test_nonconformant_string(void) 2156 { 2157 RPC_MESSAGE RpcMessage; 2158 MIDL_STUB_MESSAGE StubMsg; 2159 MIDL_STUB_DESC StubDesc; 2160 DWORD size; 2161 void *ptr; 2162 unsigned char *mem, *mem_orig; 2163 unsigned char memsrc[10] = "This is"; 2164 unsigned char memsrc2[10] = "This is a"; 2165 2166 static const unsigned char fmtstr_nonconf_str[] = 2167 { 2168 0x26, /* FC_CSTRING */ 2169 0x5c, /* FC_PAD */ 2170 NdrFcShort( 0xa ), /* 10 */ 2171 }; 2172 2173 StubDesc = Object_StubDesc; 2174 StubDesc.pFormatTypes = fmtstr_nonconf_str; 2175 2176 /* length < size */ 2177 NdrClientInitializeNew( 2178 &RpcMessage, 2179 &StubMsg, 2180 &StubDesc, 2181 0); 2182 2183 StubMsg.BufferLength = 0; 2184 2185 NdrNonConformantStringBufferSize( &StubMsg, memsrc, fmtstr_nonconf_str ); 2186 ok(StubMsg.BufferLength >= strlen((char *)memsrc) + 1 + 8, "length %d\n", StubMsg.BufferLength); 2187 2188 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ 2189 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 2190 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 2191 2192 ptr = NdrNonConformantStringMarshall( &StubMsg, memsrc, fmtstr_nonconf_str ); 2193 ok(ptr == NULL, "ret %p\n", ptr); 2194 size = StubMsg.Buffer - StubMsg.BufferStart; 2195 ok(size == strlen((char *)memsrc) + 1 + 8, "Buffer %p Start %p len %d\n", 2196 StubMsg.Buffer, StubMsg.BufferStart, size); 2197 ok(!memcmp(StubMsg.BufferStart + 8, memsrc, strlen((char *)memsrc) + 1), "incorrectly marshaled\n"); 2198 2199 StubMsg.Buffer = StubMsg.BufferStart; 2200 StubMsg.MemorySize = 0; 2201 mem = NULL; 2202 2203 /* Client */ 2204 my_alloc_called = 0; 2205 StubMsg.Buffer = StubMsg.BufferStart; 2206 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc)); 2207 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); 2208 ok(mem == mem_orig, "mem alloced\n"); 2209 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2210 2211 my_alloc_called = 0; 2212 StubMsg.Buffer = StubMsg.BufferStart; 2213 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1); 2214 todo_wine 2215 ok(mem == mem_orig, "mem alloced\n"); 2216 todo_wine 2217 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2218 2219 /* Server */ 2220 my_alloc_called = 0; 2221 StubMsg.IsClient = 0; 2222 mem = NULL; 2223 StubMsg.Buffer = StubMsg.BufferStart; 2224 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); 2225 ok(mem != mem_orig, "mem not alloced\n"); 2226 ok(mem != StubMsg.BufferStart + 8, "mem pointing at buffer\n"); 2227 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); 2228 NdrOleFree(mem); 2229 2230 my_alloc_called = 0; 2231 mem = mem_orig; 2232 StubMsg.Buffer = StubMsg.BufferStart; 2233 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); 2234 ok(mem == mem_orig, "mem alloced\n"); 2235 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2236 2237 my_alloc_called = 0; 2238 mem = mem_orig; 2239 StubMsg.Buffer = StubMsg.BufferStart; 2240 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1); 2241 todo_wine 2242 ok(mem == mem_orig, "mem alloced\n"); 2243 todo_wine 2244 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2245 2246 HeapFree(GetProcessHeap(), 0, mem_orig); 2247 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); 2248 2249 /* length = size */ 2250 NdrClientInitializeNew( 2251 &RpcMessage, 2252 &StubMsg, 2253 &StubDesc, 2254 0); 2255 2256 StubMsg.BufferLength = 0; 2257 2258 NdrNonConformantStringBufferSize( &StubMsg, memsrc2, fmtstr_nonconf_str ); 2259 ok(StubMsg.BufferLength >= strlen((char *)memsrc2) + 1 + 8, "length %d\n", StubMsg.BufferLength); 2260 2261 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ 2262 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 2263 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 2264 2265 ptr = NdrNonConformantStringMarshall( &StubMsg, memsrc2, fmtstr_nonconf_str ); 2266 ok(ptr == NULL, "ret %p\n", ptr); 2267 size = StubMsg.Buffer - StubMsg.BufferStart; 2268 ok(size == strlen((char *)memsrc2) + 1 + 8, "Buffer %p Start %p len %d\n", 2269 StubMsg.Buffer, StubMsg.BufferStart, size); 2270 ok(!memcmp(StubMsg.BufferStart + 8, memsrc2, strlen((char *)memsrc2) + 1), "incorrectly marshaled\n"); 2271 2272 StubMsg.Buffer = StubMsg.BufferStart; 2273 StubMsg.MemorySize = 0; 2274 mem = NULL; 2275 2276 /* Client */ 2277 my_alloc_called = 0; 2278 StubMsg.Buffer = StubMsg.BufferStart; 2279 mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc)); 2280 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); 2281 ok(mem == mem_orig, "mem alloced\n"); 2282 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2283 2284 my_alloc_called = 0; 2285 StubMsg.Buffer = StubMsg.BufferStart; 2286 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1); 2287 todo_wine 2288 ok(mem == mem_orig, "mem alloced\n"); 2289 todo_wine 2290 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2291 2292 /* Server */ 2293 my_alloc_called = 0; 2294 StubMsg.IsClient = 0; 2295 mem = NULL; 2296 StubMsg.Buffer = StubMsg.BufferStart; 2297 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); 2298 ok(mem != mem_orig, "mem not alloced\n"); 2299 ok(mem != StubMsg.BufferStart + 8, "mem pointing at buffer\n"); 2300 ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); 2301 NdrOleFree(mem); 2302 2303 my_alloc_called = 0; 2304 mem = mem_orig; 2305 StubMsg.Buffer = StubMsg.BufferStart; 2306 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); 2307 ok(mem == mem_orig, "mem alloced\n"); 2308 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2309 2310 my_alloc_called = 0; 2311 mem = mem_orig; 2312 StubMsg.Buffer = StubMsg.BufferStart; 2313 NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1); 2314 todo_wine 2315 ok(mem == mem_orig, "mem alloced\n"); 2316 todo_wine 2317 ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); 2318 2319 HeapFree(GetProcessHeap(), 0, mem_orig); 2320 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); 2321 } 2322 2323 static void test_conf_complex_struct(void) 2324 { 2325 RPC_MESSAGE RpcMessage; 2326 MIDL_STUB_MESSAGE StubMsg; 2327 MIDL_STUB_DESC StubDesc; 2328 void *ptr; 2329 unsigned int i; 2330 struct conf_complex 2331 { 2332 unsigned int size; 2333 unsigned int *array[1]; 2334 }; 2335 struct conf_complex *memsrc; 2336 struct conf_complex *mem; 2337 2338 static const unsigned char fmtstr_complex_struct[] = 2339 { 2340 /* 0 */ 2341 0x1b, /* FC_CARRAY */ 2342 0x3, /* 3 */ 2343 /* 2 */ NdrFcShort( 0x4 ), /* 4 */ 2344 /* 4 */ 0x8, /* Corr desc: FC_LONG */ 2345 0x0, /* */ 2346 /* 6 */ NdrFcShort( 0xfffc ), /* -4 */ 2347 /* 8 */ 2348 0x4b, /* FC_PP */ 2349 0x5c, /* FC_PAD */ 2350 /* 10 */ 2351 0x48, /* FC_VARIABLE_REPEAT */ 2352 0x49, /* FC_FIXED_OFFSET */ 2353 /* 12 */ NdrFcShort( 0x4 ), /* 4 */ 2354 /* 14 */ NdrFcShort( 0x0 ), /* 0 */ 2355 /* 16 */ NdrFcShort( 0x1 ), /* 1 */ 2356 /* 18 */ NdrFcShort( 0x0 ), /* 0 */ 2357 /* 20 */ NdrFcShort( 0x0 ), /* 0 */ 2358 /* 22 */ 0x12, 0x8, /* FC_UP [simple_pointer] */ 2359 /* 24 */ 0x8, /* FC_LONG */ 2360 0x5c, /* FC_PAD */ 2361 /* 26 */ 2362 0x5b, /* FC_END */ 2363 2364 0x8, /* FC_LONG */ 2365 /* 28 */ 0x5c, /* FC_PAD */ 2366 0x5b, /* FC_END */ 2367 /* 30 */ 2368 0x1a, /* FC_BOGUS_STRUCT */ 2369 0x3, /* 3 */ 2370 /* 32 */ NdrFcShort( 0x4 ), /* 4 */ 2371 /* 34 */ NdrFcShort( 0xffffffde ), /* Offset= -34 (0) */ 2372 /* 36 */ NdrFcShort( 0x0 ), /* Offset= 0 (36) */ 2373 /* 38 */ 0x8, /* FC_LONG */ 2374 0x5b, /* FC_END */ 2375 }; 2376 2377 memsrc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2378 FIELD_OFFSET(struct conf_complex, array[20])); 2379 memsrc->size = 20; 2380 2381 StubDesc = Object_StubDesc; 2382 StubDesc.pFormatTypes = fmtstr_complex_struct; 2383 2384 NdrClientInitializeNew( 2385 &RpcMessage, 2386 &StubMsg, 2387 &StubDesc, 2388 0); 2389 2390 StubMsg.BufferLength = 0; 2391 NdrComplexStructBufferSize( &StubMsg, 2392 (unsigned char *)memsrc, 2393 &fmtstr_complex_struct[30] ); 2394 ok(StubMsg.BufferLength >= 28, "length %d\n", StubMsg.BufferLength); 2395 2396 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ 2397 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 2398 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 2399 2400 ptr = NdrComplexStructMarshall( &StubMsg, (unsigned char *)memsrc, 2401 &fmtstr_complex_struct[30] ); 2402 ok(ptr == NULL, "ret %p\n", ptr); 2403 ok(*(unsigned int *)StubMsg.BufferStart == 20, "Conformance should have been 20 instead of %d\n", *(unsigned int *)StubMsg.BufferStart); 2404 ok(*(unsigned int *)(StubMsg.BufferStart + 4) == 20, "conf_complex.size should have been 20 instead of %d\n", *(unsigned int *)(StubMsg.BufferStart + 4)); 2405 for (i = 0; i < 20; i++) 2406 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)); 2407 2408 /* Server */ 2409 my_alloc_called = 0; 2410 StubMsg.IsClient = 0; 2411 mem = NULL; 2412 StubMsg.Buffer = StubMsg.BufferStart; 2413 ptr = NdrComplexStructUnmarshall( &StubMsg, (unsigned char **)&mem, &fmtstr_complex_struct[30], 0); 2414 ok(ptr == NULL, "ret %p\n", ptr); 2415 ok(mem->size == 20, "mem->size wasn't unmarshalled correctly (%d)\n", mem->size); 2416 ok(mem->array[0] == NULL, "mem->array[0] wasn't unmarshalled correctly (%p)\n", mem->array[0]); 2417 StubMsg.pfnFree(mem); 2418 2419 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); 2420 HeapFree(GetProcessHeap(), 0, memsrc); 2421 } 2422 2423 2424 static void test_conf_complex_array(void) 2425 { 2426 RPC_MESSAGE RpcMessage; 2427 MIDL_STUB_MESSAGE StubMsg; 2428 MIDL_STUB_DESC StubDesc; 2429 void *ptr; 2430 unsigned int i, j; 2431 struct conf_complex 2432 { 2433 unsigned int dim1, dim2; 2434 DWORD **array; 2435 }; 2436 struct conf_complex memsrc; 2437 struct conf_complex *mem; 2438 DWORD *buf, expected_length; 2439 2440 static const unsigned char fmtstr_complex_array[] = 2441 { 2442 2443 /* 0 */ 0x21, /* FC_BOGUS_ARRAY */ 2444 0x3, /* 3 */ 2445 /* 2 */ NdrFcShort( 0x0 ), /* 0 */ 2446 /* 4 */ 0x19, 0x0, /* Corr desc: field pointer, FC_ULONG */ 2447 /* 6 */ NdrFcShort( 0x4 ), /* 4 */ 2448 /* 8 */ NdrFcLong( 0xffffffff ), /* -1 */ 2449 /* 12 */ 0x8, /* FC_LONG */ 2450 0x5b, /* FC_END */ 2451 /* 14 */ 2452 0x21, /* FC_BOGUS_ARRAY */ 2453 0x3, /* 3 */ 2454 /* 16 */ NdrFcShort( 0x0 ), /* 0 */ 2455 /* 18 */ 0x19, /* Corr desc: field pointer, FC_ULONG */ 2456 0x0, /* */ 2457 /* 20 */ NdrFcShort( 0x0 ), /* 0 */ 2458 /* 22 */ NdrFcLong( 0xffffffff ), /* -1 */ 2459 /* 26 */ 0x12, 0x0, /* FC_UP */ 2460 /* 28 */ NdrFcShort( 0xffe4 ), /* Offset= -28 (0) */ 2461 /* 30 */ 0x5c, /* FC_PAD */ 2462 0x5b, /* FC_END */ 2463 2464 #ifdef _WIN64 2465 /* 32 */ 0x1a, /* FC_BOGUS_STRUCT */ 2466 0x3, /* 3 */ 2467 /* 34 */ NdrFcShort( 0x10 ), /* 16 */ 2468 /* 36 */ NdrFcShort( 0x0 ), /* 0 */ 2469 /* 38 */ NdrFcShort( 0x6 ), /* Offset= 6 (44) */ 2470 /* 40 */ 0x8, /* FC_LONG */ 2471 0x8, /* FC_LONG */ 2472 /* 42 */ 0x36, /* FC_POINTER */ 2473 0x5b, /* FC_END */ 2474 /* 44 */ 2475 0x12, 0x0, /* FC_UP */ 2476 /* 46 */ NdrFcShort( 0xffe0 ), /* Offset= -32 (14) */ 2477 #else 2478 /* 32 */ 2479 0x16, /* FC_PSTRUCT */ 2480 0x3, /* 3 */ 2481 /* 34 */ NdrFcShort( 0xc ), /* 12 */ 2482 /* 36 */ 0x4b, /* FC_PP */ 2483 0x5c, /* FC_PAD */ 2484 /* 38 */ 0x46, /* FC_NO_REPEAT */ 2485 0x5c, /* FC_PAD */ 2486 /* 40 */ NdrFcShort( 0x8 ), /* 8 */ 2487 /* 42 */ NdrFcShort( 0x8 ), /* 8 */ 2488 /* 44 */ 0x12, 0x0, /* FC_UP */ 2489 /* 46 */ NdrFcShort( 0xffe0 ), /* Offset= -32 (14) */ 2490 /* 48 */ 0x5b, /* FC_END */ 2491 0x8, /* FC_LONG */ 2492 /* 50 */ 0x8, /* FC_LONG */ 2493 0x8, /* FC_LONG */ 2494 /* 52 */ 0x5c, /* FC_PAD */ 2495 0x5b, /* FC_END */ 2496 #endif 2497 }; 2498 2499 memsrc.dim1 = 5; 2500 memsrc.dim2 = 3; 2501 2502 memsrc.array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, memsrc.dim1 * sizeof(DWORD*)); 2503 2504 for(i = 0; i < memsrc.dim1; i++) 2505 { 2506 memsrc.array[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, memsrc.dim2 * sizeof(DWORD)); 2507 for(j = 0; j < memsrc.dim2; j++) 2508 memsrc.array[i][j] = i * memsrc.dim2 + j; 2509 } 2510 2511 StubDesc = Object_StubDesc; 2512 StubDesc.pFormatTypes = fmtstr_complex_array; 2513 2514 NdrClientInitializeNew( 2515 &RpcMessage, 2516 &StubMsg, 2517 &StubDesc, 2518 0); 2519 2520 StubMsg.BufferLength = 0; 2521 2522 #ifdef _WIN64 2523 NdrComplexStructBufferSize( &StubMsg, 2524 (unsigned char *)&memsrc, 2525 &fmtstr_complex_array[32] ); 2526 #else 2527 NdrSimpleStructBufferSize( &StubMsg, 2528 (unsigned char *)&memsrc, 2529 &fmtstr_complex_array[32] ); 2530 #endif 2531 2532 expected_length = (4 + memsrc.dim1 * (2 + memsrc.dim2)) * 4; 2533 ok(StubMsg.BufferLength >= expected_length, "length %d\n", StubMsg.BufferLength); 2534 2535 /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ 2536 StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); 2537 StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; 2538 2539 #ifdef _WIN64 2540 ptr = NdrComplexStructMarshall( &StubMsg, (unsigned char *)&memsrc, 2541 &fmtstr_complex_array[32] ); 2542 #else 2543 ptr = NdrSimpleStructMarshall( &StubMsg, (unsigned char *)&memsrc, 2544 &fmtstr_complex_array[32] ); 2545 #endif 2546 2547 ok(ptr == NULL, "ret %p\n", ptr); 2548 ok((char*)StubMsg.Buffer == (char*)StubMsg.BufferStart + expected_length, "not at expected length\n"); 2549 2550 buf = (DWORD *)StubMsg.BufferStart; 2551 2552 ok(*buf == memsrc.dim1, "dim1 should have been %d instead of %08x\n", memsrc.dim1, *buf); 2553 buf++; 2554 ok(*buf == memsrc.dim2, "dim2 should have been %d instead of %08x\n", memsrc.dim2, *buf); 2555 buf++; 2556 ok(*buf != 0, "pointer id should be non-zero\n"); 2557 buf++; 2558 ok(*buf == memsrc.dim1, "Conformance should have been %d instead of %08x\n", memsrc.dim1, *buf); 2559 buf++; 2560 for(i = 0; i < memsrc.dim1; i++) 2561 { 2562 ok(*buf != 0, "pointer id[%d] should be non-zero\n", i); 2563 buf++; 2564 } 2565 for(i = 0; i < memsrc.dim1; i++) 2566 { 2567 ok(*buf == memsrc.dim2, "Conformance should have been %d instead of %08x\n", memsrc.dim2, *buf); 2568 buf++; 2569 for(j = 0; j < memsrc.dim2; j++) 2570 { 2571 ok(*buf == i * memsrc.dim2 + j, "got %08x\n", *buf); 2572 buf++; 2573 } 2574 } 2575 2576 ok((void*)buf == StubMsg.Buffer, "not at end of buffer\n"); 2577 2578 /* Server */ 2579 my_alloc_called = 0; 2580 StubMsg.IsClient = 0; 2581 mem = NULL; 2582 StubMsg.Buffer = StubMsg.BufferStart; 2583 #ifdef _WIN64 2584 ptr = NdrComplexStructUnmarshall( &StubMsg, (unsigned char **)&mem, &fmtstr_complex_array[32], 0); 2585 #else 2586 ptr = NdrSimpleStructUnmarshall( &StubMsg, (unsigned char **)&mem, &fmtstr_complex_array[32], 0); 2587 #endif 2588 ok(ptr == NULL, "ret %p\n", ptr); 2589 ok(mem->dim1 == memsrc.dim1, "mem->dim1 wasn't unmarshalled correctly (%d)\n", mem->dim1); 2590 ok(mem->dim2 == memsrc.dim2, "mem->dim2 wasn't unmarshalled correctly (%d)\n", mem->dim2); 2591 ok(mem->array[1][0] == memsrc.dim2, "mem->array[1][0] wasn't unmarshalled correctly (%d)\n", mem->array[1][0]); 2592 2593 StubMsg.Buffer = StubMsg.BufferStart; 2594 #ifdef _WIN64 2595 NdrComplexStructFree( &StubMsg, (unsigned char*)mem, &fmtstr_complex_array[32]); 2596 #else 2597 NdrSimpleStructFree( &StubMsg, (unsigned char*)mem, &fmtstr_complex_array[32]); 2598 #endif 2599 2600 HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); 2601 2602 for(i = 0; i < memsrc.dim1; i++) 2603 HeapFree(GetProcessHeap(), 0, memsrc.array[i]); 2604 HeapFree(GetProcessHeap(), 0, memsrc.array); 2605 } 2606 2607 static void test_ndr_buffer(void) 2608 { 2609 static unsigned char ncalrpc[] = "ncalrpc"; 2610 static unsigned char endpoint[] = "winetest:test_ndr_buffer"; 2611 RPC_MESSAGE RpcMessage; 2612 MIDL_STUB_MESSAGE StubMsg; 2613 MIDL_STUB_DESC StubDesc = Object_StubDesc; 2614 unsigned char *ret; 2615 unsigned char *binding; 2616 RPC_BINDING_HANDLE Handle; 2617 RPC_STATUS status; 2618 ULONG prev_buffer_length; 2619 BOOL old_buffer_valid_location; 2620 2621 StubDesc.RpcInterfaceInformation = (void *)&IFoo___RpcServerInterface; 2622 2623 status = RpcServerUseProtseqEpA(ncalrpc, 20, endpoint, NULL); 2624 ok(RPC_S_OK == status, "RpcServerUseProtseqEp failed with status %u\n", status); 2625 status = RpcServerRegisterIf(IFoo_v0_0_s_ifspec, NULL, NULL); 2626 ok(RPC_S_OK == status, "RpcServerRegisterIf failed with status %u\n", status); 2627 status = RpcServerListen(1, 20, TRUE); 2628 ok(RPC_S_OK == status, "RpcServerListen failed with status %u\n", status); 2629 if (status != RPC_S_OK) 2630 { 2631 /* Failed to create a server, running client tests is useless */ 2632 return; 2633 } 2634 2635 status = RpcStringBindingComposeA(NULL, ncalrpc, NULL, endpoint, NULL, &binding); 2636 ok(status == RPC_S_OK, "RpcStringBindingCompose failed (%u)\n", status); 2637 2638 status = RpcBindingFromStringBindingA(binding, &Handle); 2639 ok(status == RPC_S_OK, "RpcBindingFromStringBinding failed (%u)\n", status); 2640 RpcStringFreeA(&binding); 2641 2642 NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 5); 2643 2644 ret = NdrGetBuffer(&StubMsg, 10, Handle); 2645 ok(ret == StubMsg.Buffer, "NdrGetBuffer should have returned the same value as StubMsg.Buffer instead of %p\n", ret); 2646 ok(RpcMessage.Handle != NULL, "RpcMessage.Handle should not have been NULL\n"); 2647 ok(RpcMessage.Buffer != NULL, "RpcMessage.Buffer should not have been NULL\n"); 2648 ok(RpcMessage.BufferLength == 10 || 2649 broken(RpcMessage.BufferLength == 12), /* win2k */ 2650 "RpcMessage.BufferLength should have been 10 instead of %d\n", RpcMessage.BufferLength); 2651 ok(RpcMessage.RpcFlags == 0, "RpcMessage.RpcFlags should have been 0x0 instead of 0x%x\n", RpcMessage.RpcFlags); 2652 ok(StubMsg.Buffer != NULL, "Buffer should not have been NULL\n"); 2653 ok(!StubMsg.BufferStart, "BufferStart should have been NULL instead of %p\n", StubMsg.BufferStart); 2654 ok(!StubMsg.BufferEnd, "BufferEnd should have been NULL instead of %p\n", StubMsg.BufferEnd); 2655 todo_wine 2656 ok(StubMsg.BufferLength == 0, "BufferLength should have left as 0 instead of being set to %d\n", StubMsg.BufferLength); 2657 old_buffer_valid_location = !StubMsg.fBufferValid; 2658 if (old_buffer_valid_location) 2659 ok(broken(StubMsg.CorrDespIncrement == TRUE), "fBufferValid should have been TRUE instead of 0x%x\n", StubMsg.CorrDespIncrement); 2660 else 2661 ok(StubMsg.fBufferValid, "fBufferValid should have been non-zero instead of 0x%x\n", StubMsg.fBufferValid); 2662 2663 prev_buffer_length = RpcMessage.BufferLength; 2664 StubMsg.BufferLength = 1; 2665 NdrFreeBuffer(&StubMsg); 2666 ok(RpcMessage.Handle != NULL, "RpcMessage.Handle should not have been NULL\n"); 2667 ok(RpcMessage.Buffer != NULL, "RpcMessage.Buffer should not have been NULL\n"); 2668 ok(RpcMessage.BufferLength == prev_buffer_length, "RpcMessage.BufferLength should have been left as %d instead of %d\n", prev_buffer_length, RpcMessage.BufferLength); 2669 ok(StubMsg.Buffer != NULL, "Buffer should not have been NULL\n"); 2670 ok(StubMsg.BufferLength == 1, "BufferLength should have left as 1 instead of being set to %d\n", StubMsg.BufferLength); 2671 if (old_buffer_valid_location) 2672 ok(broken(StubMsg.CorrDespIncrement == FALSE), "fBufferValid should have been FALSE instead of 0x%x\n", StubMsg.CorrDespIncrement); 2673 else 2674 ok(!StubMsg.fBufferValid, "fBufferValid should have been FALSE instead of %d\n", StubMsg.fBufferValid); 2675 2676 /* attempt double-free */ 2677 NdrFreeBuffer(&StubMsg); 2678 2679 RpcBindingFree(&Handle); 2680 2681 status = RpcServerUnregisterIf(NULL, NULL, FALSE); 2682 ok(status == RPC_S_OK, "RpcServerUnregisterIf failed (%u)\n", status); 2683 } 2684 2685 static void test_NdrMapCommAndFaultStatus(void) 2686 { 2687 RPC_STATUS rpc_status; 2688 MIDL_STUB_MESSAGE StubMsg; 2689 RPC_MESSAGE RpcMessage; 2690 2691 NdrClientInitializeNew(&RpcMessage, &StubMsg, &Object_StubDesc, 5); 2692 2693 for (rpc_status = 0; rpc_status < 10000; rpc_status++) 2694 { 2695 RPC_STATUS status; 2696 ULONG comm_status = 0; 2697 ULONG fault_status = 0; 2698 ULONG expected_comm_status = 0; 2699 ULONG expected_fault_status = 0; 2700 status = NdrMapCommAndFaultStatus(&StubMsg, &comm_status, &fault_status, rpc_status); 2701 ok(status == RPC_S_OK, "NdrMapCommAndFaultStatus failed with error %d\n", status); 2702 switch (rpc_status) 2703 { 2704 case ERROR_INVALID_HANDLE: 2705 case RPC_S_INVALID_BINDING: 2706 case RPC_S_UNKNOWN_IF: 2707 case RPC_S_SERVER_UNAVAILABLE: 2708 case RPC_S_SERVER_TOO_BUSY: 2709 case RPC_S_CALL_FAILED_DNE: 2710 case RPC_S_PROTOCOL_ERROR: 2711 case RPC_S_UNSUPPORTED_TRANS_SYN: 2712 case RPC_S_UNSUPPORTED_TYPE: 2713 case RPC_S_PROCNUM_OUT_OF_RANGE: 2714 case EPT_S_NOT_REGISTERED: 2715 case RPC_S_COMM_FAILURE: 2716 expected_comm_status = rpc_status; 2717 break; 2718 default: 2719 expected_fault_status = rpc_status; 2720 } 2721 ok(comm_status == expected_comm_status, "NdrMapCommAndFaultStatus should have mapped %d to comm status %d instead of %d\n", 2722 rpc_status, expected_comm_status, comm_status); 2723 ok(fault_status == expected_fault_status, "NdrMapCommAndFaultStatus should have mapped %d to fault status %d instead of %d\n", 2724 rpc_status, expected_fault_status, fault_status); 2725 } 2726 } 2727 2728 static void test_NdrGetUserMarshalInfo(void) 2729 { 2730 RPC_STATUS status; 2731 MIDL_STUB_MESSAGE stubmsg; 2732 USER_MARSHAL_CB umcb; 2733 NDR_USER_MARSHAL_INFO umi; 2734 unsigned char buffer[16]; 2735 void *rpc_channel_buffer = (void *)(ULONG_PTR)0xcafebabe; 2736 RPC_MESSAGE rpc_msg; 2737 2738 /* unmarshall */ 2739 2740 memset(&rpc_msg, 0xcc, sizeof(rpc_msg)); 2741 rpc_msg.Buffer = buffer; 2742 rpc_msg.BufferLength = 16; 2743 2744 memset(&stubmsg, 0xcc, sizeof(stubmsg)); 2745 stubmsg.RpcMsg = &rpc_msg; 2746 stubmsg.dwDestContext = MSHCTX_INPROC; 2747 stubmsg.pvDestContext = NULL; 2748 stubmsg.Buffer = buffer + 15; 2749 stubmsg.BufferLength = 0; 2750 stubmsg.BufferEnd = NULL; 2751 stubmsg.pRpcChannelBuffer = rpc_channel_buffer; 2752 stubmsg.StubDesc = NULL; 2753 stubmsg.pfnAllocate = my_alloc; 2754 stubmsg.pfnFree = my_free; 2755 2756 memset(&umcb, 0xcc, sizeof(umcb)); 2757 umcb.Flags = MAKELONG(MSHCTX_INPROC, NDR_LOCAL_DATA_REPRESENTATION); 2758 umcb.pStubMsg = &stubmsg; 2759 umcb.Signature = USER_MARSHAL_CB_SIGNATURE; 2760 umcb.CBType = USER_MARSHAL_CB_UNMARSHALL; 2761 2762 memset(&umi, 0xaa, sizeof(umi)); 2763 2764 status = NdrGetUserMarshalInfo(&umcb.Flags, 1, &umi); 2765 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status); 2766 ok( umi.InformationLevel == 1, 2767 "umi.InformationLevel was %u instead of 1\n", 2768 umi.InformationLevel); 2769 ok( U1(umi).Level1.Buffer == buffer + 15, 2770 "umi.Level1.Buffer was %p instead of %p\n", 2771 U1(umi).Level1.Buffer, buffer); 2772 ok( U1(umi).Level1.BufferSize == 1, 2773 "umi.Level1.BufferSize was %u instead of 1\n", 2774 U1(umi).Level1.BufferSize); 2775 ok( U1(umi).Level1.pfnAllocate == my_alloc, 2776 "umi.Level1.pfnAllocate was %p instead of %p\n", 2777 U1(umi).Level1.pfnAllocate, my_alloc); 2778 ok( U1(umi).Level1.pfnFree == my_free, 2779 "umi.Level1.pfnFree was %p instead of %p\n", 2780 U1(umi).Level1.pfnFree, my_free); 2781 ok( U1(umi).Level1.pRpcChannelBuffer == rpc_channel_buffer, 2782 "umi.Level1.pRpcChannelBuffer was %p instead of %p\n", 2783 U1(umi).Level1.pRpcChannelBuffer, rpc_channel_buffer); 2784 2785 /* buffer size */ 2786 2787 rpc_msg.Buffer = buffer; 2788 rpc_msg.BufferLength = 16; 2789 2790 stubmsg.Buffer = buffer; 2791 stubmsg.BufferLength = 16; 2792 stubmsg.BufferEnd = NULL; 2793 2794 umcb.CBType = USER_MARSHAL_CB_BUFFER_SIZE; 2795 2796 memset(&umi, 0xaa, sizeof(umi)); 2797 2798 status = NdrGetUserMarshalInfo(&umcb.Flags, 1, &umi); 2799 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status); 2800 ok( umi.InformationLevel == 1, 2801 "umi.InformationLevel was %u instead of 1\n", 2802 umi.InformationLevel); 2803 ok( U1(umi).Level1.Buffer == NULL, 2804 "umi.Level1.Buffer was %p instead of NULL\n", 2805 U1(umi).Level1.Buffer); 2806 ok( U1(umi).Level1.BufferSize == 0, 2807 "umi.Level1.BufferSize was %u instead of 0\n", 2808 U1(umi).Level1.BufferSize); 2809 ok( U1(umi).Level1.pfnAllocate == my_alloc, 2810 "umi.Level1.pfnAllocate was %p instead of %p\n", 2811 U1(umi).Level1.pfnAllocate, my_alloc); 2812 ok( U1(umi).Level1.pfnFree == my_free, 2813 "umi.Level1.pfnFree was %p instead of %p\n", 2814 U1(umi).Level1.pfnFree, my_free); 2815 ok( U1(umi).Level1.pRpcChannelBuffer == rpc_channel_buffer, 2816 "umi.Level1.pRpcChannelBuffer was %p instead of %p\n", 2817 U1(umi).Level1.pRpcChannelBuffer, rpc_channel_buffer); 2818 2819 /* marshall */ 2820 2821 rpc_msg.Buffer = buffer; 2822 rpc_msg.BufferLength = 16; 2823 2824 stubmsg.Buffer = buffer + 15; 2825 stubmsg.BufferLength = 0; 2826 stubmsg.BufferEnd = NULL; 2827 2828 umcb.CBType = USER_MARSHAL_CB_MARSHALL; 2829 2830 memset(&umi, 0xaa, sizeof(umi)); 2831 2832 status = NdrGetUserMarshalInfo(&umcb.Flags, 1, &umi); 2833 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status); 2834 ok( umi.InformationLevel == 1, 2835 "umi.InformationLevel was %u instead of 1\n", 2836 umi.InformationLevel); 2837 ok( U1(umi).Level1.Buffer == buffer + 15, 2838 "umi.Level1.Buffer was %p instead of %p\n", 2839 U1(umi).Level1.Buffer, buffer); 2840 ok( U1(umi).Level1.BufferSize == 1, 2841 "umi.Level1.BufferSize was %u instead of 1\n", 2842 U1(umi).Level1.BufferSize); 2843 ok( U1(umi).Level1.pfnAllocate == my_alloc, 2844 "umi.Level1.pfnAllocate was %p instead of %p\n", 2845 U1(umi).Level1.pfnAllocate, my_alloc); 2846 ok( U1(umi).Level1.pfnFree == my_free, 2847 "umi.Level1.pfnFree was %p instead of %p\n", 2848 U1(umi).Level1.pfnFree, my_free); 2849 ok( U1(umi).Level1.pRpcChannelBuffer == rpc_channel_buffer, 2850 "umi.Level1.pRpcChannelBuffer was %p instead of %p\n", 2851 U1(umi).Level1.pRpcChannelBuffer, rpc_channel_buffer); 2852 2853 /* free */ 2854 2855 rpc_msg.Buffer = buffer; 2856 rpc_msg.BufferLength = 16; 2857 2858 stubmsg.Buffer = buffer; 2859 stubmsg.BufferLength = 16; 2860 stubmsg.BufferEnd = NULL; 2861 2862 umcb.CBType = USER_MARSHAL_CB_FREE; 2863 2864 memset(&umi, 0xaa, sizeof(umi)); 2865 2866 status = NdrGetUserMarshalInfo(&umcb.Flags, 1, &umi); 2867 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status); 2868 ok( umi.InformationLevel == 1, 2869 "umi.InformationLevel was %u instead of 1\n", 2870 umi.InformationLevel); 2871 ok( U1(umi).Level1.Buffer == NULL, 2872 "umi.Level1.Buffer was %p instead of NULL\n", 2873 U1(umi).Level1.Buffer); 2874 ok( U1(umi).Level1.BufferSize == 0, 2875 "umi.Level1.BufferSize was %u instead of 0\n", 2876 U1(umi).Level1.BufferSize); 2877 ok( U1(umi).Level1.pfnAllocate == my_alloc, 2878 "umi.Level1.pfnAllocate was %p instead of %p\n", 2879 U1(umi).Level1.pfnAllocate, my_alloc); 2880 ok( U1(umi).Level1.pfnFree == my_free, 2881 "umi.Level1.pfnFree was %p instead of %p\n", 2882 U1(umi).Level1.pfnFree, my_free); 2883 ok( U1(umi).Level1.pRpcChannelBuffer == rpc_channel_buffer, 2884 "umi.Level1.pRpcChannelBuffer was %p instead of %p\n", 2885 U1(umi).Level1.pRpcChannelBuffer, rpc_channel_buffer); 2886 2887 /* boundary test */ 2888 2889 rpc_msg.Buffer = buffer; 2890 rpc_msg.BufferLength = 15; 2891 2892 stubmsg.Buffer = buffer + 15; 2893 stubmsg.BufferLength = 0; 2894 stubmsg.BufferEnd = NULL; 2895 2896 umcb.CBType = USER_MARSHAL_CB_MARSHALL; 2897 2898 status = NdrGetUserMarshalInfo(&umcb.Flags, 1, &umi); 2899 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status); 2900 ok( U1(umi).Level1.BufferSize == 0, 2901 "umi.Level1.BufferSize was %u instead of 0\n", 2902 U1(umi).Level1.BufferSize); 2903 2904 /* error conditions */ 2905 2906 rpc_msg.BufferLength = 14; 2907 status = NdrGetUserMarshalInfo(&umcb.Flags, 1, &umi); 2908 ok(status == ERROR_INVALID_USER_BUFFER, 2909 "NdrGetUserMarshalInfo should have failed with ERROR_INVALID_USER_BUFFER instead of %d\n", status); 2910 2911 rpc_msg.BufferLength = 15; 2912 status = NdrGetUserMarshalInfo(&umcb.Flags, 9999, &umi); 2913 ok(status == RPC_S_INVALID_ARG, 2914 "NdrGetUserMarshalInfo should have failed with RPC_S_INVALID_ARG instead of %d\n", status); 2915 2916 umcb.CBType = 9999; 2917 status = NdrGetUserMarshalInfo(&umcb.Flags, 1, &umi); 2918 ok(status == RPC_S_OK, "NdrGetUserMarshalInfo failed with error %d\n", status); 2919 2920 umcb.CBType = USER_MARSHAL_CB_MARSHALL; 2921 umcb.Signature = 0; 2922 status = NdrGetUserMarshalInfo(&umcb.Flags, 1, &umi); 2923 ok(status == RPC_S_INVALID_ARG, 2924 "NdrGetUserMarshalInfo should have failed with RPC_S_INVALID_ARG instead of %d\n", status); 2925 } 2926 2927 static void test_MesEncodeFixedBufferHandleCreate(void) 2928 { 2929 ULONG encoded_size; 2930 RPC_STATUS status; 2931 handle_t handle; 2932 char *buffer; 2933 2934 status = MesEncodeFixedBufferHandleCreate(NULL, 0, NULL, NULL); 2935 ok(status == RPC_S_INVALID_ARG, "got %d\n", status); 2936 2937 status = MesEncodeFixedBufferHandleCreate(NULL, 0, NULL, &handle); 2938 ok(status == RPC_S_INVALID_ARG, "got %d\n", status); 2939 2940 status = MesEncodeFixedBufferHandleCreate((char*)0xdeadbeef, 0, NULL, &handle); 2941 ok(status == RPC_X_INVALID_BUFFER, "got %d\n", status); 2942 2943 buffer = (void*)((0xdeadbeef + 7) & ~7); 2944 status = MesEncodeFixedBufferHandleCreate(buffer, 0, NULL, &handle); 2945 ok(status == RPC_S_INVALID_ARG, "got %d\n", status); 2946 2947 status = MesEncodeFixedBufferHandleCreate(buffer, 0, &encoded_size, &handle); 2948 todo_wine 2949 ok(status == RPC_S_INVALID_ARG, "got %d\n", status); 2950 if (status == RPC_S_OK) { 2951 MesHandleFree(handle); 2952 } 2953 status = MesEncodeFixedBufferHandleCreate(buffer, 32, NULL, &handle); 2954 ok(status == RPC_S_INVALID_ARG, "got %d\n", status); 2955 2956 status = MesEncodeFixedBufferHandleCreate(buffer, 32, &encoded_size, &handle); 2957 ok(status == RPC_S_OK, "got %d\n", status); 2958 2959 status = MesBufferHandleReset(NULL, MES_DYNAMIC_BUFFER_HANDLE, MES_ENCODE, 2960 &buffer, 32, &encoded_size); 2961 ok(status == RPC_S_INVALID_ARG, "got %d\n", status); 2962 2963 /* convert to dynamic buffer handle */ 2964 status = MesBufferHandleReset(handle, MES_DYNAMIC_BUFFER_HANDLE, MES_ENCODE, 2965 &buffer, 32, &encoded_size); 2966 ok(status == RPC_S_OK, "got %d\n", status); 2967 2968 status = MesBufferHandleReset(handle, MES_DYNAMIC_BUFFER_HANDLE, MES_ENCODE, 2969 NULL, 32, &encoded_size); 2970 ok(status == RPC_S_INVALID_ARG, "got %d\n", status); 2971 2972 status = MesBufferHandleReset(handle, MES_DYNAMIC_BUFFER_HANDLE, MES_ENCODE, 2973 &buffer, 32, NULL); 2974 ok(status == RPC_S_INVALID_ARG, "got %d\n", status); 2975 2976 /* invalid handle type */ 2977 status = MesBufferHandleReset(handle, MES_DYNAMIC_BUFFER_HANDLE+1, MES_ENCODE, 2978 &buffer, 32, &encoded_size); 2979 ok(status == RPC_S_INVALID_ARG, "got %d\n", status); 2980 2981 status = MesHandleFree(handle); 2982 ok(status == RPC_S_OK, "got %d\n", status); 2983 } 2984 2985 static void test_NdrCorrelationInitialize(void) 2986 { 2987 MIDL_STUB_MESSAGE stub_msg; 2988 BYTE buf[256]; 2989 2990 memset( &stub_msg, 0, sizeof(stub_msg) ); 2991 memset( buf, 0, sizeof(buf) ); 2992 2993 NdrCorrelationInitialize( &stub_msg, buf, sizeof(buf), 0 ); 2994 ok( stub_msg.CorrDespIncrement == 2 || 2995 broken(stub_msg.CorrDespIncrement == 0), /* <= Win 2003 */ 2996 "got %d\n", stub_msg.CorrDespIncrement ); 2997 2998 memset( &stub_msg, 0, sizeof(stub_msg) ); 2999 memset( buf, 0, sizeof(buf) ); 3000 3001 stub_msg.CorrDespIncrement = 1; 3002 NdrCorrelationInitialize( &stub_msg, buf, sizeof(buf), 0 ); 3003 ok( stub_msg.CorrDespIncrement == 1, "got %d\n", stub_msg.CorrDespIncrement ); 3004 } 3005 3006 START_TEST( ndr_marshall ) 3007 { 3008 determine_pointer_marshalling_style(); 3009 3010 test_ndr_simple_type(); 3011 test_simple_types(); 3012 test_nontrivial_pointer_types(); 3013 test_simple_struct(); 3014 test_struct_align(); 3015 test_iface_ptr(); 3016 test_fullpointer_xlat(); 3017 test_client_init(); 3018 test_server_init(); 3019 test_ndr_allocate(); 3020 test_conformant_array(); 3021 test_conformant_string(); 3022 test_nonconformant_string(); 3023 test_conf_complex_struct(); 3024 test_conf_complex_array(); 3025 test_ndr_buffer(); 3026 test_NdrMapCommAndFaultStatus(); 3027 test_NdrGetUserMarshalInfo(); 3028 test_MesEncodeFixedBufferHandleCreate(); 3029 test_NdrCorrelationInitialize(); 3030 } 3031