kernel32: GlobalMemoryStatusEx: return the size of physical memory + swapsize in...
[wine] / dlls / ole32 / tests / compobj.c
1 /*
2  * Component Object Tests
3  *
4  * Copyright 2005 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 COBJMACROS
22 #define CONST_VTABLE
23
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "objbase.h"
29 #include "shlguid.h"
30
31 #include "wine/test.h"
32
33 /* functions that are not present on all versions of Windows */
34 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
35
36 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
37 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
38 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
39
40 static const CLSID CLSID_non_existent =   { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
41 static const CLSID CLSID_CDeviceMoniker = { 0x4315d437, 0x5b8c, 0x11d0, { 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86 } };
42 static WCHAR devicedotone[] = {'d','e','v','i','c','e','.','1',0};
43 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
44 static WCHAR wszCLSID_CDeviceMoniker[] =
45 {
46     '{',
47     '4','3','1','5','d','4','3','7','-',
48     '5','b','8','c','-',
49     '1','1','d','0','-',
50     'b','d','3','b','-',
51     '0','0','a','0','c','9','1','1','c','e','8','6',
52     '}',0
53 };
54
55 static const IID IID_IWineTest =
56 {
57     0x5201163f,
58     0x8164,
59     0x4fd0,
60     {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
61 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
62
63 static LONG cLocks;
64
65 static void LockModule(void)
66 {
67     InterlockedIncrement(&cLocks);
68 }
69
70 static void UnlockModule(void)
71 {
72     InterlockedDecrement(&cLocks);
73 }
74
75 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
76     LPCLASSFACTORY iface,
77     REFIID riid,
78     LPVOID *ppvObj)
79 {
80     if (ppvObj == NULL) return E_POINTER;
81
82     if (IsEqualGUID(riid, &IID_IUnknown) ||
83         IsEqualGUID(riid, &IID_IClassFactory))
84     {
85         *ppvObj = (LPVOID)iface;
86         IClassFactory_AddRef(iface);
87         return S_OK;
88     }
89
90     *ppvObj = NULL;
91     return E_NOINTERFACE;
92 }
93
94 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
95 {
96     LockModule();
97     return 2; /* non-heap-based object */
98 }
99
100 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
101 {
102     UnlockModule();
103     return 1; /* non-heap-based object */
104 }
105
106 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
107     LPCLASSFACTORY iface,
108     LPUNKNOWN pUnkOuter,
109     REFIID riid,
110     LPVOID *ppvObj)
111 {
112     *ppvObj = NULL;
113     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
114     return E_NOINTERFACE;
115 }
116
117 static HRESULT WINAPI Test_IClassFactory_LockServer(
118     LPCLASSFACTORY iface,
119     BOOL fLock)
120 {
121     return S_OK;
122 }
123
124 static const IClassFactoryVtbl TestClassFactory_Vtbl =
125 {
126     Test_IClassFactory_QueryInterface,
127     Test_IClassFactory_AddRef,
128     Test_IClassFactory_Release,
129     Test_IClassFactory_CreateInstance,
130     Test_IClassFactory_LockServer
131 };
132
133 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
134
135 static void test_ProgIDFromCLSID(void)
136 {
137     LPWSTR progid;
138     HRESULT hr = ProgIDFromCLSID(&CLSID_CDeviceMoniker, &progid);
139     ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
140     if (hr == S_OK)
141     {
142         ok(!lstrcmpiW(progid, devicedotone), "Didn't get expected prog ID\n");
143         CoTaskMemFree(progid);
144     }
145
146     progid = (LPWSTR)0xdeadbeef;
147     hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
148     ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
149     ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
150
151     hr = ProgIDFromCLSID(&CLSID_CDeviceMoniker, NULL);
152     ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
153 }
154
155 static void test_CLSIDFromProgID(void)
156 {
157     CLSID clsid;
158     HRESULT hr = CLSIDFromProgID(devicedotone, &clsid);
159     ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
160     ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
161
162     hr = CLSIDFromString(devicedotone, &clsid);
163     ok_ole_success(hr, "CLSIDFromString");
164     ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
165
166     /* test some failure cases */
167
168     hr = CLSIDFromProgID(wszNonExistent, NULL);
169     ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
170
171     hr = CLSIDFromProgID(NULL, &clsid);
172     ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
173
174     memset(&clsid, 0xcc, sizeof(clsid));
175     hr = CLSIDFromProgID(wszNonExistent, &clsid);
176     ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
177     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
178 }
179
180 static void test_CLSIDFromString(void)
181 {
182     CLSID clsid;
183     HRESULT hr = CLSIDFromString(wszCLSID_CDeviceMoniker, &clsid);
184     ok_ole_success(hr, "CLSIDFromString");
185     ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
186
187     hr = CLSIDFromString(NULL, &clsid);
188     ok_ole_success(hr, "CLSIDFromString");
189     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
190 }
191
192 static void test_CoCreateInstance(void)
193 {
194     REFCLSID rclsid = &CLSID_MyComputer;
195     IUnknown *pUnk = (IUnknown *)0xdeadbeef;
196     HRESULT hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
197     ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
198     ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
199
200     OleInitialize(NULL);
201     hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
202     ok_ole_success(hr, "CoCreateInstance");
203     IUnknown_Release(pUnk);
204     OleUninitialize();
205
206     hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
207     ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
208 }
209
210 static void test_CoGetClassObject(void)
211 {
212     IUnknown *pUnk = (IUnknown *)0xdeadbeef;
213     HRESULT hr = CoGetClassObject(&CLSID_MyComputer, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
214     ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
215     ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
216
217     hr = CoGetClassObject(&CLSID_MyComputer, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
218     ok(hr == E_INVALIDARG, "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
219 }
220
221 static ATOM register_dummy_class(void)
222 {
223     WNDCLASS wc =
224     {
225         0,
226         DefWindowProc,
227         0,
228         0,
229         GetModuleHandle(NULL),
230         NULL,
231         LoadCursor(NULL, IDC_ARROW),
232         (HBRUSH)(COLOR_BTNFACE+1),
233         NULL,
234         TEXT("WineOleTestClass"),
235     };
236
237     return RegisterClass(&wc);
238 }
239
240 static void test_ole_menu(void)
241 {
242         HWND hwndFrame;
243         HRESULT hr;
244
245         hwndFrame = CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
246         hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
247         todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
248
249         DestroyWindow(hwndFrame);
250 }
251
252
253 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
254 {
255     if (ppvObj == NULL) return E_POINTER;
256
257     if (IsEqualGUID(riid, &IID_IUnknown) ||
258         IsEqualGUID(riid, &IID_IClassFactory))
259     {
260         *ppvObj = (LPVOID)iface;
261         IMessageFilter_AddRef(iface);
262         return S_OK;
263     }
264
265     return E_NOINTERFACE;
266 }
267
268 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
269 {
270     return 2; /* non-heap object */
271 }
272
273 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
274 {
275     return 1; /* non-heap object */
276 }
277
278 static DWORD WINAPI MessageFilter_HandleInComingCall(
279   IMessageFilter *iface,
280   DWORD dwCallType,
281   HTASK threadIDCaller,
282   DWORD dwTickCount,
283   LPINTERFACEINFO lpInterfaceInfo)
284 {
285     trace("HandleInComingCall\n");
286     return SERVERCALL_ISHANDLED;
287 }
288
289 static DWORD WINAPI MessageFilter_RetryRejectedCall(
290   IMessageFilter *iface,
291   HTASK threadIDCallee,
292   DWORD dwTickCount,
293   DWORD dwRejectType)
294 {
295     trace("RetryRejectedCall\n");
296     return 0;
297 }
298
299 static DWORD WINAPI MessageFilter_MessagePending(
300   IMessageFilter *iface,
301   HTASK threadIDCallee,
302   DWORD dwTickCount,
303   DWORD dwPendingType)
304 {
305     trace("MessagePending\n");
306     return PENDINGMSG_WAITNOPROCESS;
307 }
308
309 static const IMessageFilterVtbl MessageFilter_Vtbl =
310 {
311     MessageFilter_QueryInterface,
312     MessageFilter_AddRef,
313     MessageFilter_Release,
314     MessageFilter_HandleInComingCall,
315     MessageFilter_RetryRejectedCall,
316     MessageFilter_MessagePending
317 };
318
319 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
320
321 static void test_CoRegisterMessageFilter(void)
322 {
323     HRESULT hr;
324     IMessageFilter *prev_filter;
325
326     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
327     ok(hr == CO_E_NOT_SUPPORTED,
328         "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
329         hr);
330
331     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
332     prev_filter = (IMessageFilter *)0xdeadbeef;
333     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
334     ok(hr == CO_E_NOT_SUPPORTED,
335         "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
336         hr);
337     ok(prev_filter == (IMessageFilter *)0xdeadbeef,
338         "prev_filter should have been set to %p\n", prev_filter);
339     CoUninitialize();
340
341     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
342
343     hr = CoRegisterMessageFilter(NULL, NULL);
344     ok_ole_success(hr, "CoRegisterMessageFilter");
345
346     prev_filter = (IMessageFilter *)0xdeadbeef;
347     hr = CoRegisterMessageFilter(NULL, &prev_filter);
348     ok_ole_success(hr, "CoRegisterMessageFilter");
349     ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
350
351     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
352     ok_ole_success(hr, "CoRegisterMessageFilter");
353     ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
354
355     hr = CoRegisterMessageFilter(NULL, NULL);
356     ok_ole_success(hr, "CoRegisterMessageFilter");
357
358     CoUninitialize();
359 }
360
361 static HRESULT WINAPI Test_IUnknown_QueryInterface(
362     LPUNKNOWN iface,
363     REFIID riid,
364     LPVOID *ppvObj)
365 {
366     if (ppvObj == NULL) return E_POINTER;
367
368     if (IsEqualIID(riid, &IID_IUnknown) ||
369         IsEqualIID(riid, &IID_IWineTest))
370     {
371         *ppvObj = (LPVOID)iface;
372         IUnknown_AddRef(iface);
373         return S_OK;
374     }
375
376     *ppvObj = NULL;
377     return E_NOINTERFACE;
378 }
379
380 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
381 {
382     return 2; /* non-heap-based object */
383 }
384
385 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
386 {
387     return 1; /* non-heap-based object */
388 }
389
390 static const IUnknownVtbl TestUnknown_Vtbl =
391 {
392     Test_IUnknown_QueryInterface,
393     Test_IUnknown_AddRef,
394     Test_IUnknown_Release,
395 };
396
397 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
398
399 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
400     IPSFactoryBuffer * This,
401     /* [in] */ REFIID riid,
402     /* [iid_is][out] */ void **ppvObject)
403 {
404     if (IsEqualIID(riid, &IID_IUnknown) ||
405         IsEqualIID(riid, &IID_IPSFactoryBuffer))
406     {
407         *ppvObject = This;
408         IPSFactoryBuffer_AddRef(This);
409         return S_OK;
410     }
411     return E_NOINTERFACE;
412 }
413
414 static ULONG WINAPI PSFactoryBuffer_AddRef(
415     IPSFactoryBuffer * This)
416 {
417     return 2;
418 }
419
420 static ULONG WINAPI PSFactoryBuffer_Release(
421     IPSFactoryBuffer * This)
422 {
423     return 1;
424 }
425
426 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
427     IPSFactoryBuffer * This,
428     /* [in] */ IUnknown *pUnkOuter,
429     /* [in] */ REFIID riid,
430     /* [out] */ IRpcProxyBuffer **ppProxy,
431     /* [out] */ void **ppv)
432 {
433     return E_NOTIMPL;
434 }
435
436 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
437     IPSFactoryBuffer * This,
438     /* [in] */ REFIID riid,
439     /* [unique][in] */ IUnknown *pUnkServer,
440     /* [out] */ IRpcStubBuffer **ppStub)
441 {
442     return E_NOTIMPL;
443 }
444
445 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
446 {
447     PSFactoryBuffer_QueryInterface,
448     PSFactoryBuffer_AddRef,
449     PSFactoryBuffer_Release,
450     PSFactoryBuffer_CreateProxy,
451     PSFactoryBuffer_CreateStub
452 };
453
454 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
455
456 static const CLSID CLSID_WineTestPSFactoryBuffer =
457 {
458     0x52011640,
459     0x8164,
460     0x4fd0,
461     {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
462 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
463
464 static void test_CoRegisterPSClsid(void)
465 {
466     HRESULT hr;
467     DWORD dwRegistrationKey;
468     IStream *stream;
469     CLSID clsid;
470
471     hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
472     ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returened CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
473
474     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
475
476     hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
477         CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
478     ok_ole_success(hr, "CoRegisterClassObject");
479
480     hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
481     ok_ole_success(hr, "CoRegisterPSClsid");
482
483     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
484     ok_ole_success(hr, "CreateStreamOnHGlobal");
485
486     hr = CoMarshalInterface(stream, &IID_IWineTest, (IUnknown *)&Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
487     ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
488     IStream_Release(stream);
489
490     hr = CoRevokeClassObject(dwRegistrationKey);
491     ok_ole_success(hr, "CoRevokeClassObject");
492
493     CoUninitialize();
494
495     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
496
497     hr = CoGetPSClsid(&IID_IWineTest, &clsid);
498     ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
499
500     CoUninitialize();
501 }
502
503 static void test_CoGetPSClsid(void)
504 {
505     HRESULT hr;
506     CLSID clsid;
507
508     hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
509     ok(hr == CO_E_NOTINITIALIZED,
510        "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
511        hr);
512
513     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
514
515     hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
516     ok_ole_success(hr, "CoGetPSClsid");
517
518     hr = CoGetPSClsid(&IID_IWineTest, &clsid);
519     ok(hr == REGDB_E_IIDNOTREG,
520        "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
521        hr);
522
523     hr = CoGetPSClsid(&IID_IClassFactory, NULL);
524     ok(hr == E_INVALIDARG,
525        "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
526        hr);
527
528     CoUninitialize();
529 }
530
531 /* basic test, mainly for invalid arguments. see marshal.c for more */
532 static void test_CoUnmarshalInterface(void)
533 {
534     IUnknown *pProxy;
535     IStream *pStream;
536     HRESULT hr;
537
538     hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
539     ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
540
541     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
542     ok_ole_success(hr, "CreateStreamOnHGlobal");
543
544     hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
545     todo_wine
546     ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
547
548     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
549
550     hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
551     ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
552
553     CoUninitialize();
554
555     hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
556     ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
557
558     IStream_Release(pStream);
559 }
560
561 static void test_CoGetInterfaceAndReleaseStream(void)
562 {
563     HRESULT hr;
564     IUnknown *pUnk;
565
566     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
567
568     hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
569     ok(hr == E_INVALIDARG, "hr %08x\n", hr);
570
571     CoUninitialize();
572 }
573
574 /* basic test, mainly for invalid arguments. see marshal.c for more */
575 static void test_CoMarshalInterface(void)
576 {
577     IStream *pStream;
578     HRESULT hr;
579     static const LARGE_INTEGER llZero;
580
581     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
582
583     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
584     ok_ole_success(hr, "CreateStreamOnHGlobal");
585
586     hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
587     ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
588
589     hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
590     ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
591
592     hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
593     ok_ole_success(hr, "CoMarshalInterface");
594
595     /* stream not rewound */
596     hr = CoReleaseMarshalData(pStream);
597     ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
598
599     hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
600     ok_ole_success(hr, "IStream_Seek");
601
602     hr = CoReleaseMarshalData(pStream);
603     ok_ole_success(hr, "CoReleaseMarshalData");
604
605     IStream_Release(pStream);
606
607     CoUninitialize();
608 }
609
610 static void test_CoMarshalInterThreadInterfaceInStream(void)
611 {
612     IStream *pStream;
613     HRESULT hr;
614     IClassFactory *pProxy;
615
616     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
617
618     cLocks = 0;
619
620     hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
621     ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
622
623     hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
624     ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
625
626     ok_no_locks();
627
628     hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
629     ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
630
631     ok_more_than_one_lock();
632
633     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
634     ok_ole_success(hr, "CoUnmarshalInterface");
635
636     IClassFactory_Release(pProxy);
637
638     ok_no_locks();
639
640     CoUninitialize();
641 }
642
643 static void test_CoRegisterClassObject(void)
644 {
645     static const CLSID CLSID_WineOOPTest = {
646         0x5201163f,
647         0x8164,
648         0x4fd0,
649         {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
650     }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
651     DWORD cookie;
652     HRESULT hr;
653
654     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
655
656     /* CLSCTX_INPROC_SERVER */
657     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
658                                CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
659     ok_ole_success(hr, "CoRegisterClassObject");
660     hr = CoRevokeClassObject(cookie);
661     ok_ole_success(hr, "CoRevokeClassObject");
662
663     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
664                                CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
665     ok_ole_success(hr, "CoRegisterClassObject");
666     hr = CoRevokeClassObject(cookie);
667     ok_ole_success(hr, "CoRevokeClassObject");
668
669     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
670                                CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
671     ok_ole_success(hr, "CoRegisterClassObject");
672     hr = CoRevokeClassObject(cookie);
673     ok_ole_success(hr, "CoRevokeClassObject");
674
675     /* CLSCTX_LOCAL_SERVER */
676     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
677                                CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
678     ok_ole_success(hr, "CoRegisterClassObject");
679     hr = CoRevokeClassObject(cookie);
680     ok_ole_success(hr, "CoRevokeClassObject");
681
682     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
683                                CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
684     ok_ole_success(hr, "CoRegisterClassObject");
685     hr = CoRevokeClassObject(cookie);
686     ok_ole_success(hr, "CoRevokeClassObject");
687
688     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
689                                CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
690     ok_ole_success(hr, "CoRegisterClassObject");
691     hr = CoRevokeClassObject(cookie);
692     ok_ole_success(hr, "CoRevokeClassObject");
693
694     /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
695     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
696                                CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
697     ok_ole_success(hr, "CoRegisterClassObject");
698     hr = CoRevokeClassObject(cookie);
699     ok_ole_success(hr, "CoRevokeClassObject");
700
701     CoUninitialize();
702 }
703
704 START_TEST(compobj)
705 {
706     HMODULE hOle32 = GetModuleHandle("ole32");
707     if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
708     {
709         trace("You need DCOM95 installed to run this test\n");
710         return;
711     }
712
713     test_ProgIDFromCLSID();
714     test_CLSIDFromProgID();
715     test_CLSIDFromString();
716     test_CoCreateInstance();
717     test_ole_menu();
718     test_CoGetClassObject();
719     test_CoRegisterMessageFilter();
720     test_CoRegisterPSClsid();
721     test_CoGetPSClsid();
722     test_CoUnmarshalInterface();
723     test_CoGetInterfaceAndReleaseStream();
724     test_CoMarshalInterface();
725     test_CoMarshalInterThreadInterfaceInStream();
726     test_CoRegisterClassObject();
727 }