2 * Component Object Tests
4 * Copyright 2005 Robert Shearman
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.
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.
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
30 #include "urlmon.h" /* for CLSID_FileProtocol */
32 #include "wine/test.h"
34 /* functions that are not present on all versions of Windows */
35 HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
36 HRESULT (WINAPI
* pCoGetObjectContext
)(REFIID riid
, LPVOID
*ppv
);
38 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
39 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
40 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
42 static const CLSID CLSID_non_existent
= { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
43 static const CLSID CLSID_CDeviceMoniker
= { 0x4315d437, 0x5b8c, 0x11d0, { 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86 } };
44 static WCHAR devicedotone
[] = {'d','e','v','i','c','e','.','1',0};
45 static const WCHAR wszNonExistent
[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
46 static WCHAR wszCLSID_CDeviceMoniker
[] =
49 '4','3','1','5','d','4','3','7','-',
53 '0','0','a','0','c','9','1','1','c','e','8','6',
57 static const IID IID_IWineTest
=
62 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
63 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
64 static const CLSID CLSID_WineOOPTest
= {
68 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
69 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
73 static void LockModule(void)
75 InterlockedIncrement(&cLocks
);
78 static void UnlockModule(void)
80 InterlockedDecrement(&cLocks
);
83 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
88 if (ppvObj
== NULL
) return E_POINTER
;
90 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
91 IsEqualGUID(riid
, &IID_IClassFactory
))
93 *ppvObj
= (LPVOID
)iface
;
94 IClassFactory_AddRef(iface
);
102 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
105 return 2; /* non-heap-based object */
108 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
111 return 1; /* non-heap-based object */
114 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
115 LPCLASSFACTORY iface
,
121 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
122 return E_NOINTERFACE
;
125 static HRESULT WINAPI
Test_IClassFactory_LockServer(
126 LPCLASSFACTORY iface
,
132 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
134 Test_IClassFactory_QueryInterface
,
135 Test_IClassFactory_AddRef
,
136 Test_IClassFactory_Release
,
137 Test_IClassFactory_CreateInstance
,
138 Test_IClassFactory_LockServer
141 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
143 static void test_ProgIDFromCLSID(void)
146 HRESULT hr
= ProgIDFromCLSID(&CLSID_CDeviceMoniker
, &progid
);
147 ok(hr
== S_OK
, "ProgIDFromCLSID failed with error 0x%08x\n", hr
);
150 ok(!lstrcmpiW(progid
, devicedotone
), "Didn't get expected prog ID\n");
151 CoTaskMemFree(progid
);
154 progid
= (LPWSTR
)0xdeadbeef;
155 hr
= ProgIDFromCLSID(&CLSID_non_existent
, &progid
);
156 ok(hr
== REGDB_E_CLASSNOTREG
, "ProgIDFromCLSID returned %08x\n", hr
);
157 ok(progid
== NULL
, "ProgIDFromCLSID returns with progid %p\n", progid
);
159 hr
= ProgIDFromCLSID(&CLSID_CDeviceMoniker
, NULL
);
160 ok(hr
== E_INVALIDARG
, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr
);
163 static void test_CLSIDFromProgID(void)
166 HRESULT hr
= CLSIDFromProgID(devicedotone
, &clsid
);
167 ok(hr
== S_OK
, "CLSIDFromProgID failed with error 0x%08x\n", hr
);
168 ok(IsEqualCLSID(&clsid
, &CLSID_CDeviceMoniker
), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
170 hr
= CLSIDFromString(devicedotone
, &clsid
);
171 ok_ole_success(hr
, "CLSIDFromString");
172 ok(IsEqualCLSID(&clsid
, &CLSID_CDeviceMoniker
), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
174 /* test some failure cases */
176 hr
= CLSIDFromProgID(wszNonExistent
, NULL
);
177 ok(hr
== E_INVALIDARG
, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
179 hr
= CLSIDFromProgID(NULL
, &clsid
);
180 ok(hr
== E_INVALIDARG
, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
182 memset(&clsid
, 0xcc, sizeof(clsid
));
183 hr
= CLSIDFromProgID(wszNonExistent
, &clsid
);
184 ok(hr
== CO_E_CLASSSTRING
, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr
);
185 ok(IsEqualCLSID(&clsid
, &CLSID_NULL
), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
188 static void test_CLSIDFromString(void)
191 HRESULT hr
= CLSIDFromString(wszCLSID_CDeviceMoniker
, &clsid
);
192 ok_ole_success(hr
, "CLSIDFromString");
193 ok(IsEqualCLSID(&clsid
, &CLSID_CDeviceMoniker
), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
195 hr
= CLSIDFromString(NULL
, &clsid
);
196 ok_ole_success(hr
, "CLSIDFromString");
197 ok(IsEqualCLSID(&clsid
, &CLSID_NULL
), "clsid wasn't equal to CLSID_NULL\n");
200 static void test_StringFromGUID2(void)
204 /* Test corner cases for buffer size */
205 len
= StringFromGUID2(&CLSID_CDeviceMoniker
,str
,50);
206 ok(len
== 39, "len: %d (expected 39)\n", len
);
207 ok(!lstrcmpiW(str
, wszCLSID_CDeviceMoniker
),"string wan't equal for CLSID_CDeviceMoniker\n");
209 memset(str
,0,sizeof str
);
210 len
= StringFromGUID2(&CLSID_CDeviceMoniker
,str
,39);
211 ok(len
== 39, "len: %d (expected 39)\n", len
);
212 ok(!lstrcmpiW(str
, wszCLSID_CDeviceMoniker
),"string wan't equal for CLSID_CDeviceMoniker\n");
214 len
= StringFromGUID2(&CLSID_CDeviceMoniker
,str
,38);
215 ok(len
== 0, "len: %d (expected 0)\n", len
);
217 len
= StringFromGUID2(&CLSID_CDeviceMoniker
,str
,30);
218 ok(len
== 0, "len: %d (expected 0)\n", len
);
221 static void test_CoCreateInstance(void)
223 REFCLSID rclsid
= &CLSID_MyComputer
;
224 IUnknown
*pUnk
= (IUnknown
*)0xdeadbeef;
225 HRESULT hr
= CoCreateInstance(rclsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
226 ok(hr
== CO_E_NOTINITIALIZED
, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
227 ok(pUnk
== NULL
, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk
);
230 hr
= CoCreateInstance(rclsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
231 ok_ole_success(hr
, "CoCreateInstance");
232 if(pUnk
) IUnknown_Release(pUnk
);
235 hr
= CoCreateInstance(rclsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
236 ok(hr
== CO_E_NOTINITIALIZED
, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
239 static void test_CoGetClassObject(void)
241 IUnknown
*pUnk
= (IUnknown
*)0xdeadbeef;
242 HRESULT hr
= CoGetClassObject(&CLSID_MyComputer
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IUnknown
, (void **)&pUnk
);
243 ok(hr
== CO_E_NOTINITIALIZED
, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
244 ok(pUnk
== NULL
, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk
);
246 hr
= CoGetClassObject(&CLSID_MyComputer
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IUnknown
, NULL
);
247 ok(hr
== E_INVALIDARG
, "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
250 static ATOM
register_dummy_class(void)
258 GetModuleHandle(NULL
),
260 LoadCursor(NULL
, IDC_ARROW
),
261 (HBRUSH
)(COLOR_BTNFACE
+1),
263 TEXT("WineOleTestClass"),
266 return RegisterClass(&wc
);
269 static void test_ole_menu(void)
274 hwndFrame
= CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, NULL
);
275 hr
= OleSetMenuDescriptor(NULL
, hwndFrame
, NULL
, NULL
, NULL
);
276 todo_wine
ok_ole_success(hr
, "OleSetMenuDescriptor");
278 DestroyWindow(hwndFrame
);
282 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
284 if (ppvObj
== NULL
) return E_POINTER
;
286 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
287 IsEqualGUID(riid
, &IID_IClassFactory
))
289 *ppvObj
= (LPVOID
)iface
;
290 IMessageFilter_AddRef(iface
);
294 return E_NOINTERFACE
;
297 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
299 return 2; /* non-heap object */
302 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
304 return 1; /* non-heap object */
307 static DWORD WINAPI
MessageFilter_HandleInComingCall(
308 IMessageFilter
*iface
,
310 HTASK threadIDCaller
,
312 LPINTERFACEINFO lpInterfaceInfo
)
314 trace("HandleInComingCall\n");
315 return SERVERCALL_ISHANDLED
;
318 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
319 IMessageFilter
*iface
,
320 HTASK threadIDCallee
,
324 trace("RetryRejectedCall\n");
328 static DWORD WINAPI
MessageFilter_MessagePending(
329 IMessageFilter
*iface
,
330 HTASK threadIDCallee
,
334 trace("MessagePending\n");
335 return PENDINGMSG_WAITNOPROCESS
;
338 static const IMessageFilterVtbl MessageFilter_Vtbl
=
340 MessageFilter_QueryInterface
,
341 MessageFilter_AddRef
,
342 MessageFilter_Release
,
343 MessageFilter_HandleInComingCall
,
344 MessageFilter_RetryRejectedCall
,
345 MessageFilter_MessagePending
348 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
350 static void test_CoRegisterMessageFilter(void)
353 IMessageFilter
*prev_filter
;
355 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
356 ok(hr
== CO_E_NOT_SUPPORTED
,
357 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
360 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
361 prev_filter
= (IMessageFilter
*)0xdeadbeef;
362 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
363 ok(hr
== CO_E_NOT_SUPPORTED
,
364 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
366 ok(prev_filter
== (IMessageFilter
*)0xdeadbeef,
367 "prev_filter should have been set to %p\n", prev_filter
);
370 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
372 hr
= CoRegisterMessageFilter(NULL
, NULL
);
373 ok_ole_success(hr
, "CoRegisterMessageFilter");
375 prev_filter
= (IMessageFilter
*)0xdeadbeef;
376 hr
= CoRegisterMessageFilter(NULL
, &prev_filter
);
377 ok_ole_success(hr
, "CoRegisterMessageFilter");
378 ok(prev_filter
== NULL
, "prev_filter should have been set to NULL instead of %p\n", prev_filter
);
380 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
381 ok_ole_success(hr
, "CoRegisterMessageFilter");
382 ok(prev_filter
== NULL
, "prev_filter should have been set to NULL instead of %p\n", prev_filter
);
384 hr
= CoRegisterMessageFilter(NULL
, NULL
);
385 ok_ole_success(hr
, "CoRegisterMessageFilter");
390 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
395 if (ppvObj
== NULL
) return E_POINTER
;
397 if (IsEqualIID(riid
, &IID_IUnknown
) ||
398 IsEqualIID(riid
, &IID_IWineTest
))
400 *ppvObj
= (LPVOID
)iface
;
401 IUnknown_AddRef(iface
);
406 return E_NOINTERFACE
;
409 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
411 return 2; /* non-heap-based object */
414 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
416 return 1; /* non-heap-based object */
419 static const IUnknownVtbl TestUnknown_Vtbl
=
421 Test_IUnknown_QueryInterface
,
422 Test_IUnknown_AddRef
,
423 Test_IUnknown_Release
,
426 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
428 static HRESULT WINAPI
PSFactoryBuffer_QueryInterface(
429 IPSFactoryBuffer
* This
,
430 /* [in] */ REFIID riid
,
431 /* [iid_is][out] */ void **ppvObject
)
433 if (IsEqualIID(riid
, &IID_IUnknown
) ||
434 IsEqualIID(riid
, &IID_IPSFactoryBuffer
))
437 IPSFactoryBuffer_AddRef(This
);
440 return E_NOINTERFACE
;
443 static ULONG WINAPI
PSFactoryBuffer_AddRef(
444 IPSFactoryBuffer
* This
)
449 static ULONG WINAPI
PSFactoryBuffer_Release(
450 IPSFactoryBuffer
* This
)
455 static HRESULT WINAPI
PSFactoryBuffer_CreateProxy(
456 IPSFactoryBuffer
* This
,
457 /* [in] */ IUnknown
*pUnkOuter
,
458 /* [in] */ REFIID riid
,
459 /* [out] */ IRpcProxyBuffer
**ppProxy
,
460 /* [out] */ void **ppv
)
465 static HRESULT WINAPI
PSFactoryBuffer_CreateStub(
466 IPSFactoryBuffer
* This
,
467 /* [in] */ REFIID riid
,
468 /* [unique][in] */ IUnknown
*pUnkServer
,
469 /* [out] */ IRpcStubBuffer
**ppStub
)
474 static IPSFactoryBufferVtbl PSFactoryBufferVtbl
=
476 PSFactoryBuffer_QueryInterface
,
477 PSFactoryBuffer_AddRef
,
478 PSFactoryBuffer_Release
,
479 PSFactoryBuffer_CreateProxy
,
480 PSFactoryBuffer_CreateStub
483 static IPSFactoryBuffer PSFactoryBuffer
= { &PSFactoryBufferVtbl
};
485 static const CLSID CLSID_WineTestPSFactoryBuffer
=
490 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
491 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
493 static void test_CoRegisterPSClsid(void)
496 DWORD dwRegistrationKey
;
500 hr
= CoRegisterPSClsid(&IID_IWineTest
, &CLSID_WineTestPSFactoryBuffer
);
501 ok(hr
== CO_E_NOTINITIALIZED
, "CoRegisterPSClsid should have returened CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
503 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
505 hr
= CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer
, (IUnknown
*)&PSFactoryBuffer
,
506 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, &dwRegistrationKey
);
507 ok_ole_success(hr
, "CoRegisterClassObject");
509 hr
= CoRegisterPSClsid(&IID_IWineTest
, &CLSID_WineTestPSFactoryBuffer
);
510 ok_ole_success(hr
, "CoRegisterPSClsid");
512 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
513 ok_ole_success(hr
, "CreateStreamOnHGlobal");
515 hr
= CoMarshalInterface(stream
, &IID_IWineTest
, (IUnknown
*)&Test_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
516 ok(hr
== E_NOTIMPL
, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr
);
517 IStream_Release(stream
);
519 hr
= CoRevokeClassObject(dwRegistrationKey
);
520 ok_ole_success(hr
, "CoRevokeClassObject");
524 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
526 hr
= CoGetPSClsid(&IID_IWineTest
, &clsid
);
527 ok(hr
== REGDB_E_IIDNOTREG
, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr
);
532 static void test_CoGetPSClsid(void)
537 hr
= CoGetPSClsid(&IID_IClassFactory
, &clsid
);
538 ok(hr
== CO_E_NOTINITIALIZED
,
539 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
542 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
544 hr
= CoGetPSClsid(&IID_IClassFactory
, &clsid
);
545 ok_ole_success(hr
, "CoGetPSClsid");
547 hr
= CoGetPSClsid(&IID_IWineTest
, &clsid
);
548 ok(hr
== REGDB_E_IIDNOTREG
,
549 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
552 hr
= CoGetPSClsid(&IID_IClassFactory
, NULL
);
553 ok(hr
== E_INVALIDARG
,
554 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
560 /* basic test, mainly for invalid arguments. see marshal.c for more */
561 static void test_CoUnmarshalInterface(void)
567 hr
= CoUnmarshalInterface(NULL
, &IID_IUnknown
, (void **)&pProxy
);
568 ok(hr
== E_INVALIDARG
, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
570 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
571 ok_ole_success(hr
, "CreateStreamOnHGlobal");
573 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
575 ok(hr
== CO_E_NOTINITIALIZED
, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
577 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
579 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
580 ok(hr
== STG_E_READFAULT
, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr
);
584 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, NULL
);
585 ok(hr
== E_INVALIDARG
, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
587 IStream_Release(pStream
);
590 static void test_CoGetInterfaceAndReleaseStream(void)
595 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
597 hr
= CoGetInterfaceAndReleaseStream(NULL
, &IID_IUnknown
, (void**)&pUnk
);
598 ok(hr
== E_INVALIDARG
, "hr %08x\n", hr
);
603 /* basic test, mainly for invalid arguments. see marshal.c for more */
604 static void test_CoMarshalInterface(void)
608 static const LARGE_INTEGER llZero
;
610 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
612 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
613 ok_ole_success(hr
, "CreateStreamOnHGlobal");
615 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, NULL
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
616 ok(hr
== E_INVALIDARG
, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
618 hr
= CoMarshalInterface(NULL
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
619 ok(hr
== E_INVALIDARG
, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
621 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
622 ok_ole_success(hr
, "CoMarshalInterface");
624 /* stream not rewound */
625 hr
= CoReleaseMarshalData(pStream
);
626 ok(hr
== STG_E_READFAULT
, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr
);
628 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
629 ok_ole_success(hr
, "IStream_Seek");
631 hr
= CoReleaseMarshalData(pStream
);
632 ok_ole_success(hr
, "CoReleaseMarshalData");
634 IStream_Release(pStream
);
639 static void test_CoMarshalInterThreadInterfaceInStream(void)
643 IClassFactory
*pProxy
;
645 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
649 hr
= CoMarshalInterThreadInterfaceInStream(&IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, NULL
);
650 ok(hr
== E_INVALIDARG
, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
652 hr
= CoMarshalInterThreadInterfaceInStream(&IID_IUnknown
, NULL
, &pStream
);
653 ok(hr
== E_INVALIDARG
, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
657 hr
= CoMarshalInterThreadInterfaceInStream(&IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, &pStream
);
658 ok_ole_success(hr
, "CoMarshalInterThreadInterfaceInStream");
660 ok_more_than_one_lock();
662 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
663 ok_ole_success(hr
, "CoUnmarshalInterface");
665 IClassFactory_Release(pProxy
);
666 IStream_Release(pStream
);
673 static void test_CoRegisterClassObject(void)
679 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
681 /* CLSCTX_INPROC_SERVER */
682 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
683 CLSCTX_INPROC_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
684 ok_ole_success(hr
, "CoRegisterClassObject");
685 hr
= CoRevokeClassObject(cookie
);
686 ok_ole_success(hr
, "CoRevokeClassObject");
688 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
689 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, &cookie
);
690 ok_ole_success(hr
, "CoRegisterClassObject");
691 hr
= CoRevokeClassObject(cookie
);
692 ok_ole_success(hr
, "CoRevokeClassObject");
694 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
695 CLSCTX_INPROC_SERVER
, REGCLS_MULTI_SEPARATE
, &cookie
);
696 ok_ole_success(hr
, "CoRegisterClassObject");
697 hr
= CoRevokeClassObject(cookie
);
698 ok_ole_success(hr
, "CoRevokeClassObject");
700 /* CLSCTX_LOCAL_SERVER */
701 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
702 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
703 ok_ole_success(hr
, "CoRegisterClassObject");
704 hr
= CoRevokeClassObject(cookie
);
705 ok_ole_success(hr
, "CoRevokeClassObject");
707 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
708 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
, &cookie
);
709 ok_ole_success(hr
, "CoRegisterClassObject");
710 hr
= CoRevokeClassObject(cookie
);
711 ok_ole_success(hr
, "CoRevokeClassObject");
713 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
714 CLSCTX_LOCAL_SERVER
, REGCLS_MULTI_SEPARATE
, &cookie
);
715 ok_ole_success(hr
, "CoRegisterClassObject");
716 hr
= CoRevokeClassObject(cookie
);
717 ok_ole_success(hr
, "CoRevokeClassObject");
719 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
720 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
721 CLSCTX_INPROC_SERVER
|CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
722 ok_ole_success(hr
, "CoRegisterClassObject");
723 hr
= CoRevokeClassObject(cookie
);
724 ok_ole_success(hr
, "CoRevokeClassObject");
726 /* test whether registered class becomes invalid when apartment is destroyed */
727 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
728 CLSCTX_INPROC_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
729 ok_ole_success(hr
, "CoRegisterClassObject");
732 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
734 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
, NULL
,
735 &IID_IClassFactory
, (void **)&pcf
);
736 ok(hr
== REGDB_E_CLASSNOTREG
, "object registered in an apartment shouldn't accessible after it is destroyed\n");
738 /* crashes with at least win9x DCOM! */
740 hr
= CoRevokeClassObject(cookie
);
745 static HRESULT
get_class_object(CLSCTX clsctx
)
750 hr
= CoGetClassObject(&CLSID_WineOOPTest
, clsctx
, NULL
, &IID_IClassFactory
,
754 IClassFactory_Release(pcf
);
759 static DWORD CALLBACK
get_class_object_thread(LPVOID pv
)
761 CLSCTX clsctx
= (CLSCTX
)(DWORD_PTR
)pv
;
764 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
766 hr
= get_class_object(clsctx
);
773 static DWORD CALLBACK
get_class_object_proxy_thread(LPVOID pv
)
775 CLSCTX clsctx
= (CLSCTX
)(DWORD_PTR
)pv
;
780 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
782 hr
= CoGetClassObject(&CLSID_WineOOPTest
, clsctx
, NULL
, &IID_IClassFactory
,
787 hr
= IClassFactory_QueryInterface(pcf
, &IID_IMultiQI
, (void **)&pMQI
);
789 IMultiQI_Release(pMQI
);
790 IClassFactory_Release(pcf
);
798 static DWORD CALLBACK
register_class_object_thread(LPVOID pv
)
803 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
805 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
806 CLSCTX_INPROC_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
813 static DWORD CALLBACK
revoke_class_object_thread(LPVOID pv
)
815 DWORD cookie
= (DWORD_PTR
)pv
;
818 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
820 hr
= CoRevokeClassObject(cookie
);
827 static void test_registered_object_thread_affinity(void)
835 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
837 /* CLSCTX_INPROC_SERVER */
839 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
840 CLSCTX_INPROC_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
841 ok_ole_success(hr
, "CoRegisterClassObject");
843 thread
= CreateThread(NULL
, 0, get_class_object_thread
, (LPVOID
)CLSCTX_INPROC_SERVER
, 0, &tid
);
844 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
845 WaitForSingleObject(thread
, INFINITE
);
846 GetExitCodeThread(thread
, &exitcode
);
848 ok(hr
== REGDB_E_CLASSNOTREG
, "CoGetClassObject on inproc object "
849 "registered in different thread should return REGDB_E_CLASSNOTREG "
850 "instead of 0x%08x\n", hr
);
852 hr
= get_class_object(CLSCTX_INPROC_SERVER
);
853 ok(hr
== S_OK
, "CoGetClassObject on inproc object registered in same "
854 "thread should return S_OK instead of 0x%08x\n", hr
);
856 thread
= CreateThread(NULL
, 0, register_class_object_thread
, NULL
, 0, &tid
);
857 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
858 WaitForSingleObject(thread
, INFINITE
);
859 GetExitCodeThread(thread
, &exitcode
);
861 ok(hr
== S_OK
, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr
);
863 hr
= CoRevokeClassObject(cookie
);
864 ok_ole_success(hr
, "CoRevokeClassObject");
866 /* CLSCTX_LOCAL_SERVER */
868 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&Test_ClassFactory
,
869 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
, &cookie
);
870 ok_ole_success(hr
, "CoRegisterClassObject");
872 thread
= CreateThread(NULL
, 0, get_class_object_proxy_thread
, (LPVOID
)CLSCTX_LOCAL_SERVER
, 0, &tid
);
873 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
874 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
) == WAIT_OBJECT_0
+ 1)
877 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
879 TranslateMessage(&msg
);
880 DispatchMessageA(&msg
);
883 GetExitCodeThread(thread
, &exitcode
);
885 ok(hr
== S_OK
, "CoGetClassObject on local server object "
886 "registered in different thread should return S_OK "
887 "instead of 0x%08x\n", hr
);
889 hr
= get_class_object(CLSCTX_LOCAL_SERVER
);
890 ok(hr
== S_OK
, "CoGetClassObject on local server object registered in same "
891 "thread should return S_OK instead of 0x%08x\n", hr
);
893 thread
= CreateThread(NULL
, 0, revoke_class_object_thread
, (LPVOID
)cookie
, 0, &tid
);
894 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
895 WaitForSingleObject(thread
, INFINITE
);
896 GetExitCodeThread(thread
, &exitcode
);
898 ok(hr
== RPC_E_WRONG_THREAD
, "CoRevokeClassObject called from different "
899 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr
);
901 thread
= CreateThread(NULL
, 0, register_class_object_thread
, NULL
, 0, &tid
);
902 ok(thread
!= NULL
, "CreateThread failed with error %d\n", GetLastError());
903 WaitForSingleObject(thread
, INFINITE
);
904 GetExitCodeThread(thread
, &exitcode
);
906 ok(hr
== S_OK
, "CoRegisterClassObject with same CLSID but in different "
907 "thread should return S_OK instead of 0x%08x\n", hr
);
909 hr
= CoRevokeClassObject(cookie
);
910 ok_ole_success(hr
, "CoRevokeClassObject");
915 static DWORD CALLBACK
free_libraries_thread(LPVOID p
)
917 CoFreeUnusedLibraries();
921 static inline BOOL
is_module_loaded(const char *module
)
923 return GetModuleHandle(module
) ? TRUE
: FALSE
;
926 static void test_CoFreeUnusedLibraries(void)
933 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
935 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
937 hr
= CoCreateInstance(&CLSID_FileProtocol
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
938 if (hr
== REGDB_E_CLASSNOTREG
)
940 trace("IE not installed so can't run CoFreeUnusedLibraries test\n");
943 ok_ole_success(hr
, "CoCreateInstance");
945 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
947 ok(pUnk
!= NULL
, "Expected a valid pointer\n");
949 IUnknown_Release(pUnk
);
951 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
953 thread
= CreateThread(NULL
, 0, free_libraries_thread
, NULL
, 0, &tid
);
954 WaitForSingleObject(thread
, INFINITE
);
957 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
959 CoFreeUnusedLibraries();
961 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
966 static void test_CoGetObjectContext(void)
970 IComThreadingInfo
*pComThreadingInfo
;
974 if (!pCoGetObjectContext
)
976 skip("CoGetObjectContext not present\n");
980 hr
= pCoGetObjectContext(&IID_IComThreadingInfo
, (void **)&pComThreadingInfo
);
981 ok(hr
== CO_E_NOTINITIALIZED
, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr
);
982 ok(pComThreadingInfo
== NULL
, "pComThreadingInfo should have been set to NULL\n");
984 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
986 hr
= pCoGetObjectContext(&IID_IComThreadingInfo
, (void **)&pComThreadingInfo
);
987 ok_ole_success(hr
, "CoGetObjectContext");
989 hr
= IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo
, &apttype
);
990 ok_ole_success(hr
, "IComThreadingInfo_GetCurrentApartmentType");
991 ok(apttype
== APTTYPE_MAINSTA
, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype
);
993 hr
= IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo
, &thdtype
);
994 ok_ole_success(hr
, "IComThreadingInfo_GetCurrentThreadType");
995 ok(thdtype
== THDTYPE_PROCESSMESSAGES
, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype
);
997 refs
= IComThreadingInfo_Release(pComThreadingInfo
);
998 ok(refs
== 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs
);
1002 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1004 hr
= pCoGetObjectContext(&IID_IComThreadingInfo
, (void **)&pComThreadingInfo
);
1005 ok_ole_success(hr
, "CoGetObjectContext");
1007 hr
= IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo
, &apttype
);
1008 ok_ole_success(hr
, "IComThreadingInfo_GetCurrentApartmentType");
1009 ok(apttype
== APTTYPE_MTA
, "apartment type should be APTTYPE_MTA instead of %d\n", apttype
);
1011 hr
= IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo
, &thdtype
);
1012 ok_ole_success(hr
, "IComThreadingInfo_GetCurrentThreadType");
1013 ok(thdtype
== THDTYPE_BLOCKMESSAGES
, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype
);
1015 refs
= IComThreadingInfo_Release(pComThreadingInfo
);
1016 ok(refs
== 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs
);
1023 HMODULE hOle32
= GetModuleHandle("ole32");
1024 pCoGetObjectContext
= (void*)GetProcAddress(hOle32
, "CoGetObjectContext");
1025 if (!(pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx")))
1027 trace("You need DCOM95 installed to run this test\n");
1031 test_ProgIDFromCLSID();
1032 test_CLSIDFromProgID();
1033 test_CLSIDFromString();
1034 test_StringFromGUID2();
1035 test_CoCreateInstance();
1037 test_CoGetClassObject();
1038 test_CoRegisterMessageFilter();
1039 test_CoRegisterPSClsid();
1040 test_CoGetPSClsid();
1041 test_CoUnmarshalInterface();
1042 test_CoGetInterfaceAndReleaseStream();
1043 test_CoMarshalInterface();
1044 test_CoMarshalInterThreadInterfaceInStream();
1045 test_CoRegisterClassObject();
1046 test_registered_object_thread_affinity();
1047 test_CoFreeUnusedLibraries();
1048 test_CoGetObjectContext();