Merge my current work done on the kd++ branch:
[reactos.git] / rostests / winetests / ole32 / 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 WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27
28 #include <stdarg.h>
29
30 #include <windef.h>
31 #include <winbase.h>
32 #include <winreg.h>
33 #define USE_COM_CONTEXT_DEF
34 //#include "initguid.h"
35 //#include "objbase.h"
36 //#include "shlguid.h"
37 #include <ole2.h>
38 //#include "urlmon.h" /* for CLSID_FileProtocol */
39
40 #include <ctxtcall.h>
41
42 #include <wine/test.h>
43
44 extern const IID GUID_NULL;
45
46 /* functions that are not present on all versions of Windows */
47 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
48 static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
49 static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
50 static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
51 static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
52 static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
53
54 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
55 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
56 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
57
58 static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
59 static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
60 static WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
61 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
62 static WCHAR wszCLSID_StdFont[] =
63 {
64 '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
65 '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
66 };
67
68 static const IID IID_IWineTest =
69 {
70 0x5201163f,
71 0x8164,
72 0x4fd0,
73 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
74 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
75 static const CLSID CLSID_WineOOPTest = {
76 0x5201163f,
77 0x8164,
78 0x4fd0,
79 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
80 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
81
82 static LONG cLocks;
83
84 static void LockModule(void)
85 {
86 InterlockedIncrement(&cLocks);
87 }
88
89 static void UnlockModule(void)
90 {
91 InterlockedDecrement(&cLocks);
92 }
93
94 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
95 LPCLASSFACTORY iface,
96 REFIID riid,
97 LPVOID *ppvObj)
98 {
99 if (ppvObj == NULL) return E_POINTER;
100
101 if (IsEqualGUID(riid, &IID_IUnknown) ||
102 IsEqualGUID(riid, &IID_IClassFactory))
103 {
104 *ppvObj = iface;
105 IClassFactory_AddRef(iface);
106 return S_OK;
107 }
108
109 *ppvObj = NULL;
110 return E_NOINTERFACE;
111 }
112
113 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
114 {
115 LockModule();
116 return 2; /* non-heap-based object */
117 }
118
119 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
120 {
121 UnlockModule();
122 return 1; /* non-heap-based object */
123 }
124
125 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
126 LPCLASSFACTORY iface,
127 IUnknown *pUnkOuter,
128 REFIID riid,
129 LPVOID *ppvObj)
130 {
131 *ppvObj = NULL;
132 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
133 return E_NOINTERFACE;
134 }
135
136 static HRESULT WINAPI Test_IClassFactory_LockServer(
137 LPCLASSFACTORY iface,
138 BOOL fLock)
139 {
140 return S_OK;
141 }
142
143 static const IClassFactoryVtbl TestClassFactory_Vtbl =
144 {
145 Test_IClassFactory_QueryInterface,
146 Test_IClassFactory_AddRef,
147 Test_IClassFactory_Release,
148 Test_IClassFactory_CreateInstance,
149 Test_IClassFactory_LockServer
150 };
151
152 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
153
154 static void test_ProgIDFromCLSID(void)
155 {
156 LPWSTR progid;
157 HRESULT hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
158 ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
159 if (hr == S_OK)
160 {
161 ok(!lstrcmpiW(progid, stdfont), "Didn't get expected prog ID\n");
162 CoTaskMemFree(progid);
163 }
164
165 progid = (LPWSTR)0xdeadbeef;
166 hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
167 ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
168 ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
169
170 hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
171 ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
172 }
173
174 static void test_CLSIDFromProgID(void)
175 {
176 CLSID clsid;
177 HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
178 ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
179 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
180
181 hr = CLSIDFromString(stdfont, &clsid);
182 ok_ole_success(hr, "CLSIDFromString");
183 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
184
185 /* test some failure cases */
186
187 hr = CLSIDFromProgID(wszNonExistent, NULL);
188 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
189
190 hr = CLSIDFromProgID(NULL, &clsid);
191 ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
192
193 memset(&clsid, 0xcc, sizeof(clsid));
194 hr = CLSIDFromProgID(wszNonExistent, &clsid);
195 ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
196 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
197 }
198
199 static void test_CLSIDFromString(void)
200 {
201 CLSID clsid;
202 WCHAR wszCLSID_Broken[50];
203 UINT i;
204
205 HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
206 ok_ole_success(hr, "CLSIDFromString");
207 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
208
209 hr = CLSIDFromString(NULL, &clsid);
210 ok_ole_success(hr, "CLSIDFromString");
211 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
212
213 lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
214 for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
215 wszCLSID_Broken[i] = 'A';
216 wszCLSID_Broken[i] = '\0';
217
218 memset(&clsid, 0, sizeof(CLSID));
219 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
220 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
221 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
222
223 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
224 memset(&clsid, 0, sizeof(CLSID));
225 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
226 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
227 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
228
229 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
230 memset(&clsid, 0, sizeof(CLSID));
231 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
232 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
233 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
234
235 wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
236 memset(&clsid, 0, sizeof(CLSID));
237 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
238 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
239 ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
240
241 memset(&clsid, 0xcc, sizeof(CLSID));
242 hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
243 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
244 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
245
246 wszCLSID_Broken[9] = '*';
247 memset(&clsid, 0xcc, sizeof(CLSID));
248 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
249 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
250 ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
251 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
252
253 wszCLSID_Broken[3] = '*';
254 memset(&clsid, 0xcc, sizeof(CLSID));
255 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
256 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
257 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
258 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
259
260 wszCLSID_Broken[3] = '\0';
261 memset(&clsid, 0xcc, sizeof(CLSID));
262 hr = CLSIDFromString(wszCLSID_Broken, &clsid);
263 ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
264 ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
265 ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
266 }
267
268 static void test_StringFromGUID2(void)
269 {
270 WCHAR str[50];
271 int len;
272
273 /* invalid pointer */
274 SetLastError(0xdeadbeef);
275 len = StringFromGUID2(NULL,str,50);
276 ok(len == 0, "len: %d (expected 0)\n", len);
277 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
278
279 /* Test corner cases for buffer size */
280 len = StringFromGUID2(&CLSID_StdFont,str,50);
281 ok(len == 39, "len: %d (expected 39)\n", len);
282 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
283
284 memset(str,0,sizeof str);
285 len = StringFromGUID2(&CLSID_StdFont,str,39);
286 ok(len == 39, "len: %d (expected 39)\n", len);
287 ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
288
289 len = StringFromGUID2(&CLSID_StdFont,str,38);
290 ok(len == 0, "len: %d (expected 0)\n", len);
291
292 len = StringFromGUID2(&CLSID_StdFont,str,30);
293 ok(len == 0, "len: %d (expected 0)\n", len);
294 }
295
296 struct info
297 {
298 HANDLE wait, stop;
299 };
300
301 static DWORD CALLBACK ole_initialize_thread(LPVOID pv)
302 {
303 HRESULT hr;
304 struct info *info = pv;
305
306 hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
307
308 SetEvent(info->wait);
309 WaitForSingleObject(info->stop, 10000);
310
311 CoUninitialize();
312 return hr;
313 }
314
315 static void test_CoCreateInstance(void)
316 {
317 HRESULT hr;
318 HANDLE thread;
319 DWORD tid, exitcode;
320 IUnknown *pUnk;
321 struct info info;
322 REFCLSID rclsid = &CLSID_InternetZoneManager;
323
324 pUnk = (IUnknown *)0xdeadbeef;
325 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
326 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
327 ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
328
329 OleInitialize(NULL);
330
331 /* test errors returned for non-registered clsids */
332 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
333 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
334 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pUnk);
335 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
336 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (void **)&pUnk);
337 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
338 hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_REMOTE_SERVER, &IID_IUnknown, (void **)&pUnk);
339 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
340
341 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
342 if(hr == REGDB_E_CLASSNOTREG)
343 {
344 skip("IE not installed so can't test CoCreateInstance\n");
345 OleUninitialize();
346 return;
347 }
348
349 ok_ole_success(hr, "CoCreateInstance");
350 if(pUnk) IUnknown_Release(pUnk);
351 OleUninitialize();
352
353 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
354 ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
355
356 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
357 thread has already done so */
358
359 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
360 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
361
362 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
363 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
364
365 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
366 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
367
368 ok( !WaitForSingleObject(info.wait, 10000 ), "wait timed out\n" );
369
370 pUnk = (IUnknown *)0xdeadbeef;
371 hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
372 ok(hr == S_OK, "CoCreateInstance should have returned S_OK instead of 0x%08x\n", hr);
373 if (pUnk) IUnknown_Release(pUnk);
374
375 SetEvent(info.stop);
376 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
377
378 GetExitCodeThread(thread, &exitcode);
379 hr = exitcode;
380 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
381
382 CloseHandle(thread);
383 CloseHandle(info.wait);
384 CloseHandle(info.stop);
385 }
386
387 static void test_CoGetClassObject(void)
388 {
389 HRESULT hr;
390 HANDLE thread;
391 DWORD tid, exitcode;
392 IUnknown *pUnk;
393 struct info info;
394 REFCLSID rclsid = &CLSID_InternetZoneManager;
395 HKEY hkey;
396 LONG res;
397
398 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
399 ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
400 ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
401
402 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
403 ok(hr == E_INVALIDARG ||
404 broken(hr == CO_E_NOTINITIALIZED), /* win9x */
405 "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
406
407 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
408 thread has already done so */
409
410 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
411 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
412
413 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
414 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
415
416 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
417 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
418
419 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
420
421 pUnk = (IUnknown *)0xdeadbeef;
422 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
423 if(hr == REGDB_E_CLASSNOTREG)
424 skip("IE not installed so can't test CoGetClassObject\n");
425 else
426 {
427 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
428 if (pUnk) IUnknown_Release(pUnk);
429 }
430
431 SetEvent(info.stop);
432 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
433
434 GetExitCodeThread(thread, &exitcode);
435 hr = exitcode;
436 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
437
438 CloseHandle(thread);
439 CloseHandle(info.wait);
440 CloseHandle(info.stop);
441
442 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
443
444 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
445 if (hr == S_OK)
446 {
447 IUnknown_Release(pUnk);
448
449 res = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &hkey);
450 ok(!res, "RegOpenKeyExA returned %d\n", res);
451
452 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
453 ok(!res, "RegOverridePredefKey returned %d\n", res);
454
455 hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
456 ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
457
458 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
459 ok(!res, "RegOverridePredefKey returned %d\n", res);
460
461 if (hr == S_OK) IUnknown_Release(pUnk);
462 RegCloseKey(hkey);
463 }
464 CoUninitialize();
465 }
466
467 static ATOM register_dummy_class(void)
468 {
469 WNDCLASS wc =
470 {
471 0,
472 DefWindowProc,
473 0,
474 0,
475 GetModuleHandle(NULL),
476 NULL,
477 LoadCursor(NULL, IDC_ARROW),
478 (HBRUSH)(COLOR_BTNFACE+1),
479 NULL,
480 TEXT("WineOleTestClass"),
481 };
482
483 return RegisterClass(&wc);
484 }
485
486 static void test_ole_menu(void)
487 {
488 HWND hwndFrame;
489 HRESULT hr;
490
491 hwndFrame = CreateWindow(MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
492 hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
493 todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
494
495 DestroyWindow(hwndFrame);
496 }
497
498
499 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
500 {
501 if (ppvObj == NULL) return E_POINTER;
502
503 if (IsEqualGUID(riid, &IID_IUnknown) ||
504 IsEqualGUID(riid, &IID_IClassFactory))
505 {
506 *ppvObj = iface;
507 IMessageFilter_AddRef(iface);
508 return S_OK;
509 }
510
511 return E_NOINTERFACE;
512 }
513
514 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
515 {
516 return 2; /* non-heap object */
517 }
518
519 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
520 {
521 return 1; /* non-heap object */
522 }
523
524 static DWORD WINAPI MessageFilter_HandleInComingCall(
525 IMessageFilter *iface,
526 DWORD dwCallType,
527 HTASK threadIDCaller,
528 DWORD dwTickCount,
529 LPINTERFACEINFO lpInterfaceInfo)
530 {
531 trace("HandleInComingCall\n");
532 return SERVERCALL_ISHANDLED;
533 }
534
535 static DWORD WINAPI MessageFilter_RetryRejectedCall(
536 IMessageFilter *iface,
537 HTASK threadIDCallee,
538 DWORD dwTickCount,
539 DWORD dwRejectType)
540 {
541 trace("RetryRejectedCall\n");
542 return 0;
543 }
544
545 static DWORD WINAPI MessageFilter_MessagePending(
546 IMessageFilter *iface,
547 HTASK threadIDCallee,
548 DWORD dwTickCount,
549 DWORD dwPendingType)
550 {
551 trace("MessagePending\n");
552 return PENDINGMSG_WAITNOPROCESS;
553 }
554
555 static const IMessageFilterVtbl MessageFilter_Vtbl =
556 {
557 MessageFilter_QueryInterface,
558 MessageFilter_AddRef,
559 MessageFilter_Release,
560 MessageFilter_HandleInComingCall,
561 MessageFilter_RetryRejectedCall,
562 MessageFilter_MessagePending
563 };
564
565 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
566
567 static void test_CoRegisterMessageFilter(void)
568 {
569 HRESULT hr;
570 IMessageFilter *prev_filter;
571
572 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
573 ok(hr == CO_E_NOT_SUPPORTED,
574 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
575 hr);
576
577 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
578 prev_filter = (IMessageFilter *)0xdeadbeef;
579 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
580 ok(hr == CO_E_NOT_SUPPORTED,
581 "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
582 hr);
583 ok(prev_filter == (IMessageFilter *)0xdeadbeef,
584 "prev_filter should have been set to %p\n", prev_filter);
585 CoUninitialize();
586
587 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
588
589 hr = CoRegisterMessageFilter(NULL, NULL);
590 ok_ole_success(hr, "CoRegisterMessageFilter");
591
592 prev_filter = (IMessageFilter *)0xdeadbeef;
593 hr = CoRegisterMessageFilter(NULL, &prev_filter);
594 ok_ole_success(hr, "CoRegisterMessageFilter");
595 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
596
597 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
598 ok_ole_success(hr, "CoRegisterMessageFilter");
599 ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
600
601 hr = CoRegisterMessageFilter(NULL, NULL);
602 ok_ole_success(hr, "CoRegisterMessageFilter");
603
604 CoUninitialize();
605 }
606
607 static HRESULT WINAPI Test_IUnknown_QueryInterface(
608 IUnknown *iface,
609 REFIID riid,
610 LPVOID *ppvObj)
611 {
612 if (ppvObj == NULL) return E_POINTER;
613
614 if (IsEqualIID(riid, &IID_IUnknown) ||
615 IsEqualIID(riid, &IID_IWineTest))
616 {
617 *ppvObj = iface;
618 IUnknown_AddRef(iface);
619 return S_OK;
620 }
621
622 *ppvObj = NULL;
623 return E_NOINTERFACE;
624 }
625
626 static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
627 {
628 return 2; /* non-heap-based object */
629 }
630
631 static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
632 {
633 return 1; /* non-heap-based object */
634 }
635
636 static const IUnknownVtbl TestUnknown_Vtbl =
637 {
638 Test_IUnknown_QueryInterface,
639 Test_IUnknown_AddRef,
640 Test_IUnknown_Release,
641 };
642
643 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
644
645 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
646 IPSFactoryBuffer * This,
647 /* [in] */ REFIID riid,
648 /* [iid_is][out] */ void **ppvObject)
649 {
650 if (IsEqualIID(riid, &IID_IUnknown) ||
651 IsEqualIID(riid, &IID_IPSFactoryBuffer))
652 {
653 *ppvObject = This;
654 IPSFactoryBuffer_AddRef(This);
655 return S_OK;
656 }
657 return E_NOINTERFACE;
658 }
659
660 static ULONG WINAPI PSFactoryBuffer_AddRef(
661 IPSFactoryBuffer * This)
662 {
663 return 2;
664 }
665
666 static ULONG WINAPI PSFactoryBuffer_Release(
667 IPSFactoryBuffer * This)
668 {
669 return 1;
670 }
671
672 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
673 IPSFactoryBuffer * This,
674 /* [in] */ IUnknown *pUnkOuter,
675 /* [in] */ REFIID riid,
676 /* [out] */ IRpcProxyBuffer **ppProxy,
677 /* [out] */ void **ppv)
678 {
679 return E_NOTIMPL;
680 }
681
682 static HRESULT WINAPI PSFactoryBuffer_CreateStub(
683 IPSFactoryBuffer * This,
684 /* [in] */ REFIID riid,
685 /* [unique][in] */ IUnknown *pUnkServer,
686 /* [out] */ IRpcStubBuffer **ppStub)
687 {
688 return E_NOTIMPL;
689 }
690
691 static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
692 {
693 PSFactoryBuffer_QueryInterface,
694 PSFactoryBuffer_AddRef,
695 PSFactoryBuffer_Release,
696 PSFactoryBuffer_CreateProxy,
697 PSFactoryBuffer_CreateStub
698 };
699
700 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
701
702 static const CLSID CLSID_WineTestPSFactoryBuffer =
703 {
704 0x52011640,
705 0x8164,
706 0x4fd0,
707 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
708 }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
709
710 static void test_CoRegisterPSClsid(void)
711 {
712 HRESULT hr;
713 DWORD dwRegistrationKey;
714 IStream *stream;
715 CLSID clsid;
716
717 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
718 ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
719
720 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
721
722 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
723 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
724 ok_ole_success(hr, "CoRegisterClassObject");
725
726 hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
727 ok_ole_success(hr, "CoRegisterPSClsid");
728
729 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
730 ok_ole_success(hr, "CreateStreamOnHGlobal");
731
732 hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
733 ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
734 IStream_Release(stream);
735
736 hr = CoRevokeClassObject(dwRegistrationKey);
737 ok_ole_success(hr, "CoRevokeClassObject");
738
739 CoUninitialize();
740
741 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
742
743 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
744 ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
745
746 CoUninitialize();
747 }
748
749 static void test_CoGetPSClsid(void)
750 {
751 HRESULT hr;
752 CLSID clsid;
753 HKEY hkey;
754 LONG res;
755
756 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
757 ok(hr == CO_E_NOTINITIALIZED,
758 "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
759 hr);
760
761 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
762
763 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
764 ok_ole_success(hr, "CoGetPSClsid");
765
766 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
767 ok(hr == REGDB_E_IIDNOTREG,
768 "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
769 hr);
770
771 hr = CoGetPSClsid(&IID_IClassFactory, NULL);
772 ok(hr == E_INVALIDARG,
773 "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
774 hr);
775
776 if (!pRegOverridePredefKey)
777 {
778 win_skip("RegOverridePredefKey not available\n");
779 CoUninitialize();
780 return;
781 }
782 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
783 ok_ole_success(hr, "CoGetPSClsid");
784
785 res = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &hkey);
786 ok(!res, "RegOpenKeyExA returned %d\n", res);
787
788 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
789 ok(!res, "RegOverridePredefKey returned %d\n", res);
790
791 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
792 ok_ole_success(hr, "CoGetPSClsid");
793
794 res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
795 ok(!res, "RegOverridePredefKey returned %d\n", res);
796
797 RegCloseKey(hkey);
798 CoUninitialize();
799 }
800
801 /* basic test, mainly for invalid arguments. see marshal.c for more */
802 static void test_CoUnmarshalInterface(void)
803 {
804 IUnknown *pProxy;
805 IStream *pStream;
806 HRESULT hr;
807
808 hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
809 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
810
811 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
812 ok_ole_success(hr, "CreateStreamOnHGlobal");
813
814 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
815 todo_wine
816 ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
817
818 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
819
820 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
821 ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
822
823 CoUninitialize();
824
825 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
826 ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
827
828 IStream_Release(pStream);
829 }
830
831 static void test_CoGetInterfaceAndReleaseStream(void)
832 {
833 HRESULT hr;
834 IUnknown *pUnk;
835
836 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
837
838 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
839 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
840
841 CoUninitialize();
842 }
843
844 /* basic test, mainly for invalid arguments. see marshal.c for more */
845 static void test_CoMarshalInterface(void)
846 {
847 IStream *pStream;
848 HRESULT hr;
849 static const LARGE_INTEGER llZero;
850
851 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
852
853 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
854 ok_ole_success(hr, "CreateStreamOnHGlobal");
855
856 hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
857 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
858
859 hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
860 ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
861
862 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
863 ok_ole_success(hr, "CoMarshalInterface");
864
865 /* stream not rewound */
866 hr = CoReleaseMarshalData(pStream);
867 ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
868
869 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
870 ok_ole_success(hr, "IStream_Seek");
871
872 hr = CoReleaseMarshalData(pStream);
873 ok_ole_success(hr, "CoReleaseMarshalData");
874
875 IStream_Release(pStream);
876
877 CoUninitialize();
878 }
879
880 static void test_CoMarshalInterThreadInterfaceInStream(void)
881 {
882 IStream *pStream;
883 HRESULT hr;
884 IClassFactory *pProxy;
885
886 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
887
888 cLocks = 0;
889
890 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
891 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
892
893 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
894 ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
895
896 ok_no_locks();
897
898 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
899 ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
900
901 ok_more_than_one_lock();
902
903 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
904 ok_ole_success(hr, "CoUnmarshalInterface");
905
906 IClassFactory_Release(pProxy);
907 IStream_Release(pStream);
908
909 ok_no_locks();
910
911 CoUninitialize();
912 }
913
914 static void test_CoRegisterClassObject(void)
915 {
916 DWORD cookie;
917 HRESULT hr;
918 IClassFactory *pcf;
919
920 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
921
922 /* CLSCTX_INPROC_SERVER */
923 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
924 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
925 ok_ole_success(hr, "CoRegisterClassObject");
926 hr = CoRevokeClassObject(cookie);
927 ok_ole_success(hr, "CoRevokeClassObject");
928
929 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
930 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
931 ok_ole_success(hr, "CoRegisterClassObject");
932 hr = CoRevokeClassObject(cookie);
933 ok_ole_success(hr, "CoRevokeClassObject");
934
935 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
936 CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
937 ok_ole_success(hr, "CoRegisterClassObject");
938 hr = CoRevokeClassObject(cookie);
939 ok_ole_success(hr, "CoRevokeClassObject");
940
941 /* CLSCTX_LOCAL_SERVER */
942 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
943 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
944 ok_ole_success(hr, "CoRegisterClassObject");
945 hr = CoRevokeClassObject(cookie);
946 ok_ole_success(hr, "CoRevokeClassObject");
947
948 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
949 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
950 ok_ole_success(hr, "CoRegisterClassObject");
951 hr = CoRevokeClassObject(cookie);
952 ok_ole_success(hr, "CoRevokeClassObject");
953
954 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
955 CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
956 ok_ole_success(hr, "CoRegisterClassObject");
957 hr = CoRevokeClassObject(cookie);
958 ok_ole_success(hr, "CoRevokeClassObject");
959
960 /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
961 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
962 CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
963 ok_ole_success(hr, "CoRegisterClassObject");
964 hr = CoRevokeClassObject(cookie);
965 ok_ole_success(hr, "CoRevokeClassObject");
966
967 /* test whether an object that doesn't support IClassFactory can be
968 * registered for CLSCTX_LOCAL_SERVER */
969 hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
970 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
971 ok_ole_success(hr, "CoRegisterClassObject");
972 hr = CoRevokeClassObject(cookie);
973 ok_ole_success(hr, "CoRevokeClassObject");
974
975 /* test whether registered class becomes invalid when apartment is destroyed */
976 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
977 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
978 ok_ole_success(hr, "CoRegisterClassObject");
979
980 CoUninitialize();
981 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
982
983 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
984 &IID_IClassFactory, (void **)&pcf);
985 ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
986
987 /* crashes with at least win9x DCOM! */
988 if (0)
989 CoRevokeClassObject(cookie);
990
991 CoUninitialize();
992 }
993
994 static HRESULT get_class_object(CLSCTX clsctx)
995 {
996 HRESULT hr;
997 IClassFactory *pcf;
998
999 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1000 (void **)&pcf);
1001
1002 if (SUCCEEDED(hr))
1003 IClassFactory_Release(pcf);
1004
1005 return hr;
1006 }
1007
1008 static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1009 {
1010 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1011 HRESULT hr;
1012
1013 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1014
1015 hr = get_class_object(clsctx);
1016
1017 CoUninitialize();
1018
1019 return hr;
1020 }
1021
1022 static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1023 {
1024 CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1025 HRESULT hr;
1026 IClassFactory *pcf;
1027 IMultiQI *pMQI;
1028
1029 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1030
1031 hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1032 (void **)&pcf);
1033
1034 if (SUCCEEDED(hr))
1035 {
1036 hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1037 if (SUCCEEDED(hr))
1038 IMultiQI_Release(pMQI);
1039 IClassFactory_Release(pcf);
1040 }
1041
1042 CoUninitialize();
1043
1044 return hr;
1045 }
1046
1047 static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1048 {
1049 HRESULT hr;
1050 DWORD cookie;
1051
1052 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1053
1054 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1055 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1056
1057 CoUninitialize();
1058
1059 return hr;
1060 }
1061
1062 static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1063 {
1064 DWORD cookie = (DWORD_PTR)pv;
1065 HRESULT hr;
1066
1067 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1068
1069 hr = CoRevokeClassObject(cookie);
1070
1071 CoUninitialize();
1072
1073 return hr;
1074 }
1075
1076 static void test_registered_object_thread_affinity(void)
1077 {
1078 HRESULT hr;
1079 DWORD cookie;
1080 HANDLE thread;
1081 DWORD tid;
1082 DWORD exitcode;
1083
1084 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1085
1086 /* CLSCTX_INPROC_SERVER */
1087
1088 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1089 CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1090 ok_ole_success(hr, "CoRegisterClassObject");
1091
1092 thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1093 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1094 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1095 GetExitCodeThread(thread, &exitcode);
1096 hr = exitcode;
1097 ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1098 "registered in different thread should return REGDB_E_CLASSNOTREG "
1099 "instead of 0x%08x\n", hr);
1100
1101 hr = get_class_object(CLSCTX_INPROC_SERVER);
1102 ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1103 "thread should return S_OK instead of 0x%08x\n", hr);
1104
1105 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1106 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1107 ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1108 GetExitCodeThread(thread, &exitcode);
1109 hr = exitcode;
1110 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1111
1112 hr = CoRevokeClassObject(cookie);
1113 ok_ole_success(hr, "CoRevokeClassObject");
1114
1115 /* CLSCTX_LOCAL_SERVER */
1116
1117 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1118 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1119 ok_ole_success(hr, "CoRegisterClassObject");
1120
1121 thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1122 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1123 while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1124 {
1125 MSG msg;
1126 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1127 {
1128 TranslateMessage(&msg);
1129 DispatchMessageA(&msg);
1130 }
1131 }
1132 GetExitCodeThread(thread, &exitcode);
1133 hr = exitcode;
1134 ok(hr == S_OK, "CoGetClassObject on local server object "
1135 "registered in different thread should return S_OK "
1136 "instead of 0x%08x\n", hr);
1137
1138 hr = get_class_object(CLSCTX_LOCAL_SERVER);
1139 ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1140 "thread should return S_OK instead of 0x%08x\n", hr);
1141
1142 thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid);
1143 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1144 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1145 GetExitCodeThread(thread, &exitcode);
1146 hr = exitcode;
1147 ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different "
1148 "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1149
1150 thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1151 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1152 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1153 GetExitCodeThread(thread, &exitcode);
1154 hr = exitcode;
1155 ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1156 "thread should return S_OK instead of 0x%08x\n", hr);
1157
1158 hr = CoRevokeClassObject(cookie);
1159 ok_ole_success(hr, "CoRevokeClassObject");
1160
1161 CoUninitialize();
1162 }
1163
1164 static DWORD CALLBACK free_libraries_thread(LPVOID p)
1165 {
1166 CoFreeUnusedLibraries();
1167 return 0;
1168 }
1169
1170 static inline BOOL is_module_loaded(const char *module)
1171 {
1172 return GetModuleHandle(module) != 0;
1173 }
1174
1175 static void test_CoFreeUnusedLibraries(void)
1176 {
1177 HRESULT hr;
1178 IUnknown *pUnk;
1179 DWORD tid;
1180 HANDLE thread;
1181
1182 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1183
1184 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1185
1186 hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1187 if (hr == REGDB_E_CLASSNOTREG)
1188 {
1189 skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1190 CoUninitialize();
1191 return;
1192 }
1193 ok_ole_success(hr, "CoCreateInstance");
1194
1195 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1196
1197 ok(pUnk != NULL ||
1198 broken(pUnk == NULL), /* win9x */
1199 "Expected a valid pointer\n");
1200 if (pUnk)
1201 IUnknown_Release(pUnk);
1202
1203 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1204
1205 thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1206 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1207 CloseHandle(thread);
1208
1209 ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1210
1211 CoFreeUnusedLibraries();
1212
1213 ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1214
1215 CoUninitialize();
1216 }
1217
1218 static void test_CoGetObjectContext(void)
1219 {
1220 HRESULT hr;
1221 ULONG refs;
1222 IComThreadingInfo *pComThreadingInfo;
1223 IContextCallback *pContextCallback;
1224 IObjContext *pObjContext;
1225 APTTYPE apttype;
1226 THDTYPE thdtype;
1227 struct info info;
1228 HANDLE thread;
1229 DWORD tid, exitcode;
1230
1231 if (!pCoGetObjectContext)
1232 {
1233 skip("CoGetObjectContext not present\n");
1234 return;
1235 }
1236
1237 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1238 ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1239 ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1240
1241 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1242 thread has already done so */
1243
1244 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
1245 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1246
1247 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
1248 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1249
1250 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1251 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1252
1253 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1254
1255 pComThreadingInfo = NULL;
1256 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1257 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1258 IComThreadingInfo_Release(pComThreadingInfo);
1259
1260 SetEvent(info.stop);
1261 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1262
1263 GetExitCodeThread(thread, &exitcode);
1264 hr = exitcode;
1265 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1266
1267 CloseHandle(thread);
1268 CloseHandle(info.wait);
1269 CloseHandle(info.stop);
1270
1271 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1272
1273 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1274 ok_ole_success(hr, "CoGetObjectContext");
1275
1276 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1277 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1278 ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1279
1280 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1281 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1282 ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1283
1284 refs = IComThreadingInfo_Release(pComThreadingInfo);
1285 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1286
1287 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1288 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1289
1290 if (hr == S_OK)
1291 {
1292 refs = IContextCallback_Release(pContextCallback);
1293 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1294 }
1295
1296 CoUninitialize();
1297
1298 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1299
1300 hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1301 ok_ole_success(hr, "CoGetObjectContext");
1302
1303 hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1304 ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1305 ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1306
1307 hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1308 ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1309 ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1310
1311 refs = IComThreadingInfo_Release(pComThreadingInfo);
1312 ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1313
1314 hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1315 ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1316
1317 if (hr == S_OK)
1318 {
1319 refs = IContextCallback_Release(pContextCallback);
1320 ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1321 }
1322
1323 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1324 ok_ole_success(hr, "CoGetObjectContext");
1325
1326 refs = IObjContext_Release(pObjContext);
1327 ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
1328
1329 CoUninitialize();
1330 }
1331
1332 typedef struct {
1333 IUnknown IUnknown_iface;
1334 LONG refs;
1335 } Test_CallContext;
1336
1337 static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
1338 {
1339 return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
1340 }
1341
1342 static HRESULT WINAPI Test_CallContext_QueryInterface(
1343 IUnknown *iface,
1344 REFIID riid,
1345 LPVOID *ppvObj)
1346 {
1347 if (ppvObj == NULL) return E_POINTER;
1348
1349 if (IsEqualGUID(riid, &IID_IUnknown))
1350 {
1351 *ppvObj = iface;
1352 IUnknown_AddRef(iface);
1353 return S_OK;
1354 }
1355
1356 *ppvObj = NULL;
1357 return E_NOINTERFACE;
1358 }
1359
1360 static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
1361 {
1362 Test_CallContext *This = impl_from_IUnknown(iface);
1363 return InterlockedIncrement(&This->refs);
1364 }
1365
1366 static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
1367 {
1368 Test_CallContext *This = impl_from_IUnknown(iface);
1369 ULONG refs = InterlockedDecrement(&This->refs);
1370 if (!refs)
1371 HeapFree(GetProcessHeap(), 0, This);
1372 return refs;
1373 }
1374
1375 static const IUnknownVtbl TestCallContext_Vtbl =
1376 {
1377 Test_CallContext_QueryInterface,
1378 Test_CallContext_AddRef,
1379 Test_CallContext_Release
1380 };
1381
1382 static void test_CoGetCallContext(void)
1383 {
1384 HRESULT hr;
1385 ULONG refs;
1386 IUnknown *pUnk;
1387 Test_CallContext *test_object;
1388
1389 if (!pCoSwitchCallContext)
1390 {
1391 skip("CoSwitchCallContext not present\n");
1392 return;
1393 }
1394
1395 CoInitialize(NULL);
1396
1397 test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
1398 test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
1399 test_object->refs = 1;
1400
1401 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1402 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1403
1404 pUnk = (IUnknown*)0xdeadbeef;
1405 hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
1406 ok_ole_success(hr, "CoSwitchCallContext");
1407 ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
1408 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1409 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1410 IUnknown_Release(&test_object->IUnknown_iface);
1411
1412 pUnk = (IUnknown*)0xdeadbeef;
1413 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1414 ok_ole_success(hr, "CoGetCallContext");
1415 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1416 &test_object->IUnknown_iface, pUnk);
1417 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1418 ok(refs == 3, "Expected refcount 3, got %d\n", refs);
1419 IUnknown_Release(&test_object->IUnknown_iface);
1420 IUnknown_Release(pUnk);
1421
1422 pUnk = (IUnknown*)0xdeadbeef;
1423 hr = pCoSwitchCallContext(NULL, &pUnk);
1424 ok_ole_success(hr, "CoSwitchCallContext");
1425 ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1426 &test_object->IUnknown_iface, pUnk);
1427 refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1428 ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1429 IUnknown_Release(&test_object->IUnknown_iface);
1430
1431 hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1432 ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1433
1434 IUnknown_Release(&test_object->IUnknown_iface);
1435
1436 CoUninitialize();
1437 }
1438
1439 static void test_CoGetContextToken(void)
1440 {
1441 HRESULT hr;
1442 ULONG refs;
1443 ULONG_PTR token;
1444 IObjContext *ctx;
1445 struct info info;
1446 HANDLE thread;
1447 DWORD tid, exitcode;
1448
1449 if (!pCoGetContextToken)
1450 {
1451 win_skip("CoGetContextToken not present\n");
1452 return;
1453 }
1454
1455 token = 0xdeadbeef;
1456 hr = pCoGetContextToken(&token);
1457 ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
1458 ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
1459
1460 /* show that COM doesn't have to be initialized for multi-threaded apartments if another
1461 thread has already done so */
1462
1463 info.wait = CreateEvent(NULL, TRUE, FALSE, NULL);
1464 ok(info.wait != NULL, "CreateEvent failed with error %d\n", GetLastError());
1465
1466 info.stop = CreateEvent(NULL, TRUE, FALSE, NULL);
1467 ok(info.stop != NULL, "CreateEvent failed with error %d\n", GetLastError());
1468
1469 thread = CreateThread(NULL, 0, ole_initialize_thread, &info, 0, &tid);
1470 ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1471
1472 ok( !WaitForSingleObject(info.wait, 10000), "wait timed out\n" );
1473
1474 token = 0;
1475 hr = pCoGetContextToken(&token);
1476 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1477
1478 SetEvent(info.stop);
1479 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1480
1481 GetExitCodeThread(thread, &exitcode);
1482 hr = exitcode;
1483 ok(hr == S_OK, "thread should have returned S_OK instead of 0x%08x\n", hr);
1484
1485 CloseHandle(thread);
1486 CloseHandle(info.wait);
1487 CloseHandle(info.stop);
1488
1489 CoInitialize(NULL);
1490
1491 hr = pCoGetContextToken(NULL);
1492 ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
1493
1494 token = 0;
1495 hr = pCoGetContextToken(&token);
1496 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1497 ok(token, "Expected token != 0\n");
1498
1499 refs = IUnknown_AddRef((IUnknown *)token);
1500 todo_wine ok(refs == 1, "Expected 1, got %u\n", refs);
1501
1502 hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
1503 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1504 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1505
1506 refs = IUnknown_AddRef((IUnknown *)ctx);
1507 todo_wine ok(refs == 3, "Expected 3, got %u\n", refs);
1508
1509 refs = IUnknown_Release((IUnknown *)ctx);
1510 todo_wine ok(refs == 2, "Expected 2, got %u\n", refs);
1511
1512 refs = IUnknown_Release((IUnknown *)token);
1513 ok(refs == 1, "Expected 1, got %u\n", refs);
1514
1515 /* CoGetContextToken does not add a reference */
1516 token = 0;
1517 hr = pCoGetContextToken(&token);
1518 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1519 ok(token, "Expected token != 0\n");
1520 todo_wine ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
1521
1522 refs = IUnknown_AddRef((IUnknown *)ctx);
1523 ok(refs == 2, "Expected 1, got %u\n", refs);
1524
1525 refs = IUnknown_Release((IUnknown *)ctx);
1526 ok(refs == 1, "Expected 0, got %u\n", refs);
1527
1528 refs = IUnknown_Release((IUnknown *)ctx);
1529 ok(refs == 0, "Expected 0, got %u\n", refs);
1530
1531 CoUninitialize();
1532 }
1533
1534 static void test_CoGetTreatAsClass(void)
1535 {
1536 HRESULT hr;
1537 CLSID out;
1538 static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1539
1540 if (!pCoGetTreatAsClass)
1541 {
1542 win_skip("CoGetTreatAsClass not present\n");
1543 return;
1544 }
1545 hr = pCoGetTreatAsClass(&deadbeef,&out);
1546 ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
1547 ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
1548 }
1549
1550 static void test_CoInitializeEx(void)
1551 {
1552 HRESULT hr;
1553
1554 hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1555 ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
1556
1557 /* Calling OleInitialize for the first time should yield S_OK even with
1558 * apartment already initialized by previous CoInitialize(Ex) calls. */
1559 hr = OleInitialize(NULL);
1560 ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
1561
1562 /* Subsequent calls to OleInitialize should return S_FALSE */
1563 hr = OleInitialize(NULL);
1564 ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
1565
1566 /* Cleanup */
1567 CoUninitialize();
1568 OleUninitialize();
1569 }
1570
1571 START_TEST(compobj)
1572 {
1573 HMODULE hOle32 = GetModuleHandle("ole32");
1574 HMODULE hAdvapi32 = GetModuleHandle("advapi32");
1575 pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
1576 pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
1577 pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
1578 pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
1579 pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
1580 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
1581 {
1582 trace("You need DCOM95 installed to run this test\n");
1583 return;
1584 }
1585
1586 test_ProgIDFromCLSID();
1587 test_CLSIDFromProgID();
1588 test_CLSIDFromString();
1589 test_StringFromGUID2();
1590 test_CoCreateInstance();
1591 test_ole_menu();
1592 test_CoGetClassObject();
1593 test_CoRegisterMessageFilter();
1594 test_CoRegisterPSClsid();
1595 test_CoGetPSClsid();
1596 test_CoUnmarshalInterface();
1597 test_CoGetInterfaceAndReleaseStream();
1598 test_CoMarshalInterface();
1599 test_CoMarshalInterThreadInterfaceInStream();
1600 test_CoRegisterClassObject();
1601 test_registered_object_thread_affinity();
1602 test_CoFreeUnusedLibraries();
1603 test_CoGetObjectContext();
1604 test_CoGetCallContext();
1605 test_CoGetContextToken();
1606 test_CoGetTreatAsClass();
1607 test_CoInitializeEx();
1608 }