1 /*
2  * User Marshaling Tests
3  *
4  * Copyright 2004-2006 Robert Shearman for CodeWeavers
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 COBJMACROS
22 #define CONST_VTABLE
23 #include <stdarg.h>
24 
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
28 #include "objidl.h"
29 
30 #include "wine/test.h"
31 
32 ULONG __RPC_USER HMETAFILE_UserSize(ULONG *, ULONG, HMETAFILE *);
33 unsigned char * __RPC_USER HMETAFILE_UserMarshal(ULONG *, unsigned char *, HMETAFILE *);
34 unsigned char * __RPC_USER HMETAFILE_UserUnmarshal(ULONG *, unsigned char *, HMETAFILE *);
35 void __RPC_USER HMETAFILE_UserFree(ULONG *, HMETAFILE *);
36 
37 ULONG __RPC_USER HENHMETAFILE_UserSize(ULONG *, ULONG, HENHMETAFILE *);
38 unsigned char * __RPC_USER HENHMETAFILE_UserMarshal  (ULONG *, unsigned char *, HENHMETAFILE *);
39 unsigned char * __RPC_USER HENHMETAFILE_UserUnmarshal(ULONG *, unsigned char *, HENHMETAFILE *);
40 void  __RPC_USER HENHMETAFILE_UserFree(ULONG *, HENHMETAFILE *);
41 
42 ULONG __RPC_USER HMETAFILEPICT_UserSize(ULONG *, ULONG, HMETAFILEPICT *);
43 unsigned char * __RPC_USER HMETAFILEPICT_UserMarshal  (ULONG *, unsigned char *, HMETAFILEPICT *);
44 unsigned char * __RPC_USER HMETAFILEPICT_UserUnmarshal(ULONG *, unsigned char *, HMETAFILEPICT *);
45 void __RPC_USER HMETAFILEPICT_UserFree(ULONG *, HMETAFILEPICT *);
46 
47 ULONG __RPC_USER HBRUSH_UserSize(ULONG *, ULONG, HBRUSH *);
48 unsigned char * __RPC_USER HBRUSH_UserMarshal(ULONG *, unsigned char *, HBRUSH *);
49 unsigned char * __RPC_USER HBRUSH_UserUnmarshal(ULONG *, unsigned char *, HBRUSH *);
50 void __RPC_USER HBRUSH_UserFree(ULONG *, HBRUSH *);
51 
52 static BOOL g_expect_user_alloc;
53 static void * WINAPI user_allocate(SIZE_T size)
54 {
55     ok(g_expect_user_alloc, "unexpected user_allocate call\n");
56     return CoTaskMemAlloc(size);
57 }
58 
59 static BOOL g_expect_user_free;
60 static void WINAPI user_free(void *p)
61 {
62     ok(g_expect_user_free, "unexpected user_free call\n");
63     CoTaskMemFree(p);
64 }
65 
66 static void init_user_marshal_cb(USER_MARSHAL_CB *umcb,
67                                  PMIDL_STUB_MESSAGE stub_msg,
68                                  PRPC_MESSAGE rpc_msg, unsigned char *buffer,
69                                  unsigned int size, MSHCTX context)
70 {
71     memset(rpc_msg, 0, sizeof(*rpc_msg));
72     rpc_msg->Buffer = buffer;
73     rpc_msg->BufferLength = size;
74 
75     memset(stub_msg, 0, sizeof(*stub_msg));
76     stub_msg->RpcMsg = rpc_msg;
77     stub_msg->Buffer = buffer;
78     stub_msg->pfnAllocate = user_allocate;
79     stub_msg->pfnFree = user_free;
80 
81     memset(umcb, 0, sizeof(*umcb));
82     umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION);
83     umcb->pStubMsg = stub_msg;
84     umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
85     umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE;
86 }
87 
88 #define RELEASEMARSHALDATA WM_USER
89 
90 struct host_object_data
91 {
92     IStream *stream;
93     IID iid;
94     IUnknown *object;
95     MSHLFLAGS marshal_flags;
96     HANDLE marshal_event;
97     IMessageFilter *filter;
98 };
99 
100 static DWORD CALLBACK host_object_proc(LPVOID p)
101 {
102     struct host_object_data *data = p;
103     HRESULT hr;
104     MSG msg;
105 
106     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
107 
108     if (data->filter)
109     {
110         IMessageFilter * prev_filter = NULL;
111         hr = CoRegisterMessageFilter(data->filter, &prev_filter);
112         if (prev_filter) IMessageFilter_Release(prev_filter);
113         ok(hr == S_OK, "got %08x\n", hr);
114     }
115 
116     hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
117     ok(hr == S_OK, "got %08x\n", hr);
118 
119     /* force the message queue to be created before signaling parent thread */
120     PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
121 
122     SetEvent(data->marshal_event);
123 
124     while (GetMessageA(&msg, NULL, 0, 0))
125     {
126         if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
127         {
128             CoReleaseMarshalData(data->stream);
129             SetEvent((HANDLE)msg.lParam);
130         }
131         else
132             DispatchMessageA(&msg);
133     }
134 
135     HeapFree(GetProcessHeap(), 0, data);
136 
137     CoUninitialize();
138 
139     return hr;
140 }
141 
142 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
143 {
144     DWORD tid = 0;
145     HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
146     struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
147 
148     data->stream = stream;
149     data->iid = *riid;
150     data->object = object;
151     data->marshal_flags = marshal_flags;
152     data->marshal_event = marshal_event;
153     data->filter = filter;
154 
155     *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
156 
157     /* wait for marshaling to complete before returning */
158     ok( !WaitForSingleObject(marshal_event, 10000), "wait timed out\n" );
159     CloseHandle(marshal_event);
160 
161     return tid;
162 }
163 
164 static void end_host_object(DWORD tid, HANDLE thread)
165 {
166     BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
167     ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
168     /* be careful of races - don't return until hosting thread has terminated */
169     ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
170     CloseHandle(thread);
171 }
172 
173 static const char cf_marshaled[] =
174 {
175     0x9, 0x0, 0x0, 0x0,
176     0x0, 0x0, 0x0, 0x0,
177     0x9, 0x0, 0x0, 0x0,
178     'M', 0x0, 'y', 0x0,
179     'F', 0x0, 'o', 0x0,
180     'r', 0x0, 'm', 0x0,
181     'a', 0x0, 't', 0x0,
182     0x0, 0x0
183 };
184 
185 static void test_marshal_CLIPFORMAT(void)
186 {
187     USER_MARSHAL_CB umcb;
188     MIDL_STUB_MESSAGE stub_msg;
189     RPC_MESSAGE rpc_msg;
190     unsigned char *buffer, *buffer_end;
191     ULONG i, size;
192     CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
193     CLIPFORMAT cf2;
194 
195     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
196     size = CLIPFORMAT_UserSize(&umcb.Flags, 1, &cf);
197     ok(size == 12 + sizeof(cf_marshaled) ||
198        broken(size == 16 + sizeof(cf_marshaled)),  /* win64 adds 4 extra (unused) bytes */
199               "CLIPFORMAT: Wrong size %d\n", size);
200 
201     buffer = HeapAlloc(GetProcessHeap(), 0, size);
202     memset( buffer, 0xcc, size );
203     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
204     buffer_end = CLIPFORMAT_UserMarshal(&umcb.Flags, buffer + 1, &cf);
205     ok(buffer_end == buffer + 12 + sizeof(cf_marshaled), "got %p buffer %p\n", buffer_end, buffer);
206     ok(*(LONG *)(buffer + 4) == WDT_REMOTE_CALL, "CLIPFORMAT: Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(LONG *)(buffer + 0));
207     ok(*(DWORD *)(buffer + 8) == cf, "CLIPFORMAT: Marshaled value should be 0x%04x instead of 0x%04x\n", cf, *(DWORD *)(buffer + 4));
208     ok(!memcmp(buffer + 12, cf_marshaled, min( sizeof(cf_marshaled), size-12 )), "Marshaled data differs\n");
209     if (size > sizeof(cf_marshaled) + 12)  /* make sure the extra bytes are not used */
210         for (i = sizeof(cf_marshaled) + 12; i < size; i++)
211             ok( buffer[i] == 0xcc, "buffer offset %u has been set to %x\n", i, buffer[i] );
212 
213     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
214     buffer_end = CLIPFORMAT_UserUnmarshal(&umcb.Flags, buffer + 1, &cf2);
215     ok(buffer_end == buffer + 12 + sizeof(cf_marshaled), "got %p buffer %p\n", buffer_end, buffer);
216     ok(cf == cf2, "CLIPFORMAT: Didn't unmarshal properly\n");
217     HeapFree(GetProcessHeap(), 0, buffer);
218 
219     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
220     CLIPFORMAT_UserFree(&umcb.Flags, &cf2);
221 }
222 
223 static void test_marshal_HWND(void)
224 {
225     USER_MARSHAL_CB umcb;
226     MIDL_STUB_MESSAGE stub_msg;
227     RPC_MESSAGE rpc_msg;
228     unsigned char *buffer, *buffer_end;
229     ULONG size;
230     HWND hwnd = GetDesktopWindow();
231     HWND hwnd2;
232     wireHWND wirehwnd;
233 
234     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
235     size = HWND_UserSize(&umcb.Flags, 1, &hwnd);
236     ok(size == 4 + sizeof(*wirehwnd), "Wrong size %d\n", size);
237 
238     buffer = HeapAlloc(GetProcessHeap(), 0, size);
239     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
240     buffer_end = HWND_UserMarshal(&umcb.Flags, buffer + 1, &hwnd);
241     ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
242     wirehwnd = (wireHWND)(buffer + 4);
243     ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehwnd->fContext);
244     ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %x\n", hwnd, wirehwnd->u.hRemote);
245 
246     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
247     buffer_end = HWND_UserUnmarshal(&umcb.Flags, buffer + 1, &hwnd2);
248     ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
249     ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
250     HeapFree(GetProcessHeap(), 0, buffer);
251 
252     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
253     HWND_UserFree(&umcb.Flags, &hwnd2);
254 }
255 
256 static void test_marshal_HGLOBAL(void)
257 {
258     USER_MARSHAL_CB umcb;
259     MIDL_STUB_MESSAGE stub_msg;
260     RPC_MESSAGE rpc_msg;
261     unsigned char *buffer;
262     ULONG size, block_size;
263     HGLOBAL hglobal;
264     HGLOBAL hglobal2;
265     unsigned char *wirehglobal;
266     int i;
267 
268     hglobal = NULL;
269     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
270     size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal);
271     /* native is poorly programmed and allocates 4/8 bytes more than it needs to
272      * here - Wine doesn't have to emulate that */
273     ok((size == 8) || broken(size == 12) || broken(size == 16), "Size should be 8, instead of %d\n", size);
274     buffer = HeapAlloc(GetProcessHeap(), 0, size);
275     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
276     HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal);
277     wirehglobal = buffer;
278     ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
279     wirehglobal += sizeof(ULONG);
280     ok(*(ULONG *)wirehglobal == 0, "buffer+4 should be HGLOBAL\n");
281     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
282     hglobal2 = NULL;
283     HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2);
284     ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
285     HeapFree(GetProcessHeap(), 0, buffer);
286     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
287     HGLOBAL_UserFree(&umcb.Flags, &hglobal2);
288 
289 
290     for(block_size = 0; block_size <= 17; block_size++)
291     {
292         ULONG actual_size, expected_size;
293 
294         hglobal = GlobalAlloc(0, block_size);
295         buffer = GlobalLock(hglobal);
296         for (i = 0; i < block_size; i++)
297             buffer[i] = i;
298         GlobalUnlock(hglobal);
299         actual_size = GlobalSize(hglobal);
300         expected_size = actual_size + 5 * sizeof(DWORD);
301         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
302         size = HGLOBAL_UserSize(&umcb.Flags, 0, &hglobal);
303         /* native is poorly programmed and allocates 4/8 bytes more than it needs to
304          * here - Wine doesn't have to emulate that */
305         ok(size == expected_size ||
306            broken(size == expected_size + 4) ||
307            broken(size == expected_size + 8),
308            "%d: got size %d\n", block_size, size);
309         buffer = HeapAlloc(GetProcessHeap(), 0, size);
310         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
311         HGLOBAL_UserMarshal(&umcb.Flags, buffer, &hglobal);
312         wirehglobal = buffer;
313         ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
314         wirehglobal += sizeof(ULONG);
315         ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0x4 should be HGLOBAL\n");
316         wirehglobal += sizeof(ULONG);
317         ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x8 %08x\n", block_size, *(ULONG *)wirehglobal);
318         wirehglobal += sizeof(ULONG);
319         ok(*(ULONG *)wirehglobal == (ULONG)(ULONG_PTR)hglobal, "buffer+0xc should be HGLOBAL\n");
320         wirehglobal += sizeof(ULONG);
321         ok(*(ULONG *)wirehglobal == actual_size, "%d: buffer+0x10 %08x\n", block_size, *(ULONG *)wirehglobal);
322         wirehglobal += sizeof(ULONG);
323         for (i = 0; i < block_size; i++)
324             ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
325 
326         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
327         hglobal2 = NULL;
328         HGLOBAL_UserUnmarshal(&umcb.Flags, buffer, &hglobal2);
329         ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
330         HeapFree(GetProcessHeap(), 0, buffer);
331         init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
332         HGLOBAL_UserFree(&umcb.Flags, &hglobal2);
333         GlobalFree(hglobal);
334     }
335 }
336 
337 static HENHMETAFILE create_emf(void)
338 {
339     const RECT rect = {0, 0, 100, 100};
340     HDC hdc = CreateEnhMetaFileA(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
341     ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
342     return CloseEnhMetaFile(hdc);
343 }
344 
345 static void test_marshal_HENHMETAFILE(void)
346 {
347     USER_MARSHAL_CB umcb;
348     MIDL_STUB_MESSAGE stub_msg;
349     RPC_MESSAGE rpc_msg;
350     unsigned char *buffer, *buffer_end;
351     ULONG size;
352     HENHMETAFILE hemf;
353     HENHMETAFILE hemf2 = NULL;
354     unsigned char *wirehemf;
355 
356     hemf = create_emf();
357 
358     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
359     size = HENHMETAFILE_UserSize(&umcb.Flags, 1, &hemf);
360     ok(size > 24, "size should be at least 24 bytes, not %d\n", size);
361     buffer = HeapAlloc(GetProcessHeap(), 0, size);
362     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
363     buffer_end = HENHMETAFILE_UserMarshal(&umcb.Flags, buffer + 1, &hemf);
364     ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
365     wirehemf = buffer + 4;
366     ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
367     wirehemf += sizeof(DWORD);
368     ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
369     wirehemf += sizeof(DWORD);
370     ok(*(DWORD *)wirehemf == (size - 0x14), "wirestgm + 0x8 should be size - 0x14 instead of 0x%08x\n", *(DWORD *)wirehemf);
371     wirehemf += sizeof(DWORD);
372     ok(*(DWORD *)wirehemf == (size - 0x14), "wirestgm + 0xc should be size - 0x14 instead of 0x%08x\n", *(DWORD *)wirehemf);
373     wirehemf += sizeof(DWORD);
374     ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD *)wirehemf);
375     /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
376      * at this point */
377 
378     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
379     buffer_end = HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer + 1, &hemf2);
380     ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
381     ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
382     HeapFree(GetProcessHeap(), 0, buffer);
383     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
384     HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
385     DeleteEnhMetaFile(hemf);
386 
387     /* test NULL emf */
388     hemf = NULL;
389 
390     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
391     size = HENHMETAFILE_UserSize(&umcb.Flags, 1, &hemf);
392     ok(size == 12, "size should be 12 bytes, not %d\n", size);
393     buffer = HeapAlloc(GetProcessHeap(), 0, size);
394     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
395     buffer_end = HENHMETAFILE_UserMarshal(&umcb.Flags, buffer + 1, &hemf);
396     ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
397     wirehemf = buffer + 4;
398     ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
399     wirehemf += sizeof(DWORD);
400     ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
401 
402     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
403     buffer_end = HENHMETAFILE_UserUnmarshal(&umcb.Flags, buffer + 1, &hemf2);
404     ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
405     ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
406     HeapFree(GetProcessHeap(), 0, buffer);
407     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
408     HENHMETAFILE_UserFree(&umcb.Flags, &hemf2);
409 }
410 
411 static HMETAFILE create_mf(void)
412 {
413     RECT rect = {0, 0, 100, 100};
414     HDC hdc = CreateMetaFileA(NULL);
415     ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
416     return CloseMetaFile(hdc);
417 }
418 
419 static void test_marshal_HMETAFILE(void)
420 {
421     USER_MARSHAL_CB umcb;
422     MIDL_STUB_MESSAGE stub_msg;
423     RPC_MESSAGE rpc_msg;
424     unsigned char *buffer;
425     ULONG size;
426     HMETAFILE hmf;
427     HMETAFILE hmf2 = NULL;
428     unsigned char *wirehmf;
429 
430     hmf = create_mf();
431 
432     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
433     size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
434     ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
435     buffer = HeapAlloc(GetProcessHeap(), 0, size);
436     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
437     HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
438     wirehmf = buffer;
439     ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
440     wirehmf += sizeof(DWORD);
441     ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
442     wirehmf += sizeof(DWORD);
443     ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
444     wirehmf += sizeof(DWORD);
445     ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
446     wirehmf += sizeof(DWORD);
447     ok(*(WORD *)wirehmf == 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmf);
448     wirehmf += sizeof(DWORD);
449     /* ... rest of data not tested - refer to tests for GetMetaFileBits
450      * at this point */
451 
452     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
453     HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
454     ok(hmf2 != NULL, "HMETAFILE didn't unmarshal\n");
455     HeapFree(GetProcessHeap(), 0, buffer);
456     HMETAFILE_UserFree(&umcb.Flags, &hmf2);
457     DeleteMetaFile(hmf);
458 
459     /* test NULL emf */
460     hmf = NULL;
461 
462     size = HMETAFILE_UserSize(&umcb.Flags, 0, &hmf);
463     ok(size == 8, "size should be 8 bytes, not %d\n", size);
464     buffer = HeapAlloc(GetProcessHeap(), 0, size);
465     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
466     HMETAFILE_UserMarshal(&umcb.Flags, buffer, &hmf);
467     wirehmf = buffer;
468     ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
469     wirehmf += sizeof(DWORD);
470     ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
471     wirehmf += sizeof(DWORD);
472 
473     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
474     HMETAFILE_UserUnmarshal(&umcb.Flags, buffer, &hmf2);
475     ok(hmf2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
476     HeapFree(GetProcessHeap(), 0, buffer);
477     HMETAFILE_UserFree(&umcb.Flags, &hmf2);
478 }
479 
480 #define USER_MARSHAL_PTR_PREFIX \
481   ( (DWORD)'U'         | ( (DWORD)'s' << 8 ) | \
482   ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
483 
484 static void test_marshal_HMETAFILEPICT(void)
485 {
486     USER_MARSHAL_CB umcb;
487     MIDL_STUB_MESSAGE stub_msg;
488     RPC_MESSAGE rpc_msg;
489     unsigned char *buffer, *buffer_end;
490     ULONG size;
491     HMETAFILEPICT hmfp;
492     HMETAFILEPICT hmfp2 = NULL;
493     METAFILEPICT *pmfp;
494     unsigned char *wirehmfp;
495 
496     hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(*pmfp));
497     pmfp = GlobalLock(hmfp);
498     pmfp->mm = MM_ISOTROPIC;
499     pmfp->xExt = 1;
500     pmfp->yExt = 2;
501     pmfp->hMF = create_mf();
502     GlobalUnlock(hmfp);
503 
504     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
505     size = HMETAFILEPICT_UserSize(&umcb.Flags, 1, &hmfp);
506     ok(size > 24, "size should be at least 24 bytes, not %d\n", size);
507     buffer = HeapAlloc(GetProcessHeap(), 0, size);
508     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
509     buffer_end = HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer + 1, &hmfp);
510     wirehmfp = buffer + 4;
511     ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
512     wirehmfp += sizeof(DWORD);
513     ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
514     wirehmfp += sizeof(DWORD);
515     ok(*(DWORD *)wirehmfp == MM_ISOTROPIC, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD *)wirehmfp);
516     wirehmfp += sizeof(DWORD);
517     ok(*(DWORD *)wirehmfp == 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
518     wirehmfp += sizeof(DWORD);
519     ok(*(DWORD *)wirehmfp == 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD *)wirehmfp);
520     wirehmfp += sizeof(DWORD);
521     ok(*(DWORD *)wirehmfp == USER_MARSHAL_PTR_PREFIX, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD *)wirehmfp);
522     wirehmfp += sizeof(DWORD);
523     ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
524     wirehmfp += sizeof(DWORD);
525     pmfp = GlobalLock(hmfp);
526     ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)pmfp->hMF, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD *)wirehmfp);
527     GlobalUnlock(hmfp);
528     wirehmfp += sizeof(DWORD);
529     /* Note use (buffer_end - buffer) instead of size here, because size is an
530      * overestimate with native */
531     ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x2c), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
532     wirehmfp += sizeof(DWORD);
533     ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x2c), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
534     wirehmfp += sizeof(DWORD);
535     ok(*(WORD *)wirehmfp == 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
536     /* ... rest of data not tested - refer to tests for GetMetaFileBits
537      * at this point */
538 
539     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
540     HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer + 1, &hmfp2);
541     ok(hmfp2 != NULL, "HMETAFILEPICT didn't unmarshal\n");
542     HeapFree(GetProcessHeap(), 0, buffer);
543     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
544     HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2);
545     pmfp = GlobalLock(hmfp);
546     DeleteMetaFile(pmfp->hMF);
547     GlobalUnlock(hmfp);
548     GlobalFree(hmfp);
549 
550     /* test NULL emf */
551     hmfp = NULL;
552 
553     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
554     size = HMETAFILEPICT_UserSize(&umcb.Flags, 1, &hmfp);
555     ok(size == 12, "size should be 12 bytes, not %d\n", size);
556     buffer = HeapAlloc(GetProcessHeap(), 0, size);
557     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
558     buffer_end = HMETAFILEPICT_UserMarshal(&umcb.Flags, buffer + 1, &hmfp);
559     ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
560     wirehmfp = buffer + 4;
561     ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
562     wirehmfp += sizeof(DWORD);
563     ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
564     wirehmfp += sizeof(DWORD);
565 
566     hmfp2 = NULL;
567     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
568     buffer_end = HMETAFILEPICT_UserUnmarshal(&umcb.Flags, buffer + 1, &hmfp2);
569     ok(buffer_end == buffer + size, "got %p buffer %p\n", buffer_end, buffer);
570     ok(hmfp2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
571     HeapFree(GetProcessHeap(), 0, buffer);
572     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
573     HMETAFILEPICT_UserFree(&umcb.Flags, &hmfp2);
574 }
575 
576 typedef struct
577 {
578     IUnknown IUnknown_iface;
579     LONG refs;
580 } TestUnknown;
581 
582 static inline TestUnknown *impl_from_IUnknown(IUnknown *iface)
583 {
584     return CONTAINING_RECORD(iface, TestUnknown, IUnknown_iface);
585 }
586 
587 static HRESULT WINAPI Test_IUnknown_QueryInterface(
588                                                    LPUNKNOWN iface,
589                                                    REFIID riid,
590                                                    LPVOID *ppvObj)
591 {
592     if (ppvObj == NULL) return E_POINTER;
593 
594     if (IsEqualGUID(riid, &IID_IUnknown))
595     {
596         *ppvObj = iface;
597         IUnknown_AddRef(iface);
598         return S_OK;
599     }
600 
601     *ppvObj = NULL;
602     return E_NOINTERFACE;
603 }
604 
605 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
606 {
607     TestUnknown *This = impl_from_IUnknown(iface);
608     return InterlockedIncrement(&This->refs);
609 }
610 
611 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
612 {
613     TestUnknown *This = impl_from_IUnknown(iface);
614     return InterlockedDecrement(&This->refs);
615 }
616 
617 static const IUnknownVtbl TestUnknown_Vtbl =
618 {
619     Test_IUnknown_QueryInterface,
620     Test_IUnknown_AddRef,
621     Test_IUnknown_Release,
622 };
623 
624 struct test_stream
625 {
626     IStream IStream_iface;
627     LONG refs;
628 };
629 
630 static inline struct test_stream *impl_from_IStream(IStream *iface)
631 {
632     return CONTAINING_RECORD(iface, struct test_stream, IStream_iface);
633 }
634 
635 static HRESULT WINAPI Test_IStream_QueryInterface(IStream *iface,
636                                                   REFIID riid, LPVOID *ppvObj)
637 {
638     if (ppvObj == NULL) return E_POINTER;
639 
640     if (IsEqualIID(riid, &IID_IUnknown) ||
641         IsEqualIID(riid, &IID_IStream))
642     {
643         *ppvObj = iface;
644         IStream_AddRef(iface);
645         return S_OK;
646     }
647 
648     *ppvObj = NULL;
649     return E_NOINTERFACE;
650 }
651 
652 static ULONG WINAPI Test_IStream_AddRef(IStream *iface)
653 {
654     struct test_stream *This = impl_from_IStream(iface);
655     return InterlockedIncrement(&This->refs);
656 }
657 
658 static ULONG WINAPI Test_IStream_Release(IStream *iface)
659 {
660     struct test_stream *This = impl_from_IStream(iface);
661     return InterlockedDecrement(&This->refs);
662 }
663 
664 static const IStreamVtbl TestStream_Vtbl =
665 {
666     Test_IStream_QueryInterface,
667     Test_IStream_AddRef,
668     Test_IStream_Release
669     /* the rest can be NULLs */
670 };
671 
672 static TestUnknown Test_Unknown = { {&TestUnknown_Vtbl}, 1 };
673 static TestUnknown Test_Unknown2 = { {&TestUnknown_Vtbl}, 1 };
674 static struct test_stream Test_Stream = { {&TestStream_Vtbl}, 1 };
675 static struct test_stream Test_Stream2 = { {&TestStream_Vtbl}, 1 };
676 
677 ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *, ULONG, ULONG, IUnknown *, REFIID);
678 unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG *, ULONG, unsigned char *, IUnknown *, REFIID);
679 unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG *, unsigned char *, IUnknown **, REFIID);
680 
681 static void marshal_WdtpInterfacePointer(DWORD umcb_ctx, DWORD ctx, BOOL client, BOOL in, BOOL out)
682 {
683     USER_MARSHAL_CB umcb;
684     MIDL_STUB_MESSAGE stub_msg;
685     RPC_MESSAGE rpc_msg;
686     unsigned char *buffer, *buffer_end;
687     ULONG size;
688     IUnknown *unk;
689     IUnknown *unk2;
690     unsigned char *wireip;
691     HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 0);
692     IStream *stm;
693     void *marshal_data;
694     LARGE_INTEGER zero;
695     ULARGE_INTEGER pos;
696     DWORD marshal_size;
697 
698     /* shows that the WdtpInterfacePointer functions don't marshal anything for
699      * NULL pointers, so code using these functions must handle that case
700      * itself */
701 
702     unk = NULL;
703     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, umcb_ctx);
704     size = WdtpInterfacePointer_UserSize(&umcb.Flags, ctx, 0, unk, &IID_IUnknown);
705     ok(size == 0, "size should be 0 bytes, not %d\n", size);
706     buffer = HeapAlloc(GetProcessHeap(), 0, size);
707     buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown);
708     ok(buffer_end == buffer, "buffer_end %p buffer %p\n", buffer_end, buffer);
709     HeapFree(GetProcessHeap(), 0, buffer);
710 
711     /* Now for a non-NULL pointer. The marshalled data are two size DWORDS and then
712        the result of CoMarshalInterface called with the LOWORD of the ctx */
713 
714     unk = &Test_Unknown.IUnknown_iface;
715     Test_Unknown.refs = 1;
716 
717     CreateStreamOnHGlobal(h, TRUE, &stm);
718     CoMarshalInterface(stm, &IID_IUnknown, unk, LOWORD(ctx), NULL, MSHLFLAGS_NORMAL);
719     zero.QuadPart = 0;
720     IStream_Seek(stm, zero, STREAM_SEEK_CUR, &pos);
721     marshal_size = pos.u.LowPart;
722     marshal_data = GlobalLock(h);
723 todo_wine
724     ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs);
725 
726     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, umcb_ctx);
727     size = WdtpInterfacePointer_UserSize(&umcb.Flags, ctx, 0, unk, &IID_IUnknown);
728     ok(size >= marshal_size + 2 * sizeof(DWORD), "marshal size %x got %x\n", marshal_size, size);
729     buffer = HeapAlloc(GetProcessHeap(), 0, size);
730     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx);
731     buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, ctx, buffer, unk, &IID_IUnknown);
732 todo_wine
733     ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs);
734     wireip = buffer;
735 
736     ok(buffer_end == buffer + marshal_size + 2 * sizeof(DWORD), "buffer_end %p buffer %p\n", buffer_end, buffer);
737 
738     ok(*(DWORD *)wireip == marshal_size, "wireip + 0x0 should be %x instead of %x\n", marshal_size, *(DWORD *)wireip);
739     wireip += sizeof(DWORD);
740     ok(*(DWORD *)wireip == marshal_size, "wireip + 0x4 should be %x instead of %x\n", marshal_size, *(DWORD *)wireip);
741     wireip += sizeof(DWORD);
742 
743     ok(!memcmp(marshal_data, wireip, marshal_size), "buffer mismatch\n");
744     GlobalUnlock(h);
745     zero.QuadPart = 0;
746     IStream_Seek(stm, zero, STREAM_SEEK_SET, NULL);
747     CoReleaseMarshalData(stm);
748     IStream_Release(stm);
749 
750     Test_Unknown2.refs = 1;
751     unk2 = &Test_Unknown2.IUnknown_iface;
752     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, umcb_ctx);
753     umcb.pStubMsg->IsClient = client;
754     umcb.pStubMsg->fIsIn = in;
755     umcb.pStubMsg->fIsOut = out;
756 
757     WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2, &IID_IUnknown);
758     ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n");
759     ok(Test_Unknown.refs == 2, "got %d\n", Test_Unknown.refs);
760     ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs);
761     HeapFree(GetProcessHeap(), 0, buffer);
762     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
763     IUnknown_Release(unk2);
764 }
765 
766 static void test_marshal_WdtpInterfacePointer(void)
767 {
768     /*
769      * There are two places where we can pass the marshalling ctx: as
770      * part of the umcb and as a separate flag.  The loword of that
771      * separate flag field is what matters.
772      */
773 
774     /* All three are marshalled as inproc */
775     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_INPROC, 0,0,0);
776     marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_INPROC,0,0,0);
777     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_INPROC, 0xffff),0,0,0);
778 
779     /* All three are marshalled as remote */
780     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,0);
781     marshal_WdtpInterfacePointer(MSHCTX_DIFFERENTMACHINE, MSHCTX_DIFFERENTMACHINE,0,0,0);
782     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MAKELONG(MSHCTX_DIFFERENTMACHINE, 0xffff),0,0,0);
783 
784     /* Test different combinations of client, in and out */
785     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,0,1);
786     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,0);
787     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,0,1,1);
788     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,0);
789     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,0,1);
790     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,0);
791     marshal_WdtpInterfacePointer(MSHCTX_INPROC, MSHCTX_DIFFERENTMACHINE,1,1,1);
792 }
793 
794 static void marshal_STGMEDIUM(BOOL client, BOOL in, BOOL out)
795 {
796     USER_MARSHAL_CB umcb;
797     MIDL_STUB_MESSAGE stub_msg;
798     RPC_MESSAGE rpc_msg;
799     unsigned char *buffer, *buffer_end, *expect_buffer, *expect_buffer_end;
800     ULONG size, expect_size;
801     STGMEDIUM med, med2;
802     IUnknown *unk = &Test_Unknown.IUnknown_iface;
803     IStream *stm = &Test_Stream.IStream_iface;
804 
805     /* TYMED_NULL with pUnkForRelease */
806 
807     Test_Unknown.refs = 1;
808 
809     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
810     expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 2 * sizeof(DWORD), unk, &IID_IUnknown);
811     expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size);
812     *(DWORD*)expect_buffer = TYMED_NULL;
813     *((DWORD*)expect_buffer + 1) = 0xdeadbeef;
814     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
815     expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer + 2 * sizeof(DWORD), unk, &IID_IUnknown);
816 
817     med.tymed = TYMED_NULL;
818     U(med).pstg = NULL;
819     med.pUnkForRelease = unk;
820 
821     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
822     size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
823     ok(size == expect_size, "size %d should be %d bytes\n", size, expect_size);
824 
825     buffer = HeapAlloc(GetProcessHeap(), 0, size);
826     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
827     buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
828     ok(buffer_end - buffer == expect_buffer_end - expect_buffer, "buffer size mismatch\n");
829     ok(*(DWORD*)buffer == TYMED_NULL, "got %08x\n", *(DWORD*)buffer);
830     ok(*((DWORD*)buffer+1) != 0, "got %08x\n", *((DWORD*)buffer+1));
831     ok(!memcmp(buffer+8, expect_buffer + 8, expect_buffer_end - expect_buffer - 8), "buffer mismatch\n");
832 
833     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
834     umcb.pStubMsg->IsClient = client;
835     umcb.pStubMsg->fIsIn = in;
836     umcb.pStubMsg->fIsOut = out;
837 
838     Test_Unknown2.refs = 1;
839     med2.tymed = TYMED_NULL;
840     U(med2).pstm = NULL;
841     med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
842 
843     STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
844 
845     ok(med2.tymed == TYMED_NULL, "got tymed %x\n", med2.tymed);
846     ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
847     ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs);
848 
849     HeapFree(GetProcessHeap(), 0, buffer);
850     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
851     STGMEDIUM_UserFree(&umcb.Flags, &med2);
852 
853     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
854     med2.tymed = TYMED_NULL;
855     U(med2).pstm = NULL;
856     med2.pUnkForRelease = NULL;
857     STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2);
858     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
859     STGMEDIUM_UserFree(&umcb.Flags, &med2);
860 
861     ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs);
862 
863     HeapFree(GetProcessHeap(), 0, expect_buffer);
864 
865     /* TYMED_ISTREAM with pUnkForRelease */
866 
867     Test_Unknown.refs = 1;
868     Test_Stream.refs = 1;
869 
870     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
871     expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 3 * sizeof(DWORD), (IUnknown*)stm, &IID_IStream);
872     expect_size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, expect_size, unk, &IID_IUnknown);
873 
874     expect_buffer = HeapAlloc(GetProcessHeap(), 0, expect_size);
875     /* There may be a hole between the two interfaces so init the buffer to something */
876     memset(expect_buffer, 0xcc, expect_size);
877     *(DWORD*)expect_buffer = TYMED_ISTREAM;
878     *((DWORD*)expect_buffer + 1) = 0xdeadbeef;
879     *((DWORD*)expect_buffer + 2) = 0xcafe;
880     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
881     expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer + 3 * sizeof(DWORD), (IUnknown*)stm, &IID_IStream);
882     expect_buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, expect_buffer_end, unk, &IID_IUnknown);
883 
884     med.tymed = TYMED_ISTREAM;
885     U(med).pstm = stm;
886     med.pUnkForRelease = unk;
887 
888     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
889     size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
890     ok(size == expect_size, "size %d should be %d bytes\n", size, expect_size);
891 
892     buffer = HeapAlloc(GetProcessHeap(), 0, size);
893     memset(buffer, 0xcc, size);
894     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
895     buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
896     ok(buffer_end - buffer == expect_buffer_end - expect_buffer, "buffer size mismatch\n");
897     ok(*(DWORD*)buffer == TYMED_ISTREAM, "got %08x\n", *(DWORD*)buffer);
898     ok(*((DWORD*)buffer+1) != 0, "got %08x\n", *((DWORD*)buffer+1));
899     ok(*((DWORD*)buffer+2) != 0, "got %08x\n", *((DWORD*)buffer+2));
900     ok(!memcmp(buffer + 12, expect_buffer + 12, (buffer_end - buffer) - 12), "buffer mismatch\n");
901 
902     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
903     umcb.pStubMsg->IsClient = client;
904     umcb.pStubMsg->fIsIn = in;
905     umcb.pStubMsg->fIsOut = out;
906 
907     Test_Stream2.refs = 1;
908     Test_Unknown2.refs = 1;
909     med2.tymed = TYMED_ISTREAM;
910     U(med2).pstm = &Test_Stream2.IStream_iface;
911     med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
912 
913     STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
914 
915     ok(med2.tymed == TYMED_ISTREAM, "got tymed %x\n", med2.tymed);
916     ok(U(med2).pstm != NULL, "Incorrectly unmarshalled\n");
917     ok(med2.pUnkForRelease != NULL, "Incorrectly unmarshalled\n");
918     ok(Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs);
919     ok(Test_Unknown2.refs == 0, "got %d\n", Test_Unknown2.refs);
920 
921     HeapFree(GetProcessHeap(), 0, buffer);
922     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
923     STGMEDIUM_UserFree(&umcb.Flags, &med2);
924 
925     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, expect_buffer, expect_size, MSHCTX_DIFFERENTMACHINE);
926     med2.tymed = TYMED_NULL;
927     U(med2).pstm = NULL;
928     med2.pUnkForRelease = NULL;
929     STGMEDIUM_UserUnmarshal(&umcb.Flags, expect_buffer, &med2);
930     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
931     STGMEDIUM_UserFree(&umcb.Flags, &med2);
932 
933     ok(Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs);
934     ok(Test_Stream.refs == 1, "got %d\n", Test_Stream.refs);
935 
936     HeapFree(GetProcessHeap(), 0, expect_buffer);
937 
938     /* TYMED_ISTREAM = NULL with pUnkForRelease = NULL */
939 
940     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
941     expect_size = 3 * sizeof(DWORD);
942 
943     med.tymed = TYMED_ISTREAM;
944     U(med).pstm = NULL;
945     med.pUnkForRelease = NULL;
946 
947     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
948     size = STGMEDIUM_UserSize(&umcb.Flags, 0, &med);
949     ok(size == expect_size, "size %d should be %d bytes\n", size, expect_size);
950 
951     buffer = HeapAlloc(GetProcessHeap(), 0, size);
952     memset(buffer, 0xcc, size);
953     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
954     buffer_end = STGMEDIUM_UserMarshal(&umcb.Flags, buffer, &med);
955     ok(buffer_end - buffer == expect_size, "buffer size mismatch\n");
956     ok(*(DWORD*)buffer == TYMED_ISTREAM, "got %08x\n", *(DWORD*)buffer);
957     ok(*((DWORD*)buffer+1) == 0, "got %08x\n", *((DWORD*)buffer+1));
958     ok(*((DWORD*)buffer+2) == 0, "got %08x\n", *((DWORD*)buffer+2));
959 
960     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
961     umcb.pStubMsg->IsClient = client;
962     umcb.pStubMsg->fIsIn = in;
963     umcb.pStubMsg->fIsOut = out;
964 
965     Test_Stream2.refs = 1;
966     Test_Unknown2.refs = 1;
967     med2.tymed = TYMED_ISTREAM;
968     U(med2).pstm = &Test_Stream2.IStream_iface;
969     med2.pUnkForRelease = &Test_Unknown2.IUnknown_iface;
970 
971     STGMEDIUM_UserUnmarshal(&umcb.Flags, buffer, &med2);
972 
973     ok(med2.tymed == TYMED_ISTREAM, "got tymed %x\n", med2.tymed);
974     ok(U(med2).pstm == NULL, "Incorrectly unmarshalled\n");
975     ok(med2.pUnkForRelease == &Test_Unknown2.IUnknown_iface, "Incorrectly unmarshalled\n");
976     ok(Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs);
977     ok(Test_Unknown2.refs == 1, "got %d\n", Test_Unknown2.refs);
978 
979     HeapFree(GetProcessHeap(), 0, buffer);
980     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
981     STGMEDIUM_UserFree(&umcb.Flags, &med2);
982 }
983 
984 static void test_marshal_STGMEDIUM(void)
985 {
986     marshal_STGMEDIUM(0, 0, 0);
987     marshal_STGMEDIUM(0, 0, 1);
988     marshal_STGMEDIUM(0, 1, 0);
989     marshal_STGMEDIUM(0, 1, 1);
990     /* For Windows versions post 2003, client side, non-[in,out] STGMEDIUMs get zero-initialised.
991        However since inline stubs don't set fIsIn or fIsOut this behaviour would break
992        ref counting in GetDataHere_Proxy for example, as we'd end up not releasing the original
993        interface.  For simplicity we don't test or implement this. */
994     marshal_STGMEDIUM(1, 1, 1);
995 }
996 
997 static void test_marshal_SNB(void)
998 {
999     static const WCHAR str1W[] = {'s','t','r','i','n','g','1',0};
1000     static const WCHAR str2W[] = {'s','t','r','2',0};
1001     unsigned char *buffer, *src, *mbuf;
1002     MIDL_STUB_MESSAGE stub_msg;
1003     WCHAR **ptrW, *dataW;
1004     USER_MARSHAL_CB umcb;
1005     RPC_MESSAGE rpc_msg;
1006     RemSNB *wiresnb;
1007     SNB snb, snb2;
1008     ULONG size;
1009 
1010     /* 4 bytes alignment */
1011     snb = NULL;
1012     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1013     size = SNB_UserSize(&umcb.Flags, 3, &snb);
1014     ok(size == 16, "Size should be 16, instead of %d\n", size);
1015 
1016     /* NULL block */
1017     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1018     size = SNB_UserSize(&umcb.Flags, 0, &snb);
1019     ok(size == 12, "Size should be 12, instead of %d\n", size);
1020 
1021     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1022     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1023     mbuf = SNB_UserMarshal(&umcb.Flags, buffer, &snb);
1024     ok(mbuf == buffer + size, "got %p, %p\n", mbuf, buffer + size);
1025 
1026     wiresnb = (RemSNB*)buffer;
1027     ok(wiresnb->ulCntStr == 0, "got %u\n", wiresnb->ulCntStr);
1028     ok(wiresnb->ulCntChar == 0, "got %u\n", wiresnb->ulCntChar);
1029     ok(*(ULONG*)wiresnb->rgString == 0, "got %u\n", *(ULONG*)wiresnb->rgString);
1030 
1031     snb2 = NULL;
1032     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1033     SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2);
1034     ok(snb2 == NULL, "got %p\n", snb2);
1035 
1036     HeapFree(GetProcessHeap(), 0, buffer);
1037     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1038     SNB_UserFree(&umcb.Flags, &snb2);
1039 
1040     /* block with actual data */
1041 
1042     /* allocate source block, n+1 pointers first, then data */
1043     src = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR*)*3 + sizeof(str1W) + sizeof(str2W));
1044     ptrW = (WCHAR**)src;
1045     dataW = *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*));
1046     ptrW++;
1047     *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*) + sizeof(str1W));
1048     ptrW++;
1049     *ptrW = NULL;
1050     lstrcpyW(dataW, str1W);
1051     dataW += lstrlenW(str1W) + 1;
1052     lstrcpyW(dataW, str2W);
1053 
1054     snb = (SNB)src;
1055     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1056     size = SNB_UserSize(&umcb.Flags, 0, &snb);
1057     ok(size == 38, "Size should be 38, instead of %d\n", size);
1058 
1059     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1060     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1061     SNB_UserMarshal(&umcb.Flags, buffer, &snb);
1062 
1063     wiresnb = (RemSNB*)buffer;
1064     ok(wiresnb->ulCntStr == 13, "got %u\n", wiresnb->ulCntStr);
1065     ok(wiresnb->ulCntChar == 2, "got %u\n", wiresnb->ulCntChar);
1066     /* payload length is stored one more time, as ULONG */
1067     ok(*(ULONG*)wiresnb->rgString == wiresnb->ulCntStr, "got %u\n", *(ULONG*)wiresnb->rgString);
1068     dataW = &wiresnb->rgString[2];
1069     ok(!lstrcmpW(dataW, str1W), "marshalled string 0: %s\n", wine_dbgstr_w(dataW));
1070     dataW += ARRAY_SIZE(str1W);
1071     ok(!lstrcmpW(dataW, str2W), "marshalled string 1: %s\n", wine_dbgstr_w(dataW));
1072 
1073     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1074 
1075     g_expect_user_alloc = TRUE;
1076     snb2 = NULL;
1077     SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2);
1078     g_expect_user_alloc = FALSE;
1079 
1080     ptrW = snb2;
1081     ok(!lstrcmpW(*ptrW, str1W), "unmarshalled string 0: %s\n", wine_dbgstr_w(*ptrW));
1082     ptrW++;
1083     ok(!lstrcmpW(*ptrW, str2W), "unmarshalled string 1: %s\n", wine_dbgstr_w(*ptrW));
1084     ptrW++;
1085     ok(*ptrW == NULL, "expected terminating NULL ptr, got %p, start %p\n", *ptrW, snb2);
1086 
1087     HeapFree(GetProcessHeap(), 0, buffer);
1088     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1089 
1090     g_expect_user_free = TRUE;
1091     SNB_UserFree(&umcb.Flags, &snb2);
1092     g_expect_user_free = FALSE;
1093 
1094     HeapFree(GetProcessHeap(), 0, src);
1095 }
1096 
1097 static void test_marshal_HDC(void)
1098 {
1099     MIDL_STUB_MESSAGE stub_msg;
1100     HDC hdc = GetDC(0), hdc2;
1101     USER_MARSHAL_CB umcb;
1102     RPC_MESSAGE rpc_msg;
1103     unsigned char *buffer, *buffer_end;
1104     wireHDC wirehdc;
1105     ULONG size;
1106 
1107     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1108     size = HDC_UserSize(&umcb.Flags, 1, &hdc);
1109     ok(size == 4 + sizeof(*wirehdc), "Wrong size %d\n", size);
1110 
1111     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1112     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1113     buffer_end = HDC_UserMarshal(&umcb.Flags, buffer + 1, &hdc);
1114     ok(buffer_end == buffer + 4 + sizeof(*wirehdc), "got %p buffer %p\n", buffer_end, buffer);
1115     wirehdc = (wireHDC)(buffer + 4);
1116     ok(wirehdc->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehdc->fContext);
1117     ok(wirehdc->u.hInproc == (LONG_PTR)hdc, "Marshaled value should be %p instead of %x\n", hdc, wirehdc->u.hRemote);
1118 
1119     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1120     buffer_end = HDC_UserUnmarshal(&umcb.Flags, buffer + 1, &hdc2);
1121     ok(buffer_end == buffer + 4 + sizeof(*wirehdc), "got %p buffer %p\n", buffer_end, buffer);
1122     ok(hdc == hdc2, "Didn't unmarshal properly\n");
1123     HeapFree(GetProcessHeap(), 0, buffer);
1124 
1125     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1126     HDC_UserFree(&umcb.Flags, &hdc2);
1127     ReleaseDC(0, hdc);
1128 }
1129 
1130 static void test_marshal_HICON(void)
1131 {
1132     static const BYTE bmp_bits[1024];
1133     MIDL_STUB_MESSAGE stub_msg;
1134     HICON hIcon, hIcon2;
1135     USER_MARSHAL_CB umcb;
1136     RPC_MESSAGE rpc_msg;
1137     unsigned char *buffer, *buffer_end;
1138     wireHICON wirehicon;
1139     ULONG size;
1140 
1141     hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits);
1142     ok(hIcon != 0, "CreateIcon failed\n");
1143 
1144     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1145     size = HICON_UserSize(&umcb.Flags, 1, &hIcon);
1146     ok(size == 4 + sizeof(*wirehicon), "Wrong size %d\n", size);
1147 
1148     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1149     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1150     buffer_end = HICON_UserMarshal(&umcb.Flags, buffer + 1, &hIcon);
1151     ok(buffer_end == buffer + 4 + sizeof(*wirehicon), "got %p buffer %p\n", buffer_end, buffer);
1152     wirehicon = (wireHICON)(buffer + 4);
1153     ok(wirehicon->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehicon->fContext);
1154     ok(wirehicon->u.hInproc == (LONG_PTR)hIcon, "Marshaled value should be %p instead of %x\n", hIcon, wirehicon->u.hRemote);
1155 
1156     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1157     buffer_end = HICON_UserUnmarshal(&umcb.Flags, buffer + 1, &hIcon2);
1158     ok(buffer_end == buffer + 4 + sizeof(*wirehicon), "got %p buffer %p\n", buffer_end, buffer);
1159     ok(hIcon == hIcon2, "Didn't unmarshal properly\n");
1160     HeapFree(GetProcessHeap(), 0, buffer);
1161 
1162     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1163     HICON_UserFree(&umcb.Flags, &hIcon2);
1164     DestroyIcon(hIcon);
1165 }
1166 
1167 static void test_marshal_HBRUSH(void)
1168 {
1169     MIDL_STUB_MESSAGE stub_msg;
1170     HBRUSH hBrush, hBrush2;
1171     USER_MARSHAL_CB umcb;
1172     RPC_MESSAGE rpc_msg;
1173     unsigned char *buffer, *buffer_end;
1174     LOGBRUSH logbrush;
1175     wireHBRUSH wirehbrush;
1176     ULONG size;
1177 
1178     logbrush.lbStyle = BS_SOLID;
1179     logbrush.lbColor = RGB(0, 0, 0);
1180     logbrush.lbHatch = 0;
1181 
1182     hBrush = CreateBrushIndirect(&logbrush);
1183     ok(hBrush != 0, "CreateBrushIndirect failed\n");
1184 
1185     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1186     size = HBRUSH_UserSize(&umcb.Flags, 1, &hBrush);
1187     ok(size == 4 + sizeof(*wirehbrush), "Wrong size %d\n", size);
1188 
1189     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1190     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1191     buffer_end = HBRUSH_UserMarshal(&umcb.Flags, buffer + 1, &hBrush);
1192     ok(buffer_end == buffer + 4 + sizeof(*wirehbrush), "got %p buffer %p\n", buffer_end, buffer);
1193     wirehbrush = (wireHBRUSH)(buffer + 4);
1194     ok(wirehbrush->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", wirehbrush->fContext);
1195     ok(wirehbrush->u.hInproc == (LONG_PTR)hBrush, "Marshaled value should be %p instead of %x\n", hBrush, wirehbrush->u.hRemote);
1196 
1197     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1198     buffer_end = HBRUSH_UserUnmarshal(&umcb.Flags, buffer + 1, &hBrush2);
1199     ok(buffer_end == buffer + 4 + sizeof(*wirehbrush), "got %p buffer %p\n", buffer_end, buffer);
1200     ok(hBrush == hBrush2, "Didn't unmarshal properly\n");
1201     HeapFree(GetProcessHeap(), 0, buffer);
1202 
1203     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1204     HBRUSH_UserFree(&umcb.Flags, &hBrush2);
1205     DeleteObject(hBrush);
1206 }
1207 
1208 static void test_marshal_HBITMAP(void)
1209 {
1210     static const ULONG header_size = FIELD_OFFSET(userBITMAP, cbSize);
1211     static BYTE bmp_bits[1024];
1212     MIDL_STUB_MESSAGE stub_msg;
1213     HBITMAP hBitmap, hBitmap2;
1214     USER_MARSHAL_CB umcb;
1215     RPC_MESSAGE rpc_msg;
1216     unsigned char *buffer, *buffer_end;
1217     unsigned char bitmap[1024];
1218     ULONG size, bitmap_size;
1219 
1220     hBitmap = CreateBitmap(16, 16, 1, 1, bmp_bits);
1221     ok(hBitmap != 0, "CreateBitmap failed\n");
1222     size = GetObjectA(hBitmap, sizeof(bitmap), bitmap);
1223     ok(size != 0, "GetObject failed\n");
1224     bitmap_size = GetBitmapBits(hBitmap, 0, NULL);
1225     ok(bitmap_size != 0, "GetBitmapBits failed\n");
1226 
1227     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
1228     size = HBITMAP_UserSize(&umcb.Flags, 1, &hBitmap);
1229     ok(size == 0xc, "Wrong size %d\n", size);
1230     buffer = HeapAlloc(GetProcessHeap(), 0, size + 4);
1231     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC);
1232     buffer_end = HBITMAP_UserMarshal(&umcb.Flags, buffer + 1, &hBitmap);
1233     ok(buffer_end == buffer + 0xc, "HBITMAP_UserMarshal() returned wrong size %d\n", (LONG)(buffer_end - buffer));
1234     ok(*(ULONG *)(buffer + 0x4) == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08x\n", *(ULONG *)(buffer + 0x4));
1235     ok(*(ULONG *)(buffer + 0x8) == (ULONG)(ULONG_PTR)hBitmap, "wirestgm + 0x4 should be bitmap handle instead of 0x%08x\n", *(ULONG *)(buffer + 0x8));
1236 
1237     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC);
1238     HBITMAP_UserUnmarshal(&umcb.Flags, buffer + 1, &hBitmap2);
1239     ok(hBitmap2 != NULL, "Didn't unmarshal properly\n");
1240     HeapFree(GetProcessHeap(), 0, buffer);
1241 
1242     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
1243     HBITMAP_UserFree(&umcb.Flags, &hBitmap2);
1244 
1245     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1246     size = HBITMAP_UserSize(&umcb.Flags, 1, &hBitmap);
1247     ok(size == 0x10 + header_size + bitmap_size ||
1248        broken(size == 0x14 + header_size + bitmap_size), /* Windows adds 4 extra (unused) bytes */
1249        "Wrong size %d\n", size);
1250 
1251     buffer = HeapAlloc(GetProcessHeap(), 0, size + 4);
1252     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1253     buffer_end = HBITMAP_UserMarshal(&umcb.Flags, buffer + 1, &hBitmap);
1254     ok(buffer_end == buffer + 0x10 + header_size + bitmap_size, "HBITMAP_UserMarshal() returned wrong size %d\n", (LONG)(buffer_end - buffer));
1255     ok(*(ULONG *)(buffer + 0x4) == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)buffer);
1256     ok(*(ULONG *)(buffer + 0x8) == (ULONG)(ULONG_PTR)hBitmap, "wirestgm + 0x4 should be bitmap handle instead of 0x%08x\n", *(ULONG *)(buffer + 0x4));
1257     ok(*(ULONG *)(buffer + 0xc) == (ULONG)(ULONG_PTR)bitmap_size, "wirestgm + 0x8 should be bitmap size instead of 0x%08x\n", *(ULONG *)(buffer + 0x4));
1258     ok(!memcmp(buffer + 0x10, bitmap, header_size), "buffer mismatch\n");
1259     ok(!memcmp(buffer + 0x10 + header_size, bmp_bits, bitmap_size), "buffer mismatch\n");
1260 
1261     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
1262     HBITMAP_UserUnmarshal(&umcb.Flags, buffer + 1, &hBitmap2);
1263     ok(hBitmap2 != NULL, "Didn't unmarshal properly\n");
1264     HeapFree(GetProcessHeap(), 0, buffer);
1265 
1266     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
1267     HBITMAP_UserFree(&umcb.Flags, &hBitmap2);
1268     DeleteObject(hBitmap);
1269 }
1270 
1271 struct obj
1272 {
1273     IDataObject IDataObject_iface;
1274 };
1275 
1276 static HRESULT WINAPI obj_QueryInterface(IDataObject *iface, REFIID iid, void **obj)
1277 {
1278     *obj = NULL;
1279 
1280     if (IsEqualGUID(iid, &IID_IUnknown) ||
1281         IsEqualGUID(iid, &IID_IDataObject))
1282         *obj = iface;
1283 
1284     if (*obj)
1285     {
1286         IDataObject_AddRef(iface);
1287         return S_OK;
1288     }
1289 
1290     return E_NOINTERFACE;
1291 }
1292 
1293 static ULONG WINAPI obj_AddRef(IDataObject *iface)
1294 {
1295     return 2;
1296 }
1297 
1298 static ULONG WINAPI obj_Release(IDataObject *iface)
1299 {
1300     return 1;
1301 }
1302 
1303 static HRESULT WINAPI obj_DO_GetDataHere(IDataObject *iface, FORMATETC *fmt,
1304                                          STGMEDIUM *med)
1305 {
1306     ok( med->pUnkForRelease == NULL, "got %p\n", med->pUnkForRelease );
1307 
1308     if (fmt->cfFormat == 2)
1309     {
1310         IStream_Release(U(med)->pstm);
1311         U(med)->pstm = &Test_Stream2.IStream_iface;
1312     }
1313 
1314     return S_OK;
1315 }
1316 
1317 static const IDataObjectVtbl obj_data_object_vtbl =
1318 {
1319     obj_QueryInterface,
1320     obj_AddRef,
1321     obj_Release,
1322     NULL, /* GetData */
1323     obj_DO_GetDataHere,
1324     NULL, /* QueryGetData */
1325     NULL, /* GetCanonicalFormatEtc */
1326     NULL, /* SetData */
1327     NULL, /* EnumFormatEtc */
1328     NULL, /* DAdvise */
1329     NULL, /* DUnadvise */
1330     NULL  /* EnumDAdvise */
1331 };
1332 
1333 static struct obj obj =
1334 {
1335     {&obj_data_object_vtbl}
1336 };
1337 
1338 static void test_GetDataHere_Proxy(void)
1339 {
1340     HRESULT hr;
1341     IStream *stm;
1342     HANDLE thread;
1343     DWORD tid;
1344     static const LARGE_INTEGER zero;
1345     IDataObject *data;
1346     FORMATETC fmt;
1347     STGMEDIUM med;
1348 
1349     hr = CreateStreamOnHGlobal( NULL, TRUE, &stm );
1350     ok( hr == S_OK, "got %08x\n", hr );
1351     tid = start_host_object2( stm, &IID_IDataObject, (IUnknown *)&obj.IDataObject_iface, MSHLFLAGS_NORMAL, NULL, &thread );
1352 
1353     IStream_Seek( stm, zero, STREAM_SEEK_SET, NULL );
1354     hr = CoUnmarshalInterface( stm, &IID_IDataObject, (void **)&data );
1355     ok( hr == S_OK, "got %08x\n", hr );
1356     IStream_Release( stm );
1357 
1358     Test_Stream.refs = 1;
1359     Test_Stream2.refs = 1;
1360     Test_Unknown.refs = 1;
1361 
1362     fmt.cfFormat = 1;
1363     fmt.ptd = NULL;
1364     fmt.dwAspect = DVASPECT_CONTENT;
1365     fmt.lindex = -1;
1366     U(med).pstm = NULL;
1367     med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
1368 
1369     fmt.tymed = med.tymed = TYMED_NULL;
1370     hr = IDataObject_GetDataHere( data, &fmt, &med );
1371     ok( hr == DV_E_TYMED, "got %08x\n", hr );
1372 
1373     for (fmt.tymed = TYMED_HGLOBAL; fmt.tymed <= TYMED_ENHMF; fmt.tymed <<= 1)
1374     {
1375         med.tymed = fmt.tymed;
1376         hr = IDataObject_GetDataHere( data, &fmt, &med );
1377         ok( hr == (fmt.tymed <= TYMED_ISTORAGE ? S_OK : DV_E_TYMED), "got %08x for tymed %d\n", hr, fmt.tymed );
1378         ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
1379     }
1380 
1381     fmt.tymed = TYMED_ISTREAM;
1382     med.tymed = TYMED_ISTORAGE;
1383     hr = IDataObject_GetDataHere( data, &fmt, &med );
1384     ok( hr == DV_E_TYMED, "got %08x\n", hr );
1385 
1386     fmt.tymed = med.tymed = TYMED_ISTREAM;
1387     U(med).pstm = &Test_Stream.IStream_iface;
1388     med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
1389 
1390     hr = IDataObject_GetDataHere( data, &fmt, &med );
1391     ok( hr == S_OK, "got %08x\n", hr );
1392 
1393     ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
1394     ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" );
1395 
1396     ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs );
1397     ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
1398 
1399     fmt.cfFormat = 2;
1400     fmt.tymed = med.tymed = TYMED_ISTREAM;
1401     U(med).pstm = &Test_Stream.IStream_iface;
1402     med.pUnkForRelease = &Test_Unknown.IUnknown_iface;
1403 
1404     hr = IDataObject_GetDataHere( data, &fmt, &med );
1405     ok( hr == S_OK, "got %08x\n", hr );
1406 
1407     ok( U(med).pstm == &Test_Stream.IStream_iface, "stm changed\n" );
1408     ok( med.pUnkForRelease == &Test_Unknown.IUnknown_iface, "punk changed\n" );
1409 
1410     ok( Test_Stream.refs == 1, "got %d\n", Test_Stream.refs );
1411     ok( Test_Unknown.refs == 1, "got %d\n", Test_Unknown.refs );
1412     ok( Test_Stream2.refs == 0, "got %d\n", Test_Stream2.refs );
1413 
1414     IDataObject_Release( data );
1415     end_host_object( tid, thread );
1416 }
1417 
1418 START_TEST(usrmarshal)
1419 {
1420     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1421 
1422     test_marshal_CLIPFORMAT();
1423     test_marshal_HWND();
1424     test_marshal_HGLOBAL();
1425     test_marshal_HENHMETAFILE();
1426     test_marshal_HMETAFILE();
1427     test_marshal_HMETAFILEPICT();
1428     test_marshal_WdtpInterfacePointer();
1429     test_marshal_STGMEDIUM();
1430     test_marshal_SNB();
1431     test_marshal_HDC();
1432     test_marshal_HICON();
1433     test_marshal_HBRUSH();
1434     test_marshal_HBITMAP();
1435 
1436     test_GetDataHere_Proxy();
1437 
1438     CoUninitialize();
1439 }
1440