~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/dispex/tests/marshal.c

Version: ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Tests for marshaling IDispatchEx
  3  *
  4  * Copyright 2005-2006 Robert Shearman
  5  * Copyright 2010 Huw Davies
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  *
 21  */
 22 
 23 #define COBJMACROS
 24 #define CONST_VTABLE
 25 
 26 #include <stdarg.h>
 27 
 28 #include "initguid.h"
 29 #include "objidl.h"
 30 #include "dispex.h"
 31 
 32 #include "wine/test.h"
 33 
 34 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\n", (unsigned long int)hr)
 35 
 36 #define RELEASEMARSHALDATA WM_USER
 37 
 38 struct host_object_data
 39 {
 40     IStream *stream;
 41     IID iid;
 42     IUnknown *object;
 43     MSHLFLAGS marshal_flags;
 44     HANDLE marshal_event;
 45     HANDLE error_event;
 46     IMessageFilter *filter;
 47 };
 48 
 49 static DWORD CALLBACK host_object_proc(LPVOID p)
 50 {
 51     struct host_object_data *data = p;
 52     HRESULT hr;
 53     MSG msg;
 54 
 55     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
 56 
 57     if (data->filter)
 58     {
 59         IMessageFilter * prev_filter = NULL;
 60         hr = CoRegisterMessageFilter(data->filter, &prev_filter);
 61         if (prev_filter) IMessageFilter_Release(prev_filter);
 62         ok_ole_success(hr, CoRegisterMessageFilter);
 63     }
 64 
 65     hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
 66 
 67     /* force the message queue to be created before signaling parent thread */
 68     PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
 69 
 70     if(hr == S_OK)
 71         SetEvent(data->marshal_event);
 72     else
 73     {
 74         win_skip("IDispatchEx marshaller not available.\n");
 75         SetEvent(data->error_event);
 76         return hr;
 77     }
 78 
 79     while (GetMessage(&msg, NULL, 0, 0))
 80     {
 81         if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
 82         {
 83             trace("releasing marshal data\n");
 84             CoReleaseMarshalData(data->stream);
 85             SetEvent((HANDLE)msg.lParam);
 86         }
 87         else
 88             DispatchMessage(&msg);
 89     }
 90 
 91     HeapFree(GetProcessHeap(), 0, data);
 92 
 93     CoUninitialize();
 94 
 95     return hr;
 96 }
 97 
 98 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
 99 {
100     DWORD tid = 0, ret;
101     HANDLE events[2];
102     struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
103 
104     data->stream = stream;
105     data->iid = *riid;
106     data->object = object;
107     data->marshal_flags = marshal_flags;
108     data->marshal_event = events[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
109     data->error_event   = events[1] = CreateEvent(NULL, FALSE, FALSE, NULL);
110     data->filter = filter;
111 
112     *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
113 
114     /* wait for marshaling to complete before returning */
115     ret = WaitForMultipleObjects(2, events, FALSE, INFINITE);
116     CloseHandle(events[0]);
117     CloseHandle(events[1]);
118 
119     if(ret == WAIT_OBJECT_0) return tid;
120 
121     WaitForSingleObject(*thread, INFINITE);
122     CloseHandle(*thread);
123     *thread = INVALID_HANDLE_VALUE;
124     return 0;
125 }
126 
127 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
128 {
129     return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
130 }
131 
132 static void end_host_object(DWORD tid, HANDLE thread)
133 {
134     BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
135     ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
136     /* be careful of races - don't return until hosting thread has terminated */
137     WaitForSingleObject(thread, INFINITE);
138     CloseHandle(thread);
139 }
140 
141 typedef struct
142 {
143     IDispatchEx IDispatchEx_iface;
144     LONG refs;
145 } dispex;
146 
147 static inline dispex *impl_from_IDispatchEx(IDispatchEx *iface)
148 {
149     return CONTAINING_RECORD(iface, dispex, IDispatchEx_iface);
150 }
151 
152 static HRESULT WINAPI dispex_QueryInterface(IDispatchEx* iface,
153                                             REFIID iid,  void **obj)
154 {
155     trace("QI {%08x-...}\n", iid->Data1);
156     if(IsEqualIID(iid, &IID_IUnknown) ||
157        IsEqualIID(iid, &IID_IDispatchEx))
158     {
159         IDispatchEx_AddRef(iface);
160         *obj = iface;
161         return S_OK;
162     }
163     else
164     {
165         *obj = NULL;
166         return E_NOINTERFACE;
167     }
168 }
169 
170 static ULONG WINAPI dispex_AddRef(IDispatchEx* iface)
171 {
172     dispex *This = impl_from_IDispatchEx(iface);
173     trace("AddRef\n");
174 
175     return InterlockedIncrement(&This->refs);
176 }
177 
178 static ULONG WINAPI dispex_Release(IDispatchEx* iface)
179 {
180     dispex *This = impl_from_IDispatchEx(iface);
181     ULONG refs = InterlockedDecrement(&This->refs);
182     trace("Release\n");
183     if(!refs)
184     {
185         HeapFree(GetProcessHeap(), 0, This);
186     }
187     return refs;
188 }
189 
190  static HRESULT WINAPI dispex_GetTypeInfoCount(IDispatchEx* iface,
191                                                UINT *pctinfo)
192 {
193     trace("\n");
194     return E_NOTIMPL;
195 }
196 
197 static HRESULT WINAPI dispex_GetTypeInfo(IDispatchEx* iface,
198                                          UINT iTInfo,
199                                          LCID lcid,
200                                          ITypeInfo **ppTInfo)
201 {
202     trace("\n");
203     return E_NOTIMPL;
204 }
205 
206 static HRESULT WINAPI dispex_GetIDsOfNames(IDispatchEx* iface,
207                                            REFIID riid,
208                                            LPOLESTR *rgszNames,
209                                            UINT cNames,
210                                            LCID lcid,
211                                            DISPID *rgDispId)
212 {
213     trace("\n");
214     return E_NOTIMPL;
215 }
216 
217 static HRESULT WINAPI dispex_Invoke(IDispatchEx* iface,
218                                     DISPID dispIdMember,
219                                     REFIID riid,
220                                     LCID lcid,
221                                     WORD wFlags,
222                                     DISPPARAMS *pDispParams,
223                                     VARIANT *pVarResult,
224                                     EXCEPINFO *pExcepInfo,
225                                     UINT *puArgErr)
226 {
227     trace("\n");
228     return E_NOTIMPL;
229 }
230 
231 static HRESULT WINAPI dispex_GetDispID(IDispatchEx* iface,
232                                        BSTR bstrName,
233                                        DWORD grfdex,
234                                        DISPID *pid)
235 {
236     trace("\n");
237     return E_NOTIMPL;
238 }
239 
240 static HRESULT WINAPI defer_fn(EXCEPINFO *except)
241 {
242     except->scode = E_OUTOFMEMORY;
243     return S_OK;
244 }
245 
246 static HRESULT WINAPI dispex_InvokeEx(IDispatchEx* iface,
247                                       DISPID id,
248                                       LCID lcid,
249                                       WORD wFlags,
250                                       DISPPARAMS *pdp,
251                                       VARIANT *pvarRes,
252                                       EXCEPINFO *pei,
253                                       IServiceProvider *pspCaller)
254 {
255     if(id == 1)
256     {
257         ok(pdp->cArgs == 0, "got %d\n", pdp->cArgs);
258         ok(pei == NULL, "got non-NULL excepinfo\n");
259         ok(pvarRes == NULL, "got non-NULL result\n");
260     }
261     else if(id == 2)
262     {
263         ok(pdp->cArgs == 2, "got %d\n", pdp->cArgs);
264         ok(V_VT(&pdp->rgvarg[0]) == VT_INT, "got %04x\n", V_VT(&pdp->rgvarg[0]));
265         ok(V_VT(&pdp->rgvarg[1]) == (VT_INT | VT_BYREF), "got %04x\n", V_VT(&pdp->rgvarg[1]));
266         ok(*V_INTREF(&pdp->rgvarg[1]) == 0xbeef, "got %08x\n", *V_INTREF(&pdp->rgvarg[1]));
267         *V_INTREF(&pdp->rgvarg[1]) = 0xdead;
268     }
269     else if(id == 3)
270     {
271         ok(pdp->cArgs == 2, "got %d\n", pdp->cArgs);
272         ok(V_VT(&pdp->rgvarg[0]) == VT_INT, "got %04x\n", V_VT(&pdp->rgvarg[0]));
273         ok(V_VT(&pdp->rgvarg[1]) == (VT_INT | VT_BYREF), "got %04x\n", V_VT(&pdp->rgvarg[1]));
274         V_VT(&pdp->rgvarg[0]) = VT_I4;
275     }
276     else if(id == 4)
277     {
278         ok(wFlags == 0xf, "got %04x\n", wFlags);
279     }
280     else if(id == 5)
281     {
282         if(pei) pei->pfnDeferredFillIn = defer_fn;
283         return DISP_E_EXCEPTION;
284     }
285     return S_OK;
286 }
287 
288 static HRESULT WINAPI dispex_DeleteMemberByName(IDispatchEx* iface,
289                                                 BSTR bstrName,
290                                                 DWORD grfdex)
291 {
292     trace("\n");
293     return E_NOTIMPL;
294 }
295 
296 static HRESULT WINAPI dispex_DeleteMemberByDispID(IDispatchEx* iface, DISPID id)
297 {
298     trace("\n");
299     return E_NOTIMPL;
300 }
301 
302 static HRESULT WINAPI dispex_GetMemberProperties(IDispatchEx* iface, DISPID id,
303                                                  DWORD grfdexFetch, DWORD *pgrfdex)
304 {
305     trace("\n");
306     return E_NOTIMPL;
307 }
308 
309 static HRESULT WINAPI dispex_GetMemberName(IDispatchEx* iface,
310                                            DISPID id, BSTR *pbstrName)
311 {
312     trace("\n");
313     return E_NOTIMPL;
314 }
315 
316 static HRESULT WINAPI dispex_GetNextDispID(IDispatchEx* iface,
317                                            DWORD grfdex,
318                                            DISPID id,
319                                            DISPID *pid)
320 {
321     trace("\n");
322     return E_NOTIMPL;
323 }
324 
325 static HRESULT WINAPI dispex_GetNameSpaceParent(IDispatchEx* iface,
326                                                 IUnknown **ppunk)
327 {
328     trace("\n");
329     return E_NOTIMPL;
330 }
331 
332 static const IDispatchExVtbl dispex_vtable =
333 {
334     dispex_QueryInterface,
335     dispex_AddRef,
336     dispex_Release,
337     dispex_GetTypeInfoCount,
338     dispex_GetTypeInfo,
339     dispex_GetIDsOfNames,
340     dispex_Invoke,
341     dispex_GetDispID,
342     dispex_InvokeEx,
343     dispex_DeleteMemberByName,
344     dispex_DeleteMemberByDispID,
345     dispex_GetMemberProperties,
346     dispex_GetMemberName,
347     dispex_GetNextDispID,
348     dispex_GetNameSpaceParent
349 };
350 
351 static IDispatchEx *dispex_create(void)
352 {
353     dispex *This;
354 
355     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
356     if (!This) return NULL;
357     This->IDispatchEx_iface.lpVtbl = &dispex_vtable;
358     This->refs = 1;
359     return (IDispatchEx *)This;
360 }
361 
362 static void test_dispex(void)
363 {
364     HRESULT hr;
365     IStream *stream;
366     DWORD tid;
367     HANDLE thread;
368     static const LARGE_INTEGER zero;
369     IDispatchEx *dispex = dispex_create();
370     DISPPARAMS params;
371     VARIANTARG args[10];
372     INT i;
373     EXCEPINFO excepinfo;
374 
375     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
376     ok(hr == S_OK, "got %08x\n", hr);
377     tid = start_host_object(stream, &IID_IDispatchEx, (IUnknown *)dispex, MSHLFLAGS_NORMAL, &thread);
378     IDispatchEx_Release(dispex);
379     if(tid == 0)
380     {
381         IStream_Release(stream);
382         return;
383     }
384 
385     IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
386     hr = CoUnmarshalInterface(stream, &IID_IDispatchEx, (void **)&dispex);
387     ok(hr == S_OK, "got %08x\n", hr);
388     IStream_Release(stream);
389 
390     params.rgvarg = NULL;
391     params.rgdispidNamedArgs = NULL;
392     params.cArgs = 0;
393     params.cNamedArgs = 0;
394     hr = IDispatchEx_InvokeEx(dispex, 1, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
395     ok(hr == S_OK, "got %08x\n", hr);
396 
397     params.rgvarg = args;
398     params.rgdispidNamedArgs = NULL;
399     params.cArgs = 2;
400     params.cNamedArgs = 0;
401     V_VT(&args[0]) = VT_INT;
402     V_INT(&args[0]) = 0xcafe;
403     V_VT(&args[1]) = VT_INT | VT_BYREF;
404     V_INTREF(&args[1]) = &i;
405     i = 0xbeef;
406     hr = IDispatchEx_InvokeEx(dispex, 2, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
407     ok(hr == S_OK, "got %08x\n", hr);
408     ok(i == 0xdead, "got %08x\n", i);
409 
410     /* change one of the argument vts */
411     i = 0xbeef;
412     hr = IDispatchEx_InvokeEx(dispex, 3, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
413     ok(hr == DISP_E_BADCALLEE, "got %08x\n", hr);
414 
415     hr = IDispatchEx_InvokeEx(dispex, 4, LOCALE_SYSTEM_DEFAULT, 0xffff, &params, NULL, NULL, NULL);
416     ok(hr == S_OK, "got %08x\n", hr);
417 
418     params.cArgs = 0;
419     hr = IDispatchEx_InvokeEx(dispex, 5, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
420     ok(hr == DISP_E_EXCEPTION, "got %08x\n", hr);
421     hr = IDispatchEx_InvokeEx(dispex, 5, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &params, NULL, &excepinfo, NULL);
422     ok(hr == DISP_E_EXCEPTION, "got %08x\n", hr);
423     ok(excepinfo.scode == E_OUTOFMEMORY, "got scode %08x\n", excepinfo.scode);
424     ok(excepinfo.pfnDeferredFillIn == NULL, "got non-NULL pfnDeferredFillIn\n");
425 
426     IDispatchEx_Release(dispex);
427     end_host_object(tid, thread);
428 }
429 
430 START_TEST(marshal)
431 {
432     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
433 
434     test_dispex();
435 
436     CoUninitialize();
437 }
438 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.