query: Add a stub implementation for LocateCatalogs.
[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
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
28 #include "shlguid.h"
29
30 #include "wine/test.h"
31
32 /* functions that are not present on all versions of Windows */
33 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
34
35 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08lx\n", hr)
36
37 static const CLSID CLSID_non_existent =   { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
38 static const CLSID CLSID_CDeviceMoniker = { 0x4315d437, 0x5b8c, 0x11d0, { 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86 } };
39 static const WCHAR devicedotone[] = {'d','e','v','i','c','e','.','1',0};
40 static const WCHAR wszCLSID_CDeviceMoniker[] =
41 {
42     '{',
43     '4','3','1','5','d','4','3','7','-',
44     '5','b','8','c','-',
45     '1','1','d','0','-',
46     'b','d','3','b','-',
47     '0','0','a','0','c','9','1','1','c','e','8','6',
48     '}',0
49 };
50
51 static const IID IID_IWineTest =
52 {
53     0x5201163f,
54     0x8164,
55     0x4fd0,
56     {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
57 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
58
59
60 static void test_ProgIDFromCLSID(void)
61 {
62     LPWSTR progid;
63     HRESULT hr = ProgIDFromCLSID(&CLSID_CDeviceMoniker, &progid);
64     ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08lx\n", hr);
65     if (hr == S_OK)
66     {
67         ok(!lstrcmpiW(progid, devicedotone), "Didn't get expected prog ID\n");
68         CoTaskMemFree(progid);
69     }
70
71     progid = (LPWSTR)0xdeadbeef;
72     hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
73     ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08lx\n", hr);
74     ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
75 }
76
77 static void test_CLSIDFromProgID(void)
78 {
79     CLSID clsid;
80     HRESULT hr = CLSIDFromProgID(devicedotone, &clsid);
81     ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08lx\n", hr);
82     ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
83
84     hr = CLSIDFromString((LPOLESTR)devicedotone, &clsid);
85     ok_ole_success(hr, "CLSIDFromString");
86     ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
87 }
88
89 static void test_CLSIDFromString(void)
90 {
91     CLSID clsid;
92     HRESULT hr = CLSIDFromString((LPOLESTR)wszCLSID_CDeviceMoniker, &clsid);
93     ok_ole_success(hr, "CLSIDFromString");
94     ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
95 }
96
97 static void test_CoCreateInstance(void)
98 {
99     REFCLSID rclsid = &CLSID_MyComputer;
100     IUnknown *pUnk = (IUnknown *)0xdeadbeef;
101     HRESULT hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
102     ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08lx\n", hr);
103     ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
104
105     OleInitialize(NULL);
106     hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
107     ok_ole_success(hr, "CoCreateInstance");
108     IUnknown_Release(pUnk);
109     OleUninitialize();
110
111     hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
112     ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08lx\n", hr);
113 }
114
115 static void test_CoGetClassObject(void)
116 {
117     IUnknown *pUnk = (IUnknown *)0xdeadbeef;
118     HRESULT hr = CoGetClassObject(&CLSID_MyComputer, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
119     ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08lx\n", hr);
120     ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
121
122     hr = CoGetClassObject(&CLSID_MyComputer, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
123     ok(hr == E_INVALIDARG, "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08lx\n", hr);
124 }
125
126 static ATOM register_dummy_class(void)
127 {
128     WNDCLASS wc =
129     {
130         0,
131         DefWindowProc,
132         0,
133         0,
134         GetModuleHandle(NULL),
135         NULL,
136         LoadCursor(NULL, IDC_ARROW),
137         (HBRUSH)(COLOR_BTNFACE+1),
138         NULL,
139         TEXT("WineOleTestClass"),
140     };
141     
142     return RegisterClass(&wc);
143 }
144
145 static void test_ole_menu(void)
146 {
147         HWND hwndFrame;
148         HRESULT hr;
149
150         hwndFrame = CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
151         hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
152         todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
153
154         DestroyWindow(hwndFrame);
155 }
156
157
158 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
159 {
160     if (ppvObj == NULL) return E_POINTER;
161
162     if (IsEqualGUID(riid, &IID_IUnknown) ||
163         IsEqualGUID(riid, &IID_IClassFactory))
164     {
165         *ppvObj = (LPVOID)iface;
166         IMessageFilter_AddRef(iface);
167         return S_OK;
168     }
169
170     return E_NOINTERFACE;
171 }
172
173 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
174 {
175     return 2; /* non-heap object */
176 }
177
178 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
179 {
180     return 1; /* non-heap object */
181 }
182
183 static DWORD WINAPI MessageFilter_HandleInComingCall(
184   IMessageFilter *iface,
185   DWORD dwCallType,
186   HTASK threadIDCaller,
187   DWORD dwTickCount,
188   LPINTERFACEINFO lpInterfaceInfo)
189 {
190     trace("HandleInComingCall\n");
191     return SERVERCALL_ISHANDLED;
192 }
193
194 static DWORD WINAPI MessageFilter_RetryRejectedCall(
195   IMessageFilter *iface,
196   HTASK threadIDCallee,
197   DWORD dwTickCount,
198   DWORD dwRejectType)
199 {
200     trace("RetryRejectedCall\n");
201     return 0;
202 }
203
204 static DWORD WINAPI MessageFilter_MessagePending(
205   IMessageFilter *iface,
206   HTASK threadIDCallee,
207   DWORD dwTickCount,
208   DWORD dwPendingType)
209 {
210     trace("MessagePending\n");
211     return PENDINGMSG_WAITNOPROCESS;
212 }
213
214 static const IMessageFilterVtbl MessageFilter_Vtbl =
215 {
216     MessageFilter_QueryInterface,
217     MessageFilter_AddRef,
218     MessageFilter_Release,
219     MessageFilter_HandleInComingCall,
220     MessageFilter_RetryRejectedCall,
221     MessageFilter_MessagePending
222 };
223
224 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
225
226 static void test_CoRegisterMessageFilter(void)
227 {
228     HRESULT hr;
229     IMessageFilter *prev_filter;
230
231 #if 0 /* crashes without an apartment! */
232     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
233 #endif
234
235     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
236     prev_filter = (IMessageFilter *)0xdeadbeef;
237     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
238     ok(hr == CO_E_NOT_SUPPORTED,
239         "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08lx\n",
240         hr);
241     ok(prev_filter == (IMessageFilter *)0xdeadbeef,
242         "prev_filter should have been set to %p\n", prev_filter);
243     CoUninitialize();
244
245     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
246
247     hr = CoRegisterMessageFilter(NULL, NULL);
248     ok_ole_success(hr, "CoRegisterMessageFilter");
249
250     prev_filter = (IMessageFilter *)0xdeadbeef;
251     hr = CoRegisterMessageFilter(NULL, &prev_filter);
252     ok_ole_success(hr, "CoRegisterMessageFilter");
253     ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
254
255     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
256     ok_ole_success(hr, "CoRegisterMessageFilter");
257     ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
258
259     hr = CoRegisterMessageFilter(NULL, NULL);
260     ok_ole_success(hr, "CoRegisterMessageFilter");
261
262     CoUninitialize();
263 }
264
265 static HRESULT WINAPI Test_IUnknown_QueryInterface(
266     LPUNKNOWN iface,
267     REFIID riid,
268     LPVOID *ppvObj)
269 {
270     if (ppvObj == NULL) return E_POINTER;
271
272     if (IsEqualIID(riid, &IID_IUnknown) ||
273         IsEqualIID(riid, &IID_IWineTest))
274     {
275         *ppvObj = (LPVOID)iface;
276         IUnknown_AddRef(iface);
277         return S_OK;
278     }
279
280     *ppvObj = NULL;
281     return E_NOINTERFACE;
282 }
283
284 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
285 {
286     return 2; /* non-heap-based object */
287 }
288
289 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
290 {
291     return 1; /* non-heap-based object */
292 }
293
294 static const IUnknownVtbl TestUnknown_Vtbl =
295 {
296     Test_IUnknown_QueryInterface,
297     Test_IUnknown_AddRef,
298     Test_IUnknown_Release,
299 };
300
301 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
302
303 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
304     IPSFactoryBuffer * This,
305     /* [in] */ REFIID riid,
306     /* [iid_is][out] */ void **ppvObject)
307 {
308     if (IsEqualIID(riid, &IID_IUnknown) ||
309         IsEqualIID(riid, &IID_IPSFactoryBuffer))
310     {
311         *ppvObject = This;
312         IPSFactoryBuffer_AddRef(This);
313         return S_OK;
314     }
315     return E_NOINTERFACE;
316 }
317         
318 static ULONG WINAPI PSFactoryBuffer_AddRef(
319     IPSFactoryBuffer * This)
320 {
321     return 2;
322 }
323
324 static ULONG WINAPI PSFactoryBuffer_Release(
325     IPSFactoryBuffer * This)
326 {
327     return 1;
328 }
329
330 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
331     IPSFactoryBuffer * This,
332     /* [in] */ IUnknown *pUnkOuter,
333     /* [in] */ REFIID riid,
334     /* [out] */ IRpcProxyBuffer **ppProxy,
335     /* [out] */ void **ppv)
336 {
337     return E_NOTIMPL;
338 }
339         
340 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
341     IPSFactoryBuffer * This,
342     /* [in] */ REFIID riid,
343     /* [unique][in] */ IUnknown *pUnkServer,
344     /* [out] */ IRpcStubBuffer **ppStub)
345 {
346     return E_NOTIMPL;
347 }
348
349 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
350 {
351     PSFactoryBuffer_QueryInterface,
352     PSFactoryBuffer_AddRef,
353     PSFactoryBuffer_Release,
354     PSFactoryBuffer_CreateProxy,
355     PSFactoryBuffer_CreateStub
356 };
357
358 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
359
360 static const CLSID CLSID_WineTestPSFactoryBuffer =
361 {
362     0x52011640,
363     0x8164,
364     0x4fd0,
365     {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
366 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
367
368 static void test_CoRegisterPSClsid(void)
369 {
370     HRESULT hr;
371     DWORD dwRegistrationKey;
372     IStream *stream;
373     CLSID clsid;
374
375     hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
376     ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returened CO_E_NOTINITIALIZED instead of 0x%08lx\n", hr);
377
378     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
379
380     hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
381         CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
382     ok_ole_success(hr, "CoRegisterClassObject");
383
384     hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
385     ok_ole_success(hr, "CoRegisterPSClsid");
386
387     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
388     ok_ole_success(hr, "CreateStreamOnHGlobal");
389
390     hr = CoMarshalInterface(stream, &IID_IWineTest, (IUnknown *)&Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
391     ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08lx\n", hr);
392     IStream_Release(stream);
393
394     hr = CoRevokeClassObject(dwRegistrationKey);
395     ok_ole_success(hr, "CoRevokeClassObject");
396
397     CoUninitialize();
398
399     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
400
401     hr = CoGetPSClsid(&IID_IWineTest, &clsid);
402     ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08lx\n", hr);
403
404     CoUninitialize();
405 }
406
407 START_TEST(compobj)
408 {
409     HMODULE hOle32 = GetModuleHandle("ole32");
410     if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
411     {
412         trace("You need DCOM95 installed to run this test\n");
413         return;
414     }
415
416     test_ProgIDFromCLSID();
417     test_CLSIDFromProgID();
418     test_CLSIDFromString();
419     test_CoCreateInstance();
420     test_ole_menu();
421     test_CoGetClassObject();
422     test_CoRegisterMessageFilter();
423     test_CoRegisterPSClsid();
424 }