ReactOS  0.4.13-dev-73-gcfe54aa
marshal.c
Go to the documentation of this file.
1 /*
2  * Marshaling Tests
3  *
4  * Copyright 2004 Robert Shearman
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_DCOM
22 #define COBJMACROS
23 #define CONST_VTABLE
24 
25 #include <stdarg.h>
26 #include <stdio.h>
27 
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31 #include "olectl.h"
32 #include "shlguid.h"
33 #include "shobjidl.h"
34 
35 #include "wine/test.h"
36 #include "wine/heap.h"
37 
38 #define DEFINE_EXPECT(func) \
39  static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
40 
41 #define SET_EXPECT(func) \
42  expect_ ## func = TRUE
43 
44 #define CHECK_EXPECT2(func) \
45  do { \
46  ok(expect_ ##func, "unexpected call " #func "\n"); \
47  called_ ## func = TRUE; \
48  }while(0)
49 
50 #define CHECK_EXPECT(func) \
51  do { \
52  CHECK_EXPECT2(func); \
53  expect_ ## func = FALSE; \
54  }while(0)
55 
56 #define CHECK_CALLED(func) \
57  do { \
58  ok(called_ ## func, "expected " #func "\n"); \
59  expect_ ## func = called_ ## func = FALSE; \
60  }while(0)
61 
62 static const GUID CLSID_WineTestPSFactoryBuffer = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
63 static const GUID CLSID_DfMarshal = { 0x0000030b, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
64 
65 /* functions that are not present on all versions of Windows */
66 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
67 static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID,REFIID,LPVOID);
68 
69 /* helper macros to make tests a bit leaner */
70 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
71 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
72 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
73 #define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0);
74 #define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0);
75 #define ok_last_release_closes(b) do {if (with_external_conn) ok(last_release_closes == b, "got %d expected %d\n", last_release_closes, b);} while(0);
76 
77 #define OBJREF_SIGNATURE (0x574f454d)
78 #define OBJREF_STANDARD (0x1)
79 #define OBJREF_CUSTOM (0x4)
80 
81 typedef struct tagDUALSTRINGARRAY {
82  unsigned short wNumEntries;
83  unsigned short wSecurityOffset;
84  unsigned short aStringArray[1];
86 
87 typedef UINT64 OXID;
88 typedef UINT64 OID;
89 typedef GUID IPID;
90 
91 typedef struct tagSTDOBJREF {
97 } STDOBJREF;
98 
99 typedef struct tagOBJREF {
103  union {
104  struct OR_STANDARD {
107  } u_standard;
108  struct OR_HANDLER {
109  STDOBJREF std;
112  } u_handler;
113  struct OR_CUSTOM {
114  CLSID clsid;
117  byte *pData;
118  } u_custom;
119  } u_objref;
120 } OBJREF;
121 
122 static const IID IID_IWineTest =
123 {
124  0x5201163f,
125  0x8164,
126  0x4fd0,
127  {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
128 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
129 
130 static const IID IID_IRemUnknown =
131 {
132  0x00000131,
133  0x0000,
134  0x0000,
135  {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
136 };
137 
138 #define EXTENTID_WineTest IID_IWineTest
139 #define CLSID_WineTest IID_IWineTest
140 
141 static const CLSID CLSID_WineOOPTest =
142 {
143  0x5201163f,
144  0x8164,
145  0x4fd0,
146  {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
147 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
148 
150 {
151  IUnknown *pProxy;
152  IMultiQI *pMQI;
153  HRESULT hr;
154 
155  pCoInitializeEx(NULL, COINIT_MULTITHREADED);
156 
157  hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
159  hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
160  ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
161  if (hr == S_OK)
162  IMultiQI_Release(pMQI);
163  IUnknown_Release(pProxy);
164 
165  CoUninitialize();
166 }
167 
168 static const LARGE_INTEGER ullZero;
169 static LONG cLocks;
170 
171 static void LockModule(void)
172 {
174 }
175 
176 static void UnlockModule(void)
177 {
179 }
180 
184 
186 {
187  ok(0, "unexpected call\n");
188  *ppv = NULL;
189  return E_NOINTERFACE;
190 }
191 
193 {
194  return 2;
195 }
196 
198 {
199  return 1;
200 }
201 
203 {
204  trace("add connection\n");
205  return ++external_connections;
206 }
207 
208 
210  DWORD reserved, BOOL fLastReleaseCloses)
211 {
212  trace("release connection %d\n", fLastReleaseCloses);
213  last_release_closes = fLastReleaseCloses;
214  return --external_connections;
215 }
216 
217 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
223 };
224 
226 
227 
229  LPUNKNOWN iface,
230  REFIID riid,
231  LPVOID *ppvObj)
232 {
233  if (ppvObj == NULL) return E_POINTER;
234 
236  {
237  *ppvObj = iface;
238  IUnknown_AddRef(iface);
239  return S_OK;
240  }
241 
242  *ppvObj = NULL;
243  return E_NOINTERFACE;
244 }
245 
247 {
248  LockModule();
249  return 2; /* non-heap-based object */
250 }
251 
253 {
254  UnlockModule();
255  return 1; /* non-heap-based object */
256 }
257 
258 static const IUnknownVtbl TestUnknown_Vtbl =
259 {
263 };
264 
266 
268 {
269  UnlockModule();
270  if(!cLocks) {
271  trace("crashing...\n");
272  *(int**)0xc = 0;
273  }
274  return 1; /* non-heap-based object */
275 }
276 
277 static const IUnknownVtbl TestCrashUnknown_Vtbl =
278 {
282 };
283 
285 
287  LPCLASSFACTORY iface,
288  REFIID riid,
289  LPVOID *ppvObj)
290 {
291  if (ppvObj == NULL) return E_POINTER;
292 
293  if (IsEqualGUID(riid, &IID_IUnknown) ||
295  /* the only other interface Wine is currently able to marshal (for testing two proxies) */
297  {
298  *ppvObj = iface;
299  IClassFactory_AddRef(iface);
300  return S_OK;
301  }
302 
303  if (with_external_conn && IsEqualGUID(riid, &IID_IExternalConnection))
304  {
305  *ppvObj = &ExternalConnection;
306  return S_OK;
307  }
308 
309  *ppvObj = NULL;
310  return E_NOINTERFACE;
311 }
312 
313 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
314 {
315  LockModule();
316  return 2; /* non-heap-based object */
317 }
318 
319 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
320 {
321  UnlockModule();
322  return 1; /* non-heap-based object */
323 }
324 
326  LPCLASSFACTORY iface,
327  LPUNKNOWN pUnkOuter,
328  REFIID riid,
329  LPVOID *ppvObj)
330 {
331  if (pUnkOuter) return CLASS_E_NOAGGREGATION;
332  return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
333 }
334 
336  LPCLASSFACTORY iface,
337  BOOL fLock)
338 {
339  return S_OK;
340 }
341 
342 static const IClassFactoryVtbl TestClassFactory_Vtbl =
343 {
349 };
350 
352 
353 DEFINE_EXPECT(Invoke);
354 DEFINE_EXPECT(CreateStub);
355 DEFINE_EXPECT(CreateProxy);
357 DEFINE_EXPECT(Disconnect);
358 
360 {
361  ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
362  *ppv = NULL;
363  return E_NOINTERFACE;
364 }
365 
367 {
368  return 2;
369 }
370 
372 {
373  return 1;
374 }
375 
377 {
379  *hwnd = (HWND)0xdeadbeef;
380  return S_OK;
381 }
382 
383 static const IOleWindowVtbl OleWindowVtbl = {
388  /* not needed */
389 };
390 
392 
394 {
396  *ppv = iface;
397  else if (IsEqualGUID(riid, &IID_IOleWindow))
398  *ppv = &Test_OleWindow;
399  else
400  {
401  *ppv = NULL;
402  return E_NOINTERFACE;
403  }
404 
405  IUnknown_AddRef((IUnknown*)*ppv);
406  return S_OK;
407 }
408 
410 {
411  return 2;
412 }
413 
415 {
416  return 1;
417 }
418 
419 static const IOleClientSiteVtbl OleClientSiteVtbl = {
423  /* we don't need the rest, we never call it */
424 };
425 
427 
428 typedef struct {
433 
435 {
436  return CONTAINING_RECORD(iface, StubBufferWrapper, IRpcStubBuffer_iface);
437 }
438 
440 {
442 
443  if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IRpcStubBuffer, riid)) {
444  *ppv = &This->IRpcStubBuffer_iface;
445  }else {
446  *ppv = NULL;
447  return E_NOINTERFACE;
448  }
449 
450  IUnknown_AddRef((IUnknown*)*ppv);
451  return S_OK;
452 }
453 
455 {
457  return InterlockedIncrement(&This->ref);
458 }
459 
461 {
464  if(!ref) {
465  IRpcStubBuffer_Release(This->buffer);
466  heap_free(This);
467  }
468  return ref;
469 }
470 
472 {
473  ok(0, "unexpected call\n");
474  return E_NOTIMPL;
475 }
476 
478 {
479  CHECK_EXPECT(Disconnect);
480 }
481 
482 static HRESULT WINAPI RpcStubBuffer_Invoke(IRpcStubBuffer *iface, RPCOLEMESSAGE *_prpcmsg,
483  IRpcChannelBuffer *_pRpcChannelBuffer)
484 {
486  void *dest_context_data;
487  DWORD dest_context;
488  HRESULT hr;
489 
490  CHECK_EXPECT(Invoke);
491 
492  hr = IRpcChannelBuffer_GetDestCtx(_pRpcChannelBuffer, &dest_context, &dest_context_data);
493  ok(hr == S_OK, "GetDestCtx failed: %08x\n", hr);
494  ok(dest_context == MSHCTX_INPROC, "desc_context = %x\n", dest_context);
495  ok(!dest_context_data, "desc_context_data = %p\n", dest_context_data);
496 
497  return IRpcStubBuffer_Invoke(This->buffer, _prpcmsg, _pRpcChannelBuffer);
498 }
499 
501 {
502  ok(0, "unexpected call\n");
503  return NULL;
504 }
505 
507 {
508  ok(0, "unexpected call\n");
509  return E_NOTIMPL;
510 }
511 
513 {
514  ok(0, "unexpected call\n");
515  return E_NOTIMPL;
516 }
517 
519 {
520  ok(0, "unexpected call\n");
521 }
522 
523 static const IRpcStubBufferVtbl RpcStubBufferVtbl = {
534 };
535 
537 
539 {
540  if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPSFactoryBuffer))
541  *ppv = iface;
542  else
543  {
544  *ppv = NULL;
545  return E_NOINTERFACE;
546  }
547  IUnknown_AddRef((IUnknown*)*ppv);
548  return S_OK;
549 }
550 
552 {
553  return 2;
554 }
555 
557 {
558  return 1;
559 }
560 
562  REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv)
563 {
564  CHECK_EXPECT(CreateProxy);
565  return IPSFactoryBuffer_CreateProxy(ps_factory_buffer, outer, riid, ppProxy, ppv);
566 }
567 
569  IUnknown *server, IRpcStubBuffer **ppStub)
570 {
572  HRESULT hr;
573 
574  CHECK_EXPECT(CreateStub);
575 
576  ok(server == (IUnknown*)&Test_OleClientSite, "unexpected server %p\n", server);
577 
578  stub = heap_alloc(sizeof(*stub));
579  stub->IRpcStubBuffer_iface.lpVtbl = &RpcStubBufferVtbl;
580  stub->ref = 1;
581 
582  hr = IPSFactoryBuffer_CreateStub(ps_factory_buffer, riid, server, &stub->buffer);
583  ok(hr == S_OK, "CreateStub failed: %08x\n", hr);
584 
585  *ppStub = &stub->IRpcStubBuffer_iface;
586  return S_OK;
587 }
588 
589 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
590 {
596 };
597 
599 
600 #define RELEASEMARSHALDATA WM_USER
601 
603 {
605  const IID *iid;
607  MSHLFLAGS marshal_flags;
612 };
613 
614 #ifndef __REACTOS__ /* FIXME: Inspect */
616 #endif
617 
619 {
620  struct host_object_data *data = p;
621  DWORD registration_key;
622  HRESULT hr;
623  MSG msg;
624 
625  pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
626 
627  if(data->register_object) {
628  hr = CoRegisterClassObject(data->register_clsid, data->register_object,
629  CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &registration_key);
630  ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr);
631  }
632 
633  if (data->filter)
634  {
635  IMessageFilter * prev_filter = NULL;
636  hr = CoRegisterMessageFilter(data->filter, &prev_filter);
637  if (prev_filter) IMessageFilter_Release(prev_filter);
639  }
640 
641  hr = CoMarshalInterface(data->stream, data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
643 
644  /* force the message queue to be created before signaling parent thread */
646 
647  SetEvent(data->marshal_event);
648 
649  while (GetMessageA(&msg, NULL, 0, 0))
650  {
651  if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
652  {
653  CoReleaseMarshalData(data->stream);
654  SetEvent((HANDLE)msg.lParam);
655  }
656  else
658  }
659 
661 
662  CoUninitialize();
663 
664  return hr;
665 }
666 
668 {
669  DWORD tid = 0;
670  struct host_object_data *data;
671 
672  data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
673  *data = *object_data;
676 
677  /* wait for marshaling to complete before returning */
678  ok( !WaitForSingleObject(data->marshal_event, 10000), "wait timed out\n" );
679  CloseHandle(data->marshal_event);
680 
681  return tid;
682 }
683 
685 {
686  struct host_object_data object_data = { stream, riid, object, marshal_flags };
687  return start_host_object2(&object_data, thread);
688 }
689 
690 /* asks thread to release the marshal data because it has to be done by the
691  * same thread that marshaled the interface in the first place. */
693 {
694  HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
696  ok( !WaitForSingleObject(event, 10000), "wait timed out\n" );
698 }
699 
701 {
703  ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
704  /* be careful of races - don't return until hosting thread has terminated */
705  ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
707 }
708 
709 /* tests failure case of interface not having a marshaler specified in the
710  * registry */
711 static void test_no_marshaler(void)
712 {
713  IStream *pStream;
714  HRESULT hr;
715 
716  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
718  hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
719  ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
720 
721  IStream_Release(pStream);
722 }
723 
724 /* tests normal marshal and then release without unmarshaling */
726 {
727  HRESULT hr;
728  IStream *pStream = NULL;
729 
730  cLocks = 0;
732 
733  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
735  hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
737 
740 
741  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
742  hr = CoReleaseMarshalData(pStream);
744  IStream_Release(pStream);
745 
746  ok_no_locks();
749 }
750 
751 /* tests success case of a same-thread marshal and unmarshal */
753 {
754  HRESULT hr;
755  IStream *pStream = NULL;
756  IUnknown *pProxy = NULL;
757 
758  cLocks = 0;
760 
761  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
763  hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
765 
768 
769  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
770  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
772  IStream_Release(pStream);
773 
777 
778  IUnknown_Release(pProxy);
779 
780  ok_no_locks();
781 }
782 
783 /* tests failure case of unmarshaling a freed object */
785 {
786  HRESULT hr;
787  IStream *pStream = NULL;
788  IClassFactory *pProxy = NULL;
789  DWORD tid;
790  void * dummy;
791  HANDLE thread;
792 
793  cLocks = 0;
795 
796  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
798  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
799 
802 
803  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
804  hr = CoReleaseMarshalData(pStream);
806 
807  ok_no_locks();
810 
811  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
812  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
814 
815  ok_no_locks();
816 
817  if (pProxy)
818  {
819  hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
820  ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
821 
822  IClassFactory_Release(pProxy);
823  }
824 
825  IStream_Release(pStream);
826 
828 }
829 
831 {
832  HRESULT hr;
833  IStream *pStream;
834  IUnknown *pProxy;
835  static const LARGE_INTEGER llZero;
836 
837  cLocks = 0;
839 
840  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
842 
843  hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
845 
848 
849  hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
850  ok_ole_success(hr, IStream_Seek);
851 
852  hr = CoUnmarshalInterface(pStream, &IID_IParseDisplayName, (void **)&pProxy);
853  ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
854 
855  ok_no_locks();
858 
859  IStream_Release(pStream);
860 }
861 
862 /* tests success case of an interthread marshal */
864 {
865  HRESULT hr;
866  IStream *pStream = NULL;
867  IUnknown *pProxy = NULL;
868  DWORD tid;
869  HANDLE thread;
870 
871  cLocks = 0;
873 
874  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
876  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
877 
880 
881  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
882  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
884  IStream_Release(pStream);
885 
888 
889  IUnknown_Release(pProxy);
890 
891  ok_no_locks();
894 
896 }
897 
898 /* the number of external references that Wine's proxy manager normally gives
899  * out, so we can test the border case of running out of references */
900 #define NORMALEXTREFS 5
901 
902 /* tests success case of an interthread marshal and then marshaling the proxy */
904 {
905  HRESULT hr;
906  IStream *pStream = NULL;
907  IUnknown *pProxy = NULL;
908  IUnknown *pProxy2 = NULL;
909  DWORD tid;
910  HANDLE thread;
911  int i;
912 
913  cLocks = 0;
915 
916  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
918  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
919 
922 
923  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
924  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
926 
928 
929  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
930  /* marshal the proxy */
931  hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
933 
935 
936  /* marshal 5 more times to exhaust the normal external references of 5 */
937  for (i = 0; i < NORMALEXTREFS; i++)
938  {
939  hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
941  }
942 
944 
945  /* release the original proxy to test that we successfully keep the
946  * original object alive */
947  IUnknown_Release(pProxy);
948 
949  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
950  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
952 
955 
956  IUnknown_Release(pProxy2);
957 
958  /* unmarshal all of the proxies to check that the object stub still exists */
959  for (i = 0; i < NORMALEXTREFS; i++)
960  {
961  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
963 
964  IUnknown_Release(pProxy2);
965  }
966 
967  ok_no_locks();
970 
971  IStream_Release(pStream);
972 
974 }
975 
976 /* tests success case of an interthread marshal and then marshaling the proxy
977  * using an iid that hasn't previously been unmarshaled */
979 {
980  HRESULT hr;
981  IStream *pStream = NULL;
982  IUnknown *pProxy = NULL;
983  IUnknown *pProxy2 = NULL;
984  DWORD tid;
985  HANDLE thread;
986 
987  cLocks = 0;
989 
990  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
992  tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
993 
996 
997  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
998  hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1000 
1002 
1003  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1004  /* marshal the proxy */
1005  hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1007 
1009 
1010  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1011  /* unmarshal the second proxy to the object */
1012  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1014  IStream_Release(pStream);
1015 
1016  /* now the proxies should be as follows:
1017  * pProxy -> &Test_ClassFactory
1018  * pProxy2 -> &Test_ClassFactory
1019  * they should NOT be as follows:
1020  * pProxy -> &Test_ClassFactory
1021  * pProxy2 -> pProxy
1022  * the above can only really be tested by looking in +ole traces
1023  */
1024 
1026 
1027  IUnknown_Release(pProxy);
1028 
1031 
1032  IUnknown_Release(pProxy2);
1033 
1034  ok_no_locks();
1037 
1039 }
1040 
1041 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
1043 {
1044  HRESULT hr;
1045  IStream *pStream = NULL;
1046  IUnknown *pProxy = NULL;
1047  IUnknown *pProxy2 = NULL;
1048  DWORD tid;
1049  HANDLE thread;
1050 
1051  cLocks = 0;
1053 
1054  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1056  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1057 
1060 
1061  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1062  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1064 
1067 
1068  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1069  /* marshal the proxy */
1070  hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
1072 
1075 
1076  /* release the original proxy to test that we successfully keep the
1077  * original object alive */
1078  IUnknown_Release(pProxy);
1079 
1080  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1081  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1082  todo_wine
1083  ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr);
1084 
1085  ok_no_locks();
1088 
1089  IStream_Release(pStream);
1090 
1092 }
1093 
1094 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
1096 {
1097  HRESULT hr;
1098  IStream *pStream = NULL;
1099  IUnknown *pProxy = NULL;
1100  IUnknown *pProxy2 = NULL;
1101  DWORD tid;
1102  HANDLE thread;
1103 
1104  cLocks = 0;
1106 
1107  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1109  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1110 
1113 
1114  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1115  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1117 
1120 
1121  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1122  /* marshal the proxy */
1123  hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
1124  ok(hr == S_OK /* WinNT */ || hr == E_INVALIDARG /* Win9x */,
1125  "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr);
1126  if (FAILED(hr))
1127  {
1128  IUnknown_Release(pProxy);
1129  goto end;
1130  }
1131 
1134 
1135  /* release the original proxy to test that we successfully keep the
1136  * original object alive */
1137  IUnknown_Release(pProxy);
1138 
1139  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1140  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1142 
1145 
1146  IUnknown_Release(pProxy2);
1147 
1150 
1151 end:
1152  IStream_Release(pStream);
1153 
1155 
1156  ok_no_locks();
1157 todo_wine {
1160 }
1161 }
1162 
1163 /* tests that stubs are released when the containing apartment is destroyed */
1165 {
1166  HRESULT hr;
1167  IStream *pStream = NULL;
1168  IUnknown *pProxy = NULL;
1169  DWORD tid;
1170  HANDLE thread;
1171 
1172  cLocks = 0;
1174 
1175  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1177  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1178 
1181 
1182  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1183  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1185  IStream_Release(pStream);
1186 
1189 
1191 
1192  ok_no_locks();
1193 todo_wine {
1196 }
1197 
1198  IUnknown_Release(pProxy);
1199 
1200  ok_no_locks();
1201 }
1202 
1203 /* tests that proxies are released when the containing apartment is destroyed */
1205 {
1206  HRESULT hr;
1207  IStream *pStream = NULL;
1208  IUnknown *pProxy = NULL;
1209  DWORD tid;
1210  HANDLE thread;
1211 
1212  cLocks = 0;
1214 
1215  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1217  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1218 
1221 
1222  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1223  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1225  IStream_Release(pStream);
1226 
1229 
1230  CoUninitialize();
1231 
1232  ok_no_locks();
1235 
1236  IUnknown_Release(pProxy);
1237 
1238  ok_no_locks();
1239 
1241 
1242  pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1243 }
1244 
1245 /* tests that proxies are released when the containing mta apartment is destroyed */
1247 {
1248  HRESULT hr;
1249  IStream *pStream = NULL;
1250  IUnknown *pProxy = NULL;
1251  DWORD tid;
1252  HANDLE thread;
1253 
1254  CoUninitialize();
1255  pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1256 
1257  cLocks = 0;
1259 
1260  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1262  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1263 
1266 
1267  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1268  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1270  IStream_Release(pStream);
1271 
1274 
1275  CoUninitialize();
1276 
1277  ok_no_locks();
1280 
1281  IUnknown_Release(pProxy);
1282 
1283  ok_no_locks();
1284 
1286 
1287  pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1288 }
1289 
1291 {
1292  DWORD registration_key;
1293  IUnknown *proxy = NULL;
1294  IOleWindow *ole_window;
1295  HWND hwnd;
1296  CLSID clsid;
1297  DWORD tid;
1298  HANDLE thread;
1299  HRESULT hr;
1300 
1302  MSHLFLAGS_NORMAL, NULL, (IUnknown*)&PSFactoryBuffer,
1304 
1305  cLocks = 0;
1307 
1309  ok_ole_success(hr, "CoGetPSClsid");
1310 
1311  hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer,
1312  (void **)&ps_factory_buffer);
1313  ok_ole_success(hr, "CoGetClassObject");
1314 
1315  hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream);
1317  tid = start_host_object2(&object_data, &thread);
1318 
1319  IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL);
1320  hr = CoUnmarshalInterface(object_data.stream, &IID_IUnknown, (void **)&proxy);
1322  IStream_Release(object_data.stream);
1323 
1325  CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &registration_key);
1326  ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr);
1327 
1329  ok(hr == S_OK, "CoRegisterPSClsid failed: %08x\n", hr);
1330 
1331  SET_EXPECT(CreateStub);
1332  SET_EXPECT(CreateProxy);
1333  hr = IUnknown_QueryInterface(proxy, &IID_IOleWindow, (void**)&ole_window);
1334  ok(hr == S_OK, "Could not get IOleWindow iface: %08x\n", hr);
1335  CHECK_CALLED(CreateStub);
1336  CHECK_CALLED(CreateProxy);
1337 
1338  SET_EXPECT(Invoke);
1340  hr = IOleWindow_GetWindow(ole_window, &hwnd);
1341  ok(hr == S_OK, "GetWindow failed: %08x\n", hr);
1342  ok((DWORD)(DWORD_PTR)hwnd == 0xdeadbeef, "hwnd = %p\n", hwnd);
1343  CHECK_CALLED(Invoke);
1345 
1346  IOleWindow_Release(ole_window);
1347 
1348  SET_EXPECT(Disconnect);
1349  IUnknown_Release(proxy);
1350 todo_wine
1351  CHECK_CALLED(Disconnect);
1352 
1353  hr = CoRevokeClassObject(registration_key);
1354  ok(hr == S_OK, "CoRevokeClassObject failed: %08x\n", hr);
1355 
1357 }
1358 
1359 static const CLSID *unmarshal_class;
1363 
1365 {
1366  if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMarshal)) {
1367  *ppv = iface;
1368  }
1369  else
1370  {
1371  *ppv = NULL;
1372  return E_NOINTERFACE;
1373  }
1374  IUnknown_AddRef((IUnknown*)*ppv);
1375  return S_OK;
1376 }
1377 
1379 {
1380  return 2;
1381 }
1382 
1384 {
1385  return 1;
1386 }
1387 
1389  void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
1390 {
1392  *clsid = *unmarshal_class;
1393  return S_OK;
1394 }
1395 
1397  void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
1398 {
1400  ok(size != NULL, "size = NULL\n");
1401 
1402  *size = 0;
1403  return S_OK;
1404 }
1405 
1407  REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
1408 {
1409  IMarshal *std_marshal;
1410  STATSTG stat;
1411  HRESULT hr;
1412 
1414 
1416  return S_OK;
1417 
1418  hr = IStream_Stat(stream, &stat, STATFLAG_DEFAULT);
1419  ok_ole_success(hr, IStream_Stat);
1420  ok(U(stat.cbSize).LowPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).LowPart);
1421  ok(U(stat.cbSize).HighPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).HighPart);
1422 
1423  hr = CoGetStandardMarshal(riid, (IUnknown*)iface,
1424  dwDestContext, NULL, mshlflags, &std_marshal);
1426  hr = IMarshal_MarshalInterface(std_marshal, stream, riid, pv,
1427  dwDestContext, pvDestContext, mshlflags);
1428  ok_ole_success(hr, IMarshal_MarshalInterface);
1429  IMarshal_Release(std_marshal);
1430 
1431  return S_OK;
1432 }
1433 
1435  IStream *stream, REFIID riid, void **ppv)
1436 {
1437  ok(0, "unexpected call\n");
1438  return E_NOTIMPL;
1439 }
1440 
1442 {
1443  ok(0, "unexpected call\n");
1444  return E_NOTIMPL;
1445 }
1446 
1448 {
1449  ok(0, "unexpected call\n");
1450  return E_NOTIMPL;
1451 }
1452 
1453 static IMarshalVtbl CustomMarshalVtbl =
1454 {
1464 };
1465 
1467 
1469 {
1470  IStream *stream;
1471  IUnknown *unk;
1472  DWORD size;
1473  HRESULT hr;
1474 
1477 
1482  MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1486 
1487  hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1488  ok_ole_success(hr, IStream_Seek);
1489  hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk);
1491  ok(unk == (IUnknown*)&CustomMarshal, "unk != &CustomMarshal\n");
1492  IUnknown_Release(unk);
1493  IStream_Release(stream);
1494 
1497 
1501  MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1505 
1506  hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1507  ok_ole_success(hr, IStream_Seek);
1510  IStream_Release(stream);
1511 
1514  MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1517  ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF));
1518 }
1519 
1521 {
1522  DWORD size, read;
1523  IStream *stream;
1524  OBJREF objref;
1525  HRESULT hr;
1526 
1529 
1535  MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1540 
1541  hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1542  ok_ole_success(hr, IStream_Seek);
1543  size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData);
1544  hr = IStream_Read(stream, &objref, size, &read);
1545  ok_ole_success(hr, IStream_Read);
1546  ok(read == size, "read = %d, expected %d\n", read, size);
1547  ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n",
1548  objref.signature);
1549  ok(objref.flags == OBJREF_CUSTOM, "objref.flags = %x\n", objref.flags);
1550  ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n",
1551  wine_dbgstr_guid(&objref.iid));
1552  ok(IsEqualIID(&objref.u_objref.u_custom.clsid, &CLSID_DfMarshal),
1553  "custom.clsid = %s\n", wine_dbgstr_guid(&objref.u_objref.u_custom.clsid));
1554  ok(!objref.u_objref.u_custom.cbExtension, "custom.cbExtension = %d\n",
1555  objref.u_objref.u_custom.cbExtension);
1556  ok(!objref.u_objref.u_custom.size, "custom.size = %d\n",
1557  objref.u_objref.u_custom.size);
1558 
1559  IStream_Release(stream);
1560 
1563  MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1566  ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF));
1567 }
1568 
1569 static void test_CoGetStandardMarshal(void)
1570 {
1571  DUALSTRINGARRAY *dualstringarr;
1572  STDOBJREF *stdobjref;
1573  OBJREF objref;
1574  IMarshal *marshal;
1575  DWORD size, read;
1576  IStream *stream;
1577  IUnknown *unk;
1578  CLSID clsid;
1579  HRESULT hr;
1580 
1583 
1585  MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &marshal);
1587 
1588  hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUnknown, &Test_Unknown,
1589  MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid);
1590  ok_ole_success(hr, IMarshal_GetUnmarshalClass);
1591  ok(IsEqualGUID(&clsid, &CLSID_StdMarshal), "clsid = %s\n", wine_dbgstr_guid(&clsid));
1592 
1593  hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IUnknown, &Test_Unknown,
1594  MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &size);
1595  ok_ole_success(hr, IMarshal_GetMarshalSizeMax);
1597  MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1599  ok(size == read, "IMarshal_GetMarshalSizeMax size = %d, expected %d\n", size, read);
1600 
1601  hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown,
1602  &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1603  ok_ole_success(hr, IMarshal_MarshalInterface);
1604 
1605  hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1606  ok_ole_success(hr, IStream_Seek);
1607  size = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray);
1608  hr = IStream_Read(stream, &objref, size, &read);
1609  ok_ole_success(hr, IStream_Read);
1610  ok(read == size, "read = %d, expected %d\n", read, size);
1611  ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n",
1612  objref.signature);
1613  ok(objref.flags == OBJREF_STANDARD, "objref.flags = %x\n", objref.flags);
1614  ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n",
1615  wine_dbgstr_guid(&objref.iid));
1616  stdobjref = &objref.u_objref.u_standard.std;
1617  ok(stdobjref->flags == 0, "stdobjref.flags = %d\n", stdobjref->flags);
1618  ok(stdobjref->cPublicRefs == 5, "stdobjref.cPublicRefs = %d\n",
1619  stdobjref->cPublicRefs);
1620  dualstringarr = &objref.u_objref.u_standard.saResAddr;
1621  ok(dualstringarr->wNumEntries == 0, "dualstringarr.wNumEntries = %d\n",
1622  dualstringarr->wNumEntries);
1623  ok(dualstringarr->wSecurityOffset == 0, "dualstringarr.wSecurityOffset = %d\n",
1624  dualstringarr->wSecurityOffset);
1625 
1626  hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1627  ok_ole_success(hr, IStream_Seek);
1628  hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUnknown, (void**)&unk);
1629  ok_ole_success(hr, IMarshal_UnmarshalInterface);
1630  IUnknown_Release(unk);
1631 
1632  hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1633  ok_ole_success(hr, IStream_Seek);
1634  hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown,
1635  &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1636  ok_ole_success(hr, IMarshal_MarshalInterface);
1637 
1638  hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1639  ok_ole_success(hr, IStream_Seek);
1640  hr = IMarshal_ReleaseMarshalData(marshal, stream);
1641  ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1642  IStream_Release(stream);
1643 
1644  IMarshal_Release(marshal);
1645 }
1647 {
1651 };
1652 
1653 /* helper for test_no_couninitialize_server */
1655 {
1656  struct ncu_params *ncu_params = p;
1657  HRESULT hr;
1658 
1659  pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1660 
1661  hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1663 
1665 
1666  ok( !WaitForSingleObject(ncu_params->unmarshal_event, 10000), "wait timed out\n" );
1667 
1668  /* die without calling CoUninitialize */
1669 
1670  return 0;
1671 }
1672 
1673 /* tests apartment that an apartment with a stub is released without deadlock
1674  * if the owning thread exits */
1676 {
1677  HRESULT hr;
1678  IStream *pStream = NULL;
1679  IUnknown *pProxy = NULL;
1680  DWORD tid;
1681  HANDLE thread;
1682  struct ncu_params ncu_params;
1683 
1684  cLocks = 0;
1686 
1689 
1690  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1692  ncu_params.stream = pStream;
1693 
1695 
1696  ok( !WaitForSingleObject(ncu_params.marshal_event, 10000), "wait timed out\n" );
1699 
1700  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1701  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1703  IStream_Release(pStream);
1704 
1707 
1709  ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1710 
1711  ok_no_locks();
1712 todo_wine {
1715 }
1716 
1720 
1721  IUnknown_Release(pProxy);
1722 
1723  ok_no_locks();
1724 }
1725 
1726 /* STA -> STA call during DLL_THREAD_DETACH */
1728 {
1729  struct ncu_params *ncu_params = p;
1730  HRESULT hr;
1731  IUnknown *pProxy = NULL;
1732 
1733  pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1734 
1735  hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
1737  IStream_Release(ncu_params->stream);
1738 
1740 
1741  /* die without calling CoUninitialize */
1742 
1743  return 0;
1744 }
1745 
1746 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1748 {
1749  HRESULT hr;
1750  IStream *pStream = NULL;
1751  DWORD tid;
1752  DWORD host_tid;
1753  HANDLE thread;
1754  HANDLE host_thread;
1755  struct ncu_params ncu_params;
1756 
1757  cLocks = 0;
1759 
1760  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1762  ncu_params.stream = pStream;
1763 
1764  /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1765  * always deadlock when called from within DllMain */
1766  host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1767  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1768 
1771 
1773 
1774  ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1776 
1777  ok_no_locks();
1780 
1781  end_host_object(host_tid, host_thread);
1782 }
1783 
1785 
1787 {
1788  IStream *stream;
1789  HRESULT hr;
1790 
1791  cLocks = 0;
1792 
1793  CoInitialize(NULL);
1794 
1797 
1798  hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1800 
1801  IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1802 
1805 
1806  ok_no_locks();
1807 
1808  hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1810 
1812 
1813  trace("CoUninitialize >>>\n");
1814  CoUninitialize();
1815  trace("CoUninitialize <<<\n");
1816 
1817  ok_no_locks();
1818 
1819  IStream_Release(stream);
1821  return 0;
1822 }
1823 
1824 static void test_crash_couninitialize(void)
1825 {
1826  HANDLE thread;
1827  DWORD tid;
1828 
1829  if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) {
1830  win_skip("Skipping crash tests on win2k.\n");
1831  return;
1832  }
1833 
1836  ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
1838  ok(crash_thread_success, "Crash thread failed\n");
1839 }
1840 
1841 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1843 {
1844  HRESULT hr;
1845  IStream *pStream = NULL;
1846  IUnknown *pProxy1 = NULL;
1847  IUnknown *pProxy2 = NULL;
1848  DWORD tid;
1849  HANDLE thread;
1850 
1851  cLocks = 0;
1853 
1854  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1856  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1857 
1860 
1861  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1862  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1864 
1867 
1868  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1869  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1871 
1873 
1874  IUnknown_Release(pProxy1);
1876  IUnknown_Release(pProxy2);
1879 
1880  /* When IExternalConnection is present COM's lifetime management
1881  * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1882  if (with_external_conn)
1883  {
1885  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1887  }
1888 
1889  /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1890  * weak has cLocks == 0, strong has cLocks > 0. */
1891  ok_no_locks();
1892 
1893  IStream_Release(pStream);
1895 }
1896 
1897 /* tests releasing after unmarshaling one object */
1899 {
1900  HRESULT hr;
1901  IStream *pStream = NULL;
1902  IUnknown *pProxy1 = NULL;
1903  IUnknown *pProxy2 = NULL;
1904  DWORD tid;
1905  HANDLE thread;
1906 
1907  cLocks = 0;
1909 
1910  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1912  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1913 
1916 
1917  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1918  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1920 
1923 
1924  /* release the remaining reference on the object by calling
1925  * CoReleaseMarshalData in the hosting thread */
1926  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1928 
1931 
1932  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1933  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1935  IStream_Release(pStream);
1936 
1939 
1940  IUnknown_Release(pProxy1);
1941 
1942  if (pProxy2)
1943  {
1945  IUnknown_Release(pProxy2);
1946  }
1947 
1948  /* this line is shows the difference between weak and strong table marshaling:
1949  * weak has cLocks == 0
1950  * strong has cLocks > 0 */
1951  ok_no_locks();
1954 
1956 }
1957 
1958 /* tests releasing after unmarshaling one object */
1960 {
1961  HRESULT hr;
1962  IStream *pStream = NULL;
1963  IUnknown *pProxy = NULL;
1964  DWORD tid;
1965  HANDLE thread;
1966 
1967  cLocks = 0;
1969 
1970  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1972  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1973 
1976 
1977  /* release the remaining reference on the object by calling
1978  * CoReleaseMarshalData in the hosting thread */
1979  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1981 
1982  ok_no_locks();
1983 
1984  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1985  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1986  todo_wine
1987  {
1988  ok(hr == CO_E_OBJNOTREG,
1989  "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1990  hr);
1991  }
1992  IStream_Release(pStream);
1993 
1994  ok_no_locks();
1996 
1998 }
1999 
2001 {
2006 };
2007 
2009 {
2010  HRESULT hr;
2011  struct duo_marshal_data *data = p;
2012  HANDLE hQuitEvent = data->hQuitEvent;
2013  MSG msg;
2014 
2015  pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2016 
2017  hr = CoMarshalInterface(data->pStream1, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags1);
2018  ok_ole_success(hr, "CoMarshalInterface");
2019 
2020  hr = CoMarshalInterface(data->pStream2, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags2);
2021  ok_ole_success(hr, "CoMarshalInterface");
2022 
2023  /* force the message queue to be created before signaling parent thread */
2025 
2026  SetEvent(data->hReadyEvent);
2027 
2029  {
2030  while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
2031  {
2032  if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
2033  {
2034  CoReleaseMarshalData(msg.wParam == 1 ? data->pStream1 : data->pStream2);
2035  SetEvent((HANDLE)msg.lParam);
2036  }
2037  else
2039  }
2040  }
2042 
2043  CoUninitialize();
2044 
2045  return 0;
2046 }
2047 
2048 /* tests interaction between table-weak and normal marshalling of an object */
2050 {
2051  HRESULT hr;
2052  IUnknown *pProxyWeak = NULL;
2053  IUnknown *pProxyNormal = NULL;
2054  DWORD tid;
2055  HANDLE thread;
2056  struct duo_marshal_data data;
2057 
2058  cLocks = 0;
2060 
2061  data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2062  data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2063  data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
2064  data.marshal_flags2 = MSHLFLAGS_NORMAL;
2065  hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
2067  hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
2069 
2071  ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
2072  CloseHandle(data.hReadyEvent);
2073 
2076 
2077  /* weak */
2078  IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2079  hr = CoUnmarshalInterface(data.pStream1, &IID_IClassFactory, (void **)&pProxyWeak);
2081 
2083 
2084  /* normal */
2085  IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
2086  hr = CoUnmarshalInterface(data.pStream2, &IID_IClassFactory, (void **)&pProxyNormal);
2088 
2090 
2091  IUnknown_Release(pProxyNormal);
2092 
2095 
2096  IUnknown_Release(pProxyWeak);
2097 
2100 
2101  /* When IExternalConnection is present COM's lifetime management
2102  * behaviour is altered; the remaining weak ref prevents stub shutdown. */
2103  if (with_external_conn)
2104  {
2106  IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2108  }
2109  ok_no_locks();
2110 
2111  IStream_Release(data.pStream1);
2112  IStream_Release(data.pStream2);
2113 
2114  SetEvent(data.hQuitEvent);
2115  ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2117 }
2118 
2120 {
2121  HRESULT hr;
2122  DWORD tid;
2123  HANDLE thread;
2124  struct duo_marshal_data data;
2125 
2126  cLocks = 0;
2128 
2129  data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2130  data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2131  data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
2132  data.marshal_flags2 = MSHLFLAGS_NORMAL;
2133  hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
2135  hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
2137 
2139  ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
2140  CloseHandle(data.hReadyEvent);
2141 
2144 
2145  /* release normal - which in the non-external conn case will free the object despite the weak ref. */
2146  IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
2148 
2151 
2152  if (with_external_conn)
2153  {
2155  IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2157  }
2158 
2159  ok_no_locks();
2160 
2161  IStream_Release(data.pStream1);
2162  IStream_Release(data.pStream2);
2163 
2164  SetEvent(data.hQuitEvent);
2165  ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2167 }
2168 
2170 {
2171  HRESULT hr;
2172  DWORD tid;
2173  HANDLE thread;
2174  struct duo_marshal_data data;
2175 
2176  cLocks = 0;
2178 
2179  data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2180  data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2181  data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
2182  data.marshal_flags2 = MSHLFLAGS_TABLEWEAK;
2183  hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
2185  hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
2187 
2189  ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
2190  CloseHandle(data.hReadyEvent);
2191 
2194 
2195  /* release one weak ref - the remaining weak ref will keep the obj alive */
2196  IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2198 
2200 
2201  IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
2203 
2204  ok_no_locks();
2205 
2206  IStream_Release(data.pStream1);
2207  IStream_Release(data.pStream2);
2208 
2209  SetEvent(data.hQuitEvent);
2210  ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2212 }
2213 
2214 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
2216 {
2217  HRESULT hr;
2218  IStream *pStream = NULL;
2219  IUnknown *pProxy1 = NULL;
2220  IUnknown *pProxy2 = NULL;
2221  DWORD tid;
2222  HANDLE thread;
2223 
2224  cLocks = 0;
2226 
2227  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2229  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
2230 
2233 
2234  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2235  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
2237 
2239 
2240  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2241  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
2243 
2245 
2246  if (pProxy1) IUnknown_Release(pProxy1);
2247  if (pProxy2) IUnknown_Release(pProxy2);
2248 
2249  /* this line is shows the difference between weak and strong table marshaling:
2250  * weak has cLocks == 0
2251  * strong has cLocks > 0 */
2253 
2254  /* release the remaining reference on the object by calling
2255  * CoReleaseMarshalData in the hosting thread */
2256  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2258  IStream_Release(pStream);
2259 
2260  ok_no_locks();
2263 
2265 }
2266 
2267 /* tests CoLockObjectExternal */
2268 static void test_lock_object_external(void)
2269 {
2270  HRESULT hr;
2271  IStream *pStream = NULL;
2272 
2273  cLocks = 0;
2275 
2276  /* test the stub manager creation aspect of CoLockObjectExternal when the
2277  * object hasn't been marshaled yet */
2279 
2282 
2284 
2285  ok_no_locks();
2288 
2289  /* test our empty stub manager being handled correctly in
2290  * CoMarshalInterface */
2292 
2293  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2295  hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2297 
2299 
2302 
2303  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2304  hr = CoReleaseMarshalData(pStream);
2306  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2307 
2311 
2313 
2317 
2319 
2320  ok_no_locks();
2323 
2324  /* test CoLockObjectExternal releases reference to object with
2325  * fLastUnlockReleases as TRUE and there are only strong references on
2326  * the object */
2328 
2331 
2333 
2334  ok_no_locks();
2337 
2338  /* test CoLockObjectExternal doesn't release the last reference to an
2339  * object with fLastUnlockReleases as TRUE and there is a weak reference
2340  * on the object */
2341  hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
2343 
2346 
2348 
2351 
2353 
2357 
2359 
2360  ok_no_locks();
2361 
2362  IStream_Release(pStream);
2363 }
2364 
2365 /* tests disconnecting stubs */
2366 static void test_disconnect_stub(void)
2367 {
2368  HRESULT hr;
2369  IStream *pStream = NULL;
2370 
2371  cLocks = 0;
2373 
2374  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2376  hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2378 
2380 
2382 
2385 
2386  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2387  hr = CoReleaseMarshalData(pStream);
2389  IStream_Release(pStream);
2390 
2393 
2395 
2396  ok_no_locks();
2398 
2399  hr = CoDisconnectObject(NULL, 0);
2400  ok( hr == E_INVALIDARG, "wrong status %x\n", hr );
2401 }
2402 
2403 /* tests failure case of a same-thread marshal and unmarshal twice */
2405 {
2406  HRESULT hr;
2407  IStream *pStream = NULL;
2408  IUnknown *pProxy1 = NULL;
2409  IUnknown *pProxy2 = NULL;
2410 
2411  cLocks = 0;
2413 
2414  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2416  hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2418 
2421 
2422  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2423  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
2425 
2429 
2430  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2431  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
2433  "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
2434 
2435  IStream_Release(pStream);
2436 
2438 
2439  IUnknown_Release(pProxy1);
2440 
2441  ok_no_locks();
2442 }
2443 
2444 /* tests success case of marshaling and unmarshaling an HRESULT */
2445 static void test_hresult_marshaling(void)
2446 {
2447  HRESULT hr;
2448  HRESULT hr_marshaled = 0;
2449  IStream *pStream = NULL;
2450  static const HRESULT E_DEADBEEF = 0xdeadbeef;
2451 
2452  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2454 
2455  hr = CoMarshalHresult(pStream, E_DEADBEEF);
2457 
2458  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2459  hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
2460  ok_ole_success(hr, IStream_Read);
2461 
2462  ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
2463 
2464  hr_marshaled = 0;
2465  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2466  hr = CoUnmarshalHresult(pStream, &hr_marshaled);
2468 
2469  ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
2470 
2471  IStream_Release(pStream);
2472 }
2473 
2474 
2475 /* helper for test_proxy_used_in_wrong_thread */
2477 {
2478  IClassFactory * cf = p;
2479  HRESULT hr;
2480  IUnknown * proxy = NULL;
2481 
2482  hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2483  todo_wine
2485  "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
2486  hr);
2487 
2488  hr = IClassFactory_QueryInterface(cf, &IID_IMultiQI, (LPVOID *)&proxy);
2489  /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
2490  trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr);
2491  if (SUCCEEDED(hr))
2492  IUnknown_Release(proxy);
2493 
2494  hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
2495  /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2496  trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr);
2497  if (SUCCEEDED(hr))
2498  IUnknown_Release(proxy);
2499 
2500  pCoInitializeEx(NULL, COINIT_MULTITHREADED);
2501 
2502  hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2503  if (proxy) IUnknown_Release(proxy);
2505  "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
2506  hr);
2507 
2508  hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
2509  /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2510  trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr);
2511 
2512  /* now be really bad and release the proxy from the wrong apartment */
2513  IClassFactory_Release(cf);
2514 
2515  CoUninitialize();
2516 
2517  return 0;
2518 }
2519 
2520 /* tests failure case of a using a proxy in the wrong apartment */
2522 {
2523  HRESULT hr;
2524  IStream *pStream = NULL;
2525  IUnknown *pProxy = NULL;
2526  DWORD tid, tid2;
2527  HANDLE thread;
2528  HANDLE host_thread;
2529 
2530  cLocks = 0;
2531 
2532  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2534  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
2535 
2537 
2538  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2539  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
2541  IStream_Release(pStream);
2542 
2544 
2545  /* do a call that will fail, but result in IRemUnknown being used by the proxy */
2546  IUnknown_QueryInterface(pProxy, &IID_IStream, (LPVOID *)&pStream);
2547 
2548  /* create a thread that we can misbehave in */
2549  thread = CreateThread(NULL, 0, bad_thread_proc, pProxy, 0, &tid2);
2550 
2551  ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2553 
2554  /* do release statement on Win9x that we should have done above */
2555  if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
2556  IUnknown_Release(pProxy);
2557 
2558  ok_no_locks();
2559 
2560  end_host_object(tid, host_thread);
2561 }
2562 
2564 {
2565  if (ppvObj == NULL) return E_POINTER;
2566 
2567  if (IsEqualGUID(riid, &IID_IUnknown) ||
2569  {
2570  *ppvObj = iface;
2571  IMessageFilter_AddRef(iface);
2572  return S_OK;
2573  }
2574 
2575  return E_NOINTERFACE;
2576 }
2577 
2579 {
2580  return 2; /* non-heap object */
2581 }
2582 
2584 {
2585  return 1; /* non-heap object */
2586 }
2587 
2589  IMessageFilter *iface,
2590  DWORD dwCallType,
2591  HTASK threadIDCaller,
2592  DWORD dwTickCount,
2593  LPINTERFACEINFO lpInterfaceInfo)
2594 {
2595  static int callcount = 0;
2596  DWORD ret;
2597  trace("HandleInComingCall\n");
2598  switch (callcount)
2599  {
2600  case 0:
2601  ret = SERVERCALL_REJECTED;
2602  break;
2603  case 1:
2604  ret = SERVERCALL_RETRYLATER;
2605  break;
2606  default:
2607  ret = SERVERCALL_ISHANDLED;
2608  break;
2609  }
2610  callcount++;
2611  return ret;
2612 }
2613 
2615  IMessageFilter *iface,
2616  HTASK threadIDCallee,
2617  DWORD dwTickCount,
2618  DWORD dwRejectType)
2619 {
2620  trace("RetryRejectedCall\n");
2621  return 0;
2622 }
2623 
2625  IMessageFilter *iface,
2626  HTASK threadIDCallee,
2627  DWORD dwTickCount,
2628  DWORD dwPendingType)
2629 {
2630  trace("MessagePending\n");
2631  return PENDINGMSG_WAITNOPROCESS;
2632 }
2633 
2634 static const IMessageFilterVtbl MessageFilter_Vtbl =
2635 {
2642 };
2643 
2645 
2646 static void test_message_filter(void)
2647 {
2648  HRESULT hr;
2649  IClassFactory *cf = NULL;
2650  DWORD tid;
2651  IUnknown *proxy = NULL;
2652  IMessageFilter *prev_filter = NULL;
2653  HANDLE thread;
2654 
2655  struct host_object_data object_data = { NULL, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory,
2656  MSHLFLAGS_NORMAL, &MessageFilter };
2657 
2658  cLocks = 0;
2659 
2660  hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream);
2662  tid = start_host_object2(&object_data, &thread);
2663 
2665 
2666  IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL);
2667  hr = CoUnmarshalInterface(object_data.stream, &IID_IClassFactory, (void **)&cf);
2669  IStream_Release(object_data.stream);
2670 
2672 
2673  hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2674  ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr);
2675  if (proxy) IUnknown_Release(proxy);
2676  proxy = NULL;
2677 
2678  hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
2680 
2681  hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2682  ok_ole_success(hr, IClassFactory_CreateInstance);
2683 
2684  IUnknown_Release(proxy);
2685 
2686  IClassFactory_Release(cf);
2687 
2688  ok_no_locks();
2689 
2691 
2692  hr = CoRegisterMessageFilter(prev_filter, NULL);
2694 }
2695 
2696 /* test failure case of trying to unmarshal from bad stream */
2697 static void test_bad_marshal_stream(void)
2698 {
2699  HRESULT hr;
2700  IStream *pStream = NULL;
2701 
2702  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2704  hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2706 
2708 
2709  /* try to read beyond end of stream */
2710  hr = CoReleaseMarshalData(pStream);
2711  ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
2712 
2713  /* now release for real */
2714  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2715  hr = CoReleaseMarshalData(pStream);
2717 
2718  IStream_Release(pStream);
2719 }
2720 
2721 /* tests that proxies implement certain interfaces */
2722 static void test_proxy_interfaces(void)
2723 {
2724  HRESULT hr;
2725  IStream *pStream = NULL;
2726  IUnknown *pProxy = NULL;
2727  IUnknown *pOtherUnknown = NULL;
2728  DWORD tid;
2729  HANDLE thread;
2730 
2731  cLocks = 0;
2732 
2733  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2735  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2736 
2738 
2739  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2740  hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
2742  IStream_Release(pStream);
2743 
2745 
2746  hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
2747  ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
2748  if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2749 
2750  hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
2751  ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity);
2752  if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2753 
2754  hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
2755  ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
2756  if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2757 
2758  hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
2759  ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
2760  if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2761 
2762  /* IMarshal2 is also supported on NT-based systems, but is pretty much
2763  * useless as it has no more methods over IMarshal that it inherits from. */
2764 
2765  IUnknown_Release(pProxy);
2766 
2767  ok_no_locks();
2768 
2770 }
2771 
2772 typedef struct
2773 {
2776 } HeapUnknown;
2777 
2779 {
2780  return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
2781 }
2782 
2784 {
2785  if (IsEqualIID(riid, &IID_IUnknown))
2786  {
2787  IUnknown_AddRef(iface);
2788  *ppv = iface;
2789  return S_OK;
2790  }
2791  *ppv = NULL;
2792  return E_NOINTERFACE;
2793 }
2794 
2796 {
2798  return InterlockedIncrement((LONG*)&This->refs);
2799 }
2800 
2802 {
2804  ULONG refs = InterlockedDecrement((LONG*)&This->refs);
2805  if (!refs) HeapFree(GetProcessHeap(), 0, This);
2806  return refs;
2807 }
2808 
2809 static const IUnknownVtbl HeapUnknown_Vtbl =
2810 {
2814 };
2815 
2817 {
2818  HRESULT hr;
2819  IPSFactoryBuffer *psfb;
2821  LPVOID lpvtbl;
2822  ULONG refs;
2823  CLSID clsid;
2824  HeapUnknown *pUnkOuter = HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
2825 
2826  pUnkOuter->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
2827  pUnkOuter->refs = 1;
2828 
2829  hr = CoGetPSClsid(riid, &clsid);
2831 
2832  hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
2834 
2835  hr = IPSFactoryBuffer_CreateProxy(psfb, &pUnkOuter->IUnknown_iface, riid, &proxy, &lpvtbl);
2836  ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
2837  ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2838 
2839  /* release our reference to the outer unknown object - the PS factory
2840  * buffer will have AddRef's it in the CreateProxy call */
2841  refs = IUnknown_Release(&pUnkOuter->IUnknown_iface);
2842  ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
2843 
2844  /* Not checking return, unreliable on native. Maybe it leaks references? */
2845  IPSFactoryBuffer_Release(psfb);
2846 
2847  refs = IUnknown_Release((IUnknown *)lpvtbl);
2848  ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2849 
2850  refs = IRpcProxyBuffer_Release(proxy);
2851  ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2852 }
2853 
2855 {
2856  HRESULT hr;
2857  IPSFactoryBuffer *psfb;
2859  ULONG refs;
2860  CLSID clsid;
2861 
2862  cLocks = 0;
2863 
2864  hr = CoGetPSClsid(riid, &clsid);
2866 
2867  hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
2869 
2870  hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
2871  ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
2872 
2873  /* Not checking return, unreliable on native. Maybe it leaks references? */
2874  IPSFactoryBuffer_Release(psfb);
2875 
2877 
2878  IRpcStubBuffer_Disconnect(stub);
2879 
2880  ok_no_locks();
2881 
2882  refs = IRpcStubBuffer_Release(stub);
2883  ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2884 }
2885 
2887 
2889  LPCLASSFACTORY iface,
2890  LPUNKNOWN pUnkOuter,
2891  REFIID riid,
2892  LPVOID *ppvObj)
2893 {
2894  DWORD_PTR res;
2895  if (IsEqualIID(riid, &IID_IWineTest))
2896  {
2898  ok(ret, "Timed out sending a message to originating window during RPC call\n");
2899  }
2900  *ppvObj = NULL;
2901  return S_FALSE;
2902 }
2903 
2904 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
2905 {
2911 };
2912 
2914 
2916 {
2917  switch (msg)
2918  {
2919  case WM_USER:
2920  {
2921  HRESULT hr;
2922  IStream *pStream = NULL;
2924  IUnknown *object;
2925  DWORD tid;
2926  HANDLE thread;
2927 
2928  cLocks = 0;
2929 
2930  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2932  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2933 
2935 
2936  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2937  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2939  IStream_Release(pStream);
2940 
2942 
2943  /* note the use of the magic IID_IWineTest value to tell remote thread
2944  * to try to send a message back to us */
2945  hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
2946  ok(hr == S_FALSE, "expected S_FALSE, got %d\n", hr);
2947 
2948  IClassFactory_Release(proxy);
2949 
2950  ok_no_locks();
2951 
2953 
2954  PostMessageA(hwnd, WM_QUIT, 0, 0);
2955 
2956  return 0;
2957  }
2958  case WM_USER+1:
2959  {
2960  HRESULT hr;
2961  IStream *pStream = NULL;
2963  IUnknown *object;
2964  DWORD tid;
2965  HANDLE thread;
2966 
2967  cLocks = 0;
2968 
2969  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2971  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2972 
2974 
2975  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2976  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2978  IStream_Release(pStream);
2979 
2981 
2982  /* post quit message before a doing a COM call to show that a pending
2983  * WM_QUIT message doesn't stop the call from succeeding */
2984  PostMessageA(hwnd, WM_QUIT, 0, 0);
2985  hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
2986  ok(hr == S_FALSE, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr);
2987 
2988  IClassFactory_Release(proxy);
2989 
2990  ok_no_locks();
2991 
2993 
2994  return 0;
2995  }
2996  case WM_USER+2:
2997  {
2998  HRESULT hr;
2999  IStream *pStream = NULL;
3001  IUnknown *object;
3002  DWORD tid;
3003  HANDLE thread;
3004 
3005  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3007  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
3008 
3009  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3010  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
3012  IStream_Release(pStream);
3013 
3014  /* shows that COM calls executed during the processing of sent
3015  * messages should fail */
3016  hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
3018  "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr);
3019 
3020  IClassFactory_Release(proxy);
3021 
3023 
3024  PostQuitMessage(0);
3025 
3026  return 0;
3027  }
3028  default:
3029  return DefWindowProcA(hwnd, msg, wparam, lparam);
3030  }
3031 }
3032 
3033 static void register_test_window(void)
3034 {
3035  WNDCLASSA wndclass;
3036 
3037  memset(&wndclass, 0, sizeof(wndclass));
3038  wndclass.lpfnWndProc = window_proc;
3039  wndclass.lpszClassName = "WineCOMTest";
3040  RegisterClassA(&wndclass);
3041 }
3042 
3043 static void test_message_reentrancy(void)
3044 {
3045  MSG msg;
3046 
3048  ok(hwnd_app != NULL, "Window creation failed\n");
3049 
3050  /* start message re-entrancy test */
3051  PostMessageA(hwnd_app, WM_USER, 0, 0);
3052 
3053  while (GetMessageA(&msg, NULL, 0, 0))
3054  {
3057  }
3059 }
3060 
3062  LPCLASSFACTORY iface,
3063  LPUNKNOWN pUnkOuter,
3064  REFIID riid,
3065  LPVOID *ppvObj)
3066 {
3067  *ppvObj = NULL;
3068  SendMessageA(hwnd_app, WM_USER+2, 0, 0);
3069  return S_OK;
3070 }
3071 
3072 static IClassFactoryVtbl TestMsgClassFactory_Vtbl =
3073 {
3079 };
3080 
3082 
3083 static void test_call_from_message(void)
3084 {
3085  MSG msg;
3086  IStream *pStream;
3087  HRESULT hr;
3089  DWORD tid;
3090  HANDLE thread;
3091  IUnknown *object;
3092 
3094  ok(hwnd_app != NULL, "Window creation failed\n");
3095 
3096  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3098  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread);
3099 
3101 
3102  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3103  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
3105  IStream_Release(pStream);
3106 
3108 
3109  /* start message re-entrancy test */
3110  hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
3111  ok_ole_success(hr, IClassFactory_CreateInstance);
3112 
3113  IClassFactory_Release(proxy);
3114 
3115  ok_no_locks();
3116 
3118 
3119  while (GetMessageA(&msg, NULL, 0, 0))
3120  {
3123  }
3125 }
3126 
3127 static void test_WM_QUIT_handling(void)
3128 {
3129  MSG msg;
3130 
3132  ok(hwnd_app != NULL, "Window creation failed\n");
3133 
3134  /* start WM_QUIT handling test */
3135  PostMessageA(hwnd_app, WM_USER+1, 0, 0);
3136 
3137  while (GetMessageA(&msg, NULL, 0, 0))
3138  {
3141  }
3142 }
3143 
3145 {
3146  static SIZE_T global_size_alignment = -1;
3147  if (global_size_alignment == -1)
3148  {
3149  void *p = GlobalAlloc(GMEM_FIXED, 1);
3150  global_size_alignment = GlobalSize(p);
3151  GlobalFree(p);
3152  }
3153 
3154  return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
3155 }
3156 
3157 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
3158 {
3159  HGLOBAL hglobal;
3160  DWORD size;
3161  char *marshal_data;
3162  HRESULT hr;
3163 
3164  hr = GetHGlobalFromStream(pStream, &hglobal);
3166 
3167  size = GlobalSize(hglobal);
3168 
3169  marshal_data = GlobalLock(hglobal);
3170 
3171  if (mshctx == MSHCTX_INPROC)
3172  {
3173  DWORD expected_size = round_global_size(3*sizeof(DWORD) + sizeof(GUID));
3174  ok(size == expected_size ||
3175  broken(size == (2*sizeof(DWORD))) /* Win9x & NT4 */,
3176  "size should have been %d instead of %d\n", expected_size, size);
3177 
3178  ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
3179  marshal_data += sizeof(DWORD);
3180  ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
3181  marshal_data += sizeof(void *);
3182  if (sizeof(void*) == 4 && size >= 3*sizeof(DWORD))
3183  {
3184  ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
3185  marshal_data += sizeof(DWORD);
3186  }
3187  if (size >= 3*sizeof(DWORD) + sizeof(GUID))
3188  {
3189  trace("got guid data: %s\n", wine_dbgstr_guid((GUID *)marshal_data));
3190  }
3191  }
3192  else
3193  {
3194  ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
3195  ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
3196  "marshal data should be filled by standard marshal and start with MEOW signature\n");
3197  }
3198 
3199  GlobalUnlock(hglobal);
3200 }
3201 
3203 {
3204  HRESULT hr;
3205  IUnknown *pFTUnknown;
3206  IMarshal *pFTMarshal;
3207  IStream *pStream;
3208  IUnknown *pProxy;
3209  static const LARGE_INTEGER llZero;
3210  CLSID clsid;
3211 
3212  cLocks = 0;
3213  hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
3215  hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
3216  ok_ole_success(hr, IUnknown_QueryInterface);
3217  IUnknown_Release(pFTUnknown);
3218 
3219  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3221 
3222  /* inproc normal marshaling */
3223 
3224  hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory,
3225  &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid);
3226  ok_ole_success(hr, IMarshal_GetUnmarshalClass);
3227  ok(IsEqualIID(&clsid, &CLSID_InProcFreeMarshaler), "clsid = %s\n",
3229 
3230  hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3231  &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3232  ok_ole_success(hr, IMarshal_MarshalInterface);
3233 
3235 
3236  test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
3237 
3238  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3239  hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3240  ok_ole_success(hr, IMarshal_UnmarshalInterface);
3241 
3242  IUnknown_Release(pProxy);
3243 
3244  ok_no_locks();
3245 
3246  /* inproc table-strong marshaling */
3247 
3248  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3249  hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3250  (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
3251  MSHLFLAGS_TABLESTRONG);
3252  ok_ole_success(hr, IMarshal_MarshalInterface);
3253 
3255 
3256  test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
3257 
3258  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3259  hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3260  ok_ole_success(hr, IMarshal_UnmarshalInterface);
3261 
3262  IUnknown_Release(pProxy);
3263 
3265 
3266  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3267  hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
3268  ok_ole_success(hr, IMarshal_ReleaseMarshalData);
3269 
3270  ok_no_locks();
3271 
3272  /* inproc table-weak marshaling */
3273 
3274  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3275  hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3276  (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
3277  MSHLFLAGS_TABLEWEAK);
3278  ok_ole_success(hr, IMarshal_MarshalInterface);
3279 
3280  ok_no_locks();
3281 
3282  test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
3283 
3284  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3285  hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3286  ok_ole_success(hr, IMarshal_UnmarshalInterface);
3287 
3289 
3290  IUnknown_Release(pProxy);
3291 
3292  ok_no_locks();
3293 
3294  /* inproc normal marshaling (for extraordinary cases) */
3295 
3296  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3297  hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3298  &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3299  ok_ole_success(hr, IMarshal_MarshalInterface);
3300 
3302 
3303  /* this call shows that DisconnectObject does nothing */
3304  hr = IMarshal_DisconnectObject(pFTMarshal, 0);
3305  ok_ole_success(hr, IMarshal_DisconnectObject);
3306 
3308 
3309  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3310  hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
3311  ok_ole_success(hr, IMarshal_ReleaseMarshalData);
3312 
3313  ok_no_locks();
3314 
3315  /* doesn't enforce marshaling rules here and allows us to unmarshal the
3316  * interface, even though it was freed above */
3317  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3318  hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3319  ok_ole_success(hr, IMarshal_UnmarshalInterface);
3320 
3321  ok_no_locks();
3322 
3323  /* local normal marshaling */
3324 
3325  hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory,
3326  &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL, &clsid);
3327  ok_ole_success(hr, IMarshal_GetUnmarshalClass);
3328  ok(IsEqualIID(&clsid, &CLSID_StdMarshal), "clsid = %s\n",
3330 
3331  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3332  hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
3333  ok_ole_success(hr, IMarshal_MarshalInterface);
3334 
3336 
3337  test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
3338 
3339  IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3340  hr = CoReleaseMarshalData(pStream);
3342 
3343  ok_no_locks();
3344 
3345  IStream_Release(pStream);
3346  IMarshal_Release(pFTMarshal);
3347 }
3348 
3350 {
3351  HRESULT hr;
3352  char buffer[256];
3353  LPOLESTR pszClsid;
3354  HKEY hkey;
3355  DWORD dwDisposition;
3356  DWORD error;
3357 
3358  hr = StringFromCLSID(&CLSID_WineTest, &pszClsid);
3359  ok_ole_success(hr, "StringFromCLSID");
3360  strcpy(buffer, "CLSID\\");
3361  WideCharToMultiByte(CP_ACP, 0, pszClsid, -1, buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), NULL, NULL);
3362  CoTaskMemFree(pszClsid);
3363  strcat(buffer, "\\InprocHandler32");
3364  if (Register)
3365  {
3366  error = RegCreateKeyExA(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition);
3367  if (error == ERROR_ACCESS_DENIED)
3368  {
3369  skip("Not authorized to modify the Classes key\n");
3370  return E_FAIL;
3371  }
3372  ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error);
3373  if (error != ERROR_SUCCESS) hr = E_FAIL;
3374  error = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
3375  ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error);
3376  if (error != ERROR_SUCCESS) hr = E_FAIL;
3377  RegCloseKey(hkey);
3378  }
3379  else
3380  {
3382  *strrchr(buffer, '\\') = '\0';
3384  }
3385  return hr;
3386 }
3387 
3388 static void test_inproc_handler(void)
3389 {
3390  HRESULT hr;
3391  IUnknown *pObject;
3392  IUnknown *pObject2;
3393 
3395  return;
3396 
3397  hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pObject);
3398  ok_ole_success(hr, "CoCreateInstance");
3399 
3400  if (SUCCEEDED(hr))
3401  {
3402  hr = IUnknown_QueryInterface(pObject, &IID_IWineTest, (void **)&pObject2);
3403  ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr);
3404 
3405  /* it's a handler as it supports IOleObject */
3406  hr = IUnknown_QueryInterface(pObject, &IID_IOleObject, (void **)&pObject2);
3407  ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
3408  IUnknown_Release(pObject2);
3409 
3410  IUnknown_Release(pObject);
3411  }
3412 
3414 }
3415 
3417  IStdMarshalInfo *iface,
3418  REFIID riid,
3419  LPVOID *ppvObj)
3420 {
3421  if (ppvObj == NULL) return E_POINTER;
3422 
3423  if (IsEqualGUID(riid, &IID_IUnknown) ||
3424  IsEqualGUID(riid, &IID_IStdMarshalInfo))
3425  {
3426  *ppvObj = iface;
3427  IStdMarshalInfo_AddRef(iface);
3428  return S_OK;
3429  }
3430 
3431  return E_NOINTERFACE;
3432 }
3433 
3435 {
3436  LockModule();
3437  return 2; /* non-heap-based object */
3438 }
3439 
3441 {
3442  UnlockModule();
3443  return 1; /* non-heap-based object */
3444 }
3445 
3447  IStdMarshalInfo *iface,
3448  DWORD dwDestContext,
3449  void *pvDestContext,
3450  CLSID *pClsid)
3451 {
3452  *pClsid = CLSID_WineTest;
3453  return S_OK;
3454 }
3455 
3456 static const IStdMarshalInfoVtbl Test_SMI_Vtbl =
3457 {
3462 };
3463 
3465 
3466 static void test_handler_marshaling(void)
3467 {
3468  HRESULT hr;
3469  IStream *pStream = NULL;
3470  IUnknown *pProxy = NULL;
3471  IUnknown *pObject;
3472  DWORD tid;
3473  HANDLE thread;
3474  static const LARGE_INTEGER ullZero;
3475 
3477  return;
3478  cLocks = 0;
3479 
3480  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3481  ok_ole_success(hr, "CreateStreamOnHGlobal");
3482  tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_SMI, MSHLFLAGS_NORMAL, &thread);
3483 
3485 
3486  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3487  hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
3488  ok_ole_success(hr, "CoUnmarshalInterface");
3489  IStream_Release(pStream);
3490 
3491  if(hr == S_OK)
3492  {
3494 
3495  hr = IUnknown_QueryInterface(pProxy, &IID_IWineTest, (void **)&pObject);
3496  ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3497 
3498  /* it's a handler as it supports IOleObject */
3499  hr = IUnknown_QueryInterface(pProxy, &IID_IOleObject, (void **)&pObject);
3500  todo_wine
3501  ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
3502  if (SUCCEEDED(hr)) IUnknown_Release(pObject);
3503 
3504  IUnknown_Release(pProxy);
3505 
3506  ok_no_locks();
3507  }
3508 
3511 
3512  /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
3513 }
3514 
3515 
3516 static void test_client_security(void)
3517 {
3518  HRESULT hr;
3519  IStream *pStream = NULL;
3520  IClassFactory *pProxy = NULL;
3521  IUnknown *pProxy2 = NULL;
3522  IUnknown *pUnknown1 = NULL;
3523  IUnknown *pUnknown2 = NULL;
3524  IClientSecurity *pCliSec = NULL;
3525  IMarshal *pMarshal;
3526  DWORD tid;
3527  HANDLE thread;
3528  static const LARGE_INTEGER ullZero;
3529  DWORD dwAuthnSvc;
3530  DWORD dwAuthzSvc;
3531  OLECHAR *pServerPrincName;
3532  DWORD dwAuthnLevel;
3533  DWORD dwImpLevel;
3534  void *pAuthInfo;
3535  DWORD dwCapabilities;
3536  void *pv;
3537 
3538  cLocks = 0;
3539 
3540  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3541  ok_ole_success(hr, "CreateStreamOnHGlobal");
3542  tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
3543 
3544  IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3545  hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
3546  ok_ole_success(hr, "CoUnmarshalInterface");
3547  IStream_Release(pStream);
3548 
3549  hr = IClassFactory_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pUnknown1);
3550  ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
3551 
3552  hr = IClassFactory_QueryInterface(pProxy, &IID_IRemUnknown, (LPVOID*)&pProxy2);
3553  ok_ole_success(hr, "IUnknown_QueryInterface IID_IStream");
3554 
3555  hr = IUnknown_QueryInterface(pProxy2, &IID_IUnknown, (LPVOID*)&pUnknown2);
3556  ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
3557 
3558  ok(pUnknown1 == pUnknown2, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1, pUnknown2);
3559 
3560  hr = IClassFactory_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pMarshal);
3561  ok_ole_success(hr, "IUnknown_QueryInterface IID_IMarshal");
3562 
3563  hr = IClassFactory_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pCliSec);
3564  ok_ole_success(hr, "IUnknown_QueryInterface IID_IClientSecurity");
3565 
3566  hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3567  todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket (all NULLs)");
3568 
3569  hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pMarshal, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3570  todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3571 
3572  hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
3573  todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket");
3574 
3575  hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthInfo, dwCapabilities);
3576  todo_wine ok_ole_success(hr, "IClientSecurity_SetBlanket");
3577 
3578  hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IWineTest, &pv);
3579  ok(hr == E_NOINTERFACE, "COM call should have succeeded instead of returning 0x%08x\n", hr);
3580 
3581  hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pMarshal, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
3582  todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3583 
3584  hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, 0xdeadbeef, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
3585  todo_wine ok(hr == E_INVALIDARG, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3586 
3587  CoTaskMemFree(pServerPrincName);
3588 
3589  hr = IClientSecurity_QueryBlanket(pCliSec, pUnknown1, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
3590  todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket(IUnknown)");
3591 
3592  CoTaskMemFree(pServerPrincName);
3593 
3594  IClassFactory_Release(pProxy);
3595  IUnknown_Release(pProxy2);
3596  IUnknown_Release(pUnknown1);
3597  IUnknown_Release(pUnknown2);
3598  IMarshal_Release(pMarshal);
3599  IClientSecurity_Release(pCliSec);
3600 
3602 }
3603 
3605 
3606 static void LockModuleOOP(void)
3607 {
3608  InterlockedIncrement(&cLocks); /* for test purposes only */
3610 }
3611 
3612 static void UnlockModuleOOP(void)
3613 {
3614  InterlockedDecrement(&cLocks); /* for test purposes only */
3615  if (!CoReleaseServerProcess())
3617 }
3618 
3619 static HWND hwnd_app;
3620 
3622 {
3623  IPersist IPersist_iface; /* a nice short interface */
3624 };
3625 
3627 {
3628  *obj = NULL;
3629 
3630  if (IsEqualGUID(iid, &IID_IUnknown) ||
3631  IsEqualGUID(iid, &IID_IPersist))
3632  *obj = iface;
3633 
3634  if (*obj)
3635  {
3636  IPersist_AddRef(iface);
3637  return S_OK;
3638  }
3639  return E_NOINTERFACE;
3640 }
3641 
3643 {
3644  return 2;
3645 }
3646 
3648 {
3649  return 1;
3650 }
3651 
3653 {
3654  HRESULT hr;
3655 
3656  *clsid = IID_IUnknown;
3657 
3658  /* Test calling CoDisconnectObject within a COM call */
3659  hr = CoDisconnectObject((IUnknown *)iface, 0);
3660  ok(hr == S_OK, "got %08x\n", hr);
3661 
3662  /* Initialize and uninitialize the apartment to show that we
3663  * remain in the autojoined mta */
3664  hr = pCoInitializeEx( NULL, COINIT_MULTITHREADED );
3665  ok( hr == S_FALSE, "got %08x\n", hr );
3666  CoUninitialize();
3667 
3668  return S_OK;
3669 }
3670 
3671 static const IPersistVtbl local_server_persist_vtbl =
3672 {
3677 };
3678 
3680 {
3682 };
3683 
3685  LPCLASSFACTORY iface,
3686  REFIID riid,
3687  LPVOID *ppvObj)
3688 {
3689  if (ppvObj == NULL) return E_POINTER;
3690 
3691  if (IsEqualGUID(riid, &IID_IUnknown) ||
3693  {
3694  *ppvObj = iface;
3695  IClassFactory_AddRef(iface);
3696  return S_OK;
3697  }
3698 
3699  return E_NOINTERFACE;
3700 }
3701 
3702 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
3703 {
3704  return 2; /* non-heap-based object */
3705 }
3706 
3707 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
3708 {
3709  return 1; /* non-heap-based object */
3710 }
3711 
3713  LPCLASSFACTORY iface,
3714  LPUNKNOWN pUnkOuter,
3715  REFIID riid,
3716  LPVOID *ppvObj)
3717 {
3718  IPersist *persist = &local_server_class.IPersist_iface;
3719  HRESULT hr;
3720  IPersist_AddRef( persist );
3721  hr = IPersist_QueryInterface( persist, riid, ppvObj );
3722  IPersist_Release( persist );
3723  return hr;
3724 }
3725 
3727  LPCLASSFACTORY iface,
3728  BOOL fLock)
3729 {
3730  if (fLock)
3731  LockModuleOOP();
3732  else
3733  UnlockModuleOOP();
3734  return S_OK;
3735 }
3736 
3737 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
3738 {
3744 };
3745 
3747 
3749 {
3750  DWORD cookie;
3751  HRESULT hr;
3752  HANDLE ready_event;
3753  DWORD wait;
3754  HANDLE handles[2];
3755 
3757  ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
3758  handles[0] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
3759  handles[1] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event");
3760 
3761 again:
3763  CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
3765 
3766  SetEvent(ready_event);
3767 
3768  do
3769  {
3770  wait = MsgWaitForMultipleObjects(2, handles, FALSE, 30000, QS_ALLINPUT);
3771  if (wait == WAIT_OBJECT_0+2)
3772  {
3773  MSG msg;
3774 
3775  if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
3776  {
3777  trace("Message 0x%x\n", msg.message);
3780  }
3781  }
3782  else if (wait == WAIT_OBJECT_0+1)
3783  {
3784  hr = CoRevokeClassObject(cookie);
3786  goto again;
3787  }
3788  }
3789  while (wait == WAIT_OBJECT_0+2);
3790 
3791  ok( wait == WAIT_OBJECT_0, "quit event wait timed out\n" );
3792  hr = CoRevokeClassObject(cookie);
3794  CloseHandle(handles[0]);
3795  CloseHandle(handles[1]);
3796 }
3797 
3798 static HANDLE create_target_process(const char *arg)
3799 {
3800  char **argv;
3801  char cmdline[MAX_PATH];
3802  BOOL ret;
3804  STARTUPINFOA si = { 0 };
3805  si.cb = sizeof(si);
3806 
3807  pi.hThread = NULL;
3808  pi.hProcess = NULL;
3810  sprintf(cmdline, "\"%s\" %s %s", argv[0], argv[1], arg);
3811  ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
3812  ok(ret, "CreateProcess failed with error: %u\n", GetLastError());
3813  if (pi.hThread) CloseHandle(pi.hThread);
3814  return pi.hProcess;
3815 }
3816 
3817 /* tests functions commonly used by out of process COM servers */
3818 static void test_local_server(void)
3819 {
3820  DWORD cookie;
3821  HRESULT hr;
3822  IClassFactory * cf;
3823  IPersist *persist;
3824  DWORD ret;
3825  HANDLE process;
3826  HANDLE quit_event;
3827  HANDLE ready_event;
3828  HANDLE repeat_event;
3829  CLSID clsid;
3830 
3832 
3833  cLocks = 0;
3834 
3835  /* Start the object suspended */
3837  CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
3839 
3840  /* ... and CoGetClassObject does not find it and fails when it looks for the
3841  * class in the registry */
3842  hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
3844  ok(hr == REGDB_E_CLASSNOTREG || /* NT */
3845  hr == S_OK /* Win9x */,
3846  "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3847 
3848  /* Resume the object suspended above ... */
3851 
3852  /* ... and now it should succeed */
3853  hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
3856 
3857  /* Now check the locking is working */
3858  /* NOTE: we are accessing the class directly, not through a proxy */
3859 
3860  ok_no_locks();
3861 
3862  hr = IClassFactory_LockServer(cf, TRUE);
3863  ok_ole_success(hr, IClassFactory_LockServer);
3864 
3866 
3867  IClassFactory_LockServer(cf, FALSE);
3868  ok_ole_success(hr, IClassFactory_LockServer);
3869 
3870  ok_no_locks();
3871 
3872  IClassFactory_Release(cf);
3873 
3874  /* wait for shutdown signal */
3876  ok(ret != WAIT_TIMEOUT, "Server didn't shut down\n");
3877 
3878  /* try to connect again after SCM has suspended registered class objects */
3879  hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
3880  &IID_IClassFactory, (LPVOID*)&cf);
3881  ok(hr == CO_E_SERVER_STOPPING || /* NT */
3882  hr == REGDB_E_CLASSNOTREG || /* win2k */
3883  hr == S_OK /* Win9x */,
3884  "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3885 
3886  hr = CoRevokeClassObject(cookie);
3888 
3890 
3891  process = create_target_process("-Embedding");
3892  ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError());
3893 
3894  ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
3895  ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" );
3896 
3897  hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist);
3899 
3900  IPersist_Release(persist);
3901 
3902  hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist);
3903  ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3904 
3905  /* Re-register the class and try calling CoDisconnectObject from within a call to that object */
3906  repeat_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event");
3907  SetEvent(repeat_event);
3908  CloseHandle(repeat_event);
3909 
3910  ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" );
3911  CloseHandle(ready_event);
3912 
3913  hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist);
3915 
3916  /* GetClassID will call CoDisconnectObject */
3917  IPersist_GetClassID(persist, &clsid);
3918  IPersist_Release(persist);
3919 
3920  quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
3921  SetEvent(quit_event);
3922 
3924  CloseHandle(quit_event);
3926 }
3927 
3929 {
3932 };
3933 
3935 {
3936  HRESULT hr;
3937  struct git_params *params = pv;
3938  IClassFactory *cf;
3939 
3940  hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
3941  ok(hr == CO_E_NOTINITIALIZED ||
3942  broken(hr == E_UNEXPECTED) /* win2k */ ||
3943  broken(hr == S_OK) /* NT 4 */,
3944  "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
3945  hr);
3946  if (hr == S_OK)
3947  IClassFactory_Release(cf);
3948 
3949  CoInitialize(NULL);
3950 
3951  hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
3952  ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
3953 
3954  IClassFactory_Release(cf);
3955 
3956  CoUninitialize();
3957 
3958  return hr;
3959 }
3960 
3961 static void test_globalinterfacetable(void)
3962 {
3963  HRESULT hr;
3965  DWORD cookie;
3966  HANDLE thread;