1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Component Object Tests
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2005 Robert Shearman
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck 
2166f35ef8SAmine Khaldi #define COBJMACROS
2266f35ef8SAmine Khaldi #define CONST_VTABLE
23c2c66affSColin Finck 
2466f35ef8SAmine Khaldi #include <stdarg.h>
2566f35ef8SAmine Khaldi #include <stdio.h>
2666f35ef8SAmine Khaldi 
2766f35ef8SAmine Khaldi #include "windef.h"
2866f35ef8SAmine Khaldi #include "winbase.h"
2966f35ef8SAmine Khaldi #define USE_COM_CONTEXT_DEF
3066f35ef8SAmine Khaldi #include "objbase.h"
3166f35ef8SAmine Khaldi #include "shlguid.h"
3266f35ef8SAmine Khaldi #include "urlmon.h" /* for CLSID_FileProtocol */
3366f35ef8SAmine Khaldi #include "dde.h"
3466f35ef8SAmine Khaldi #include "cguid.h"
3566f35ef8SAmine Khaldi 
3666f35ef8SAmine Khaldi #include "ctxtcall.h"
3766f35ef8SAmine Khaldi 
3866f35ef8SAmine Khaldi #include "wine/test.h"
395c1bcfecSAmine Khaldi #include "initguid.h"
40c2c66affSColin Finck 
41c2c66affSColin Finck #define DEFINE_EXPECT(func) \
42fc6e4ed5SAmine Khaldi     static BOOL expect_ ## func = FALSE; static unsigned int called_ ## func = 0
43c2c66affSColin Finck 
44c2c66affSColin Finck #define SET_EXPECT(func) \
45c2c66affSColin Finck     expect_ ## func = TRUE
46c2c66affSColin Finck 
47c2c66affSColin Finck #define CHECK_EXPECT2(func) \
48c2c66affSColin Finck     do { \
49c2c66affSColin Finck         ok(expect_ ##func, "unexpected call " #func "\n"); \
50fc6e4ed5SAmine Khaldi         called_ ## func++; \
51c2c66affSColin Finck     }while(0)
52c2c66affSColin Finck 
53c2c66affSColin Finck #define CHECK_EXPECT(func) \
54c2c66affSColin Finck     do { \
55c2c66affSColin Finck         CHECK_EXPECT2(func); \
56c2c66affSColin Finck         expect_ ## func = FALSE; \
57c2c66affSColin Finck     }while(0)
58c2c66affSColin Finck 
59fc6e4ed5SAmine Khaldi #define CHECK_CALLED(func, n) \
60c2c66affSColin Finck     do { \
61fc6e4ed5SAmine Khaldi         ok(called_ ## func == n, "expected " #func " called %u times, got %u\n", n, called_ ## func); \
62fc6e4ed5SAmine Khaldi         expect_ ## func = FALSE; \
63fc6e4ed5SAmine Khaldi         called_ ## func = 0; \
64c2c66affSColin Finck     }while(0)
65c2c66affSColin Finck 
66c2c66affSColin Finck DEFINE_EXPECT(CreateStub);
67fc6e4ed5SAmine Khaldi DEFINE_EXPECT(PreInitialize);
68fc6e4ed5SAmine Khaldi DEFINE_EXPECT(PostInitialize);
69fc6e4ed5SAmine Khaldi DEFINE_EXPECT(PreUninitialize);
70fc6e4ed5SAmine Khaldi DEFINE_EXPECT(PostUninitialize);
71c2c66affSColin Finck 
72c2c66affSColin Finck /* functions that are not present on all versions of Windows */
73c2c66affSColin Finck static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
74c2c66affSColin Finck static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
75c2c66affSColin Finck static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
76c2c66affSColin Finck static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
77c2c66affSColin Finck static HRESULT (WINAPI * pCoTreatAsClass)(REFCLSID clsidOld, REFCLSID pClsidNew);
78c2c66affSColin Finck static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
79c2c66affSColin Finck static HRESULT (WINAPI * pCoGetApartmentType)(APTTYPE *type, APTTYPEQUALIFIER *qualifier);
80c2c66affSColin Finck static LONG (WINAPI * pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
81c2c66affSColin Finck static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
82c2c66affSColin Finck 
83c2c66affSColin Finck static BOOL   (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
84c2c66affSColin Finck static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
85c2c66affSColin Finck static BOOL   (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
86c2c66affSColin Finck static BOOL   (WINAPI *pIsWow64Process)(HANDLE, LPBOOL);
87c2c66affSColin Finck static void   (WINAPI *pReleaseActCtx)(HANDLE);
88c2c66affSColin Finck 
89c2c66affSColin Finck #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
90c2c66affSColin Finck #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
91c2c66affSColin Finck #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
92c2c66affSColin Finck 
93c2c66affSColin Finck static const CLSID CLSID_non_existent =   { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
94c2c66affSColin Finck static const CLSID CLSID_StdFont = { 0x0be35203, 0x8f91, 0x11ce, { 0x9d, 0xe3, 0x00, 0xaa, 0x00, 0x4b, 0xb8, 0x51 } };
95c2c66affSColin Finck static const GUID IID_Testiface = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
96c2c66affSColin Finck static const GUID IID_Testiface2 = { 0x32222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
97c2c66affSColin Finck static const GUID IID_Testiface3 = { 0x42222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
98c2c66affSColin Finck static const GUID IID_Testiface4 = { 0x52222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
99c2c66affSColin Finck static const GUID IID_Testiface5 = { 0x62222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
100c2c66affSColin Finck static const GUID IID_Testiface6 = { 0x72222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
101c2c66affSColin Finck static const GUID IID_TestPS = { 0x66666666, 0x8888, 0x7777, { 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 } };
102c2c66affSColin Finck 
103c2c66affSColin Finck DEFINE_GUID(CLSID_testclsid, 0xacd014c7,0x9535,0x4fac,0x8b,0x53,0xa4,0x8c,0xa7,0xf4,0xd7,0x26);
104c2c66affSColin Finck 
105c2c66affSColin Finck static const WCHAR stdfont[] = {'S','t','d','F','o','n','t',0};
106c2c66affSColin Finck static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
107c2c66affSColin Finck static const WCHAR wszCLSID_StdFont[] =
108c2c66affSColin Finck {
109c2c66affSColin Finck     '{','0','b','e','3','5','2','0','3','-','8','f','9','1','-','1','1','c','e','-',
110c2c66affSColin Finck     '9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
111c2c66affSColin Finck };
112c2c66affSColin Finck static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
113c2c66affSColin Finck static const WCHAR cf_brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
114c2c66affSColin Finck                                     'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0};
115c2c66affSColin Finck 
116c2c66affSColin Finck DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
117c2c66affSColin Finck DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
118c2c66affSColin Finck 
119c2c66affSColin Finck static LONG cLocks;
120c2c66affSColin Finck 
LockModule(void)121c2c66affSColin Finck static void LockModule(void)
122c2c66affSColin Finck {
123c2c66affSColin Finck     InterlockedIncrement(&cLocks);
124c2c66affSColin Finck }
125c2c66affSColin Finck 
UnlockModule(void)126c2c66affSColin Finck static void UnlockModule(void)
127c2c66affSColin Finck {
128c2c66affSColin Finck     InterlockedDecrement(&cLocks);
129c2c66affSColin Finck }
130c2c66affSColin Finck 
Test_IClassFactory_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID * ppvObj)131c2c66affSColin Finck static HRESULT WINAPI Test_IClassFactory_QueryInterface(
132c2c66affSColin Finck     LPCLASSFACTORY iface,
133c2c66affSColin Finck     REFIID riid,
134c2c66affSColin Finck     LPVOID *ppvObj)
135c2c66affSColin Finck {
136c2c66affSColin Finck     if (ppvObj == NULL) return E_POINTER;
137c2c66affSColin Finck 
138c2c66affSColin Finck     if (IsEqualGUID(riid, &IID_IUnknown) ||
139c2c66affSColin Finck         IsEqualGUID(riid, &IID_IClassFactory))
140c2c66affSColin Finck     {
141c2c66affSColin Finck         *ppvObj = iface;
142c2c66affSColin Finck         IClassFactory_AddRef(iface);
143c2c66affSColin Finck         return S_OK;
144c2c66affSColin Finck     }
145c2c66affSColin Finck 
146c2c66affSColin Finck     *ppvObj = NULL;
147c2c66affSColin Finck     return E_NOINTERFACE;
148c2c66affSColin Finck }
149c2c66affSColin Finck 
Test_IClassFactory_AddRef(LPCLASSFACTORY iface)150c2c66affSColin Finck static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
151c2c66affSColin Finck {
152c2c66affSColin Finck     LockModule();
153c2c66affSColin Finck     return 2; /* non-heap-based object */
154c2c66affSColin Finck }
155c2c66affSColin Finck 
Test_IClassFactory_Release(LPCLASSFACTORY iface)156c2c66affSColin Finck static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
157c2c66affSColin Finck {
158c2c66affSColin Finck     UnlockModule();
159c2c66affSColin Finck     return 1; /* non-heap-based object */
160c2c66affSColin Finck }
161c2c66affSColin Finck 
162c2c66affSColin Finck static IID create_instance_iid;
Test_IClassFactory_CreateInstance(LPCLASSFACTORY iface,IUnknown * pUnkOuter,REFIID riid,LPVOID * ppvObj)163c2c66affSColin Finck static HRESULT WINAPI Test_IClassFactory_CreateInstance(
164c2c66affSColin Finck     LPCLASSFACTORY iface,
165c2c66affSColin Finck     IUnknown *pUnkOuter,
166c2c66affSColin Finck     REFIID riid,
167c2c66affSColin Finck     LPVOID *ppvObj)
168c2c66affSColin Finck {
169c2c66affSColin Finck     *ppvObj = NULL;
170c2c66affSColin Finck     create_instance_iid = *riid;
171c2c66affSColin Finck     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
172c2c66affSColin Finck     return E_NOINTERFACE;
173c2c66affSColin Finck }
174c2c66affSColin Finck 
Test_IClassFactory_LockServer(LPCLASSFACTORY iface,BOOL fLock)175c2c66affSColin Finck static HRESULT WINAPI Test_IClassFactory_LockServer(
176c2c66affSColin Finck     LPCLASSFACTORY iface,
177c2c66affSColin Finck     BOOL fLock)
178c2c66affSColin Finck {
179c2c66affSColin Finck     return S_OK;
180c2c66affSColin Finck }
181c2c66affSColin Finck 
182c2c66affSColin Finck static const IClassFactoryVtbl TestClassFactory_Vtbl =
183c2c66affSColin Finck {
184c2c66affSColin Finck     Test_IClassFactory_QueryInterface,
185c2c66affSColin Finck     Test_IClassFactory_AddRef,
186c2c66affSColin Finck     Test_IClassFactory_Release,
187c2c66affSColin Finck     Test_IClassFactory_CreateInstance,
188c2c66affSColin Finck     Test_IClassFactory_LockServer
189c2c66affSColin Finck };
190c2c66affSColin Finck 
191c2c66affSColin Finck static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
192c2c66affSColin Finck 
193c2c66affSColin Finck static WCHAR manifest_path[MAX_PATH];
194c2c66affSColin Finck 
create_manifest_file(const char * filename,const char * manifest)195c2c66affSColin Finck static BOOL create_manifest_file(const char *filename, const char *manifest)
196c2c66affSColin Finck {
197c2c66affSColin Finck     int manifest_len;
198c2c66affSColin Finck     DWORD size;
199c2c66affSColin Finck     HANDLE file;
200c2c66affSColin Finck     WCHAR path[MAX_PATH];
201c2c66affSColin Finck 
202c2c66affSColin Finck     MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
2035c1bcfecSAmine Khaldi     GetFullPathNameW(path, ARRAY_SIZE(manifest_path), manifest_path, NULL);
204c2c66affSColin Finck 
205c2c66affSColin Finck     manifest_len = strlen(manifest);
206c2c66affSColin Finck     file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
207c2c66affSColin Finck                        FILE_ATTRIBUTE_NORMAL, NULL);
208c2c66affSColin Finck     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
209c2c66affSColin Finck     if(file == INVALID_HANDLE_VALUE)
210c2c66affSColin Finck         return FALSE;
211c2c66affSColin Finck     WriteFile(file, manifest, manifest_len, &size, NULL);
212c2c66affSColin Finck     CloseHandle(file);
213c2c66affSColin Finck 
214c2c66affSColin Finck     return TRUE;
215c2c66affSColin Finck }
216c2c66affSColin Finck 
activate_context(const char * manifest,ULONG_PTR * cookie)217c2c66affSColin Finck static HANDLE activate_context(const char *manifest, ULONG_PTR *cookie)
218c2c66affSColin Finck {
219c2c66affSColin Finck     WCHAR path[MAX_PATH];
220c2c66affSColin Finck     ACTCTXW actctx;
221c2c66affSColin Finck     HANDLE handle;
222c2c66affSColin Finck     BOOL ret;
223c2c66affSColin Finck 
224c2c66affSColin Finck     if (!pCreateActCtxW) return NULL;
225c2c66affSColin Finck 
226c2c66affSColin Finck     create_manifest_file("file.manifest", manifest);
227c2c66affSColin Finck 
228c2c66affSColin Finck     MultiByteToWideChar( CP_ACP, 0, "file.manifest", -1, path, MAX_PATH );
229c2c66affSColin Finck     memset(&actctx, 0, sizeof(ACTCTXW));
230c2c66affSColin Finck     actctx.cbSize = sizeof(ACTCTXW);
231c2c66affSColin Finck     actctx.lpSource = path;
232c2c66affSColin Finck 
233c2c66affSColin Finck     handle = pCreateActCtxW(&actctx);
234c2c66affSColin Finck     ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* some old XP/2k3 versions */,
235c2c66affSColin Finck         "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
236c2c66affSColin Finck     if (handle == INVALID_HANDLE_VALUE)
237c2c66affSColin Finck     {
238c2c66affSColin Finck         win_skip("activation context generation failed, some tests will be skipped\n");
239c2c66affSColin Finck         handle = NULL;
240c2c66affSColin Finck     }
241c2c66affSColin Finck 
242c2c66affSColin Finck     ok(actctx.cbSize == sizeof(ACTCTXW), "actctx.cbSize=%d\n", actctx.cbSize);
243c2c66affSColin Finck     ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
244c2c66affSColin Finck     ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
245c2c66affSColin Finck     ok(actctx.wProcessorArchitecture == 0, "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
246c2c66affSColin Finck     ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId);
247c2c66affSColin Finck     ok(actctx.lpAssemblyDirectory == NULL, "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
248c2c66affSColin Finck     ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
249c2c66affSColin Finck     ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n", actctx.lpApplicationName);
250c2c66affSColin Finck     ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
251c2c66affSColin Finck 
252c2c66affSColin Finck     DeleteFileA("file.manifest");
253c2c66affSColin Finck 
254c2c66affSColin Finck     if (handle)
255c2c66affSColin Finck     {
256c2c66affSColin Finck         ret = pActivateActCtx(handle, cookie);
257c2c66affSColin Finck         ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
258c2c66affSColin Finck     }
259c2c66affSColin Finck 
260c2c66affSColin Finck     return handle;
261c2c66affSColin Finck }
262c2c66affSColin Finck 
263c2c66affSColin Finck static const char actctx_manifest[] =
264c2c66affSColin Finck "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
265c2c66affSColin Finck "<assemblyIdentity version=\"1.2.3.4\"  name=\"Wine.Test\" type=\"win32\""
266c2c66affSColin Finck " publicKeyToken=\"6595b6414666f1df\" />"
267c2c66affSColin Finck "<file name=\"testlib.dll\">"
268c2c66affSColin Finck "    <comClass"
269c2c66affSColin Finck "              clsid=\"{0000033a-0000-0000-c000-000000000046}\""
270c2c66affSColin Finck "              progid=\"FTMarshal\""
271c2c66affSColin Finck "    />"
272c2c66affSColin Finck "    <comClass"
273c2c66affSColin Finck "              clsid=\"{5201163f-8164-4fd0-a1a2-5d5a3654d3bd}\""
274c2c66affSColin Finck "              progid=\"WineOOPTest\""
275c2c66affSColin Finck "    />"
276c2c66affSColin Finck "    <comClass description=\"Test com class\""
277c2c66affSColin Finck "              clsid=\"{12345678-1234-1234-1234-56789abcdef0}\""
278c2c66affSColin Finck "              progid=\"ProgId.ProgId\""
279c2c66affSColin Finck "              miscStatusIcon=\"recomposeonresize\""
280c2c66affSColin Finck "    />"
281c2c66affSColin Finck "    <comClass description=\"CustomFont Description\" clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb851}\""
282c2c66affSColin Finck "              progid=\"CustomFont\""
283c2c66affSColin Finck "              miscStatusIcon=\"recomposeonresize\""
284c2c66affSColin Finck "              miscStatusContent=\"insideout\""
285c2c66affSColin Finck "    />"
286c2c66affSColin Finck "    <comClass description=\"StdFont Description\" clsid=\"{0be35203-8f91-11ce-9de3-00aa004bb852}\""
287c2c66affSColin Finck "              progid=\"StdFont\""
288c2c66affSColin Finck "    />"
289c2c66affSColin Finck "    <comClass clsid=\"{62222222-1234-1234-1234-56789abcdef0}\" >"
290c2c66affSColin Finck "        <progid>ProgId.ProgId.1</progid>"
291c2c66affSColin Finck "    </comClass>"
292c2c66affSColin Finck "    <comInterfaceProxyStub "
293c2c66affSColin Finck "        name=\"Iifaceps\""
294c2c66affSColin Finck "        iid=\"{22222222-1234-1234-1234-56789abcdef0}\""
295c2c66affSColin Finck "        proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
296c2c66affSColin Finck "    />"
297c2c66affSColin Finck "</file>"
298c2c66affSColin Finck "    <comInterfaceExternalProxyStub "
299c2c66affSColin Finck "        name=\"Iifaceps2\""
300c2c66affSColin Finck "        iid=\"{32222222-1234-1234-1234-56789abcdef0}\""
301c2c66affSColin Finck "    />"
302c2c66affSColin Finck "    <comInterfaceExternalProxyStub "
303c2c66affSColin Finck "        name=\"Iifaceps3\""
304c2c66affSColin Finck "        iid=\"{42222222-1234-1234-1234-56789abcdef0}\""
305c2c66affSColin Finck "        proxyStubClsid32=\"{66666666-8888-7777-6666-555555555555}\""
306c2c66affSColin Finck "    />"
307c2c66affSColin Finck "    <comInterfaceExternalProxyStub "
308c2c66affSColin Finck "        name=\"Iifaceps4\""
309c2c66affSColin Finck "        iid=\"{52222222-1234-1234-1234-56789abcdef0}\""
310c2c66affSColin Finck "        proxyStubClsid32=\"{00000000-0000-0000-0000-000000000000}\""
311c2c66affSColin Finck "    />"
312c2c66affSColin Finck "    <clrClass "
313c2c66affSColin Finck "        clsid=\"{72222222-1234-1234-1234-56789abcdef0}\""
314c2c66affSColin Finck "        name=\"clrclass\""
315c2c66affSColin Finck "    >"
316c2c66affSColin Finck "        <progid>clrprogid.1</progid>"
317c2c66affSColin Finck "    </clrClass>"
318c2c66affSColin Finck "</assembly>";
319c2c66affSColin Finck 
320c2c66affSColin Finck DEFINE_GUID(CLSID_Testclass, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0);
321c2c66affSColin Finck 
test_ProgIDFromCLSID(void)322c2c66affSColin Finck static void test_ProgIDFromCLSID(void)
323c2c66affSColin Finck {
324c2c66affSColin Finck     ULONG_PTR cookie = 0;
325c2c66affSColin Finck     LPWSTR progid;
326c2c66affSColin Finck     HANDLE handle;
327c2c66affSColin Finck     HRESULT hr;
328c2c66affSColin Finck 
329c2c66affSColin Finck     hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
330c2c66affSColin Finck     ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08x\n", hr);
331c2c66affSColin Finck     if (hr == S_OK)
332c2c66affSColin Finck     {
333c2c66affSColin Finck         ok(!lstrcmpiW(progid, stdfont), "Didn't get expected prog ID\n");
334c2c66affSColin Finck         CoTaskMemFree(progid);
335c2c66affSColin Finck     }
336c2c66affSColin Finck 
337c2c66affSColin Finck     progid = (LPWSTR)0xdeadbeef;
338c2c66affSColin Finck     hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
339c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "ProgIDFromCLSID returned %08x\n", hr);
340c2c66affSColin Finck     ok(progid == NULL, "ProgIDFromCLSID returns with progid %p\n", progid);
341c2c66affSColin Finck 
342c2c66affSColin Finck     hr = ProgIDFromCLSID(&CLSID_StdFont, NULL);
343c2c66affSColin Finck     ok(hr == E_INVALIDARG, "ProgIDFromCLSID should return E_INVALIDARG instead of 0x%08x\n", hr);
344c2c66affSColin Finck 
345c2c66affSColin Finck     if ((handle = activate_context(actctx_manifest, &cookie)))
346c2c66affSColin Finck     {
347c2c66affSColin Finck         static const WCHAR customfontW[] = {'C','u','s','t','o','m','F','o','n','t',0};
348c2c66affSColin Finck 
349c2c66affSColin Finck         hr = ProgIDFromCLSID(&CLSID_non_existent, &progid);
350c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
351c2c66affSColin Finck         ok(!lstrcmpiW(progid, progidW), "got %s\n", wine_dbgstr_w(progid));
352c2c66affSColin Finck         CoTaskMemFree(progid);
353c2c66affSColin Finck 
354c2c66affSColin Finck         /* try something registered and redirected */
355c2c66affSColin Finck         progid = NULL;
356c2c66affSColin Finck         hr = ProgIDFromCLSID(&CLSID_StdFont, &progid);
357c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
358c2c66affSColin Finck         ok(!lstrcmpiW(progid, customfontW), "got wrong progid %s\n", wine_dbgstr_w(progid));
359c2c66affSColin Finck         CoTaskMemFree(progid);
360c2c66affSColin Finck 
361c2c66affSColin Finck         /* classes without default progid, progid list is not used */
362c2c66affSColin Finck         progid = (void *)0xdeadbeef;
363c2c66affSColin Finck         hr = ProgIDFromCLSID(&IID_Testiface5, &progid);
364c2c66affSColin Finck         ok(hr == REGDB_E_CLASSNOTREG && progid == NULL, "got 0x%08x, progid %p\n", hr, progid);
365c2c66affSColin Finck 
366c2c66affSColin Finck         progid = (void *)0xdeadbeef;
367c2c66affSColin Finck         hr = ProgIDFromCLSID(&IID_Testiface6, &progid);
368c2c66affSColin Finck         ok(hr == REGDB_E_CLASSNOTREG && progid == NULL, "got 0x%08x, progid %p\n", hr, progid);
369c2c66affSColin Finck 
370c2c66affSColin Finck         pDeactivateActCtx(0, cookie);
371c2c66affSColin Finck         pReleaseActCtx(handle);
372c2c66affSColin Finck     }
373c2c66affSColin Finck }
374c2c66affSColin Finck 
test_CLSIDFromProgID(void)375c2c66affSColin Finck static void test_CLSIDFromProgID(void)
376c2c66affSColin Finck {
377c2c66affSColin Finck     ULONG_PTR cookie = 0;
378c2c66affSColin Finck     HANDLE handle;
379c2c66affSColin Finck     CLSID clsid;
380c2c66affSColin Finck     HRESULT hr = CLSIDFromProgID(stdfont, &clsid);
381c2c66affSColin Finck     ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08x\n", hr);
382c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
383c2c66affSColin Finck 
384c2c66affSColin Finck     hr = CLSIDFromString(stdfont, &clsid);
385c2c66affSColin Finck     ok_ole_success(hr, "CLSIDFromString");
386c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
387c2c66affSColin Finck 
388c2c66affSColin Finck     /* test some failure cases */
389c2c66affSColin Finck 
390c2c66affSColin Finck     hr = CLSIDFromProgID(wszNonExistent, NULL);
391c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
392c2c66affSColin Finck 
393c2c66affSColin Finck     hr = CLSIDFromProgID(NULL, &clsid);
394c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CLSIDFromProgID should have returned E_INVALIDARG instead of 0x%08x\n", hr);
395c2c66affSColin Finck 
396c2c66affSColin Finck     memset(&clsid, 0xcc, sizeof(clsid));
397c2c66affSColin Finck     hr = CLSIDFromProgID(wszNonExistent, &clsid);
398c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "CLSIDFromProgID on nonexistent ProgID should have returned CO_E_CLASSSTRING instead of 0x%08x\n", hr);
399c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "CLSIDFromProgID should have set clsid to all-zeros on failure\n");
400c2c66affSColin Finck 
401c2c66affSColin Finck     /* fails without proper context */
402c2c66affSColin Finck     memset(&clsid, 0xcc, sizeof(clsid));
403c2c66affSColin Finck     hr = CLSIDFromProgID(progidW, &clsid);
404c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
405c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "wrong clsid\n");
406c2c66affSColin Finck 
407c2c66affSColin Finck     if ((handle = activate_context(actctx_manifest, &cookie)))
408c2c66affSColin Finck     {
409c2c66affSColin Finck         GUID clsid1;
410c2c66affSColin Finck 
411c2c66affSColin Finck         memset(&clsid, 0xcc, sizeof(clsid));
412c2c66affSColin Finck         hr = CLSIDFromProgID(wszNonExistent, &clsid);
413c2c66affSColin Finck         ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
414c2c66affSColin Finck         ok(IsEqualCLSID(&clsid, &CLSID_NULL), "should have zero CLSID on failure\n");
415c2c66affSColin Finck 
416c2c66affSColin Finck         /* CLSIDFromString() doesn't check activation context */
417c2c66affSColin Finck         hr = CLSIDFromString(progidW, &clsid);
418c2c66affSColin Finck         ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
419c2c66affSColin Finck 
420c2c66affSColin Finck         clsid = CLSID_NULL;
421c2c66affSColin Finck         hr = CLSIDFromProgID(progidW, &clsid);
422c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
423c2c66affSColin Finck         /* it returns generated CLSID here */
424c2c66affSColin Finck         ok(!IsEqualCLSID(&clsid, &CLSID_non_existent) && !IsEqualCLSID(&clsid, &CLSID_NULL),
425c2c66affSColin Finck                  "got wrong clsid %s\n", wine_dbgstr_guid(&clsid));
426c2c66affSColin Finck 
427c2c66affSColin Finck         /* duplicate progid present in context - returns generated guid here too */
428c2c66affSColin Finck         clsid = CLSID_NULL;
429c2c66affSColin Finck         hr = CLSIDFromProgID(stdfont, &clsid);
430c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
431c2c66affSColin Finck         clsid1 = CLSID_StdFont;
432c2c66affSColin Finck         /* that's where it differs from StdFont */
433c2c66affSColin Finck         clsid1.Data4[7] = 0x52;
434c2c66affSColin Finck         ok(!IsEqualCLSID(&clsid, &CLSID_StdFont) && !IsEqualCLSID(&clsid, &CLSID_NULL) && !IsEqualCLSID(&clsid, &clsid1),
435c2c66affSColin Finck             "got %s\n", wine_dbgstr_guid(&clsid));
436c2c66affSColin Finck 
437c2c66affSColin Finck         pDeactivateActCtx(0, cookie);
438c2c66affSColin Finck         pReleaseActCtx(handle);
439c2c66affSColin Finck     }
440c2c66affSColin Finck }
441c2c66affSColin Finck 
test_CLSIDFromString(void)442c2c66affSColin Finck static void test_CLSIDFromString(void)
443c2c66affSColin Finck {
444c2c66affSColin Finck     CLSID clsid;
445c2c66affSColin Finck     WCHAR wszCLSID_Broken[50];
446c2c66affSColin Finck     UINT i;
447c2c66affSColin Finck 
448c2c66affSColin Finck     HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid);
449c2c66affSColin Finck     ok_ole_success(hr, "CLSIDFromString");
450c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
451c2c66affSColin Finck 
452c2c66affSColin Finck     memset(&clsid, 0xab, sizeof(clsid));
453c2c66affSColin Finck     hr = CLSIDFromString(NULL, &clsid);
454c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
455c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
456c2c66affSColin Finck 
457c2c66affSColin Finck     /* string is longer, but starts with a valid CLSID */
458c2c66affSColin Finck     memset(&clsid, 0, sizeof(clsid));
459c2c66affSColin Finck     hr = CLSIDFromString(cf_brokenW, &clsid);
460c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
461c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &IID_IClassFactory), "got %s\n", wine_dbgstr_guid(&clsid));
462c2c66affSColin Finck 
463c2c66affSColin Finck     lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
464c2c66affSColin Finck     for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
465c2c66affSColin Finck         wszCLSID_Broken[i] = 'A';
466c2c66affSColin Finck     wszCLSID_Broken[i] = '\0';
467c2c66affSColin Finck 
468c2c66affSColin Finck     memset(&clsid, 0, sizeof(CLSID));
469c2c66affSColin Finck     hr = CLSIDFromString(wszCLSID_Broken, &clsid);
470c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
471c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
472c2c66affSColin Finck 
473c2c66affSColin Finck     wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A';
474c2c66affSColin Finck     memset(&clsid, 0, sizeof(CLSID));
475c2c66affSColin Finck     hr = CLSIDFromString(wszCLSID_Broken, &clsid);
476c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
477c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
478c2c66affSColin Finck 
479c2c66affSColin Finck     wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0';
480c2c66affSColin Finck     memset(&clsid, 0, sizeof(CLSID));
481c2c66affSColin Finck     hr = CLSIDFromString(wszCLSID_Broken, &clsid);
482c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
483c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
484c2c66affSColin Finck 
485c2c66affSColin Finck     wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0';
486c2c66affSColin Finck     memset(&clsid, 0, sizeof(CLSID));
487c2c66affSColin Finck     hr = CLSIDFromString(wszCLSID_Broken, &clsid);
488c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
489c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
490c2c66affSColin Finck 
491c2c66affSColin Finck     memset(&clsid, 0xcc, sizeof(CLSID));
492c2c66affSColin Finck     hr = CLSIDFromString(wszCLSID_Broken+1, &clsid);
493c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
494c2c66affSColin Finck     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
495c2c66affSColin Finck 
496c2c66affSColin Finck     wszCLSID_Broken[9] = '*';
497c2c66affSColin Finck     memset(&clsid, 0xcc, sizeof(CLSID));
498c2c66affSColin Finck     hr = CLSIDFromString(wszCLSID_Broken, &clsid);
499c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
500c2c66affSColin Finck     ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1);
501c2c66affSColin Finck     ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
502c2c66affSColin Finck 
503c2c66affSColin Finck     wszCLSID_Broken[3] = '*';
504c2c66affSColin Finck     memset(&clsid, 0xcc, sizeof(CLSID));
505c2c66affSColin Finck     hr = CLSIDFromString(wszCLSID_Broken, &clsid);
506c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
507c2c66affSColin Finck     ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
508c2c66affSColin Finck     ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
509c2c66affSColin Finck 
510c2c66affSColin Finck     wszCLSID_Broken[3] = '\0';
511c2c66affSColin Finck     memset(&clsid, 0xcc, sizeof(CLSID));
512c2c66affSColin Finck     hr = CLSIDFromString(wszCLSID_Broken, &clsid);
513c2c66affSColin Finck     ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr);
514c2c66affSColin Finck     ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1);
515c2c66affSColin Finck     ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
516c2c66affSColin Finck }
517c2c66affSColin Finck 
test_IIDFromString(void)518c2c66affSColin Finck static void test_IIDFromString(void)
519c2c66affSColin Finck {
520c2c66affSColin Finck     static const WCHAR cfW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
521c2c66affSColin Finck                                     'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
522c2c66affSColin Finck     static const WCHAR brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
523c2c66affSColin Finck                                         'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
524c2c66affSColin Finck     static const WCHAR broken2W[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
525c2c66affSColin Finck                                         'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
526c2c66affSColin Finck     static const WCHAR broken3W[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
527c2c66affSColin Finck                                         'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
528c2c66affSColin Finck     HRESULT hr;
529c2c66affSColin Finck     IID iid;
530c2c66affSColin Finck 
531c2c66affSColin Finck     hr = IIDFromString(wszCLSID_StdFont, &iid);
532c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
533c2c66affSColin Finck     ok(IsEqualIID(&iid, &CLSID_StdFont), "got iid %s\n", wine_dbgstr_guid(&iid));
534c2c66affSColin Finck 
535c2c66affSColin Finck     memset(&iid, 0xab, sizeof(iid));
536c2c66affSColin Finck     hr = IIDFromString(NULL, &iid);
537c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
538c2c66affSColin Finck     ok(IsEqualIID(&iid, &CLSID_NULL), "got iid %s\n", wine_dbgstr_guid(&iid));
539c2c66affSColin Finck 
540c2c66affSColin Finck     hr = IIDFromString(cfW, &iid);
541c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
542c2c66affSColin Finck     ok(IsEqualIID(&iid, &IID_IClassFactory), "got iid %s\n", wine_dbgstr_guid(&iid));
543c2c66affSColin Finck 
544c2c66affSColin Finck     /* string starts with a valid IID but is longer */
545c2c66affSColin Finck     memset(&iid, 0xab, sizeof(iid));
546c2c66affSColin Finck     hr = IIDFromString(cf_brokenW, &iid);
547c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
548c2c66affSColin Finck     ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
549c2c66affSColin Finck 
550c2c66affSColin Finck     /* invalid IID in a valid format */
551c2c66affSColin Finck     memset(&iid, 0xab, sizeof(iid));
552c2c66affSColin Finck     hr = IIDFromString(brokenW, &iid);
553c2c66affSColin Finck     ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
554c2c66affSColin Finck     ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
555c2c66affSColin Finck 
556c2c66affSColin Finck     memset(&iid, 0xab, sizeof(iid));
557c2c66affSColin Finck     hr = IIDFromString(broken2W, &iid);
558c2c66affSColin Finck     ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
559c2c66affSColin Finck     ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
560c2c66affSColin Finck 
561c2c66affSColin Finck     /* format is broken, but string length is okay */
562c2c66affSColin Finck     memset(&iid, 0xab, sizeof(iid));
563c2c66affSColin Finck     hr = IIDFromString(broken3W, &iid);
564c2c66affSColin Finck     ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
565c2c66affSColin Finck     ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
566c2c66affSColin Finck 
567c2c66affSColin Finck     /* invalid string */
568c2c66affSColin Finck     memset(&iid, 0xab, sizeof(iid));
569c2c66affSColin Finck     hr = IIDFromString(wszNonExistent, &iid);
570c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
571c2c66affSColin Finck     ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
572c2c66affSColin Finck 
573c2c66affSColin Finck     /* valid ProgID */
574c2c66affSColin Finck     memset(&iid, 0xab, sizeof(iid));
575c2c66affSColin Finck     hr = IIDFromString(stdfont, &iid);
576c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
577c2c66affSColin Finck     ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
578c2c66affSColin Finck }
579c2c66affSColin Finck 
test_StringFromGUID2(void)580c2c66affSColin Finck static void test_StringFromGUID2(void)
581c2c66affSColin Finck {
582c2c66affSColin Finck   WCHAR str[50];
583c2c66affSColin Finck   int len;
584c2c66affSColin Finck 
585c2c66affSColin Finck   /* invalid pointer */
586c2c66affSColin Finck   SetLastError(0xdeadbeef);
587c2c66affSColin Finck   len = StringFromGUID2(NULL,str,50);
588c2c66affSColin Finck   ok(len == 0, "len: %d (expected 0)\n", len);
589c2c66affSColin Finck   ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %x\n", GetLastError());
590c2c66affSColin Finck 
591c2c66affSColin Finck   /* Test corner cases for buffer size */
592c2c66affSColin Finck   len = StringFromGUID2(&CLSID_StdFont,str,50);
593c2c66affSColin Finck   ok(len == 39, "len: %d (expected 39)\n", len);
594c2c66affSColin Finck   ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
595c2c66affSColin Finck 
596c2c66affSColin Finck   memset(str,0,sizeof str);
597c2c66affSColin Finck   len = StringFromGUID2(&CLSID_StdFont,str,39);
598c2c66affSColin Finck   ok(len == 39, "len: %d (expected 39)\n", len);
599c2c66affSColin Finck   ok(!lstrcmpiW(str, wszCLSID_StdFont),"string wasn't equal for CLSID_StdFont\n");
600c2c66affSColin Finck 
601c2c66affSColin Finck   len = StringFromGUID2(&CLSID_StdFont,str,38);
602c2c66affSColin Finck   ok(len == 0, "len: %d (expected 0)\n", len);
603c2c66affSColin Finck 
604c2c66affSColin Finck   len = StringFromGUID2(&CLSID_StdFont,str,30);
605c2c66affSColin Finck   ok(len == 0, "len: %d (expected 0)\n", len);
606c2c66affSColin Finck }
607c2c66affSColin Finck 
608a6cdf4ffSAmine Khaldi #define test_apt_type(t, q) _test_apt_type(t, q, __LINE__)
_test_apt_type(APTTYPE expected_type,APTTYPEQUALIFIER expected_qualifier,int line)609a6cdf4ffSAmine Khaldi static void _test_apt_type(APTTYPE expected_type, APTTYPEQUALIFIER expected_qualifier, int line)
610c2c66affSColin Finck {
611c2c66affSColin Finck     APTTYPEQUALIFIER qualifier = ~0u;
612c2c66affSColin Finck     APTTYPE type = ~0u;
613c2c66affSColin Finck     HRESULT hr;
614c2c66affSColin Finck 
615c2c66affSColin Finck     if (!pCoGetApartmentType)
616c2c66affSColin Finck         return;
617c2c66affSColin Finck 
618c2c66affSColin Finck     hr = pCoGetApartmentType(&type, &qualifier);
619c2c66affSColin Finck     ok_(__FILE__, line)(hr == S_OK || hr == CO_E_NOTINITIALIZED, "Unexpected return code: 0x%08x\n", hr);
620c2c66affSColin Finck     ok_(__FILE__, line)(type == expected_type, "Wrong apartment type %d, expected %d\n", type, expected_type);
621c2c66affSColin Finck     ok_(__FILE__, line)(qualifier == expected_qualifier, "Wrong apartment qualifier %d, expected %d\n", qualifier,
622c2c66affSColin Finck         expected_qualifier);
623c2c66affSColin Finck }
624c2c66affSColin Finck 
test_CoCreateInstance(void)625c2c66affSColin Finck static void test_CoCreateInstance(void)
626c2c66affSColin Finck {
627c2c66affSColin Finck     HRESULT hr;
628c2c66affSColin Finck     IUnknown *pUnk;
629c2c66affSColin Finck     REFCLSID rclsid = &CLSID_InternetZoneManager;
630c2c66affSColin Finck 
631c2c66affSColin Finck     pUnk = (IUnknown *)0xdeadbeef;
632c2c66affSColin Finck     hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
633c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
634c2c66affSColin Finck     ok(pUnk == NULL, "CoCreateInstance should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
635c2c66affSColin Finck 
636c2c66affSColin Finck     OleInitialize(NULL);
637c2c66affSColin Finck 
638c2c66affSColin Finck     /* test errors returned for non-registered clsids */
639c2c66affSColin Finck     hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
640c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
641c2c66affSColin Finck     hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pUnk);
642c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered inproc handler should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
643c2c66affSColin Finck     hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_LOCAL_SERVER, &IID_IUnknown, (void **)&pUnk);
644c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered local server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
645c2c66affSColin Finck     hr = CoCreateInstance(&CLSID_non_existent, NULL, CLSCTX_REMOTE_SERVER, &IID_IUnknown, (void **)&pUnk);
646c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance for non-registered remote server should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
647c2c66affSColin Finck 
648c2c66affSColin Finck     hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
649c2c66affSColin Finck     if(hr == REGDB_E_CLASSNOTREG)
650c2c66affSColin Finck     {
651c2c66affSColin Finck         skip("IE not installed so can't test CoCreateInstance\n");
652c2c66affSColin Finck         OleUninitialize();
653c2c66affSColin Finck         return;
654c2c66affSColin Finck     }
655c2c66affSColin Finck 
656c2c66affSColin Finck     ok_ole_success(hr, "CoCreateInstance");
657c2c66affSColin Finck     if(pUnk) IUnknown_Release(pUnk);
658c2c66affSColin Finck     OleUninitialize();
659c2c66affSColin Finck 
660c2c66affSColin Finck     hr = CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
661c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
662c2c66affSColin Finck 
663a6cdf4ffSAmine Khaldi     test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
664c2c66affSColin Finck }
665c2c66affSColin Finck 
test_CoGetClassObject(void)666c2c66affSColin Finck static void test_CoGetClassObject(void)
667c2c66affSColin Finck {
668c2c66affSColin Finck     HRESULT hr;
669a6cdf4ffSAmine Khaldi     HANDLE handle;
670c2c66affSColin Finck     ULONG_PTR cookie;
671c2c66affSColin Finck     IUnknown *pUnk;
672c2c66affSColin Finck     REFCLSID rclsid = &CLSID_InternetZoneManager;
673c2c66affSColin Finck     HKEY hkey;
674c2c66affSColin Finck     LONG res;
675c2c66affSColin Finck 
676c2c66affSColin Finck     hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
677c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "CoGetClassObject should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
678c2c66affSColin Finck     ok(pUnk == NULL, "CoGetClassObject should have changed the passed in pointer to NULL, instead of %p\n", pUnk);
679c2c66affSColin Finck 
680c2c66affSColin Finck     hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, NULL);
681c2c66affSColin Finck     ok(hr == E_INVALIDARG ||
682c2c66affSColin Finck        broken(hr == CO_E_NOTINITIALIZED), /* win9x */
683c2c66affSColin Finck        "CoGetClassObject should have returned E_INVALIDARG instead of 0x%08x\n", hr);
684c2c66affSColin Finck 
685a6cdf4ffSAmine Khaldi     test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
686c2c66affSColin Finck 
687c2c66affSColin Finck     if (!pRegOverridePredefKey)
688c2c66affSColin Finck     {
689c2c66affSColin Finck         win_skip("RegOverridePredefKey not available\n");
690c2c66affSColin Finck         return;
691c2c66affSColin Finck     }
692c2c66affSColin Finck 
693c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
694c2c66affSColin Finck 
695c2c66affSColin Finck     hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
696c2c66affSColin Finck     if (hr == S_OK)
697c2c66affSColin Finck     {
698c2c66affSColin Finck         IUnknown_Release(pUnk);
699c2c66affSColin Finck 
700c2c66affSColin Finck         res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
701c2c66affSColin Finck                              KEY_ALL_ACCESS, NULL, &hkey, NULL);
702c2c66affSColin Finck         ok(!res, "RegCreateKeyEx returned %d\n", res);
703c2c66affSColin Finck 
704c2c66affSColin Finck         res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
705c2c66affSColin Finck         ok(!res, "RegOverridePredefKey returned %d\n", res);
706c2c66affSColin Finck 
707c2c66affSColin Finck         hr = CoGetClassObject(rclsid, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
708c2c66affSColin Finck         ok(hr == S_OK, "CoGetClassObject should have returned S_OK instead of 0x%08x\n", hr);
709c2c66affSColin Finck 
710c2c66affSColin Finck         res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
711c2c66affSColin Finck         ok(!res, "RegOverridePredefKey returned %d\n", res);
712c2c66affSColin Finck 
713c2c66affSColin Finck         if (hr == S_OK) IUnknown_Release(pUnk);
714c2c66affSColin Finck         RegCloseKey(hkey);
715c2c66affSColin Finck     }
716c2c66affSColin Finck 
717c2c66affSColin Finck     hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
718c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
719c2c66affSColin Finck     IUnknown_Release(pUnk);
720c2c66affSColin Finck 
721c2c66affSColin Finck     /* context redefines FreeMarshaler CLSID */
722c2c66affSColin Finck     if ((handle = activate_context(actctx_manifest, &cookie)))
723c2c66affSColin Finck     {
724c2c66affSColin Finck         hr = CoGetClassObject(&CLSID_InProcFreeMarshaler, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&pUnk);
725c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
726c2c66affSColin Finck         IUnknown_Release(pUnk);
727c2c66affSColin Finck 
728c2c66affSColin Finck         pDeactivateActCtx(0, cookie);
729c2c66affSColin Finck         pReleaseActCtx(handle);
730c2c66affSColin Finck     }
731c2c66affSColin Finck 
732c2c66affSColin Finck     CoUninitialize();
733c2c66affSColin Finck }
734c2c66affSColin Finck 
test_CoCreateInstanceEx(void)735c2c66affSColin Finck static void test_CoCreateInstanceEx(void)
736c2c66affSColin Finck {
737c2c66affSColin Finck     MULTI_QI qi_res = { &IID_IMoniker };
738c2c66affSColin Finck     DWORD cookie;
739c2c66affSColin Finck     HRESULT hr;
740c2c66affSColin Finck 
741c2c66affSColin Finck     CoInitialize(NULL);
742c2c66affSColin Finck 
743c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
744c2c66affSColin Finck                                CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
745c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
746c2c66affSColin Finck 
747c2c66affSColin Finck     create_instance_iid = IID_NULL;
748c2c66affSColin Finck     hr = CoCreateInstanceEx(&CLSID_WineOOPTest, NULL, CLSCTX_INPROC_SERVER, NULL, 1, &qi_res);
749c2c66affSColin Finck     ok(hr == E_NOINTERFACE, "CoCreateInstanceEx failed: %08x\n", hr);
750c2c66affSColin Finck     ok(IsEqualGUID(&create_instance_iid, qi_res.pIID), "Unexpected CreateInstance iid %s\n",
751c2c66affSColin Finck        wine_dbgstr_guid(&create_instance_iid));
752c2c66affSColin Finck 
753c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
754c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
755c2c66affSColin Finck 
756c2c66affSColin Finck     CoUninitialize();
757c2c66affSColin Finck }
758c2c66affSColin Finck 
register_dummy_class(void)759c2c66affSColin Finck static ATOM register_dummy_class(void)
760c2c66affSColin Finck {
761c2c66affSColin Finck     WNDCLASSA wc =
762c2c66affSColin Finck     {
763c2c66affSColin Finck         0,
764c2c66affSColin Finck         DefWindowProcA,
765c2c66affSColin Finck         0,
766c2c66affSColin Finck         0,
767c2c66affSColin Finck         GetModuleHandleA(NULL),
768c2c66affSColin Finck         NULL,
769c2c66affSColin Finck         LoadCursorA(NULL, (LPSTR)IDC_ARROW),
770c2c66affSColin Finck         (HBRUSH)(COLOR_BTNFACE+1),
771c2c66affSColin Finck         NULL,
772c2c66affSColin Finck         "WineOleTestClass",
773c2c66affSColin Finck     };
774c2c66affSColin Finck 
775c2c66affSColin Finck     return RegisterClassA(&wc);
776c2c66affSColin Finck }
777c2c66affSColin Finck 
test_ole_menu(void)778c2c66affSColin Finck static void test_ole_menu(void)
779c2c66affSColin Finck {
780c2c66affSColin Finck 	HWND hwndFrame;
781c2c66affSColin Finck 	HRESULT hr;
782c2c66affSColin Finck 
783c2c66affSColin Finck 	hwndFrame = CreateWindowA((LPCSTR)MAKEINTATOM(register_dummy_class()), "Test", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
784c2c66affSColin Finck 	hr = OleSetMenuDescriptor(NULL, hwndFrame, NULL, NULL, NULL);
785c2c66affSColin Finck 	todo_wine ok_ole_success(hr, "OleSetMenuDescriptor");
786c2c66affSColin Finck 
787c2c66affSColin Finck 	DestroyWindow(hwndFrame);
788c2c66affSColin Finck }
789c2c66affSColin Finck 
790c2c66affSColin Finck 
MessageFilter_QueryInterface(IMessageFilter * iface,REFIID riid,void ** ppvObj)791c2c66affSColin Finck static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
792c2c66affSColin Finck {
793c2c66affSColin Finck     if (ppvObj == NULL) return E_POINTER;
794c2c66affSColin Finck 
795c2c66affSColin Finck     if (IsEqualGUID(riid, &IID_IUnknown) ||
796fc6e4ed5SAmine Khaldi         IsEqualGUID(riid, &IID_IMessageFilter))
797c2c66affSColin Finck     {
798c2c66affSColin Finck         *ppvObj = iface;
799c2c66affSColin Finck         IMessageFilter_AddRef(iface);
800c2c66affSColin Finck         return S_OK;
801c2c66affSColin Finck     }
802c2c66affSColin Finck 
803c2c66affSColin Finck     return E_NOINTERFACE;
804c2c66affSColin Finck }
805c2c66affSColin Finck 
MessageFilter_AddRef(IMessageFilter * iface)806c2c66affSColin Finck static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
807c2c66affSColin Finck {
808c2c66affSColin Finck     return 2; /* non-heap object */
809c2c66affSColin Finck }
810c2c66affSColin Finck 
MessageFilter_Release(IMessageFilter * iface)811c2c66affSColin Finck static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
812c2c66affSColin Finck {
813c2c66affSColin Finck     return 1; /* non-heap object */
814c2c66affSColin Finck }
815c2c66affSColin Finck 
MessageFilter_HandleInComingCall(IMessageFilter * iface,DWORD dwCallType,HTASK threadIDCaller,DWORD dwTickCount,LPINTERFACEINFO lpInterfaceInfo)816c2c66affSColin Finck static DWORD WINAPI MessageFilter_HandleInComingCall(
817c2c66affSColin Finck   IMessageFilter *iface,
818c2c66affSColin Finck   DWORD dwCallType,
819c2c66affSColin Finck   HTASK threadIDCaller,
820c2c66affSColin Finck   DWORD dwTickCount,
821c2c66affSColin Finck   LPINTERFACEINFO lpInterfaceInfo)
822c2c66affSColin Finck {
823c2c66affSColin Finck     trace("HandleInComingCall\n");
824c2c66affSColin Finck     return SERVERCALL_ISHANDLED;
825c2c66affSColin Finck }
826c2c66affSColin Finck 
MessageFilter_RetryRejectedCall(IMessageFilter * iface,HTASK threadIDCallee,DWORD dwTickCount,DWORD dwRejectType)827c2c66affSColin Finck static DWORD WINAPI MessageFilter_RetryRejectedCall(
828c2c66affSColin Finck   IMessageFilter *iface,
829c2c66affSColin Finck   HTASK threadIDCallee,
830c2c66affSColin Finck   DWORD dwTickCount,
831c2c66affSColin Finck   DWORD dwRejectType)
832c2c66affSColin Finck {
833c2c66affSColin Finck     trace("RetryRejectedCall\n");
834c2c66affSColin Finck     return 0;
835c2c66affSColin Finck }
836c2c66affSColin Finck 
MessageFilter_MessagePending(IMessageFilter * iface,HTASK threadIDCallee,DWORD dwTickCount,DWORD dwPendingType)837c2c66affSColin Finck static DWORD WINAPI MessageFilter_MessagePending(
838c2c66affSColin Finck   IMessageFilter *iface,
839c2c66affSColin Finck   HTASK threadIDCallee,
840c2c66affSColin Finck   DWORD dwTickCount,
841c2c66affSColin Finck   DWORD dwPendingType)
842c2c66affSColin Finck {
843c2c66affSColin Finck     trace("MessagePending\n");
844*e26c8bc6STimo Kreuzer     ros_skip_flaky
84566f35ef8SAmine Khaldi     todo_wine ok(0, "unexpected call\n");
846c2c66affSColin Finck     return PENDINGMSG_WAITNOPROCESS;
847c2c66affSColin Finck }
848c2c66affSColin Finck 
849c2c66affSColin Finck static const IMessageFilterVtbl MessageFilter_Vtbl =
850c2c66affSColin Finck {
851c2c66affSColin Finck     MessageFilter_QueryInterface,
852c2c66affSColin Finck     MessageFilter_AddRef,
853c2c66affSColin Finck     MessageFilter_Release,
854c2c66affSColin Finck     MessageFilter_HandleInComingCall,
855c2c66affSColin Finck     MessageFilter_RetryRejectedCall,
856c2c66affSColin Finck     MessageFilter_MessagePending
857c2c66affSColin Finck };
858c2c66affSColin Finck 
859c2c66affSColin Finck static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
860c2c66affSColin Finck 
test_CoRegisterMessageFilter(void)861c2c66affSColin Finck static void test_CoRegisterMessageFilter(void)
862c2c66affSColin Finck {
863c2c66affSColin Finck     HRESULT hr;
864c2c66affSColin Finck     IMessageFilter *prev_filter;
865c2c66affSColin Finck 
866c2c66affSColin Finck     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
867c2c66affSColin Finck     ok(hr == CO_E_NOT_SUPPORTED,
868c2c66affSColin Finck         "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
869c2c66affSColin Finck         hr);
870c2c66affSColin Finck 
871c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
872c2c66affSColin Finck     prev_filter = (IMessageFilter *)0xdeadbeef;
873c2c66affSColin Finck     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
874c2c66affSColin Finck     ok(hr == CO_E_NOT_SUPPORTED,
875c2c66affSColin Finck         "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08x\n",
876c2c66affSColin Finck         hr);
877c2c66affSColin Finck     ok(prev_filter == (IMessageFilter *)0xdeadbeef,
878c2c66affSColin Finck         "prev_filter should have been set to %p\n", prev_filter);
879c2c66affSColin Finck     CoUninitialize();
880c2c66affSColin Finck 
881c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
882c2c66affSColin Finck 
883c2c66affSColin Finck     hr = CoRegisterMessageFilter(NULL, NULL);
884c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterMessageFilter");
885c2c66affSColin Finck 
886c2c66affSColin Finck     prev_filter = (IMessageFilter *)0xdeadbeef;
887c2c66affSColin Finck     hr = CoRegisterMessageFilter(NULL, &prev_filter);
888c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterMessageFilter");
889c2c66affSColin Finck     ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
890c2c66affSColin Finck 
891c2c66affSColin Finck     hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
892c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterMessageFilter");
893c2c66affSColin Finck     ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
894c2c66affSColin Finck 
895c2c66affSColin Finck     hr = CoRegisterMessageFilter(NULL, NULL);
896c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterMessageFilter");
897c2c66affSColin Finck 
898c2c66affSColin Finck     CoUninitialize();
899c2c66affSColin Finck }
900c2c66affSColin Finck 
901c2c66affSColin Finck static IUnknown Test_Unknown;
902c2c66affSColin Finck 
EnumOLEVERB_QueryInterface(IEnumOLEVERB * iface,REFIID riid,void ** ppv)903c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_QueryInterface(IEnumOLEVERB *iface, REFIID riid, void **ppv)
904c2c66affSColin Finck {
905c2c66affSColin Finck     return IUnknown_QueryInterface(&Test_Unknown, riid, ppv);
906c2c66affSColin Finck }
907c2c66affSColin Finck 
EnumOLEVERB_AddRef(IEnumOLEVERB * iface)908c2c66affSColin Finck static ULONG WINAPI EnumOLEVERB_AddRef(IEnumOLEVERB *iface)
909c2c66affSColin Finck {
910c2c66affSColin Finck     return 2;
911c2c66affSColin Finck }
912c2c66affSColin Finck 
EnumOLEVERB_Release(IEnumOLEVERB * iface)913c2c66affSColin Finck static ULONG WINAPI EnumOLEVERB_Release(IEnumOLEVERB *iface)
914c2c66affSColin Finck {
915c2c66affSColin Finck     return 1;
916c2c66affSColin Finck }
917c2c66affSColin Finck 
EnumOLEVERB_Next(IEnumOLEVERB * iface,ULONG celt,OLEVERB * rgelt,ULONG * fetched)918c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_Next(IEnumOLEVERB *iface, ULONG celt, OLEVERB *rgelt, ULONG *fetched)
919c2c66affSColin Finck {
920c2c66affSColin Finck     ok(0, "unexpected call\n");
921c2c66affSColin Finck     return E_NOTIMPL;
922c2c66affSColin Finck }
923c2c66affSColin Finck 
EnumOLEVERB_Skip(IEnumOLEVERB * iface,ULONG celt)924c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_Skip(IEnumOLEVERB *iface, ULONG celt)
925c2c66affSColin Finck {
926c2c66affSColin Finck     ok(0, "unexpected call\n");
927c2c66affSColin Finck     return E_NOTIMPL;
928c2c66affSColin Finck }
929c2c66affSColin Finck 
EnumOLEVERB_Reset(IEnumOLEVERB * iface)930c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_Reset(IEnumOLEVERB *iface)
931c2c66affSColin Finck {
932c2c66affSColin Finck     ok(0, "unexpected call\n");
933c2c66affSColin Finck     return E_NOTIMPL;
934c2c66affSColin Finck }
935c2c66affSColin Finck 
EnumOLEVERB_Clone(IEnumOLEVERB * iface,IEnumOLEVERB ** ppenum)936c2c66affSColin Finck static HRESULT WINAPI EnumOLEVERB_Clone(IEnumOLEVERB *iface, IEnumOLEVERB **ppenum)
937c2c66affSColin Finck {
938c2c66affSColin Finck     ok(0, "unexpected call\n");
939c2c66affSColin Finck     return E_NOTIMPL;
940c2c66affSColin Finck }
941c2c66affSColin Finck 
942c2c66affSColin Finck static const IEnumOLEVERBVtbl EnumOLEVERBVtbl = {
943c2c66affSColin Finck     EnumOLEVERB_QueryInterface,
944c2c66affSColin Finck     EnumOLEVERB_AddRef,
945c2c66affSColin Finck     EnumOLEVERB_Release,
946c2c66affSColin Finck     EnumOLEVERB_Next,
947c2c66affSColin Finck     EnumOLEVERB_Skip,
948c2c66affSColin Finck     EnumOLEVERB_Reset,
949c2c66affSColin Finck     EnumOLEVERB_Clone
950c2c66affSColin Finck };
951c2c66affSColin Finck 
952c2c66affSColin Finck static IEnumOLEVERB EnumOLEVERB = { &EnumOLEVERBVtbl };
953c2c66affSColin Finck 
Test_IUnknown_QueryInterface(IUnknown * iface,REFIID riid,LPVOID * ppvObj)954c2c66affSColin Finck static HRESULT WINAPI Test_IUnknown_QueryInterface(
955c2c66affSColin Finck     IUnknown *iface,
956c2c66affSColin Finck     REFIID riid,
957c2c66affSColin Finck     LPVOID *ppvObj)
958c2c66affSColin Finck {
959c2c66affSColin Finck     if (ppvObj == NULL) return E_POINTER;
960c2c66affSColin Finck 
961c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IWineTest)) {
962c2c66affSColin Finck         *ppvObj = iface;
963c2c66affSColin Finck     }else if(IsEqualIID(riid, &IID_IEnumOLEVERB)) {
964c2c66affSColin Finck         *ppvObj = &EnumOLEVERB;
965c2c66affSColin Finck     }else {
966c2c66affSColin Finck         *ppvObj = NULL;
967c2c66affSColin Finck         return E_NOINTERFACE;
968c2c66affSColin Finck     }
969c2c66affSColin Finck 
970c2c66affSColin Finck     IUnknown_AddRef((IUnknown*)*ppvObj);
971c2c66affSColin Finck     return S_OK;
972c2c66affSColin Finck }
973c2c66affSColin Finck 
Test_IUnknown_AddRef(IUnknown * iface)974c2c66affSColin Finck static ULONG WINAPI Test_IUnknown_AddRef(IUnknown *iface)
975c2c66affSColin Finck {
976c2c66affSColin Finck     return 2; /* non-heap-based object */
977c2c66affSColin Finck }
978c2c66affSColin Finck 
Test_IUnknown_Release(IUnknown * iface)979c2c66affSColin Finck static ULONG WINAPI Test_IUnknown_Release(IUnknown *iface)
980c2c66affSColin Finck {
981c2c66affSColin Finck     return 1; /* non-heap-based object */
982c2c66affSColin Finck }
983c2c66affSColin Finck 
984c2c66affSColin Finck static const IUnknownVtbl TestUnknown_Vtbl =
985c2c66affSColin Finck {
986c2c66affSColin Finck     Test_IUnknown_QueryInterface,
987c2c66affSColin Finck     Test_IUnknown_AddRef,
988c2c66affSColin Finck     Test_IUnknown_Release,
989c2c66affSColin Finck };
990c2c66affSColin Finck 
991c2c66affSColin Finck static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
992c2c66affSColin Finck 
993c2c66affSColin Finck static IPSFactoryBuffer *ps_factory_buffer;
994c2c66affSColin Finck 
PSFactoryBuffer_QueryInterface(IPSFactoryBuffer * This,REFIID riid,void ** ppvObject)995c2c66affSColin Finck static HRESULT WINAPI PSFactoryBuffer_QueryInterface(
996c2c66affSColin Finck     IPSFactoryBuffer * This,
997c2c66affSColin Finck     /* [in] */ REFIID riid,
998c2c66affSColin Finck     /* [iid_is][out] */ void **ppvObject)
999c2c66affSColin Finck {
1000c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IUnknown) ||
1001c2c66affSColin Finck         IsEqualIID(riid, &IID_IPSFactoryBuffer))
1002c2c66affSColin Finck     {
1003c2c66affSColin Finck         *ppvObject = This;
1004c2c66affSColin Finck         IPSFactoryBuffer_AddRef(This);
1005c2c66affSColin Finck         return S_OK;
1006c2c66affSColin Finck     }
1007c2c66affSColin Finck     return E_NOINTERFACE;
1008c2c66affSColin Finck }
1009c2c66affSColin Finck 
PSFactoryBuffer_AddRef(IPSFactoryBuffer * This)1010c2c66affSColin Finck static ULONG WINAPI PSFactoryBuffer_AddRef(
1011c2c66affSColin Finck     IPSFactoryBuffer * This)
1012c2c66affSColin Finck {
1013c2c66affSColin Finck     return 2;
1014c2c66affSColin Finck }
1015c2c66affSColin Finck 
PSFactoryBuffer_Release(IPSFactoryBuffer * This)1016c2c66affSColin Finck static ULONG WINAPI PSFactoryBuffer_Release(
1017c2c66affSColin Finck     IPSFactoryBuffer * This)
1018c2c66affSColin Finck {
1019c2c66affSColin Finck     return 1;
1020c2c66affSColin Finck }
1021c2c66affSColin Finck 
PSFactoryBuffer_CreateProxy(IPSFactoryBuffer * This,IUnknown * pUnkOuter,REFIID riid,IRpcProxyBuffer ** ppProxy,void ** ppv)1022c2c66affSColin Finck static HRESULT WINAPI PSFactoryBuffer_CreateProxy(
1023c2c66affSColin Finck     IPSFactoryBuffer * This,
1024c2c66affSColin Finck     /* [in] */ IUnknown *pUnkOuter,
1025c2c66affSColin Finck     /* [in] */ REFIID riid,
1026c2c66affSColin Finck     /* [out] */ IRpcProxyBuffer **ppProxy,
1027c2c66affSColin Finck     /* [out] */ void **ppv)
1028c2c66affSColin Finck {
1029c2c66affSColin Finck     return E_NOTIMPL;
1030c2c66affSColin Finck }
1031c2c66affSColin Finck 
PSFactoryBuffer_CreateStub(IPSFactoryBuffer * This,REFIID riid,IUnknown * pUnkServer,IRpcStubBuffer ** ppStub)1032c2c66affSColin Finck static HRESULT WINAPI PSFactoryBuffer_CreateStub(
1033c2c66affSColin Finck     IPSFactoryBuffer * This,
1034c2c66affSColin Finck     /* [in] */ REFIID riid,
1035c2c66affSColin Finck     /* [unique][in] */ IUnknown *pUnkServer,
1036c2c66affSColin Finck     /* [out] */ IRpcStubBuffer **ppStub)
1037c2c66affSColin Finck {
1038c2c66affSColin Finck     CHECK_EXPECT(CreateStub);
1039c2c66affSColin Finck 
1040fc6e4ed5SAmine Khaldi     ok(pUnkServer == &Test_Unknown, "unexpected pUnkServer %p\n", pUnkServer);
1041c2c66affSColin Finck     if(!ps_factory_buffer)
1042c2c66affSColin Finck         return E_NOTIMPL;
1043c2c66affSColin Finck 
1044c2c66affSColin Finck     return IPSFactoryBuffer_CreateStub(ps_factory_buffer, &IID_IEnumOLEVERB, pUnkServer, ppStub);
1045c2c66affSColin Finck }
1046c2c66affSColin Finck 
1047c2c66affSColin Finck static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
1048c2c66affSColin Finck {
1049c2c66affSColin Finck     PSFactoryBuffer_QueryInterface,
1050c2c66affSColin Finck     PSFactoryBuffer_AddRef,
1051c2c66affSColin Finck     PSFactoryBuffer_Release,
1052c2c66affSColin Finck     PSFactoryBuffer_CreateProxy,
1053c2c66affSColin Finck     PSFactoryBuffer_CreateStub
1054c2c66affSColin Finck };
1055c2c66affSColin Finck 
1056c2c66affSColin Finck static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl };
1057c2c66affSColin Finck 
1058c2c66affSColin Finck static const CLSID CLSID_WineTestPSFactoryBuffer =
1059c2c66affSColin Finck {
1060c2c66affSColin Finck     0x52011640,
1061c2c66affSColin Finck     0x8164,
1062c2c66affSColin Finck     0x4fd0,
1063c2c66affSColin Finck     {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1064c2c66affSColin Finck }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
1065c2c66affSColin Finck 
register_ps_clsid_thread(void * context)1066c2c66affSColin Finck static DWORD CALLBACK register_ps_clsid_thread(void *context)
1067c2c66affSColin Finck {
1068c2c66affSColin Finck     HRESULT hr;
1069c2c66affSColin Finck     CLSID clsid = {0};
1070c2c66affSColin Finck 
1071c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1072c2c66affSColin Finck 
1073c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1074c2c66affSColin Finck     ok_ole_success(hr, "CoGetPSClsid");
1075c2c66affSColin Finck     ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1076c2c66affSColin Finck                    wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1077c2c66affSColin Finck 
1078c2c66affSColin Finck     /* test registering a PSClsid in an apartment which is then destroyed */
1079c2c66affSColin Finck     hr = CoRegisterPSClsid(&IID_TestPS, &clsid);
1080c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterPSClsid");
1081c2c66affSColin Finck 
1082c2c66affSColin Finck     CoUninitialize();
1083c2c66affSColin Finck 
1084c2c66affSColin Finck     return hr;
1085c2c66affSColin Finck }
1086c2c66affSColin Finck 
test_CoRegisterPSClsid(void)1087c2c66affSColin Finck static void test_CoRegisterPSClsid(void)
1088c2c66affSColin Finck {
1089c2c66affSColin Finck     HRESULT hr;
1090c2c66affSColin Finck     DWORD dwRegistrationKey;
1091c2c66affSColin Finck     IStream *stream;
1092c2c66affSColin Finck     CLSID clsid;
1093c2c66affSColin Finck     HANDLE thread;
1094c2c66affSColin Finck     DWORD tid;
1095c2c66affSColin Finck 
1096c2c66affSColin Finck     hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1097c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1098c2c66affSColin Finck 
1099c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1100c2c66affSColin Finck 
1101c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
1102c2c66affSColin Finck         CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey);
1103c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1104c2c66affSColin Finck 
1105c2c66affSColin Finck     hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1106c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterPSClsid");
1107c2c66affSColin Finck 
1108c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1109c2c66affSColin Finck     ok_ole_success(hr, "CoGetPSClsid");
1110c2c66affSColin Finck     ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1111c2c66affSColin Finck                    wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1112c2c66affSColin Finck 
1113c2c66affSColin Finck     thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid);
1114c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1115c2c66affSColin Finck     ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
1116c2c66affSColin Finck     CloseHandle(thread);
1117c2c66affSColin Finck 
1118c2c66affSColin Finck     hr = CoGetPSClsid(&IID_TestPS, &clsid);
1119c2c66affSColin Finck     ok_ole_success(hr, "CoGetPSClsid");
1120c2c66affSColin Finck     ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1121c2c66affSColin Finck                    wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1122c2c66affSColin Finck 
1123c2c66affSColin Finck     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1124c2c66affSColin Finck     ok_ole_success(hr, "CreateStreamOnHGlobal");
1125c2c66affSColin Finck 
1126c2c66affSColin Finck     SET_EXPECT(CreateStub);
1127c2c66affSColin Finck     hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1128c2c66affSColin Finck     ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1129fc6e4ed5SAmine Khaldi     CHECK_CALLED(CreateStub, 1);
1130c2c66affSColin Finck 
1131c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IEnumOLEVERB, &clsid);
1132c2c66affSColin Finck     ok_ole_success(hr, "CoGetPSClsid");
1133c2c66affSColin Finck 
1134c2c66affSColin Finck     hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void **)&ps_factory_buffer);
1135c2c66affSColin Finck     ok_ole_success(hr, "CoGetClassObject");
1136c2c66affSColin Finck 
1137c2c66affSColin Finck     hr = CoRegisterPSClsid(&IID_IEnumOLEVERB, &CLSID_WineTestPSFactoryBuffer);
1138c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterPSClsid");
1139c2c66affSColin Finck 
1140c2c66affSColin Finck     SET_EXPECT(CreateStub);
1141c2c66affSColin Finck     hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1142c2c66affSColin Finck     ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
1143fc6e4ed5SAmine Khaldi     CHECK_CALLED(CreateStub, 1);
1144c2c66affSColin Finck 
1145c2c66affSColin Finck     hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1146c2c66affSColin Finck     ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
1147c2c66affSColin Finck 
1148c2c66affSColin Finck     IStream_Release(stream);
1149c2c66affSColin Finck     IPSFactoryBuffer_Release(ps_factory_buffer);
1150c2c66affSColin Finck     ps_factory_buffer = NULL;
1151c2c66affSColin Finck 
1152c2c66affSColin Finck     hr = CoRevokeClassObject(dwRegistrationKey);
1153c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1154c2c66affSColin Finck 
1155c2c66affSColin Finck     CoUninitialize();
1156c2c66affSColin Finck 
1157c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1158c2c66affSColin Finck 
1159c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1160c2c66affSColin Finck     ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
1161c2c66affSColin Finck 
1162c2c66affSColin Finck     hr = CoGetPSClsid(&IID_TestPS, &clsid);
1163c2c66affSColin Finck     ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
1164c2c66affSColin Finck 
1165c2c66affSColin Finck     CoUninitialize();
1166c2c66affSColin Finck 
1167c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1168c2c66affSColin Finck 
1169c2c66affSColin Finck     hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
1170c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterPSClsid");
1171c2c66affSColin Finck 
1172c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1173c2c66affSColin Finck     ok_ole_success(hr, "CoGetPSClsid");
1174c2c66affSColin Finck     ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1175c2c66affSColin Finck                    wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1176c2c66affSColin Finck 
1177c2c66affSColin Finck     thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid);
1178c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1179c2c66affSColin Finck     ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
1180c2c66affSColin Finck     CloseHandle(thread);
1181c2c66affSColin Finck 
1182c2c66affSColin Finck     hr = CoGetPSClsid(&IID_TestPS, &clsid);
1183c2c66affSColin Finck     ok_ole_success(hr, "CoGetPSClsid");
1184c2c66affSColin Finck     ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
1185c2c66affSColin Finck                    wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
1186c2c66affSColin Finck 
1187c2c66affSColin Finck     CoUninitialize();
1188c2c66affSColin Finck }
1189c2c66affSColin Finck 
test_CoGetPSClsid(void)1190c2c66affSColin Finck static void test_CoGetPSClsid(void)
1191c2c66affSColin Finck {
1192c2c66affSColin Finck     ULONG_PTR cookie;
1193c2c66affSColin Finck     HANDLE handle;
1194c2c66affSColin Finck     HRESULT hr;
1195c2c66affSColin Finck     CLSID clsid;
1196c2c66affSColin Finck     HKEY hkey;
1197c2c66affSColin Finck     LONG res;
1198c2c66affSColin Finck     const BOOL is_win64 = (sizeof(void*) != sizeof(int));
1199c2c66affSColin Finck     BOOL is_wow64 = FALSE;
1200c2c66affSColin Finck 
1201c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1202c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED,
1203c2c66affSColin Finck        "CoGetPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n",
1204c2c66affSColin Finck        hr);
1205c2c66affSColin Finck 
1206c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1207c2c66affSColin Finck 
1208c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1209c2c66affSColin Finck     ok_ole_success(hr, "CoGetPSClsid");
1210c2c66affSColin Finck 
1211c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IWineTest, &clsid);
1212c2c66affSColin Finck     ok(hr == REGDB_E_IIDNOTREG,
1213c2c66affSColin Finck        "CoGetPSClsid for random IID returned 0x%08x instead of REGDB_E_IIDNOTREG\n",
1214c2c66affSColin Finck        hr);
1215c2c66affSColin Finck 
1216c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IClassFactory, NULL);
1217c2c66affSColin Finck     ok(hr == E_INVALIDARG,
1218c2c66affSColin Finck        "CoGetPSClsid for null clsid returned 0x%08x instead of E_INVALIDARG\n",
1219c2c66affSColin Finck        hr);
1220c2c66affSColin Finck 
1221c2c66affSColin Finck     if (!pRegOverridePredefKey)
1222c2c66affSColin Finck     {
1223c2c66affSColin Finck         win_skip("RegOverridePredefKey not available\n");
1224c2c66affSColin Finck         CoUninitialize();
1225c2c66affSColin Finck         return;
1226c2c66affSColin Finck     }
1227c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1228c2c66affSColin Finck     ok_ole_success(hr, "CoGetPSClsid");
1229c2c66affSColin Finck 
1230c2c66affSColin Finck     res = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Classes", 0, NULL, 0,
1231c2c66affSColin Finck                           KEY_ALL_ACCESS, NULL, &hkey, NULL);
1232c2c66affSColin Finck     ok(!res, "RegCreateKeyEx returned %d\n", res);
1233c2c66affSColin Finck 
1234c2c66affSColin Finck     res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, hkey);
1235c2c66affSColin Finck     ok(!res, "RegOverridePredefKey returned %d\n", res);
1236c2c66affSColin Finck 
1237c2c66affSColin Finck     hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
1238c2c66affSColin Finck     ok_ole_success(hr, "CoGetPSClsid");
1239c2c66affSColin Finck 
1240c2c66affSColin Finck     res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
1241c2c66affSColin Finck     ok(!res, "RegOverridePredefKey returned %d\n", res);
1242c2c66affSColin Finck 
1243c2c66affSColin Finck     RegCloseKey(hkey);
1244c2c66affSColin Finck 
1245c2c66affSColin Finck     /* not registered CLSID */
1246c2c66affSColin Finck     hr = CoGetPSClsid(&IID_Testiface, &clsid);
1247c2c66affSColin Finck     ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1248c2c66affSColin Finck 
1249c2c66affSColin Finck     if ((handle = activate_context(actctx_manifest, &cookie)))
1250c2c66affSColin Finck     {
1251c2c66affSColin Finck         memset(&clsid, 0, sizeof(clsid));
1252c2c66affSColin Finck         hr = CoGetPSClsid(&IID_Testiface, &clsid);
1253c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
1254c2c66affSColin Finck         ok(IsEqualGUID(&clsid, &IID_Testiface), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1255c2c66affSColin Finck 
1256c2c66affSColin Finck         memset(&clsid, 0, sizeof(clsid));
1257c2c66affSColin Finck         hr = CoGetPSClsid(&IID_Testiface2, &clsid);
1258c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
1259c2c66affSColin Finck         ok(IsEqualGUID(&clsid, &IID_Testiface2), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1260c2c66affSColin Finck 
1261c2c66affSColin Finck         memset(&clsid, 0, sizeof(clsid));
1262c2c66affSColin Finck         hr = CoGetPSClsid(&IID_Testiface3, &clsid);
1263c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
1264c2c66affSColin Finck         ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1265c2c66affSColin Finck 
1266c2c66affSColin Finck         memset(&clsid, 0xaa, sizeof(clsid));
1267c2c66affSColin Finck         hr = CoGetPSClsid(&IID_Testiface4, &clsid);
1268c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
1269c2c66affSColin Finck         ok(IsEqualGUID(&clsid, &GUID_NULL), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1270c2c66affSColin Finck 
1271c2c66affSColin Finck         /* register same interface and try to get CLSID back */
1272c2c66affSColin Finck         hr = CoRegisterPSClsid(&IID_Testiface, &IID_Testiface4);
1273c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
1274c2c66affSColin Finck         memset(&clsid, 0, sizeof(clsid));
1275c2c66affSColin Finck         hr = CoGetPSClsid(&IID_Testiface, &clsid);
1276c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
1277c2c66affSColin Finck         ok(IsEqualGUID(&clsid, &IID_Testiface4), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1278c2c66affSColin Finck 
1279c2c66affSColin Finck         pDeactivateActCtx(0, cookie);
1280c2c66affSColin Finck         pReleaseActCtx(handle);
1281c2c66affSColin Finck     }
1282c2c66affSColin Finck 
1283c2c66affSColin Finck     if (pRegDeleteKeyExA &&
1284c2c66affSColin Finck         (is_win64 ||
1285c2c66affSColin Finck          (pIsWow64Process && pIsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
1286c2c66affSColin Finck     {
1287c2c66affSColin Finck         static GUID IID_DeadBeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
1288c2c66affSColin Finck         static const char clsidDeadBeef[] = "{deadbeef-dead-beef-dead-beefdeadbeef}";
1289c2c66affSColin Finck         static const char clsidA[] = "{66666666-8888-7777-6666-555555555555}";
1290c2c66affSColin Finck         HKEY hkey_iface, hkey_psclsid;
1291c2c66affSColin Finck         REGSAM opposite = is_win64 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
1292c2c66affSColin Finck 
1293c2c66affSColin Finck         hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1294c2c66affSColin Finck         ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
1295c2c66affSColin Finck 
1296c2c66affSColin Finck         res = RegCreateKeyExA(HKEY_CLASSES_ROOT, "Interface",
1297c2c66affSColin Finck                               0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_iface, NULL);
1298c2c66affSColin Finck         ok(!res, "RegCreateKeyEx returned %d\n", res);
1299c2c66affSColin Finck         res = RegCreateKeyExA(hkey_iface, clsidDeadBeef,
1300c2c66affSColin Finck                               0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey, NULL);
1301c2c66affSColin Finck         if (res == ERROR_ACCESS_DENIED)
1302c2c66affSColin Finck         {
1303c2c66affSColin Finck             win_skip("Failed to create a key, skipping some of CoGetPSClsid() tests\n");
1304c2c66affSColin Finck             goto cleanup;
1305c2c66affSColin Finck         }
1306c2c66affSColin Finck 
1307c2c66affSColin Finck         ok(!res, "RegCreateKeyEx returned %d\n", res);
1308c2c66affSColin Finck         res = RegCreateKeyExA(hkey, "ProxyStubClsid32",
1309c2c66affSColin Finck                               0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_psclsid, NULL);
1310c2c66affSColin Finck         ok(!res, "RegCreateKeyEx returned %d\n", res);
1311c2c66affSColin Finck         res = RegSetValueExA(hkey_psclsid, NULL, 0, REG_SZ, (const BYTE *)clsidA, strlen(clsidA)+1);
1312c2c66affSColin Finck         ok(!res, "RegSetValueEx returned %d\n", res);
1313c2c66affSColin Finck         RegCloseKey(hkey_psclsid);
1314c2c66affSColin Finck 
1315c2c66affSColin Finck         hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
1316c2c66affSColin Finck         ok_ole_success(hr, "CoGetPSClsid");
1317c2c66affSColin Finck         ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
1318c2c66affSColin Finck 
1319c2c66affSColin Finck         res = pRegDeleteKeyExA(hkey, "ProxyStubClsid32", opposite, 0);
1320c2c66affSColin Finck         ok(!res, "RegDeleteKeyEx returned %d\n", res);
1321c2c66affSColin Finck         RegCloseKey(hkey);
1322c2c66affSColin Finck         res = pRegDeleteKeyExA(hkey_iface, clsidDeadBeef, opposite, 0);
1323c2c66affSColin Finck         ok(!res, "RegDeleteKeyEx returned %d\n", res);
1324c2c66affSColin Finck 
1325c2c66affSColin Finck     cleanup:
1326c2c66affSColin Finck         RegCloseKey(hkey_iface);
1327c2c66affSColin Finck     }
1328c2c66affSColin Finck 
1329c2c66affSColin Finck     CoUninitialize();
1330c2c66affSColin Finck }
1331c2c66affSColin Finck 
1332c2c66affSColin Finck /* basic test, mainly for invalid arguments. see marshal.c for more */
test_CoUnmarshalInterface(void)1333c2c66affSColin Finck static void test_CoUnmarshalInterface(void)
1334c2c66affSColin Finck {
1335c2c66affSColin Finck     IUnknown *pProxy;
1336c2c66affSColin Finck     IStream *pStream;
1337c2c66affSColin Finck     HRESULT hr;
1338c2c66affSColin Finck 
1339c2c66affSColin Finck     hr = CoUnmarshalInterface(NULL, &IID_IUnknown, (void **)&pProxy);
1340c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1341c2c66affSColin Finck 
1342c2c66affSColin Finck     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1343c2c66affSColin Finck     ok_ole_success(hr, "CreateStreamOnHGlobal");
1344c2c66affSColin Finck 
1345c2c66affSColin Finck     hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1346c2c66affSColin Finck     todo_wine
1347c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "CoUnmarshalInterface should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1348c2c66affSColin Finck 
1349c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1350c2c66affSColin Finck 
1351c2c66affSColin Finck     hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1352c2c66affSColin Finck     ok(hr == STG_E_READFAULT, "CoUnmarshalInterface should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1353c2c66affSColin Finck 
1354c2c66affSColin Finck     CoUninitialize();
1355c2c66affSColin Finck 
1356c2c66affSColin Finck     hr = CoUnmarshalInterface(pStream, &IID_IUnknown, NULL);
1357c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CoUnmarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1358c2c66affSColin Finck 
1359c2c66affSColin Finck     IStream_Release(pStream);
1360c2c66affSColin Finck }
1361c2c66affSColin Finck 
test_CoGetInterfaceAndReleaseStream(void)1362c2c66affSColin Finck static void test_CoGetInterfaceAndReleaseStream(void)
1363c2c66affSColin Finck {
1364c2c66affSColin Finck     HRESULT hr;
1365c2c66affSColin Finck     IUnknown *pUnk;
1366c2c66affSColin Finck 
1367c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1368c2c66affSColin Finck 
1369c2c66affSColin Finck     hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
1370c2c66affSColin Finck     ok(hr == E_INVALIDARG, "hr %08x\n", hr);
1371c2c66affSColin Finck 
1372c2c66affSColin Finck     CoUninitialize();
1373c2c66affSColin Finck }
1374c2c66affSColin Finck 
1375c2c66affSColin Finck /* basic test, mainly for invalid arguments. see marshal.c for more */
test_CoMarshalInterface(void)1376c2c66affSColin Finck static void test_CoMarshalInterface(void)
1377c2c66affSColin Finck {
1378c2c66affSColin Finck     IStream *pStream;
1379c2c66affSColin Finck     HRESULT hr;
1380c2c66affSColin Finck     static const LARGE_INTEGER llZero;
1381c2c66affSColin Finck 
1382c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1383c2c66affSColin Finck 
1384c2c66affSColin Finck     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1385c2c66affSColin Finck     ok_ole_success(hr, "CreateStreamOnHGlobal");
1386c2c66affSColin Finck 
1387c2c66affSColin Finck     hr = CoMarshalInterface(pStream, &IID_IUnknown, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1388c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1389c2c66affSColin Finck 
1390c2c66affSColin Finck     hr = CoMarshalInterface(NULL, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1391c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CoMarshalInterface should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1392c2c66affSColin Finck 
1393c2c66affSColin Finck     hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1394c2c66affSColin Finck     ok_ole_success(hr, "CoMarshalInterface");
1395c2c66affSColin Finck 
1396c2c66affSColin Finck     /* stream not rewound */
1397c2c66affSColin Finck     hr = CoReleaseMarshalData(pStream);
1398c2c66affSColin Finck     ok(hr == STG_E_READFAULT, "CoReleaseMarshalData should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1399c2c66affSColin Finck 
1400c2c66affSColin Finck     hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1401c2c66affSColin Finck     ok_ole_success(hr, "IStream_Seek");
1402c2c66affSColin Finck 
1403c2c66affSColin Finck     hr = CoReleaseMarshalData(pStream);
1404c2c66affSColin Finck     ok_ole_success(hr, "CoReleaseMarshalData");
1405c2c66affSColin Finck 
1406c2c66affSColin Finck     IStream_Release(pStream);
1407c2c66affSColin Finck 
1408c2c66affSColin Finck     CoUninitialize();
1409c2c66affSColin Finck }
1410c2c66affSColin Finck 
test_CoMarshalInterThreadInterfaceInStream(void)1411c2c66affSColin Finck static void test_CoMarshalInterThreadInterfaceInStream(void)
1412c2c66affSColin Finck {
1413c2c66affSColin Finck     IStream *pStream;
1414c2c66affSColin Finck     HRESULT hr;
1415c2c66affSColin Finck     IClassFactory *pProxy;
1416c2c66affSColin Finck 
1417c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1418c2c66affSColin Finck 
1419c2c66affSColin Finck     cLocks = 0;
1420c2c66affSColin Finck 
1421c2c66affSColin Finck     hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, NULL);
1422c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1423c2c66affSColin Finck 
1424c2c66affSColin Finck     hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, NULL, &pStream);
1425c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CoMarshalInterThreadInterfaceInStream should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1426c2c66affSColin Finck 
1427c2c66affSColin Finck     ok_no_locks();
1428c2c66affSColin Finck 
1429c2c66affSColin Finck     hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, (IUnknown *)&Test_ClassFactory, &pStream);
1430c2c66affSColin Finck     ok_ole_success(hr, "CoMarshalInterThreadInterfaceInStream");
1431c2c66affSColin Finck 
1432c2c66affSColin Finck     ok_more_than_one_lock();
1433c2c66affSColin Finck 
1434c2c66affSColin Finck     hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1435c2c66affSColin Finck     ok_ole_success(hr, "CoUnmarshalInterface");
1436c2c66affSColin Finck 
1437c2c66affSColin Finck     IClassFactory_Release(pProxy);
1438c2c66affSColin Finck     IStream_Release(pStream);
1439c2c66affSColin Finck 
1440c2c66affSColin Finck     ok_no_locks();
1441c2c66affSColin Finck 
1442c2c66affSColin Finck     CoUninitialize();
1443c2c66affSColin Finck }
1444c2c66affSColin Finck 
test_CoRegisterClassObject(void)1445c2c66affSColin Finck static void test_CoRegisterClassObject(void)
1446c2c66affSColin Finck {
1447c2c66affSColin Finck     ULONG_PTR ctxcookie;
1448c2c66affSColin Finck     HANDLE handle;
1449c2c66affSColin Finck     DWORD cookie;
1450c2c66affSColin Finck     HRESULT hr;
1451c2c66affSColin Finck     IClassFactory *pcf;
1452c2c66affSColin Finck 
1453c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1454c2c66affSColin Finck 
1455c2c66affSColin Finck     /* CLSCTX_INPROC_SERVER */
1456c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1457c2c66affSColin Finck                                CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1458c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1459c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1460c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1461c2c66affSColin Finck 
1462c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1463c2c66affSColin Finck                                CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1464c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1465c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1466c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1467c2c66affSColin Finck 
1468c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1469c2c66affSColin Finck                                CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1470c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1471c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1472c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1473c2c66affSColin Finck 
1474c2c66affSColin Finck     /* CLSCTX_LOCAL_SERVER */
1475c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1476c2c66affSColin Finck                                CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1477c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1478c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1479c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1480c2c66affSColin Finck 
1481c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1482c2c66affSColin Finck                                CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1483c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1484c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1485c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1486c2c66affSColin Finck 
1487c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1488c2c66affSColin Finck                                CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE, &cookie);
1489c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1490c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1491c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1492c2c66affSColin Finck 
1493c2c66affSColin Finck     /* CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER */
1494c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1495c2c66affSColin Finck                                CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1496c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1497c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1498c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1499c2c66affSColin Finck 
1500c2c66affSColin Finck     /* test whether an object that doesn't support IClassFactory can be
1501c2c66affSColin Finck      * registered for CLSCTX_LOCAL_SERVER */
1502c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, &Test_Unknown,
1503c2c66affSColin Finck                                CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
1504c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1505c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1506c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1507c2c66affSColin Finck 
1508c2c66affSColin Finck     /* test whether registered class becomes invalid when apartment is destroyed */
1509c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1510c2c66affSColin Finck                                CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1511c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1512c2c66affSColin Finck 
1513c2c66affSColin Finck     CoUninitialize();
1514c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1515c2c66affSColin Finck 
1516c2c66affSColin Finck     hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL,
1517c2c66affSColin Finck                           &IID_IClassFactory, (void **)&pcf);
1518c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n");
1519c2c66affSColin Finck 
1520c2c66affSColin Finck     /* crashes with at least win9x DCOM! */
1521c2c66affSColin Finck     if (0)
1522c2c66affSColin Finck         CoRevokeClassObject(cookie);
1523c2c66affSColin Finck 
1524c2c66affSColin Finck     /* test that object is accessible */
1525c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, CLSCTX_INPROC_SERVER,
1526c2c66affSColin Finck         REGCLS_MULTIPLEUSE, &cookie);
1527c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
1528c2c66affSColin Finck 
1529c2c66affSColin Finck     hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1530c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
1531c2c66affSColin Finck     IClassFactory_Release(pcf);
1532c2c66affSColin Finck 
1533c2c66affSColin Finck     /* context now contains CLSID_WineOOPTest, test if registered one could still be used */
1534c2c66affSColin Finck     if ((handle = activate_context(actctx_manifest, &ctxcookie)))
1535c2c66affSColin Finck     {
1536c2c66affSColin Finck         hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1537c2c66affSColin Finck todo_wine
1538c2c66affSColin Finck         ok(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), "got 0x%08x\n", hr);
1539c2c66affSColin Finck 
1540c2c66affSColin Finck         pDeactivateActCtx(0, ctxcookie);
1541c2c66affSColin Finck         pReleaseActCtx(handle);
1542c2c66affSColin Finck     }
1543c2c66affSColin Finck 
1544c2c66affSColin Finck     hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&pcf);
1545c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
1546c2c66affSColin Finck     IClassFactory_Release(pcf);
1547c2c66affSColin Finck 
1548c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1549c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
1550c2c66affSColin Finck 
1551c2c66affSColin Finck     CoUninitialize();
1552c2c66affSColin Finck }
1553c2c66affSColin Finck 
get_class_object(CLSCTX clsctx)1554c2c66affSColin Finck static HRESULT get_class_object(CLSCTX clsctx)
1555c2c66affSColin Finck {
1556c2c66affSColin Finck     HRESULT hr;
1557c2c66affSColin Finck     IClassFactory *pcf;
1558c2c66affSColin Finck 
1559c2c66affSColin Finck     hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1560c2c66affSColin Finck                           (void **)&pcf);
1561c2c66affSColin Finck 
1562c2c66affSColin Finck     if (SUCCEEDED(hr))
1563c2c66affSColin Finck         IClassFactory_Release(pcf);
1564c2c66affSColin Finck 
1565c2c66affSColin Finck     return hr;
1566c2c66affSColin Finck }
1567c2c66affSColin Finck 
get_class_object_thread(LPVOID pv)1568c2c66affSColin Finck static DWORD CALLBACK get_class_object_thread(LPVOID pv)
1569c2c66affSColin Finck {
1570c2c66affSColin Finck     CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1571c2c66affSColin Finck     HRESULT hr;
1572c2c66affSColin Finck 
1573c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1574c2c66affSColin Finck 
1575c2c66affSColin Finck     hr = get_class_object(clsctx);
1576c2c66affSColin Finck 
1577c2c66affSColin Finck     CoUninitialize();
1578c2c66affSColin Finck 
1579c2c66affSColin Finck     return hr;
1580c2c66affSColin Finck }
1581c2c66affSColin Finck 
get_class_object_proxy_thread(LPVOID pv)1582c2c66affSColin Finck static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv)
1583c2c66affSColin Finck {
1584c2c66affSColin Finck     CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv;
1585c2c66affSColin Finck     HRESULT hr;
1586c2c66affSColin Finck     IClassFactory *pcf;
1587c2c66affSColin Finck     IMultiQI *pMQI;
1588c2c66affSColin Finck 
1589c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1590c2c66affSColin Finck 
1591c2c66affSColin Finck     hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory,
1592c2c66affSColin Finck                           (void **)&pcf);
1593c2c66affSColin Finck 
1594c2c66affSColin Finck     if (SUCCEEDED(hr))
1595c2c66affSColin Finck     {
1596c2c66affSColin Finck         hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI);
1597c2c66affSColin Finck         if (SUCCEEDED(hr))
1598c2c66affSColin Finck             IMultiQI_Release(pMQI);
1599c2c66affSColin Finck         IClassFactory_Release(pcf);
1600c2c66affSColin Finck     }
1601c2c66affSColin Finck 
1602c2c66affSColin Finck     CoUninitialize();
1603c2c66affSColin Finck 
1604c2c66affSColin Finck     return hr;
1605c2c66affSColin Finck }
1606c2c66affSColin Finck 
register_class_object_thread(LPVOID pv)1607c2c66affSColin Finck static DWORD CALLBACK register_class_object_thread(LPVOID pv)
1608c2c66affSColin Finck {
1609c2c66affSColin Finck     HRESULT hr;
1610c2c66affSColin Finck     DWORD cookie;
1611c2c66affSColin Finck 
1612c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1613c2c66affSColin Finck 
1614c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1615c2c66affSColin Finck                                CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1616c2c66affSColin Finck 
1617c2c66affSColin Finck     CoUninitialize();
1618c2c66affSColin Finck 
1619c2c66affSColin Finck     return hr;
1620c2c66affSColin Finck }
1621c2c66affSColin Finck 
revoke_class_object_thread(LPVOID pv)1622c2c66affSColin Finck static DWORD CALLBACK revoke_class_object_thread(LPVOID pv)
1623c2c66affSColin Finck {
1624c2c66affSColin Finck     DWORD cookie = (DWORD_PTR)pv;
1625c2c66affSColin Finck     HRESULT hr;
1626c2c66affSColin Finck 
1627c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1628c2c66affSColin Finck 
1629c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1630c2c66affSColin Finck 
1631c2c66affSColin Finck     CoUninitialize();
1632c2c66affSColin Finck 
1633c2c66affSColin Finck     return hr;
1634c2c66affSColin Finck }
1635c2c66affSColin Finck 
test_registered_object_thread_affinity(void)1636c2c66affSColin Finck static void test_registered_object_thread_affinity(void)
1637c2c66affSColin Finck {
1638c2c66affSColin Finck     HRESULT hr;
1639c2c66affSColin Finck     DWORD cookie;
1640c2c66affSColin Finck     HANDLE thread;
1641c2c66affSColin Finck     DWORD tid;
1642c2c66affSColin Finck     DWORD exitcode;
1643c2c66affSColin Finck 
1644c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1645c2c66affSColin Finck 
1646c2c66affSColin Finck     /* CLSCTX_INPROC_SERVER */
1647c2c66affSColin Finck 
1648c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1649c2c66affSColin Finck                                CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
1650c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1651c2c66affSColin Finck 
1652c2c66affSColin Finck     thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid);
1653c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1654c2c66affSColin Finck     ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1655c2c66affSColin Finck     GetExitCodeThread(thread, &exitcode);
1656c2c66affSColin Finck     hr = exitcode;
1657c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object "
1658c2c66affSColin Finck        "registered in different thread should return REGDB_E_CLASSNOTREG "
1659c2c66affSColin Finck        "instead of 0x%08x\n", hr);
1660c2c66affSColin Finck 
1661c2c66affSColin Finck     hr = get_class_object(CLSCTX_INPROC_SERVER);
1662c2c66affSColin Finck     ok(hr == S_OK, "CoGetClassObject on inproc object registered in same "
1663c2c66affSColin Finck        "thread should return S_OK instead of 0x%08x\n", hr);
1664c2c66affSColin Finck 
1665c2c66affSColin Finck     thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1666c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1667c2c66affSColin Finck     ok ( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1668c2c66affSColin Finck     GetExitCodeThread(thread, &exitcode);
1669c2c66affSColin Finck     hr = exitcode;
1670c2c66affSColin Finck     ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr);
1671c2c66affSColin Finck 
1672c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1673c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1674c2c66affSColin Finck 
1675c2c66affSColin Finck     /* CLSCTX_LOCAL_SERVER */
1676c2c66affSColin Finck 
1677c2c66affSColin Finck     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
1678c2c66affSColin Finck                                CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie);
1679c2c66affSColin Finck     ok_ole_success(hr, "CoRegisterClassObject");
1680c2c66affSColin Finck 
1681c2c66affSColin Finck     thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid);
1682c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1683c2c66affSColin Finck     while (MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT) == WAIT_OBJECT_0 + 1)
1684c2c66affSColin Finck     {
1685c2c66affSColin Finck         MSG msg;
1686c2c66affSColin Finck         while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1687c2c66affSColin Finck         {
1688c2c66affSColin Finck             TranslateMessage(&msg);
1689c2c66affSColin Finck             DispatchMessageA(&msg);
1690c2c66affSColin Finck         }
1691c2c66affSColin Finck     }
1692c2c66affSColin Finck     GetExitCodeThread(thread, &exitcode);
1693c2c66affSColin Finck     hr = exitcode;
1694c2c66affSColin Finck     ok(hr == S_OK, "CoGetClassObject on local server object "
1695c2c66affSColin Finck        "registered in different thread should return S_OK "
1696c2c66affSColin Finck        "instead of 0x%08x\n", hr);
1697c2c66affSColin Finck 
1698c2c66affSColin Finck     hr = get_class_object(CLSCTX_LOCAL_SERVER);
1699c2c66affSColin Finck     ok(hr == S_OK, "CoGetClassObject on local server object registered in same "
1700c2c66affSColin Finck        "thread should return S_OK instead of 0x%08x\n", hr);
1701c2c66affSColin Finck 
1702c2c66affSColin Finck     thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)(DWORD_PTR)cookie, 0, &tid);
1703c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1704c2c66affSColin Finck     ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1705c2c66affSColin Finck     GetExitCodeThread(thread, &exitcode);
1706c2c66affSColin Finck     hr = exitcode;
1707c2c66affSColin Finck     ok(hr == RPC_E_WRONG_THREAD || broken(hr == S_OK) /* win8 */, "CoRevokeClassObject called from different "
1708c2c66affSColin Finck        "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr);
1709c2c66affSColin Finck 
1710c2c66affSColin Finck     thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid);
1711c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
1712c2c66affSColin Finck     ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1713c2c66affSColin Finck     GetExitCodeThread(thread, &exitcode);
1714c2c66affSColin Finck     hr = exitcode;
1715c2c66affSColin Finck     ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different "
1716c2c66affSColin Finck         "thread should return S_OK instead of 0x%08x\n", hr);
1717c2c66affSColin Finck 
1718c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
1719c2c66affSColin Finck     ok_ole_success(hr, "CoRevokeClassObject");
1720c2c66affSColin Finck 
1721c2c66affSColin Finck     CoUninitialize();
1722c2c66affSColin Finck }
1723c2c66affSColin Finck 
free_libraries_thread(LPVOID p)1724c2c66affSColin Finck static DWORD CALLBACK free_libraries_thread(LPVOID p)
1725c2c66affSColin Finck {
1726c2c66affSColin Finck     CoFreeUnusedLibraries();
1727c2c66affSColin Finck     return 0;
1728c2c66affSColin Finck }
1729c2c66affSColin Finck 
is_module_loaded(const char * module)1730c2c66affSColin Finck static inline BOOL is_module_loaded(const char *module)
1731c2c66affSColin Finck {
1732c2c66affSColin Finck     return GetModuleHandleA(module) != 0;
1733c2c66affSColin Finck }
1734c2c66affSColin Finck 
test_CoFreeUnusedLibraries(void)1735c2c66affSColin Finck static void test_CoFreeUnusedLibraries(void)
1736c2c66affSColin Finck {
1737c2c66affSColin Finck     HRESULT hr;
1738c2c66affSColin Finck     IUnknown *pUnk;
1739c2c66affSColin Finck     DWORD tid;
1740c2c66affSColin Finck     HANDLE thread;
1741c2c66affSColin Finck 
1742c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1743c2c66affSColin Finck 
1744c2c66affSColin Finck     ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1745c2c66affSColin Finck 
1746c2c66affSColin Finck     hr = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pUnk);
1747c2c66affSColin Finck     if (hr == REGDB_E_CLASSNOTREG)
1748c2c66affSColin Finck     {
1749c2c66affSColin Finck         skip("IE not installed so can't run CoFreeUnusedLibraries test\n");
1750c2c66affSColin Finck         CoUninitialize();
1751c2c66affSColin Finck         return;
1752c2c66affSColin Finck     }
1753c2c66affSColin Finck     ok_ole_success(hr, "CoCreateInstance");
1754c2c66affSColin Finck 
1755c2c66affSColin Finck     ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1756c2c66affSColin Finck 
1757c2c66affSColin Finck     ok(pUnk != NULL ||
1758c2c66affSColin Finck        broken(pUnk == NULL), /* win9x */
1759c2c66affSColin Finck        "Expected a valid pointer\n");
1760c2c66affSColin Finck     if (pUnk)
1761c2c66affSColin Finck         IUnknown_Release(pUnk);
1762c2c66affSColin Finck 
1763c2c66affSColin Finck     ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1764c2c66affSColin Finck 
1765c2c66affSColin Finck     thread = CreateThread(NULL, 0, free_libraries_thread, NULL, 0, &tid);
1766c2c66affSColin Finck     ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1767c2c66affSColin Finck     CloseHandle(thread);
1768c2c66affSColin Finck 
1769c2c66affSColin Finck     ok(is_module_loaded("urlmon.dll"), "urlmon.dll should be loaded\n");
1770c2c66affSColin Finck 
1771c2c66affSColin Finck     CoFreeUnusedLibraries();
1772c2c66affSColin Finck 
1773c2c66affSColin Finck     ok(!is_module_loaded("urlmon.dll"), "urlmon.dll shouldn't be loaded\n");
1774c2c66affSColin Finck 
1775c2c66affSColin Finck     CoUninitialize();
1776c2c66affSColin Finck }
1777c2c66affSColin Finck 
test_CoGetObjectContext(void)1778c2c66affSColin Finck static void test_CoGetObjectContext(void)
1779c2c66affSColin Finck {
1780c2c66affSColin Finck     HRESULT hr;
1781c2c66affSColin Finck     ULONG refs;
1782c2c66affSColin Finck     IComThreadingInfo *pComThreadingInfo, *threadinginfo2;
1783c2c66affSColin Finck     IContextCallback *pContextCallback;
1784c2c66affSColin Finck     IObjContext *pObjContext;
1785c2c66affSColin Finck     APTTYPE apttype;
1786c2c66affSColin Finck     THDTYPE thdtype;
1787c2c66affSColin Finck     GUID id, id2;
1788c2c66affSColin Finck 
1789c2c66affSColin Finck     if (!pCoGetObjectContext)
1790c2c66affSColin Finck     {
1791c2c66affSColin Finck         win_skip("CoGetObjectContext not present\n");
1792c2c66affSColin Finck         return;
1793c2c66affSColin Finck     }
1794c2c66affSColin Finck 
1795c2c66affSColin Finck     hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1796c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "CoGetObjectContext should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
1797c2c66affSColin Finck     ok(pComThreadingInfo == NULL, "pComThreadingInfo should have been set to NULL\n");
1798c2c66affSColin Finck 
1799a6cdf4ffSAmine Khaldi     pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1800c2c66affSColin Finck 
1801a6cdf4ffSAmine Khaldi     test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE);
1802c2c66affSColin Finck 
1803c2c66affSColin Finck     hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1804a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoGetObjectContext");
1805c2c66affSColin Finck 
1806c2c66affSColin Finck     threadinginfo2 = NULL;
1807c2c66affSColin Finck     hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&threadinginfo2);
1808c2c66affSColin Finck     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
1809c2c66affSColin Finck     ok(pComThreadingInfo == threadinginfo2, "got different instance\n");
1810c2c66affSColin Finck     IComThreadingInfo_Release(threadinginfo2);
1811c2c66affSColin Finck 
1812c2c66affSColin Finck     hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, NULL);
1813c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1814c2c66affSColin Finck 
1815c2c66affSColin Finck     id = id2 = GUID_NULL;
1816c2c66affSColin Finck     hr = IComThreadingInfo_GetCurrentLogicalThreadId(pComThreadingInfo, &id);
1817c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
1818c2c66affSColin Finck 
1819c2c66affSColin Finck     hr = CoGetCurrentLogicalThreadId(&id2);
1820c2c66affSColin Finck     ok(IsEqualGUID(&id, &id2), "got %s, expected %s\n", wine_dbgstr_guid(&id), wine_dbgstr_guid(&id2));
1821c2c66affSColin Finck 
1822c2c66affSColin Finck     hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1823c2c66affSColin Finck     ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1824c2c66affSColin Finck     ok(apttype == APTTYPE_MAINSTA, "apartment type should be APTTYPE_MAINSTA instead of %d\n", apttype);
1825c2c66affSColin Finck 
1826c2c66affSColin Finck     hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1827c2c66affSColin Finck     ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1828c2c66affSColin Finck     ok(thdtype == THDTYPE_PROCESSMESSAGES, "thread type should be THDTYPE_PROCESSMESSAGES instead of %d\n", thdtype);
1829c2c66affSColin Finck 
1830c2c66affSColin Finck     refs = IComThreadingInfo_Release(pComThreadingInfo);
1831c2c66affSColin Finck     ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1832c2c66affSColin Finck 
1833c2c66affSColin Finck     hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1834c2c66affSColin Finck     ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1835c2c66affSColin Finck 
1836c2c66affSColin Finck     refs = IContextCallback_Release(pContextCallback);
1837c2c66affSColin Finck     ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1838c2c66affSColin Finck 
1839c2c66affSColin Finck     CoUninitialize();
1840c2c66affSColin Finck 
1841c2c66affSColin Finck     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1842c2c66affSColin Finck 
1843c2c66affSColin Finck     hr = pCoGetObjectContext(&IID_IComThreadingInfo, (void **)&pComThreadingInfo);
1844c2c66affSColin Finck     ok_ole_success(hr, "CoGetObjectContext");
1845c2c66affSColin Finck 
1846c2c66affSColin Finck     hr = IComThreadingInfo_GetCurrentApartmentType(pComThreadingInfo, &apttype);
1847c2c66affSColin Finck     ok_ole_success(hr, "IComThreadingInfo_GetCurrentApartmentType");
1848c2c66affSColin Finck     ok(apttype == APTTYPE_MTA, "apartment type should be APTTYPE_MTA instead of %d\n", apttype);
1849c2c66affSColin Finck 
1850c2c66affSColin Finck     hr = IComThreadingInfo_GetCurrentThreadType(pComThreadingInfo, &thdtype);
1851c2c66affSColin Finck     ok_ole_success(hr, "IComThreadingInfo_GetCurrentThreadType");
1852c2c66affSColin Finck     ok(thdtype == THDTYPE_BLOCKMESSAGES, "thread type should be THDTYPE_BLOCKMESSAGES instead of %d\n", thdtype);
1853c2c66affSColin Finck 
1854c2c66affSColin Finck     refs = IComThreadingInfo_Release(pComThreadingInfo);
1855c2c66affSColin Finck     ok(refs == 0, "pComThreadingInfo should have 0 refs instead of %d refs\n", refs);
1856c2c66affSColin Finck 
1857c2c66affSColin Finck     hr = pCoGetObjectContext(&IID_IContextCallback, (void **)&pContextCallback);
1858c2c66affSColin Finck     ok_ole_success(hr, "CoGetObjectContext(ContextCallback)");
1859c2c66affSColin Finck 
1860c2c66affSColin Finck     refs = IContextCallback_Release(pContextCallback);
1861c2c66affSColin Finck     ok(refs == 0, "pContextCallback should have 0 refs instead of %d refs\n", refs);
1862c2c66affSColin Finck 
1863c2c66affSColin Finck     hr = pCoGetObjectContext(&IID_IObjContext, (void **)&pObjContext);
1864c2c66affSColin Finck     ok_ole_success(hr, "CoGetObjectContext");
1865c2c66affSColin Finck 
1866c2c66affSColin Finck     refs = IObjContext_Release(pObjContext);
1867c2c66affSColin Finck     ok(refs == 0, "pObjContext should have 0 refs instead of %d refs\n", refs);
1868c2c66affSColin Finck 
1869c2c66affSColin Finck     CoUninitialize();
1870c2c66affSColin Finck }
1871c2c66affSColin Finck 
1872c2c66affSColin Finck typedef struct {
1873c2c66affSColin Finck     IUnknown IUnknown_iface;
1874c2c66affSColin Finck     LONG refs;
1875c2c66affSColin Finck } Test_CallContext;
1876c2c66affSColin Finck 
impl_from_IUnknown(IUnknown * iface)1877c2c66affSColin Finck static inline Test_CallContext *impl_from_IUnknown(IUnknown *iface)
1878c2c66affSColin Finck {
1879c2c66affSColin Finck     return CONTAINING_RECORD(iface, Test_CallContext, IUnknown_iface);
1880c2c66affSColin Finck }
1881c2c66affSColin Finck 
Test_CallContext_QueryInterface(IUnknown * iface,REFIID riid,LPVOID * ppvObj)1882c2c66affSColin Finck static HRESULT WINAPI Test_CallContext_QueryInterface(
1883c2c66affSColin Finck     IUnknown *iface,
1884c2c66affSColin Finck     REFIID riid,
1885c2c66affSColin Finck     LPVOID *ppvObj)
1886c2c66affSColin Finck {
1887c2c66affSColin Finck     if (ppvObj == NULL) return E_POINTER;
1888c2c66affSColin Finck 
1889c2c66affSColin Finck     if (IsEqualGUID(riid, &IID_IUnknown))
1890c2c66affSColin Finck     {
1891c2c66affSColin Finck         *ppvObj = iface;
1892c2c66affSColin Finck         IUnknown_AddRef(iface);
1893c2c66affSColin Finck         return S_OK;
1894c2c66affSColin Finck     }
1895c2c66affSColin Finck 
1896c2c66affSColin Finck     *ppvObj = NULL;
1897c2c66affSColin Finck     return E_NOINTERFACE;
1898c2c66affSColin Finck }
1899c2c66affSColin Finck 
Test_CallContext_AddRef(IUnknown * iface)1900c2c66affSColin Finck static ULONG WINAPI Test_CallContext_AddRef(IUnknown *iface)
1901c2c66affSColin Finck {
1902c2c66affSColin Finck     Test_CallContext *This = impl_from_IUnknown(iface);
1903c2c66affSColin Finck     return InterlockedIncrement(&This->refs);
1904c2c66affSColin Finck }
1905c2c66affSColin Finck 
Test_CallContext_Release(IUnknown * iface)1906c2c66affSColin Finck static ULONG WINAPI Test_CallContext_Release(IUnknown *iface)
1907c2c66affSColin Finck {
1908c2c66affSColin Finck     Test_CallContext *This = impl_from_IUnknown(iface);
1909c2c66affSColin Finck     ULONG refs = InterlockedDecrement(&This->refs);
1910c2c66affSColin Finck     if (!refs)
1911c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This);
1912c2c66affSColin Finck     return refs;
1913c2c66affSColin Finck }
1914c2c66affSColin Finck 
1915c2c66affSColin Finck static const IUnknownVtbl TestCallContext_Vtbl =
1916c2c66affSColin Finck {
1917c2c66affSColin Finck     Test_CallContext_QueryInterface,
1918c2c66affSColin Finck     Test_CallContext_AddRef,
1919c2c66affSColin Finck     Test_CallContext_Release
1920c2c66affSColin Finck };
1921c2c66affSColin Finck 
test_CoGetCallContext(void)1922c2c66affSColin Finck static void test_CoGetCallContext(void)
1923c2c66affSColin Finck {
1924c2c66affSColin Finck     HRESULT hr;
1925c2c66affSColin Finck     ULONG refs;
1926c2c66affSColin Finck     IUnknown *pUnk;
1927c2c66affSColin Finck     Test_CallContext *test_object;
1928c2c66affSColin Finck 
1929c2c66affSColin Finck     if (!pCoSwitchCallContext)
1930c2c66affSColin Finck     {
1931c2c66affSColin Finck         skip("CoSwitchCallContext not present\n");
1932c2c66affSColin Finck         return;
1933c2c66affSColin Finck     }
1934c2c66affSColin Finck 
1935c2c66affSColin Finck     CoInitialize(NULL);
1936c2c66affSColin Finck 
1937c2c66affSColin Finck     test_object = HeapAlloc(GetProcessHeap(), 0, sizeof(Test_CallContext));
1938c2c66affSColin Finck     test_object->IUnknown_iface.lpVtbl = &TestCallContext_Vtbl;
1939c2c66affSColin Finck     test_object->refs = 1;
1940c2c66affSColin Finck 
1941c2c66affSColin Finck     hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1942c2c66affSColin Finck     ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1943c2c66affSColin Finck 
1944c2c66affSColin Finck     pUnk = (IUnknown*)0xdeadbeef;
1945c2c66affSColin Finck     hr = pCoSwitchCallContext(&test_object->IUnknown_iface, &pUnk);
1946c2c66affSColin Finck     ok_ole_success(hr, "CoSwitchCallContext");
1947c2c66affSColin Finck     ok(pUnk == NULL, "expected NULL, got %p\n", pUnk);
1948c2c66affSColin Finck     refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1949c2c66affSColin Finck     ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1950c2c66affSColin Finck     IUnknown_Release(&test_object->IUnknown_iface);
1951c2c66affSColin Finck 
1952c2c66affSColin Finck     pUnk = (IUnknown*)0xdeadbeef;
1953c2c66affSColin Finck     hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1954c2c66affSColin Finck     ok_ole_success(hr, "CoGetCallContext");
1955c2c66affSColin Finck     ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1956c2c66affSColin Finck        &test_object->IUnknown_iface, pUnk);
1957c2c66affSColin Finck     refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1958c2c66affSColin Finck     ok(refs == 3, "Expected refcount 3, got %d\n", refs);
1959c2c66affSColin Finck     IUnknown_Release(&test_object->IUnknown_iface);
1960c2c66affSColin Finck     IUnknown_Release(pUnk);
1961c2c66affSColin Finck 
1962c2c66affSColin Finck     pUnk = (IUnknown*)0xdeadbeef;
1963c2c66affSColin Finck     hr = pCoSwitchCallContext(NULL, &pUnk);
1964c2c66affSColin Finck     ok_ole_success(hr, "CoSwitchCallContext");
1965c2c66affSColin Finck     ok(pUnk == &test_object->IUnknown_iface, "expected %p, got %p\n",
1966c2c66affSColin Finck        &test_object->IUnknown_iface, pUnk);
1967c2c66affSColin Finck     refs = IUnknown_AddRef(&test_object->IUnknown_iface);
1968c2c66affSColin Finck     ok(refs == 2, "Expected refcount 2, got %d\n", refs);
1969c2c66affSColin Finck     IUnknown_Release(&test_object->IUnknown_iface);
1970c2c66affSColin Finck 
1971c2c66affSColin Finck     hr = CoGetCallContext(&IID_IUnknown, (void**)&pUnk);
1972c2c66affSColin Finck     ok(hr == RPC_E_CALL_COMPLETE, "Expected RPC_E_CALL_COMPLETE, got 0x%08x\n", hr);
1973c2c66affSColin Finck 
1974c2c66affSColin Finck     IUnknown_Release(&test_object->IUnknown_iface);
1975c2c66affSColin Finck 
1976c2c66affSColin Finck     CoUninitialize();
1977c2c66affSColin Finck }
1978c2c66affSColin Finck 
test_CoGetContextToken(void)1979c2c66affSColin Finck static void test_CoGetContextToken(void)
1980c2c66affSColin Finck {
1981c2c66affSColin Finck     HRESULT hr;
1982c2c66affSColin Finck     ULONG refs;
1983c2c66affSColin Finck     ULONG_PTR token, token2;
1984c2c66affSColin Finck     IObjContext *ctx;
1985c2c66affSColin Finck 
1986c2c66affSColin Finck     if (!pCoGetContextToken)
1987c2c66affSColin Finck     {
1988c2c66affSColin Finck         win_skip("CoGetContextToken not present\n");
1989c2c66affSColin Finck         return;
1990c2c66affSColin Finck     }
1991c2c66affSColin Finck 
1992c2c66affSColin Finck     token = 0xdeadbeef;
1993c2c66affSColin Finck     hr = pCoGetContextToken(&token);
1994c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "Expected CO_E_NOTINITIALIZED, got 0x%08x\n", hr);
1995c2c66affSColin Finck     ok(token == 0xdeadbeef, "Expected 0, got 0x%lx\n", token);
1996c2c66affSColin Finck 
1997a6cdf4ffSAmine Khaldi     test_apt_type(APTTYPE_CURRENT, APTTYPEQUALIFIER_NONE);
1998c2c66affSColin Finck 
1999c2c66affSColin Finck     CoInitialize(NULL);
2000c2c66affSColin Finck 
2001a6cdf4ffSAmine Khaldi     test_apt_type(APTTYPE_MAINSTA, APTTYPEQUALIFIER_NONE);
2002c2c66affSColin Finck 
2003c2c66affSColin Finck     hr = pCoGetContextToken(NULL);
2004c2c66affSColin Finck     ok(hr == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hr);
2005c2c66affSColin Finck 
2006c2c66affSColin Finck     token = 0;
2007c2c66affSColin Finck     hr = pCoGetContextToken(&token);
2008c2c66affSColin Finck     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2009c2c66affSColin Finck     ok(token, "Expected token != 0\n");
2010c2c66affSColin Finck 
2011c2c66affSColin Finck     token2 = 0;
2012c2c66affSColin Finck     hr = pCoGetContextToken(&token2);
2013c2c66affSColin Finck     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2014c2c66affSColin Finck     ok(token2 == token, "got different token\n");
2015c2c66affSColin Finck 
2016c2c66affSColin Finck     refs = IUnknown_AddRef((IUnknown *)token);
2017c2c66affSColin Finck     ok(refs == 1, "Expected 1, got %u\n", refs);
2018c2c66affSColin Finck 
2019c2c66affSColin Finck     hr = pCoGetObjectContext(&IID_IObjContext, (void **)&ctx);
2020c2c66affSColin Finck     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2021c2c66affSColin Finck     ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
2022c2c66affSColin Finck 
2023c2c66affSColin Finck     refs = IObjContext_AddRef(ctx);
2024c2c66affSColin Finck     ok(refs == 3, "Expected 3, got %u\n", refs);
2025c2c66affSColin Finck 
2026c2c66affSColin Finck     refs = IObjContext_Release(ctx);
2027c2c66affSColin Finck     ok(refs == 2, "Expected 2, got %u\n", refs);
2028c2c66affSColin Finck 
2029c2c66affSColin Finck     refs = IUnknown_Release((IUnknown *)token);
2030c2c66affSColin Finck     ok(refs == 1, "Expected 1, got %u\n", refs);
2031c2c66affSColin Finck 
2032c2c66affSColin Finck     /* CoGetContextToken does not add a reference */
2033c2c66affSColin Finck     token = 0;
2034c2c66affSColin Finck     hr = pCoGetContextToken(&token);
2035c2c66affSColin Finck     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
2036c2c66affSColin Finck     ok(token, "Expected token != 0\n");
2037c2c66affSColin Finck     ok(ctx == (IObjContext *)token, "Expected interface pointers to be the same\n");
2038c2c66affSColin Finck 
2039c2c66affSColin Finck     refs = IObjContext_AddRef(ctx);
2040c2c66affSColin Finck     ok(refs == 2, "Expected 1, got %u\n", refs);
2041c2c66affSColin Finck 
2042c2c66affSColin Finck     refs = IObjContext_Release(ctx);
2043c2c66affSColin Finck     ok(refs == 1, "Expected 0, got %u\n", refs);
2044c2c66affSColin Finck 
2045c2c66affSColin Finck     refs = IObjContext_Release(ctx);
2046c2c66affSColin Finck     ok(refs == 0, "Expected 0, got %u\n", refs);
2047c2c66affSColin Finck 
2048c2c66affSColin Finck     CoUninitialize();
2049c2c66affSColin Finck }
2050c2c66affSColin Finck 
test_TreatAsClass(void)2051c2c66affSColin Finck static void test_TreatAsClass(void)
2052c2c66affSColin Finck {
2053c2c66affSColin Finck     HRESULT hr;
2054c2c66affSColin Finck     CLSID out;
2055c2c66affSColin Finck     static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
2056c2c66affSColin Finck     static const char deadbeefA[] = "{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}";
2057c2c66affSColin Finck     IInternetProtocol *pIP = NULL;
2058c2c66affSColin Finck     HKEY clsidkey, deadbeefkey;
2059c2c66affSColin Finck     LONG lr;
2060c2c66affSColin Finck 
2061c2c66affSColin Finck     if (!pCoGetTreatAsClass)
2062c2c66affSColin Finck     {
2063c2c66affSColin Finck         win_skip("CoGetTreatAsClass not present\n");
2064c2c66affSColin Finck         return;
2065c2c66affSColin Finck     }
2066c2c66affSColin Finck 
2067c2c66affSColin Finck     hr = pCoGetTreatAsClass(&deadbeef,&out);
2068c2c66affSColin Finck     ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
2069c2c66affSColin Finck     ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
2070c2c66affSColin Finck 
2071c2c66affSColin Finck     hr = pCoGetTreatAsClass(NULL, &out);
2072c2c66affSColin Finck     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr);
2073c2c66affSColin Finck     ok(IsEqualGUID(&out, &deadbeef), "expected no change to the clsid\n");
2074c2c66affSColin Finck 
2075c2c66affSColin Finck     hr = pCoGetTreatAsClass(&deadbeef, NULL);
2076c2c66affSColin Finck     ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr);
2077c2c66affSColin Finck 
2078c2c66affSColin Finck     lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &clsidkey);
2079c2c66affSColin Finck     ok(!lr, "Couldn't open CLSID key, error %d\n", lr);
2080c2c66affSColin Finck 
2081c2c66affSColin Finck     lr = RegCreateKeyExA(clsidkey, deadbeefA, 0, NULL, 0, KEY_WRITE, NULL, &deadbeefkey, NULL);
2082c2c66affSColin Finck     if (lr) {
2083c2c66affSColin Finck         win_skip("CoGetTreatAsClass() tests will be skipped (failed to create a test key, error %d)\n", lr);
2084c2c66affSColin Finck         RegCloseKey(clsidkey);
2085c2c66affSColin Finck         return;
2086c2c66affSColin Finck     }
2087c2c66affSColin Finck 
2088c2c66affSColin Finck     hr = pCoTreatAsClass(&deadbeef, &deadbeef);
2089c2c66affSColin Finck     ok(hr == REGDB_E_WRITEREGDB, "CoTreatAsClass gave wrong error: %08x\n", hr);
2090c2c66affSColin Finck 
2091c2c66affSColin Finck     hr = pCoTreatAsClass(&deadbeef, &CLSID_FileProtocol);
2092c2c66affSColin Finck     if(hr == REGDB_E_WRITEREGDB){
2093c2c66affSColin Finck         win_skip("Insufficient privileges to use CoTreatAsClass\n");
2094c2c66affSColin Finck         goto exit;
2095c2c66affSColin Finck     }
2096c2c66affSColin Finck     ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
2097c2c66affSColin Finck 
2098c2c66affSColin Finck     hr = pCoGetTreatAsClass(&deadbeef, &out);
2099c2c66affSColin Finck     ok(hr == S_OK, "CoGetTreatAsClass failed: %08x\n",hr);
2100c2c66affSColin Finck     ok(IsEqualGUID(&out, &CLSID_FileProtocol), "expected to get substituted clsid\n");
2101c2c66affSColin Finck 
2102c2c66affSColin Finck     OleInitialize(NULL);
2103c2c66affSColin Finck 
2104c2c66affSColin Finck     hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2105c2c66affSColin Finck     if(hr == REGDB_E_CLASSNOTREG)
2106c2c66affSColin Finck     {
2107c2c66affSColin Finck         win_skip("IE not installed so can't test CoCreateInstance\n");
2108c2c66affSColin Finck         goto exit;
2109c2c66affSColin Finck     }
2110c2c66affSColin Finck 
2111c2c66affSColin Finck     ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
2112c2c66affSColin Finck     if(pIP){
2113c2c66affSColin Finck         IInternetProtocol_Release(pIP);
2114c2c66affSColin Finck         pIP = NULL;
2115c2c66affSColin Finck     }
2116c2c66affSColin Finck 
2117c2c66affSColin Finck     hr = pCoTreatAsClass(&deadbeef, &CLSID_NULL);
2118c2c66affSColin Finck     ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
2119c2c66affSColin Finck 
2120c2c66affSColin Finck     hr = pCoGetTreatAsClass(&deadbeef, &out);
2121c2c66affSColin Finck     ok(hr == S_FALSE, "expected S_FALSE got %08x\n", hr);
2122c2c66affSColin Finck     ok(IsEqualGUID(&out, &deadbeef), "expected to get same clsid back\n");
2123c2c66affSColin Finck 
2124c2c66affSColin Finck     /* bizarrely, native's CoTreatAsClass takes some time to take effect in CoCreateInstance */
2125c2c66affSColin Finck     Sleep(200);
2126c2c66affSColin Finck 
2127c2c66affSColin Finck     hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
2128c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance gave wrong error: %08x\n", hr);
2129c2c66affSColin Finck 
2130c2c66affSColin Finck     if(pIP)
2131c2c66affSColin Finck         IInternetProtocol_Release(pIP);
2132c2c66affSColin Finck 
2133c2c66affSColin Finck exit:
2134c2c66affSColin Finck     OleUninitialize();
2135c2c66affSColin Finck     RegCloseKey(deadbeefkey);
2136c2c66affSColin Finck     RegDeleteKeyA(clsidkey, deadbeefA);
2137c2c66affSColin Finck     RegCloseKey(clsidkey);
2138c2c66affSColin Finck }
2139c2c66affSColin Finck 
test_CoInitializeEx(void)2140c2c66affSColin Finck static void test_CoInitializeEx(void)
2141c2c66affSColin Finck {
2142c2c66affSColin Finck     HRESULT hr;
2143c2c66affSColin Finck 
2144c2c66affSColin Finck     hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2145c2c66affSColin Finck     ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2146c2c66affSColin Finck 
2147c2c66affSColin Finck     /* Calling OleInitialize for the first time should yield S_OK even with
2148c2c66affSColin Finck      * apartment already initialized by previous CoInitialize(Ex) calls. */
2149c2c66affSColin Finck     hr = OleInitialize(NULL);
2150c2c66affSColin Finck     ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
2151c2c66affSColin Finck 
2152c2c66affSColin Finck     /* Subsequent calls to OleInitialize should return S_FALSE */
2153c2c66affSColin Finck     hr = OleInitialize(NULL);
2154c2c66affSColin Finck     ok(hr == S_FALSE, "Expected S_FALSE, hr = 0x%08x\n", hr);
2155c2c66affSColin Finck 
2156c2c66affSColin Finck     /* Cleanup */
2157c2c66affSColin Finck     CoUninitialize();
2158c2c66affSColin Finck     OleUninitialize();
2159c2c66affSColin Finck     OleUninitialize();
2160c2c66affSColin Finck }
2161c2c66affSColin Finck 
test_OleInitialize_InitCounting(void)2162c2c66affSColin Finck static void test_OleInitialize_InitCounting(void)
2163c2c66affSColin Finck {
2164c2c66affSColin Finck     HRESULT hr;
2165c2c66affSColin Finck     IUnknown *pUnk;
2166c2c66affSColin Finck     REFCLSID rclsid = &CLSID_InternetZoneManager;
2167c2c66affSColin Finck 
2168c2c66affSColin Finck     /* 1. OleInitialize fails but OleUninitialize is still called: apartment stays initialized */
2169c2c66affSColin Finck     hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
2170c2c66affSColin Finck     ok(hr == S_OK, "CoInitializeEx(COINIT_MULTITHREADED) failed with error 0x%08x\n", hr);
2171c2c66affSColin Finck 
2172c2c66affSColin Finck     hr = OleInitialize(NULL);
2173c2c66affSColin Finck     ok(hr == RPC_E_CHANGED_MODE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", RPC_E_CHANGED_MODE, hr);
2174c2c66affSColin Finck     OleUninitialize();
2175c2c66affSColin Finck 
2176c2c66affSColin Finck     pUnk = (IUnknown *)0xdeadbeef;
2177c2c66affSColin Finck     hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2178c2c66affSColin Finck     ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2179c2c66affSColin Finck     if (pUnk) IUnknown_Release(pUnk);
2180c2c66affSColin Finck 
2181c2c66affSColin Finck     CoUninitialize();
2182c2c66affSColin Finck 
2183c2c66affSColin Finck     /* 2. Extra multiple OleUninitialize: apartment stays initialized until CoUninitialize */
2184c2c66affSColin Finck     hr = CoInitialize(NULL);
2185c2c66affSColin Finck     ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
2186c2c66affSColin Finck 
2187c2c66affSColin Finck     hr = OleInitialize(NULL);
2188c2c66affSColin Finck     ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2189c2c66affSColin Finck     OleUninitialize();
2190c2c66affSColin Finck     OleUninitialize();
2191c2c66affSColin Finck     OleUninitialize();
2192c2c66affSColin Finck 
2193c2c66affSColin Finck     pUnk = (IUnknown *)0xdeadbeef;
2194c2c66affSColin Finck     hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2195c2c66affSColin Finck     ok(hr == S_OK, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2196c2c66affSColin Finck     if (pUnk) IUnknown_Release(pUnk);
2197c2c66affSColin Finck 
2198c2c66affSColin Finck     CoUninitialize();
2199c2c66affSColin Finck 
2200c2c66affSColin Finck     pUnk = (IUnknown *)0xdeadbeef;
2201c2c66affSColin Finck     hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2202c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
2203c2c66affSColin Finck     if (pUnk) IUnknown_Release(pUnk);
2204c2c66affSColin Finck 
2205c2c66affSColin Finck     /* 3. CoUninitialize does not formally deinit Ole */
2206c2c66affSColin Finck     hr = CoInitialize(NULL);
2207c2c66affSColin Finck     ok(hr == S_OK, "CoInitialize() failed with error 0x%08x\n", hr);
2208c2c66affSColin Finck 
2209c2c66affSColin Finck     hr = OleInitialize(NULL);
2210c2c66affSColin Finck     ok(hr == S_OK, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_OK, hr);
2211c2c66affSColin Finck 
2212c2c66affSColin Finck     CoUninitialize();
2213c2c66affSColin Finck     CoUninitialize();
2214c2c66affSColin Finck 
2215c2c66affSColin Finck     pUnk = (IUnknown *)0xdeadbeef;
2216c2c66affSColin Finck     hr = CoCreateInstance(rclsid, NULL, 0x17, &IID_IUnknown, (void **)&pUnk);
2217c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "CoCreateInstance should have returned 0x%08x instead of 0x%08x\n", CO_E_NOTINITIALIZED, hr);
2218c2c66affSColin Finck       /* COM is not initialized anymore */
2219c2c66affSColin Finck     if (pUnk) IUnknown_Release(pUnk);
2220c2c66affSColin Finck 
2221c2c66affSColin Finck     hr = OleInitialize(NULL);
2222c2c66affSColin Finck     ok(hr == S_FALSE, "OleInitialize should have returned 0x%08x instead of 0x%08x\n", S_FALSE, hr);
2223c2c66affSColin Finck       /* ... but native OleInit returns S_FALSE as if Ole is considered initialized */
2224c2c66affSColin Finck 
2225c2c66affSColin Finck     OleUninitialize();
2226c2c66affSColin Finck 
2227c2c66affSColin Finck }
2228c2c66affSColin Finck 
test_OleRegGetMiscStatus(void)2229c2c66affSColin Finck static void test_OleRegGetMiscStatus(void)
2230c2c66affSColin Finck {
2231c2c66affSColin Finck     ULONG_PTR cookie;
2232c2c66affSColin Finck     HANDLE handle;
2233c2c66affSColin Finck     DWORD status;
2234c2c66affSColin Finck     HRESULT hr;
2235c2c66affSColin Finck 
2236c2c66affSColin Finck     hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, NULL);
2237c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2238c2c66affSColin Finck 
2239c2c66affSColin Finck     status = 0xdeadbeef;
2240c2c66affSColin Finck     hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2241c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
2242c2c66affSColin Finck     ok(status == 0, "got 0x%08x\n", status);
2243c2c66affSColin Finck 
2244c2c66affSColin Finck     status = -1;
2245c2c66affSColin Finck     hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2246c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
2247c2c66affSColin Finck     ok(status == 0, "got 0x%08x\n", status);
2248c2c66affSColin Finck 
2249c2c66affSColin Finck     if ((handle = activate_context(actctx_manifest, &cookie)))
2250c2c66affSColin Finck     {
2251c2c66affSColin Finck         status = 0;
2252c2c66affSColin Finck         hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_ICON, &status);
2253c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
2254c2c66affSColin Finck         ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2255c2c66affSColin Finck 
2256c2c66affSColin Finck         /* context data takes precedence over registration info */
2257c2c66affSColin Finck         status = 0;
2258c2c66affSColin Finck         hr = OleRegGetMiscStatus(&CLSID_StdFont, DVASPECT_ICON, &status);
2259c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
2260c2c66affSColin Finck         ok(status == OLEMISC_RECOMPOSEONRESIZE, "got 0x%08x\n", status);
2261c2c66affSColin Finck 
2262c2c66affSColin Finck         /* there's no such attribute in context */
2263c2c66affSColin Finck         status = -1;
2264c2c66affSColin Finck         hr = OleRegGetMiscStatus(&CLSID_Testclass, DVASPECT_DOCPRINT, &status);
2265c2c66affSColin Finck         ok(hr == S_OK, "got 0x%08x\n", hr);
2266c2c66affSColin Finck         ok(status == 0, "got 0x%08x\n", status);
2267c2c66affSColin Finck 
2268c2c66affSColin Finck         pDeactivateActCtx(0, cookie);
2269c2c66affSColin Finck         pReleaseActCtx(handle);
2270c2c66affSColin Finck     }
2271c2c66affSColin Finck }
2272c2c66affSColin Finck 
test_OleRegGetUserType(void)2273c2c66affSColin Finck static void test_OleRegGetUserType(void)
2274c2c66affSColin Finck {
2275c2c66affSColin Finck     static const WCHAR stdfont_usertypeW[] = {'S','t','a','n','d','a','r','d',' ','F','o','n','t',0};
2276c2c66affSColin Finck     static const WCHAR stdfont2_usertypeW[] = {'C','L','S','I','D','_','S','t','d','F','o','n','t',0};
2277c2c66affSColin Finck     static const WCHAR clsidkeyW[] = {'C','L','S','I','D',0};
2278c2c66affSColin Finck     static const WCHAR defvalueW[] = {'D','e','f','a','u','l','t',' ','N','a','m','e',0};
2279c2c66affSColin Finck     static const WCHAR auxvalue0W[] = {'A','u','x',' ','N','a','m','e',' ','0',0};
2280c2c66affSColin Finck     static const WCHAR auxvalue2W[] = {'A','u','x',' ','N','a','m','e',' ','2',0};
2281c2c66affSColin Finck     static const WCHAR auxvalue3W[] = {'A','u','x',' ','N','a','m','e',' ','3',0};
2282c2c66affSColin Finck     static const WCHAR auxvalue4W[] = {'A','u','x',' ','N','a','m','e',' ','4',0};
2283c2c66affSColin Finck 
2284c2c66affSColin Finck     static const char auxvalues[][16] = {
2285c2c66affSColin Finck         "Aux Name 0",
2286c2c66affSColin Finck         "Aux Name 1",
2287c2c66affSColin Finck         "Aux Name 2",
2288c2c66affSColin Finck         "Aux Name 3",
2289c2c66affSColin Finck         "Aux Name 4"
2290c2c66affSColin Finck     };
2291c2c66affSColin Finck 
2292c2c66affSColin Finck     HKEY clsidhkey, hkey, auxhkey, classkey;
2293c2c66affSColin Finck     DWORD form, ret, disposition;
2294c2c66affSColin Finck     WCHAR clsidW[39];
2295c2c66affSColin Finck     ULONG_PTR cookie;
2296c2c66affSColin Finck     HANDLE handle;
2297c2c66affSColin Finck     HRESULT hr;
2298c2c66affSColin Finck     WCHAR *str;
2299c2c66affSColin Finck     int i;
2300c2c66affSColin Finck 
2301c2c66affSColin Finck     for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) {
2302c2c66affSColin Finck         hr = OleRegGetUserType(&CLSID_Testclass, form, NULL);
2303c2c66affSColin Finck         ok(hr == E_INVALIDARG, "form %u: got 0x%08x\n", form, hr);
2304c2c66affSColin Finck 
2305c2c66affSColin Finck         str = (void*)0xdeadbeef;
2306c2c66affSColin Finck         hr = OleRegGetUserType(&CLSID_Testclass, form, &str);
2307c2c66affSColin Finck         ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr);
2308c2c66affSColin Finck         ok(str == NULL, "form %u: got %p\n", form, str);
2309c2c66affSColin Finck 
2310c2c66affSColin Finck         /* same string returned for StdFont for all form types */
2311c2c66affSColin Finck         str = NULL;
2312c2c66affSColin Finck         hr = OleRegGetUserType(&CLSID_StdFont, form, &str);
2313c2c66affSColin Finck         ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr);
2314c2c66affSColin Finck         ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */,
2315c2c66affSColin Finck             "form %u, got %s\n", form, wine_dbgstr_w(str));
2316c2c66affSColin Finck         CoTaskMemFree(str);
2317c2c66affSColin Finck     }
2318c2c66affSColin Finck 
2319c2c66affSColin Finck     if ((handle = activate_context(actctx_manifest, &cookie)))
2320c2c66affSColin Finck     {
2321c2c66affSColin Finck         for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) {
2322c2c66affSColin Finck             str = (void*)0xdeadbeef;
2323c2c66affSColin Finck             hr = OleRegGetUserType(&CLSID_Testclass, form, &str);
2324c2c66affSColin Finck             ok(hr == REGDB_E_CLASSNOTREG, "form %u: got 0x%08x\n", form, hr);
2325c2c66affSColin Finck             ok(str == NULL, "form %u: got %s\n", form, wine_dbgstr_w(str));
2326c2c66affSColin Finck 
2327c2c66affSColin Finck             /* same string returned for StdFont for all form types */
2328c2c66affSColin Finck             str = NULL;
2329c2c66affSColin Finck             hr = OleRegGetUserType(&CLSID_StdFont, form, &str);
2330c2c66affSColin Finck             ok(hr == S_OK, "form %u: got 0x%08x\n", form, hr);
2331c2c66affSColin Finck             ok(!lstrcmpW(str, stdfont_usertypeW) || !lstrcmpW(str, stdfont2_usertypeW) /* winxp */,
2332c2c66affSColin Finck                 "form %u, got %s\n", form, wine_dbgstr_w(str));
2333c2c66affSColin Finck             CoTaskMemFree(str);
2334c2c66affSColin Finck         }
2335c2c66affSColin Finck 
2336c2c66affSColin Finck         pDeactivateActCtx(0, cookie);
2337c2c66affSColin Finck         pReleaseActCtx(handle);
2338c2c66affSColin Finck     }
2339c2c66affSColin Finck 
2340c2c66affSColin Finck     /* test using registered CLSID */
23415c1bcfecSAmine Khaldi     StringFromGUID2(&CLSID_non_existent, clsidW, ARRAY_SIZE(clsidW));
2342c2c66affSColin Finck 
2343c2c66affSColin Finck     ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsidkeyW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &clsidhkey, &disposition);
2344c2c66affSColin Finck     if (!ret)
2345c2c66affSColin Finck     {
2346c2c66affSColin Finck         ret = RegCreateKeyExW(clsidhkey, clsidW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &classkey, NULL);
2347c2c66affSColin Finck         if (ret)
2348c2c66affSColin Finck             RegCloseKey(clsidhkey);
2349c2c66affSColin Finck     }
2350c2c66affSColin Finck 
2351c2c66affSColin Finck     if (ret == ERROR_ACCESS_DENIED)
2352c2c66affSColin Finck     {
2353c2c66affSColin Finck         win_skip("Failed to create test key, skipping some of OleRegGetUserType() tests.\n");
2354c2c66affSColin Finck         return;
2355c2c66affSColin Finck     }
2356c2c66affSColin Finck 
2357c2c66affSColin Finck     ok(!ret, "failed to create a key, error %d\n", ret);
2358c2c66affSColin Finck 
2359c2c66affSColin Finck     ret = RegSetValueExW(classkey, NULL, 0, REG_SZ, (const BYTE*)defvalueW, sizeof(defvalueW));
2360c2c66affSColin Finck     ok(!ret, "got error %d\n", ret);
2361c2c66affSColin Finck 
2362c2c66affSColin Finck     ret = RegCreateKeyExA(classkey, "AuxUserType", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &auxhkey, NULL);
2363c2c66affSColin Finck     ok(!ret, "got error %d\n", ret);
2364c2c66affSColin Finck 
2365c2c66affSColin Finck     /* populate AuxUserType */
2366c2c66affSColin Finck     for (i = 0; i <= 4; i++) {
2367c2c66affSColin Finck         char name[16];
2368c2c66affSColin Finck 
2369c2c66affSColin Finck         sprintf(name, "AuxUserType\\%d", i);
2370c2c66affSColin Finck         ret = RegCreateKeyExA(classkey, name, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
2371c2c66affSColin Finck         ok(!ret, "got error %d\n", ret);
2372c2c66affSColin Finck 
2373c2c66affSColin Finck         ret = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE*)auxvalues[i], strlen(auxvalues[i]));
2374c2c66affSColin Finck         ok(!ret, "got error %d\n", ret);
2375c2c66affSColin Finck         RegCloseKey(hkey);
2376c2c66affSColin Finck     }
2377c2c66affSColin Finck 
2378c2c66affSColin Finck     str = NULL;
2379c2c66affSColin Finck     hr = OleRegGetUserType(&CLSID_non_existent, 0, &str);
2380c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
2381c2c66affSColin Finck     ok(!lstrcmpW(str, auxvalue0W), "got %s\n", wine_dbgstr_w(str));
2382c2c66affSColin Finck     CoTaskMemFree(str);
2383c2c66affSColin Finck 
2384c2c66affSColin Finck     str = NULL;
2385c2c66affSColin Finck     hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_FULL, &str);
2386c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
2387c2c66affSColin Finck     ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str));
2388c2c66affSColin Finck     CoTaskMemFree(str);
2389c2c66affSColin Finck 
2390c2c66affSColin Finck     str = NULL;
2391c2c66affSColin Finck     hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_SHORT, &str);
2392c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
2393c2c66affSColin Finck     ok(!lstrcmpW(str, auxvalue2W), "got %s\n", wine_dbgstr_w(str));
2394c2c66affSColin Finck     CoTaskMemFree(str);
2395c2c66affSColin Finck 
2396c2c66affSColin Finck     str = NULL;
2397c2c66affSColin Finck     hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME, &str);
2398c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
2399c2c66affSColin Finck     ok(!lstrcmpW(str, auxvalue3W), "got %s\n", wine_dbgstr_w(str));
2400c2c66affSColin Finck     CoTaskMemFree(str);
2401c2c66affSColin Finck 
2402c2c66affSColin Finck     str = NULL;
2403c2c66affSColin Finck     hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+1, &str);
2404c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
2405c2c66affSColin Finck     ok(!lstrcmpW(str, auxvalue4W), "got %s\n", wine_dbgstr_w(str));
2406c2c66affSColin Finck     CoTaskMemFree(str);
2407c2c66affSColin Finck 
2408c2c66affSColin Finck     str = NULL;
2409c2c66affSColin Finck     hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+2, &str);
2410c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
2411c2c66affSColin Finck     ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str));
2412c2c66affSColin Finck     CoTaskMemFree(str);
2413c2c66affSColin Finck 
2414c2c66affSColin Finck     /* registry cleanup */
2415c2c66affSColin Finck     for (i = 0; i <= 4; i++)
2416c2c66affSColin Finck     {
2417c2c66affSColin Finck         char name[2];
2418c2c66affSColin Finck         sprintf(name, "%d", i);
2419c2c66affSColin Finck         RegDeleteKeyA(auxhkey, name);
2420c2c66affSColin Finck     }
2421c2c66affSColin Finck     RegCloseKey(auxhkey);
2422c2c66affSColin Finck     RegDeleteKeyA(classkey, "AuxUserType");
2423c2c66affSColin Finck     RegCloseKey(classkey);
2424c2c66affSColin Finck     RegDeleteKeyW(clsidhkey, clsidW);
2425c2c66affSColin Finck     RegCloseKey(clsidhkey);
2426c2c66affSColin Finck     if (disposition == REG_CREATED_NEW_KEY)
2427c2c66affSColin Finck         RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID");
2428c2c66affSColin Finck }
2429c2c66affSColin Finck 
test_CoCreateGuid(void)2430c2c66affSColin Finck static void test_CoCreateGuid(void)
2431c2c66affSColin Finck {
2432c2c66affSColin Finck     HRESULT hr;
2433c2c66affSColin Finck 
2434c2c66affSColin Finck     hr = CoCreateGuid(NULL);
2435c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2436c2c66affSColin Finck }
2437c2c66affSColin Finck 
apc_test_proc(ULONG_PTR param)2438c2c66affSColin Finck static void CALLBACK apc_test_proc(ULONG_PTR param)
2439c2c66affSColin Finck {
2440c2c66affSColin Finck     /* nothing */
2441c2c66affSColin Finck }
2442c2c66affSColin Finck 
release_semaphore_thread(LPVOID arg)2443c2c66affSColin Finck static DWORD CALLBACK release_semaphore_thread( LPVOID arg )
2444c2c66affSColin Finck {
2445c2c66affSColin Finck     HANDLE handle = arg;
2446c2c66affSColin Finck     if (WaitForSingleObject(handle, 200) == WAIT_TIMEOUT)
2447c2c66affSColin Finck         ReleaseSemaphore(handle, 1, NULL);
2448c2c66affSColin Finck     return 0;
2449c2c66affSColin Finck }
2450c2c66affSColin Finck 
send_message_thread(LPVOID arg)2451c2c66affSColin Finck static DWORD CALLBACK send_message_thread(LPVOID arg)
2452c2c66affSColin Finck {
2453c2c66affSColin Finck     HWND hWnd = arg;
2454c2c66affSColin Finck     Sleep(50);
2455c2c66affSColin Finck     SendMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2456c2c66affSColin Finck     return 0;
2457c2c66affSColin Finck }
2458c2c66affSColin Finck 
send_and_post_user_message_thread(void * arg)245966f35ef8SAmine Khaldi static DWORD CALLBACK send_and_post_user_message_thread(void *arg)
246066f35ef8SAmine Khaldi {
246166f35ef8SAmine Khaldi     HWND hwnd = arg;
246266f35ef8SAmine Khaldi     Sleep(30);
246366f35ef8SAmine Khaldi     SendMessageA(hwnd, WM_USER, 0, 0);
246466f35ef8SAmine Khaldi     PostMessageA(hwnd, WM_USER, 0, 0);
246566f35ef8SAmine Khaldi     return 0;
246666f35ef8SAmine Khaldi }
246766f35ef8SAmine Khaldi 
post_message_thread(LPVOID arg)2468c2c66affSColin Finck static DWORD CALLBACK post_message_thread(LPVOID arg)
2469c2c66affSColin Finck {
2470c2c66affSColin Finck     HWND hWnd = arg;
2471c2c66affSColin Finck     Sleep(50);
2472c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2473c2c66affSColin Finck     return 0;
2474c2c66affSColin Finck }
2475c2c66affSColin Finck 
2476c2c66affSColin Finck static const char cls_name[] = "cowait_test_class";
247766f35ef8SAmine Khaldi 
247866f35ef8SAmine Khaldi static UINT cowait_msgs[100], cowait_msgs_first, cowait_msgs_last;
247966f35ef8SAmine Khaldi 
cowait_msgs_reset(void)248066f35ef8SAmine Khaldi static void cowait_msgs_reset(void)
248166f35ef8SAmine Khaldi {
248266f35ef8SAmine Khaldi     cowait_msgs_first = cowait_msgs_last = 0;
248366f35ef8SAmine Khaldi }
248466f35ef8SAmine Khaldi 
248566f35ef8SAmine Khaldi #define cowait_msgs_expect_empty() _cowait_msgs_expect_empty(__LINE__)
_cowait_msgs_expect_empty(unsigned line)248666f35ef8SAmine Khaldi static void _cowait_msgs_expect_empty(unsigned line)
248766f35ef8SAmine Khaldi {
248866f35ef8SAmine Khaldi     while(cowait_msgs_first < cowait_msgs_last) {
248966f35ef8SAmine Khaldi         ok_(__FILE__,line)(0, "unexpected message %u\n", cowait_msgs[cowait_msgs_first]);
249066f35ef8SAmine Khaldi         cowait_msgs_first++;
249166f35ef8SAmine Khaldi     }
249266f35ef8SAmine Khaldi     cowait_msgs_reset();
249366f35ef8SAmine Khaldi }
249466f35ef8SAmine Khaldi 
249566f35ef8SAmine Khaldi #define cowait_msgs_expect_notified(a) _cowait_msgs_expect_notified(__LINE__,a)
_cowait_msgs_expect_notified(unsigned line,UINT expected_msg)249666f35ef8SAmine Khaldi static void _cowait_msgs_expect_notified(unsigned line, UINT expected_msg)
249766f35ef8SAmine Khaldi {
249866f35ef8SAmine Khaldi     if(cowait_msgs_first == cowait_msgs_last) {
249966f35ef8SAmine Khaldi         ok_(__FILE__,line)(0, "expected message %u, received none\n", expected_msg);
250066f35ef8SAmine Khaldi     }else {
250166f35ef8SAmine Khaldi         ok_(__FILE__,line)(cowait_msgs[cowait_msgs_first] == expected_msg,
250266f35ef8SAmine Khaldi                            "expected message %u, received %u \n",
250366f35ef8SAmine Khaldi                            expected_msg, cowait_msgs[cowait_msgs_first]);
250466f35ef8SAmine Khaldi         cowait_msgs_first++;
250566f35ef8SAmine Khaldi     }
250666f35ef8SAmine Khaldi }
250766f35ef8SAmine Khaldi 
250866f35ef8SAmine Khaldi #define cowait_msgs_expect_queued(a,b) _cowait_msgs_expect_queued(__LINE__,a,b)
_cowait_msgs_expect_queued(unsigned line,HWND hwnd,UINT expected_msg)250966f35ef8SAmine Khaldi static void _cowait_msgs_expect_queued(unsigned line, HWND hwnd, UINT expected_msg)
251066f35ef8SAmine Khaldi {
251166f35ef8SAmine Khaldi     MSG msg;
251266f35ef8SAmine Khaldi     BOOL success;
251366f35ef8SAmine Khaldi 
251466f35ef8SAmine Khaldi     success = PeekMessageA(&msg, hwnd, expected_msg, expected_msg, PM_REMOVE);
251566f35ef8SAmine Khaldi     ok_(__FILE__,line)(success, "PeekMessageA failed: %u\n", GetLastError());
251666f35ef8SAmine Khaldi     if(success)
251766f35ef8SAmine Khaldi         ok_(__FILE__,line)(msg.message == expected_msg, "unexpected message %u, expected %u\n",
251866f35ef8SAmine Khaldi                            msg.message, expected_msg);
251966f35ef8SAmine Khaldi }
252066f35ef8SAmine Khaldi 
flush_messages(void)252166f35ef8SAmine Khaldi static void flush_messages(void)
252266f35ef8SAmine Khaldi {
252366f35ef8SAmine Khaldi     MSG msg;
252466f35ef8SAmine Khaldi     while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ));
252566f35ef8SAmine Khaldi }
252666f35ef8SAmine Khaldi 
cowait_window_proc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)252766f35ef8SAmine Khaldi static LRESULT CALLBACK cowait_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
252866f35ef8SAmine Khaldi {
25295c1bcfecSAmine Khaldi     if(cowait_msgs_last < ARRAY_SIZE(cowait_msgs))
253066f35ef8SAmine Khaldi         cowait_msgs[cowait_msgs_last++] = msg;
253166f35ef8SAmine Khaldi     if(msg == WM_DDE_FIRST)
253266f35ef8SAmine Khaldi         return 6;
253366f35ef8SAmine Khaldi     return DefWindowProcA(hwnd, msg, wparam, lparam);
253466f35ef8SAmine Khaldi }
253566f35ef8SAmine Khaldi 
cowait_unmarshal_thread(void * arg)253666f35ef8SAmine Khaldi static DWORD CALLBACK cowait_unmarshal_thread(void *arg)
253766f35ef8SAmine Khaldi {
253866f35ef8SAmine Khaldi     IStream *stream = arg;
253966f35ef8SAmine Khaldi     IEnumOLEVERB *enum_verb;
254066f35ef8SAmine Khaldi     LARGE_INTEGER zero;
254166f35ef8SAmine Khaldi     IUnknown *unk;
254266f35ef8SAmine Khaldi     HRESULT hr;
254366f35ef8SAmine Khaldi 
254466f35ef8SAmine Khaldi     CoInitialize(NULL);
254566f35ef8SAmine Khaldi 
254666f35ef8SAmine Khaldi     zero.QuadPart = 0;
254766f35ef8SAmine Khaldi     hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
254866f35ef8SAmine Khaldi     ok(hr == S_OK, "Seek failed: %08x\n", hr);
254966f35ef8SAmine Khaldi 
255066f35ef8SAmine Khaldi     hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk);
255166f35ef8SAmine Khaldi     ok(hr == S_OK, "CoUnmarshalInterface failed: %08x\n", hr);
255266f35ef8SAmine Khaldi 
255366f35ef8SAmine Khaldi     hr = IUnknown_QueryInterface(unk, &IID_IEnumOLEVERB, (void**)&enum_verb);
255466f35ef8SAmine Khaldi     ok(hr == S_OK, "QueryInterface failed: %08x\n", hr);
255566f35ef8SAmine Khaldi 
255666f35ef8SAmine Khaldi     IEnumOLEVERB_Release(enum_verb);
255766f35ef8SAmine Khaldi     IUnknown_Release(unk);
255866f35ef8SAmine Khaldi 
255966f35ef8SAmine Khaldi     CoUninitialize();
256066f35ef8SAmine Khaldi     return 0;
256166f35ef8SAmine Khaldi }
256266f35ef8SAmine Khaldi 
test_CoWaitForMultipleHandles_thread(LPVOID arg)2563c2c66affSColin Finck static DWORD CALLBACK test_CoWaitForMultipleHandles_thread(LPVOID arg)
2564c2c66affSColin Finck {
256566f35ef8SAmine Khaldi     HANDLE *handles = arg, event, thread;
256666f35ef8SAmine Khaldi     IStream *stream;
2567c2c66affSColin Finck     BOOL success;
256866f35ef8SAmine Khaldi     DWORD index, tid;
2569c2c66affSColin Finck     HRESULT hr;
2570c2c66affSColin Finck     HWND hWnd;
257166f35ef8SAmine Khaldi     UINT uMSG = 0xc065;
2572c2c66affSColin Finck     MSG msg;
257366f35ef8SAmine Khaldi     int ret;
2574c2c66affSColin Finck 
2575c2c66affSColin Finck     hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2576c2c66affSColin Finck     ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2577c2c66affSColin Finck 
2578c2c66affSColin Finck     hWnd = CreateWindowExA(0, cls_name, "Test (thread)", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2579c2c66affSColin Finck     ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
2580c2c66affSColin Finck 
2581c2c66affSColin Finck     index = 0xdeadbeef;
2582c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2583c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2584c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2585c2c66affSColin Finck     ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index);
2586c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2587c2c66affSColin Finck     ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2588c2c66affSColin Finck 
2589c2c66affSColin Finck     index = 0xdeadbeef;
2590c2c66affSColin Finck     PostMessageA(hWnd, WM_USER, 0, 0);
2591c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2592c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2593c2c66affSColin Finck     ok(index==0 || index==0xdeadbeef/* Win 8 */, "expected index 0, got %u\n", index);
2594c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_USER, WM_USER, PM_REMOVE);
2595c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2596c2c66affSColin Finck 
259766f35ef8SAmine Khaldi     /* Even if CoWaitForMultipleHandles does not pump a message it peeks
259866f35ef8SAmine Khaldi      * at ALL of them */
259966f35ef8SAmine Khaldi     index = 0xdeadbeef;
260066f35ef8SAmine Khaldi     PostMessageA(NULL, uMSG, 0, 0);
260166f35ef8SAmine Khaldi 
260266f35ef8SAmine Khaldi     hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
260366f35ef8SAmine Khaldi     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
260466f35ef8SAmine Khaldi     ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
260566f35ef8SAmine Khaldi 
260666f35ef8SAmine Khaldi     /* Make sure message was peeked at */
260766f35ef8SAmine Khaldi     ret = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE);
260866f35ef8SAmine Khaldi     ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjects returned %x\n", ret);
260966f35ef8SAmine Khaldi 
261066f35ef8SAmine Khaldi     /* But not pumped */
261166f35ef8SAmine Khaldi     success = PeekMessageA(&msg, NULL, uMSG, uMSG, PM_REMOVE);
261266f35ef8SAmine Khaldi     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
261366f35ef8SAmine Khaldi 
2614c2c66affSColin Finck     DestroyWindow(hWnd);
2615c2c66affSColin Finck     CoUninitialize();
261666f35ef8SAmine Khaldi 
261766f35ef8SAmine Khaldi     hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
261866f35ef8SAmine Khaldi     ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
261966f35ef8SAmine Khaldi 
262066f35ef8SAmine Khaldi     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
262166f35ef8SAmine Khaldi     ok(hr == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hr);
262266f35ef8SAmine Khaldi 
262366f35ef8SAmine Khaldi     hr = CoMarshalInterface(stream, &IID_IUnknown, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
262466f35ef8SAmine Khaldi     ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
262566f35ef8SAmine Khaldi 
262666f35ef8SAmine Khaldi     event = CreateEventW(NULL, TRUE, FALSE, NULL);
262766f35ef8SAmine Khaldi 
262866f35ef8SAmine Khaldi     PostQuitMessage(66);
262966f35ef8SAmine Khaldi     PostThreadMessageW(GetCurrentThreadId(), WM_QUIT, 0, 0);
263066f35ef8SAmine Khaldi 
263166f35ef8SAmine Khaldi     hr = CoRegisterMessageFilter(&MessageFilter, NULL);
263266f35ef8SAmine Khaldi     ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr);
263366f35ef8SAmine Khaldi 
263466f35ef8SAmine Khaldi     thread = CreateThread(NULL, 0, cowait_unmarshal_thread, stream, 0, &tid);
263566f35ef8SAmine Khaldi     ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
263666f35ef8SAmine Khaldi     hr = CoWaitForMultipleHandles(0, 50, 1, &event, &index);
263766f35ef8SAmine Khaldi     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
263866f35ef8SAmine Khaldi     index = WaitForSingleObject(thread, 200);
263966f35ef8SAmine Khaldi     ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
264066f35ef8SAmine Khaldi     CloseHandle(thread);
264166f35ef8SAmine Khaldi 
264266f35ef8SAmine Khaldi     hr = CoRegisterMessageFilter(NULL, NULL);
264366f35ef8SAmine Khaldi     ok(hr == S_OK, "CoRegisterMessageFilter failed: %08x\n", hr);
264466f35ef8SAmine Khaldi 
264566f35ef8SAmine Khaldi     IStream_Release(stream);
264666f35ef8SAmine Khaldi 
264766f35ef8SAmine Khaldi     CloseHandle(event);
264866f35ef8SAmine Khaldi     CoUninitialize();
2649c2c66affSColin Finck     return 0;
2650c2c66affSColin Finck }
2651c2c66affSColin Finck 
test_CoWaitForMultipleHandles(void)2652c2c66affSColin Finck static void test_CoWaitForMultipleHandles(void)
2653c2c66affSColin Finck {
2654c2c66affSColin Finck     HANDLE handles[2], thread;
2655c2c66affSColin Finck     DWORD index, tid;
2656c2c66affSColin Finck     WNDCLASSEXA wc;
2657c2c66affSColin Finck     BOOL success;
2658c2c66affSColin Finck     HRESULT hr;
2659c2c66affSColin Finck     HWND hWnd;
2660c2c66affSColin Finck     MSG msg;
2661c2c66affSColin Finck 
2662c2c66affSColin Finck     hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2663c2c66affSColin Finck     ok(hr == S_OK, "CoInitializeEx failed with error 0x%08x\n", hr);
2664c2c66affSColin Finck 
2665c2c66affSColin Finck     memset(&wc, 0, sizeof(wc));
2666c2c66affSColin Finck     wc.cbSize        = sizeof(wc);
2667c2c66affSColin Finck     wc.style         = CS_VREDRAW | CS_HREDRAW;
2668c2c66affSColin Finck     wc.hInstance     = GetModuleHandleA(0);
2669c2c66affSColin Finck     wc.hCursor       = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2670c2c66affSColin Finck     wc.hbrBackground = NULL;
2671c2c66affSColin Finck     wc.lpszClassName = cls_name;
267266f35ef8SAmine Khaldi     wc.lpfnWndProc   = cowait_window_proc;
2673c2c66affSColin Finck     success = RegisterClassExA(&wc) != 0;
2674c2c66affSColin Finck     ok(success, "RegisterClassExA failed %u\n", GetLastError());
2675c2c66affSColin Finck 
2676c2c66affSColin Finck     hWnd = CreateWindowExA(0, cls_name, "Test", WS_TILEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2677c2c66affSColin Finck     ok(hWnd != 0, "CreateWindowExA failed %u\n", GetLastError());
2678c2c66affSColin Finck     handles[0] = CreateSemaphoreA(NULL, 1, 1, NULL);
2679c2c66affSColin Finck     ok(handles[0] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2680c2c66affSColin Finck     handles[1] = CreateSemaphoreA(NULL, 1, 1, NULL);
2681c2c66affSColin Finck     ok(handles[1] != 0, "CreateSemaphoreA failed %u\n", GetLastError());
2682c2c66affSColin Finck 
2683c2c66affSColin Finck     /* test without flags */
2684c2c66affSColin Finck 
2685c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2686c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 0, handles, NULL);
2687c2c66affSColin Finck     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2688c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2689c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2690c2c66affSColin Finck 
2691c2c66affSColin Finck     index = 0xdeadbeef;
2692c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2693c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 0, NULL, &index);
2694c2c66affSColin Finck     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
2695c2c66affSColin Finck     ok(index == 0, "expected index 0, got %u\n", index);
2696c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2697c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2698c2c66affSColin Finck 
2699c2c66affSColin Finck     index = 0xdeadbeef;
2700c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2701c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 0, handles, &index);
2702c2c66affSColin Finck     ok(hr == RPC_E_NO_SYNC, "expected RPC_E_NO_SYNC, got 0x%08x\n", hr);
2703c2c66affSColin Finck     ok(index == 0, "expected index 0, got %u\n", index);
2704c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2705c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2706c2c66affSColin Finck 
2707c2c66affSColin Finck     index = 0xdeadbeef;
2708c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2709c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 1, handles, &index);
2710c2c66affSColin Finck     ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2711c2c66affSColin Finck     ok(index == 0, "expected index 0, got %u\n", index);
2712c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2713c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2714c2c66affSColin Finck 
2715c2c66affSColin Finck     index = 0xdeadbeef;
2716c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2717c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2718c2c66affSColin Finck     ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2719c2c66affSColin Finck     ok(index == 1, "expected index 1, got %u\n", index);
2720c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2721c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2722c2c66affSColin Finck 
2723c2c66affSColin Finck     index = 0xdeadbeef;
2724c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2725c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2726c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2727c2c66affSColin Finck     ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2728c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2729c2c66affSColin Finck     ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2730c2c66affSColin Finck 
2731c2c66affSColin Finck     /* test PostMessageA/SendMessageA from a different thread */
2732c2c66affSColin Finck 
2733c2c66affSColin Finck     index = 0xdeadbeef;
2734c2c66affSColin Finck     thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2735c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2736c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2737c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2738c2c66affSColin Finck     ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2739c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2740c2c66affSColin Finck     ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2741c2c66affSColin Finck     index = WaitForSingleObject(thread, 200);
2742c2c66affSColin Finck     ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2743c2c66affSColin Finck     CloseHandle(thread);
2744c2c66affSColin Finck 
2745c2c66affSColin Finck     index = 0xdeadbeef;
2746c2c66affSColin Finck     thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2747c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2748c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2749c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2750c2c66affSColin Finck     ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2751c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2752c2c66affSColin Finck     ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2753c2c66affSColin Finck     index = WaitForSingleObject(thread, 200);
2754c2c66affSColin Finck     ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2755c2c66affSColin Finck     CloseHandle(thread);
2756c2c66affSColin Finck 
2757c2c66affSColin Finck     ReleaseSemaphore(handles[0], 1, NULL);
2758c2c66affSColin Finck     ReleaseSemaphore(handles[1], 1, NULL);
2759c2c66affSColin Finck 
2760c2c66affSColin Finck     /* test with COWAIT_WAITALL */
2761c2c66affSColin Finck 
2762c2c66affSColin Finck     index = 0xdeadbeef;
2763c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2764c2c66affSColin Finck     hr = CoWaitForMultipleHandles(COWAIT_WAITALL, 50, 2, handles, &index);
2765c2c66affSColin Finck     ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2766c2c66affSColin Finck     ok(index == 0, "expected index 0, got %u\n", index);
2767c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2768c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2769c2c66affSColin Finck 
2770c2c66affSColin Finck     index = 0xdeadbeef;
2771c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2772c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2773c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2774c2c66affSColin Finck     ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2775c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2776c2c66affSColin Finck     ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2777c2c66affSColin Finck 
2778c2c66affSColin Finck     ReleaseSemaphore(handles[0], 1, NULL);
2779c2c66affSColin Finck     ReleaseSemaphore(handles[1], 1, NULL);
2780c2c66affSColin Finck 
2781c2c66affSColin Finck     /* test with COWAIT_ALERTABLE */
2782c2c66affSColin Finck 
2783c2c66affSColin Finck     index = 0xdeadbeef;
2784c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2785c2c66affSColin Finck     hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 1, handles, &index);
2786c2c66affSColin Finck     ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2787c2c66affSColin Finck     ok(index == 0, "expected index 0, got %u\n", index);
2788c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2789c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2790c2c66affSColin Finck 
2791c2c66affSColin Finck     index = 0xdeadbeef;
2792c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2793c2c66affSColin Finck     hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2794c2c66affSColin Finck     ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2795c2c66affSColin Finck     ok(index == 1, "expected index 1, got %u\n", index);
2796c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2797c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2798c2c66affSColin Finck 
2799c2c66affSColin Finck     index = 0xdeadbeef;
2800c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2801c2c66affSColin Finck     hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2802c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2803c2c66affSColin Finck     ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2804c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2805c2c66affSColin Finck     ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2806c2c66affSColin Finck 
2807c2c66affSColin Finck     index = 0xdeadbeef;
2808c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2809c2c66affSColin Finck     success = QueueUserAPC(apc_test_proc, GetCurrentThread(), 0);
2810c2c66affSColin Finck     ok(success, "QueueUserAPC failed %u\n", GetLastError());
2811c2c66affSColin Finck     hr = CoWaitForMultipleHandles(COWAIT_ALERTABLE, 50, 2, handles, &index);
2812c2c66affSColin Finck     ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
2813c2c66affSColin Finck     ok(index == WAIT_IO_COMPLETION, "expected index WAIT_IO_COMPLETION, got %u\n", index);
2814c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2815c2c66affSColin Finck     ok(success, "CoWaitForMultipleHandles unexpectedly pumped messages\n");
2816c2c66affSColin Finck 
2817c2c66affSColin Finck     /* test with COWAIT_INPUTAVAILABLE (semaphores are still locked) */
2818c2c66affSColin Finck 
2819c2c66affSColin Finck     index = 0xdeadbeef;
2820c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2821c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2822c2c66affSColin Finck     ok(success, "PeekMessageA returned FALSE\n");
2823c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 50, 2, handles, &index);
2824c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2825c2c66affSColin Finck     ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2826c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2827c2c66affSColin Finck     ok(!success, "CoWaitForMultipleHandles didn't pump any messages\n");
2828c2c66affSColin Finck 
2829c2c66affSColin Finck     index = 0xdeadbeef;
2830c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2831c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_NOREMOVE);
2832c2c66affSColin Finck     ok(success, "PeekMessageA returned FALSE\n");
2833c2c66affSColin Finck     thread = CreateThread(NULL, 0, release_semaphore_thread, handles[1], 0, &tid);
2834c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2835c2c66affSColin Finck     hr = CoWaitForMultipleHandles(COWAIT_INPUTAVAILABLE, 50, 2, handles, &index);
2836c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING || broken(hr == E_INVALIDARG) || broken(hr == S_OK) /* Win 8 */,
2837c2c66affSColin Finck        "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2838c2c66affSColin Finck     if (hr != S_OK) ReleaseSemaphore(handles[1], 1, NULL);
2839c2c66affSColin Finck     ok(index == 0 || broken(index == 1) /* Win 8 */, "expected index 0, got %u\n", index);
2840c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2841c2c66affSColin Finck     ok(!success || broken(success && hr == E_INVALIDARG),
2842c2c66affSColin Finck        "CoWaitForMultipleHandles didn't pump any messages\n");
2843c2c66affSColin Finck     index = WaitForSingleObject(thread, 200);
2844c2c66affSColin Finck     ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2845c2c66affSColin Finck     CloseHandle(thread);
2846c2c66affSColin Finck 
284766f35ef8SAmine Khaldi     cowait_msgs_reset();
284866f35ef8SAmine Khaldi     PostMessageA(hWnd, 0, 0, 0);
284966f35ef8SAmine Khaldi     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
285066f35ef8SAmine Khaldi     PostMessageA(hWnd, WM_USER+1, 0, 0);
285166f35ef8SAmine Khaldi     PostMessageA(hWnd, WM_DDE_FIRST+1, 0, 0);
285266f35ef8SAmine Khaldi     thread = CreateThread(NULL, 0, send_and_post_user_message_thread, hWnd, 0, &tid);
285366f35ef8SAmine Khaldi     ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
285466f35ef8SAmine Khaldi 
285566f35ef8SAmine Khaldi     hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
285666f35ef8SAmine Khaldi     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
285766f35ef8SAmine Khaldi 
285866f35ef8SAmine Khaldi     cowait_msgs_expect_notified(WM_DDE_FIRST);
285966f35ef8SAmine Khaldi     cowait_msgs_expect_notified(WM_DDE_FIRST+1);
286066f35ef8SAmine Khaldi     cowait_msgs_expect_notified(WM_USER);
286166f35ef8SAmine Khaldi     cowait_msgs_expect_empty();
286266f35ef8SAmine Khaldi     cowait_msgs_expect_queued(hWnd, WM_USER);
286366f35ef8SAmine Khaldi     cowait_msgs_expect_queued(hWnd, WM_USER+1);
286466f35ef8SAmine Khaldi     flush_messages();
286566f35ef8SAmine Khaldi 
286666f35ef8SAmine Khaldi     index = WaitForSingleObject(thread, 200);
286766f35ef8SAmine Khaldi     ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
286866f35ef8SAmine Khaldi     CloseHandle(thread);
286966f35ef8SAmine Khaldi 
2870c2c66affSColin Finck     /* test behaviour of WM_QUIT (semaphores are still locked) */
2871c2c66affSColin Finck 
2872c2c66affSColin Finck     PostMessageA(hWnd, WM_QUIT, 40, 0);
2873c2c66affSColin Finck     memset(&msg, 0, sizeof(msg));
2874c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2875c2c66affSColin Finck     ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2876c2c66affSColin Finck     ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2877c2c66affSColin Finck     ok(msg.wParam == 40, "expected msg.wParam = 40, got %lu\n", msg.wParam);
2878c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2879c2c66affSColin Finck     ok(!success, "PeekMessageA succeeded\n");
2880c2c66affSColin Finck 
288166f35ef8SAmine Khaldi     cowait_msgs_reset();
288266f35ef8SAmine Khaldi     PostMessageA(hWnd, WM_QUIT, 40, 0);
288366f35ef8SAmine Khaldi     PostMessageA(hWnd, 0, 0, 0);
288466f35ef8SAmine Khaldi     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
288566f35ef8SAmine Khaldi     PostMessageA(hWnd, WM_USER+1, 0, 0);
288666f35ef8SAmine Khaldi     PostMessageA(hWnd, WM_DDE_FIRST+1, 0, 0);
288766f35ef8SAmine Khaldi     thread = CreateThread(NULL, 0, send_and_post_user_message_thread, hWnd, 0, &tid);
288866f35ef8SAmine Khaldi     ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
288966f35ef8SAmine Khaldi 
289066f35ef8SAmine Khaldi     hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
289166f35ef8SAmine Khaldi     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
289266f35ef8SAmine Khaldi 
289366f35ef8SAmine Khaldi     cowait_msgs_expect_notified(WM_DDE_FIRST);
289466f35ef8SAmine Khaldi     cowait_msgs_expect_notified(WM_DDE_FIRST+1);
289566f35ef8SAmine Khaldi     cowait_msgs_expect_notified(WM_USER);
289666f35ef8SAmine Khaldi     cowait_msgs_expect_empty();
289766f35ef8SAmine Khaldi     cowait_msgs_expect_queued(hWnd, WM_USER);
289866f35ef8SAmine Khaldi     flush_messages();
289966f35ef8SAmine Khaldi 
290066f35ef8SAmine Khaldi     index = WaitForSingleObject(thread, 200);
290166f35ef8SAmine Khaldi     ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
290266f35ef8SAmine Khaldi     CloseHandle(thread);
290366f35ef8SAmine Khaldi 
2904c2c66affSColin Finck     index = 0xdeadbeef;
2905c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2906c2c66affSColin Finck     PostMessageA(hWnd, WM_QUIT, 41, 0);
2907c2c66affSColin Finck     thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2908c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2909c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2910c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2911c2c66affSColin Finck     ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2912c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2913c2c66affSColin Finck     todo_wine
2914c2c66affSColin Finck     ok(success || broken(!success) /* Win 2000/XP/8 */, "PeekMessageA failed, error %u\n", GetLastError());
2915c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2916c2c66affSColin Finck     ok(!success, "PeekMessageA succeeded\n");
2917c2c66affSColin Finck     memset(&msg, 0, sizeof(msg));
2918c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2919c2c66affSColin Finck     todo_wine
2920c2c66affSColin Finck     ok(!success || broken(success) /* Win 2000/XP/8 */, "PeekMessageA succeeded\n");
2921c2c66affSColin Finck     if (success)
2922c2c66affSColin Finck     {
2923c2c66affSColin Finck         ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2924c2c66affSColin Finck         ok(msg.wParam == 41, "expected msg.wParam = 41, got %lu\n", msg.wParam);
2925c2c66affSColin Finck     }
2926c2c66affSColin Finck     index = WaitForSingleObject(thread, 200);
2927c2c66affSColin Finck     ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2928c2c66affSColin Finck     CloseHandle(thread);
2929c2c66affSColin Finck 
2930c2c66affSColin Finck     index = 0xdeadbeef;
2931c2c66affSColin Finck     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2932c2c66affSColin Finck     PostMessageA(hWnd, WM_QUIT, 42, 0);
2933c2c66affSColin Finck     thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2934c2c66affSColin Finck     ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2935c2c66affSColin Finck     hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2936c2c66affSColin Finck     ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2937c2c66affSColin Finck     ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2938c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2939c2c66affSColin Finck     ok(!success, "CoWaitForMultipleHandles didn't pump all WM_DDE_FIRST messages\n");
2940c2c66affSColin Finck     memset(&msg, 0, sizeof(msg));
2941c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2942c2c66affSColin Finck     ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2943c2c66affSColin Finck     ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2944c2c66affSColin Finck     ok(msg.wParam == 42, "expected msg.wParam = 42, got %lu\n", msg.wParam);
2945c2c66affSColin Finck     index = WaitForSingleObject(thread, 200);
2946c2c66affSColin Finck     ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2947c2c66affSColin Finck     CloseHandle(thread);
2948c2c66affSColin Finck 
2949c2c66affSColin Finck     PostQuitMessage(43);
2950c2c66affSColin Finck     memset(&msg, 0, sizeof(msg));
2951c2c66affSColin Finck     success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2952c2c66affSColin Finck     ok(success || broken(!success) /* Win 8 */, "PeekMessageA failed, error %u\n", GetLastError());
2953c2c66affSColin Finck     if (!success)
2954c2c66affSColin Finck         win_skip("PostQuitMessage didn't queue a WM_QUIT message, skipping tests\n");
2955c2c66affSColin Finck     else
2956c2c66affSColin Finck     {
2957c2c66affSColin Finck         ok(msg.message == WM_QUIT, "expected msg.message = WM_QUIT, got %u\n", msg.message);
2958c2c66affSColin Finck         ok(msg.wParam == 43, "expected msg.wParam = 43, got %lu\n", msg.wParam);
2959c2c66affSColin Finck         success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2960c2c66affSColin Finck         ok(!success, "PeekMessageA succeeded\n");
2961c2c66affSColin Finck 
2962c2c66affSColin Finck         index = 0xdeadbeef;
2963c2c66affSColin Finck         PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2964c2c66affSColin Finck         PostQuitMessage(44);
2965c2c66affSColin Finck         thread = CreateThread(NULL, 0, post_message_thread, hWnd, 0, &tid);
2966c2c66affSColin Finck         ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2967c2c66affSColin Finck         hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2968c2c66affSColin Finck         ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2969c2c66affSColin Finck         ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2970c2c66affSColin Finck         success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2971c2c66affSColin Finck         ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2972c2c66affSColin Finck         success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2973c2c66affSColin Finck         ok(!success, "PeekMessageA succeeded\n");
2974c2c66affSColin Finck         success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2975c2c66affSColin Finck         ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n");
2976c2c66affSColin Finck         index = WaitForSingleObject(thread, 200);
2977c2c66affSColin Finck         ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2978c2c66affSColin Finck         CloseHandle(thread);
2979c2c66affSColin Finck 
2980c2c66affSColin Finck         index = 0xdeadbeef;
2981c2c66affSColin Finck         PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
2982c2c66affSColin Finck         PostQuitMessage(45);
2983c2c66affSColin Finck         thread = CreateThread(NULL, 0, send_message_thread, hWnd, 0, &tid);
2984c2c66affSColin Finck         ok(thread != NULL, "CreateThread failed, error %u\n", GetLastError());
2985c2c66affSColin Finck         hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
2986c2c66affSColin Finck         ok(hr == RPC_S_CALLPENDING, "expected RPC_S_CALLPENDING, got 0x%08x\n", hr);
2987c2c66affSColin Finck         ok(index == 0 || broken(index == 0xdeadbeef) /* Win 8 */, "expected index 0, got %u\n", index);
2988c2c66affSColin Finck         success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2989c2c66affSColin Finck         ok(success, "PeekMessageA failed, error %u\n", GetLastError());
2990c2c66affSColin Finck         success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
2991c2c66affSColin Finck         ok(!success, "PeekMessageA succeeded\n");
2992c2c66affSColin Finck         success = PeekMessageA(&msg, hWnd, WM_QUIT, WM_QUIT, PM_REMOVE);
2993c2c66affSColin Finck         ok(!success, "CoWaitForMultipleHandles didn't remove WM_QUIT messages\n");
2994c2c66affSColin Finck         index = WaitForSingleObject(thread, 200);
2995c2c66affSColin Finck         ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
2996c2c66affSColin Finck         CloseHandle(thread);
2997c2c66affSColin Finck     }
2998c2c66affSColin Finck 
2999c2c66affSColin Finck     /* test message pumping when CoWaitForMultipleHandles is called from non main apartment thread */
3000c2c66affSColin Finck     thread = CreateThread(NULL, 0, test_CoWaitForMultipleHandles_thread, handles, 0, &tid);
3001c2c66affSColin Finck     index = WaitForSingleObject(thread, 500);
3002c2c66affSColin Finck     ok(index == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
3003c2c66affSColin Finck     CloseHandle(thread);
3004c2c66affSColin Finck 
3005a6cdf4ffSAmine Khaldi     CoUninitialize();
3006a6cdf4ffSAmine Khaldi 
3007a6cdf4ffSAmine Khaldi     /* If COM was not initialized, messages are neither pumped nor peeked at */
3008a6cdf4ffSAmine Khaldi     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3009a6cdf4ffSAmine Khaldi     hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3010a6cdf4ffSAmine Khaldi     ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr);
3011a6cdf4ffSAmine Khaldi     success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE);
3012a6cdf4ffSAmine Khaldi     ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success);
3013a6cdf4ffSAmine Khaldi     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3014a6cdf4ffSAmine Khaldi     ok(success, "PeekMessage failed: %u\n", GetLastError());
3015a6cdf4ffSAmine Khaldi 
3016a6cdf4ffSAmine Khaldi     /* same in an MTA */
3017a6cdf4ffSAmine Khaldi     CoInitializeEx(NULL, COINIT_MULTITHREADED);
3018a6cdf4ffSAmine Khaldi 
3019a6cdf4ffSAmine Khaldi     PostMessageA(hWnd, WM_DDE_FIRST, 0, 0);
3020a6cdf4ffSAmine Khaldi     hr = CoWaitForMultipleHandles(0, 100, 2, handles, &index);
3021a6cdf4ffSAmine Khaldi     ok(hr == RPC_S_CALLPENDING, "got %#x\n", hr);
3022a6cdf4ffSAmine Khaldi     success = MsgWaitForMultipleObjectsEx(0, NULL, 2, QS_ALLPOSTMESSAGE, MWMO_ALERTABLE);
3023a6cdf4ffSAmine Khaldi     ok(success == 0, "MsgWaitForMultipleObjects returned %x\n", success);
3024a6cdf4ffSAmine Khaldi     success = PeekMessageA(&msg, hWnd, WM_DDE_FIRST, WM_DDE_FIRST, PM_REMOVE);
3025a6cdf4ffSAmine Khaldi     ok(success, "PeekMessage failed: %u\n", GetLastError());
3026a6cdf4ffSAmine Khaldi 
3027a6cdf4ffSAmine Khaldi     CoUninitialize();
3028a6cdf4ffSAmine Khaldi 
3029c2c66affSColin Finck     CloseHandle(handles[0]);
3030c2c66affSColin Finck     CloseHandle(handles[1]);
3031c2c66affSColin Finck     DestroyWindow(hWnd);
3032c2c66affSColin Finck 
3033c2c66affSColin Finck     success = UnregisterClassA(cls_name, GetModuleHandleA(0));
3034c2c66affSColin Finck     ok(success, "UnregisterClass failed %u\n", GetLastError());
3035c2c66affSColin Finck }
3036c2c66affSColin Finck 
test_CoGetMalloc(void)3037c2c66affSColin Finck static void test_CoGetMalloc(void)
3038c2c66affSColin Finck {
3039c2c66affSColin Finck     IMalloc *imalloc;
3040c2c66affSColin Finck     HRESULT hr;
3041c2c66affSColin Finck 
3042c2c66affSColin Finck     if (0) /* crashes on native */
3043c2c66affSColin Finck         hr = CoGetMalloc(0, NULL);
3044c2c66affSColin Finck 
3045c2c66affSColin Finck     imalloc = (void*)0xdeadbeef;
3046c2c66affSColin Finck     hr = CoGetMalloc(0, &imalloc);
3047c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3048c2c66affSColin Finck     ok(imalloc == NULL, "got %p\n", imalloc);
3049c2c66affSColin Finck 
3050c2c66affSColin Finck     imalloc = (void*)0xdeadbeef;
3051c2c66affSColin Finck     hr = CoGetMalloc(MEMCTX_SHARED, &imalloc);
3052c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3053c2c66affSColin Finck     ok(imalloc == NULL, "got %p\n", imalloc);
3054c2c66affSColin Finck 
3055c2c66affSColin Finck     imalloc = (void*)0xdeadbeef;
3056c2c66affSColin Finck     hr = CoGetMalloc(MEMCTX_MACSYSTEM, &imalloc);
3057c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3058c2c66affSColin Finck     ok(imalloc == NULL, "got %p\n", imalloc);
3059c2c66affSColin Finck 
3060c2c66affSColin Finck     imalloc = (void*)0xdeadbeef;
3061c2c66affSColin Finck     hr = CoGetMalloc(MEMCTX_UNKNOWN, &imalloc);
3062c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3063c2c66affSColin Finck     ok(imalloc == NULL, "got %p\n", imalloc);
3064c2c66affSColin Finck 
3065c2c66affSColin Finck     imalloc = (void*)0xdeadbeef;
3066c2c66affSColin Finck     hr = CoGetMalloc(MEMCTX_SAME, &imalloc);
3067c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3068c2c66affSColin Finck     ok(imalloc == NULL, "got %p\n", imalloc);
3069c2c66affSColin Finck 
3070c2c66affSColin Finck     imalloc = NULL;
3071c2c66affSColin Finck     hr = CoGetMalloc(MEMCTX_TASK, &imalloc);
3072c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3073c2c66affSColin Finck     ok(imalloc != NULL, "got %p\n", imalloc);
3074c2c66affSColin Finck     IMalloc_Release(imalloc);
3075c2c66affSColin Finck }
3076c2c66affSColin Finck 
test_CoGetApartmentType(void)3077c2c66affSColin Finck static void test_CoGetApartmentType(void)
3078c2c66affSColin Finck {
3079c2c66affSColin Finck     APTTYPEQUALIFIER qualifier;
3080c2c66affSColin Finck     APTTYPE type;
3081c2c66affSColin Finck     HRESULT hr;
3082c2c66affSColin Finck 
3083c2c66affSColin Finck     if (!pCoGetApartmentType)
3084c2c66affSColin Finck     {
3085c2c66affSColin Finck         win_skip("CoGetApartmentType not present\n");
3086c2c66affSColin Finck         return;
3087c2c66affSColin Finck     }
3088c2c66affSColin Finck 
3089c2c66affSColin Finck     hr = pCoGetApartmentType(NULL, NULL);
3090c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3091c2c66affSColin Finck 
3092c2c66affSColin Finck     type = 0xdeadbeef;
3093c2c66affSColin Finck     hr = pCoGetApartmentType(&type, NULL);
3094c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3095c2c66affSColin Finck     ok(type == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", type);
3096c2c66affSColin Finck 
3097c2c66affSColin Finck     qualifier = 0xdeadbeef;
3098c2c66affSColin Finck     hr = pCoGetApartmentType(NULL, &qualifier);
3099c2c66affSColin Finck     ok(hr == E_INVALIDARG, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3100c2c66affSColin Finck     ok(qualifier == 0xdeadbeef, "Expected 0xdeadbeef, got %u\n", qualifier);
3101c2c66affSColin Finck 
3102c2c66affSColin Finck     type = 0xdeadbeef;
3103c2c66affSColin Finck     qualifier = 0xdeadbeef;
3104c2c66affSColin Finck     hr = pCoGetApartmentType(&type, &qualifier);
3105c2c66affSColin Finck     ok(hr == CO_E_NOTINITIALIZED, "CoGetApartmentType succeeded, error: 0x%08x\n", hr);
3106c2c66affSColin Finck     ok(type == APTTYPE_CURRENT, "Expected APTTYPE_CURRENT, got %u\n", type);
3107c2c66affSColin Finck     ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3108c2c66affSColin Finck 
3109c2c66affSColin Finck     type = 0xdeadbeef;
3110c2c66affSColin Finck     qualifier = 0xdeadbeef;
3111c2c66affSColin Finck     hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3112c2c66affSColin Finck     ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr);
3113c2c66affSColin Finck     hr = pCoGetApartmentType(&type, &qualifier);
3114c2c66affSColin Finck     ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr);
3115c2c66affSColin Finck     ok(type == APTTYPE_MAINSTA, "Expected APTTYPE_MAINSTA, got %u\n", type);
3116c2c66affSColin Finck     ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3117c2c66affSColin Finck     CoUninitialize();
3118c2c66affSColin Finck 
3119c2c66affSColin Finck     type = 0xdeadbeef;
3120c2c66affSColin Finck     qualifier = 0xdeadbeef;
3121c2c66affSColin Finck     hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
3122c2c66affSColin Finck     ok(hr == S_OK, "CoInitializeEx failed, error: 0x%08x\n", hr);
3123c2c66affSColin Finck     hr = pCoGetApartmentType(&type, &qualifier);
3124c2c66affSColin Finck     ok(hr == S_OK, "CoGetApartmentType failed, error: 0x%08x\n", hr);
3125c2c66affSColin Finck     ok(type == APTTYPE_MTA, "Expected APTTYPE_MTA, got %u\n", type);
3126c2c66affSColin Finck     ok(qualifier == APTTYPEQUALIFIER_NONE, "Expected APTTYPEQUALIFIER_NONE, got %u\n", qualifier);
3127c2c66affSColin Finck     CoUninitialize();
3128c2c66affSColin Finck }
3129c2c66affSColin Finck 
testspy_QI(IMallocSpy * iface,REFIID riid,void ** obj)3130c2c66affSColin Finck static HRESULT WINAPI testspy_QI(IMallocSpy *iface, REFIID riid, void **obj)
3131c2c66affSColin Finck {
3132c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IMallocSpy) || IsEqualIID(riid, &IID_IUnknown))
3133c2c66affSColin Finck     {
3134c2c66affSColin Finck         *obj = iface;
3135c2c66affSColin Finck         IMallocSpy_AddRef(iface);
3136c2c66affSColin Finck         return S_OK;
3137c2c66affSColin Finck     }
3138c2c66affSColin Finck 
3139c2c66affSColin Finck     return E_NOINTERFACE;
3140c2c66affSColin Finck }
3141c2c66affSColin Finck 
testspy_AddRef(IMallocSpy * iface)3142c2c66affSColin Finck static ULONG WINAPI testspy_AddRef(IMallocSpy *iface)
3143c2c66affSColin Finck {
3144c2c66affSColin Finck     return 2;
3145c2c66affSColin Finck }
3146c2c66affSColin Finck 
testspy_Release(IMallocSpy * iface)3147c2c66affSColin Finck static ULONG WINAPI testspy_Release(IMallocSpy *iface)
3148c2c66affSColin Finck {
3149c2c66affSColin Finck     return 1;
3150c2c66affSColin Finck }
3151c2c66affSColin Finck 
testspy_PreAlloc(IMallocSpy * iface,SIZE_T cb)3152c2c66affSColin Finck static SIZE_T WINAPI testspy_PreAlloc(IMallocSpy *iface, SIZE_T cb)
3153c2c66affSColin Finck {
3154c2c66affSColin Finck     ok(0, "unexpected call\n");
3155c2c66affSColin Finck     return 0;
3156c2c66affSColin Finck }
3157c2c66affSColin Finck 
testspy_PostAlloc(IMallocSpy * iface,void * ptr)3158c2c66affSColin Finck static void* WINAPI testspy_PostAlloc(IMallocSpy *iface, void *ptr)
3159c2c66affSColin Finck {
3160c2c66affSColin Finck     ok(0, "unexpected call\n");
3161c2c66affSColin Finck     return NULL;
3162c2c66affSColin Finck }
3163c2c66affSColin Finck 
testspy_PreFree(IMallocSpy * iface,void * ptr,BOOL spyed)3164c2c66affSColin Finck static void* WINAPI testspy_PreFree(IMallocSpy *iface, void *ptr, BOOL spyed)
3165c2c66affSColin Finck {
3166c2c66affSColin Finck     ok(0, "unexpected call\n");
3167c2c66affSColin Finck     return NULL;
3168c2c66affSColin Finck }
3169c2c66affSColin Finck 
testspy_PostFree(IMallocSpy * iface,BOOL spyed)3170c2c66affSColin Finck static void WINAPI testspy_PostFree(IMallocSpy *iface, BOOL spyed)
3171c2c66affSColin Finck {
3172c2c66affSColin Finck     ok(0, "unexpected call\n");
3173c2c66affSColin Finck }
3174c2c66affSColin Finck 
testspy_PreRealloc(IMallocSpy * iface,void * ptr,SIZE_T cb,void ** newptr,BOOL spyed)3175c2c66affSColin Finck static SIZE_T WINAPI testspy_PreRealloc(IMallocSpy *iface, void *ptr, SIZE_T cb, void **newptr, BOOL spyed)
3176c2c66affSColin Finck {
3177c2c66affSColin Finck     ok(0, "unexpected call\n");
3178c2c66affSColin Finck     return 0;
3179c2c66affSColin Finck }
3180c2c66affSColin Finck 
testspy_PostRealloc(IMallocSpy * iface,void * ptr,BOOL spyed)3181c2c66affSColin Finck static void* WINAPI testspy_PostRealloc(IMallocSpy *iface, void *ptr, BOOL spyed)
3182c2c66affSColin Finck {
3183c2c66affSColin Finck     ok(0, "unexpected call\n");
3184c2c66affSColin Finck     return NULL;
3185c2c66affSColin Finck }
3186c2c66affSColin Finck 
testspy_PreGetSize(IMallocSpy * iface,void * ptr,BOOL spyed)3187c2c66affSColin Finck static void* WINAPI testspy_PreGetSize(IMallocSpy *iface, void *ptr, BOOL spyed)
3188c2c66affSColin Finck {
3189c2c66affSColin Finck     ok(0, "unexpected call\n");
3190c2c66affSColin Finck     return NULL;
3191c2c66affSColin Finck }
3192c2c66affSColin Finck 
testspy_PostGetSize(IMallocSpy * iface,SIZE_T actual,BOOL spyed)3193c2c66affSColin Finck static SIZE_T WINAPI testspy_PostGetSize(IMallocSpy *iface, SIZE_T actual, BOOL spyed)
3194c2c66affSColin Finck {
3195c2c66affSColin Finck     ok(0, "unexpected call\n");
3196c2c66affSColin Finck     return 0;
3197c2c66affSColin Finck }
3198c2c66affSColin Finck 
testspy_PreDidAlloc(IMallocSpy * iface,void * ptr,BOOL spyed)3199c2c66affSColin Finck static void* WINAPI testspy_PreDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed)
3200c2c66affSColin Finck {
3201c2c66affSColin Finck     ok(0, "unexpected call\n");
3202c2c66affSColin Finck     return NULL;
3203c2c66affSColin Finck }
3204c2c66affSColin Finck 
testspy_PostDidAlloc(IMallocSpy * iface,void * ptr,BOOL spyed,int actual)3205c2c66affSColin Finck static int WINAPI testspy_PostDidAlloc(IMallocSpy *iface, void *ptr, BOOL spyed, int actual)
3206c2c66affSColin Finck {
3207c2c66affSColin Finck     ok(0, "unexpected call\n");
3208c2c66affSColin Finck     return 0;
3209c2c66affSColin Finck }
3210c2c66affSColin Finck 
testspy_PreHeapMinimize(IMallocSpy * iface)3211c2c66affSColin Finck static void WINAPI testspy_PreHeapMinimize(IMallocSpy *iface)
3212c2c66affSColin Finck {
3213c2c66affSColin Finck     ok(0, "unexpected call\n");
3214c2c66affSColin Finck }
3215c2c66affSColin Finck 
testspy_PostHeapMinimize(IMallocSpy * iface)3216c2c66affSColin Finck static void WINAPI testspy_PostHeapMinimize(IMallocSpy *iface)
3217c2c66affSColin Finck {
3218c2c66affSColin Finck     ok(0, "unexpected call\n");
3219c2c66affSColin Finck }
3220c2c66affSColin Finck 
3221c2c66affSColin Finck static const IMallocSpyVtbl testspyvtbl =
3222c2c66affSColin Finck {
3223c2c66affSColin Finck     testspy_QI,
3224c2c66affSColin Finck     testspy_AddRef,
3225c2c66affSColin Finck     testspy_Release,
3226c2c66affSColin Finck     testspy_PreAlloc,
3227c2c66affSColin Finck     testspy_PostAlloc,
3228c2c66affSColin Finck     testspy_PreFree,
3229c2c66affSColin Finck     testspy_PostFree,
3230c2c66affSColin Finck     testspy_PreRealloc,
3231c2c66affSColin Finck     testspy_PostRealloc,
3232c2c66affSColin Finck     testspy_PreGetSize,
3233c2c66affSColin Finck     testspy_PostGetSize,
3234c2c66affSColin Finck     testspy_PreDidAlloc,
3235c2c66affSColin Finck     testspy_PostDidAlloc,
3236c2c66affSColin Finck     testspy_PreHeapMinimize,
3237c2c66affSColin Finck     testspy_PostHeapMinimize
3238c2c66affSColin Finck };
3239c2c66affSColin Finck 
3240c2c66affSColin Finck static IMallocSpy testspy = { &testspyvtbl };
3241c2c66affSColin Finck 
test_IMallocSpy(void)3242c2c66affSColin Finck static void test_IMallocSpy(void)
3243c2c66affSColin Finck {
3244c2c66affSColin Finck     IMalloc *imalloc;
3245c2c66affSColin Finck     HRESULT hr;
3246c2c66affSColin Finck 
3247c2c66affSColin Finck     hr = CoRegisterMallocSpy(NULL);
3248c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3249c2c66affSColin Finck 
3250c2c66affSColin Finck     hr = CoRevokeMallocSpy();
3251c2c66affSColin Finck     ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr);
3252c2c66affSColin Finck 
3253c2c66affSColin Finck     hr = CoRegisterMallocSpy(&testspy);
3254c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3255c2c66affSColin Finck 
3256c2c66affSColin Finck     hr = CoRegisterMallocSpy(NULL);
3257c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3258c2c66affSColin Finck 
3259c2c66affSColin Finck     hr = CoRegisterMallocSpy(&testspy);
3260c2c66affSColin Finck     ok(hr == CO_E_OBJISREG, "got 0x%08x\n", hr);
3261c2c66affSColin Finck 
3262c2c66affSColin Finck     imalloc = NULL;
3263c2c66affSColin Finck     hr = CoGetMalloc(MEMCTX_TASK, &imalloc);
3264c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3265c2c66affSColin Finck     ok(imalloc != NULL, "got %p\n", imalloc);
3266c2c66affSColin Finck 
3267c2c66affSColin Finck     IMalloc_Free(imalloc, NULL);
3268c2c66affSColin Finck 
3269c2c66affSColin Finck     IMalloc_Release(imalloc);
3270c2c66affSColin Finck 
3271c2c66affSColin Finck     hr = CoRevokeMallocSpy();
3272c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3273c2c66affSColin Finck 
3274c2c66affSColin Finck     hr = CoRevokeMallocSpy();
3275c2c66affSColin Finck     ok(hr == CO_E_OBJNOTREG, "got 0x%08x\n", hr);
3276c2c66affSColin Finck }
3277c2c66affSColin Finck 
test_CoGetCurrentLogicalThreadId(void)3278c2c66affSColin Finck static void test_CoGetCurrentLogicalThreadId(void)
3279c2c66affSColin Finck {
3280c2c66affSColin Finck     HRESULT hr;
3281c2c66affSColin Finck     GUID id;
3282c2c66affSColin Finck 
3283c2c66affSColin Finck     hr = CoGetCurrentLogicalThreadId(NULL);
3284c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3285c2c66affSColin Finck 
3286c2c66affSColin Finck     id = GUID_NULL;
3287c2c66affSColin Finck     hr = CoGetCurrentLogicalThreadId(&id);
3288c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3289c2c66affSColin Finck     ok(!IsEqualGUID(&id, &GUID_NULL), "got null id\n");
3290c2c66affSColin Finck }
3291c2c66affSColin Finck 
testinitialize_QI(IInitializeSpy * iface,REFIID riid,void ** obj)3292c2c66affSColin Finck static HRESULT WINAPI testinitialize_QI(IInitializeSpy *iface, REFIID riid, void **obj)
3293c2c66affSColin Finck {
3294c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IInitializeSpy) || IsEqualIID(riid, &IID_IUnknown))
3295c2c66affSColin Finck     {
3296c2c66affSColin Finck         *obj = iface;
3297c2c66affSColin Finck         IInitializeSpy_AddRef(iface);
3298c2c66affSColin Finck         return S_OK;
3299c2c66affSColin Finck     }
3300c2c66affSColin Finck 
3301c2c66affSColin Finck     *obj = NULL;
3302c2c66affSColin Finck     return E_NOINTERFACE;
3303c2c66affSColin Finck }
3304c2c66affSColin Finck 
testinitialize_AddRef(IInitializeSpy * iface)3305c2c66affSColin Finck static ULONG WINAPI testinitialize_AddRef(IInitializeSpy *iface)
3306c2c66affSColin Finck {
3307c2c66affSColin Finck     return 2;
3308c2c66affSColin Finck }
3309c2c66affSColin Finck 
testinitialize_Release(IInitializeSpy * iface)3310c2c66affSColin Finck static ULONG WINAPI testinitialize_Release(IInitializeSpy *iface)
3311c2c66affSColin Finck {
3312c2c66affSColin Finck     return 1;
3313c2c66affSColin Finck }
3314c2c66affSColin Finck 
3315fc6e4ed5SAmine Khaldi static DWORD expected_coinit_flags;
3316fc6e4ed5SAmine Khaldi static ULARGE_INTEGER init_cookies[3];
3317fc6e4ed5SAmine Khaldi static BOOL revoke_spies_on_uninit;
3318fc6e4ed5SAmine Khaldi 
testinitialize_PreInitialize(IInitializeSpy * iface,DWORD coinit,DWORD aptrefs)3319c2c66affSColin Finck static HRESULT WINAPI testinitialize_PreInitialize(IInitializeSpy *iface, DWORD coinit, DWORD aptrefs)
3320c2c66affSColin Finck {
3321fc6e4ed5SAmine Khaldi     CHECK_EXPECT2(PreInitialize);
3322fc6e4ed5SAmine Khaldi     ok(coinit == expected_coinit_flags, "Unexpected init flags %#x, expected %#x.\n", coinit, expected_coinit_flags);
3323fc6e4ed5SAmine Khaldi     return S_OK;
3324c2c66affSColin Finck }
3325c2c66affSColin Finck 
testinitialize_PostInitialize(IInitializeSpy * iface,HRESULT hr,DWORD coinit,DWORD aptrefs)3326c2c66affSColin Finck static HRESULT WINAPI testinitialize_PostInitialize(IInitializeSpy *iface, HRESULT hr, DWORD coinit, DWORD aptrefs)
3327c2c66affSColin Finck {
3328fc6e4ed5SAmine Khaldi     CHECK_EXPECT2(PostInitialize);
3329fc6e4ed5SAmine Khaldi     ok(coinit == expected_coinit_flags, "Unexpected init flags %#x, expected %#x.\n", coinit, expected_coinit_flags);
3330fc6e4ed5SAmine Khaldi     return hr;
3331c2c66affSColin Finck }
3332c2c66affSColin Finck 
testinitialize_PreUninitialize(IInitializeSpy * iface,DWORD aptrefs)3333c2c66affSColin Finck static HRESULT WINAPI testinitialize_PreUninitialize(IInitializeSpy *iface, DWORD aptrefs)
3334c2c66affSColin Finck {
3335fc6e4ed5SAmine Khaldi     HRESULT hr;
3336fc6e4ed5SAmine Khaldi     CHECK_EXPECT2(PreUninitialize);
3337fc6e4ed5SAmine Khaldi     if (revoke_spies_on_uninit)
3338fc6e4ed5SAmine Khaldi     {
3339fc6e4ed5SAmine Khaldi         hr = CoRevokeInitializeSpy(init_cookies[0]);
3340fc6e4ed5SAmine Khaldi         ok(hr == S_OK, "got 0x%08x\n", hr);
3341fc6e4ed5SAmine Khaldi 
3342fc6e4ed5SAmine Khaldi         hr = CoRevokeInitializeSpy(init_cookies[1]);
3343fc6e4ed5SAmine Khaldi         ok(hr == S_OK, "got 0x%08x\n", hr);
3344fc6e4ed5SAmine Khaldi 
3345fc6e4ed5SAmine Khaldi         hr = CoRevokeInitializeSpy(init_cookies[2]);
3346fc6e4ed5SAmine Khaldi         ok(hr == S_OK, "got 0x%08x\n", hr);
3347fc6e4ed5SAmine Khaldi 
3348fc6e4ed5SAmine Khaldi         revoke_spies_on_uninit = FALSE;
3349fc6e4ed5SAmine Khaldi     }
3350fc6e4ed5SAmine Khaldi     return S_OK;
3351c2c66affSColin Finck }
3352c2c66affSColin Finck 
testinitialize_PostUninitialize(IInitializeSpy * iface,DWORD aptrefs)3353c2c66affSColin Finck static HRESULT WINAPI testinitialize_PostUninitialize(IInitializeSpy *iface, DWORD aptrefs)
3354c2c66affSColin Finck {
3355fc6e4ed5SAmine Khaldi     CHECK_EXPECT2(PostUninitialize);
3356c2c66affSColin Finck     return E_NOTIMPL;
3357c2c66affSColin Finck }
3358c2c66affSColin Finck 
3359c2c66affSColin Finck static const IInitializeSpyVtbl testinitializevtbl =
3360c2c66affSColin Finck {
3361c2c66affSColin Finck     testinitialize_QI,
3362c2c66affSColin Finck     testinitialize_AddRef,
3363c2c66affSColin Finck     testinitialize_Release,
3364c2c66affSColin Finck     testinitialize_PreInitialize,
3365c2c66affSColin Finck     testinitialize_PostInitialize,
3366c2c66affSColin Finck     testinitialize_PreUninitialize,
3367c2c66affSColin Finck     testinitialize_PostUninitialize
3368c2c66affSColin Finck };
3369c2c66affSColin Finck 
3370c2c66affSColin Finck static IInitializeSpy testinitialize = { &testinitializevtbl };
3371c2c66affSColin Finck 
test_init_spies_proc(void * arg)3372fc6e4ed5SAmine Khaldi static DWORD WINAPI test_init_spies_proc(void *arg)
3373c2c66affSColin Finck {
3374c2c66affSColin Finck     HRESULT hr;
3375c2c66affSColin Finck 
3376fc6e4ed5SAmine Khaldi     hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
3377fc6e4ed5SAmine Khaldi     ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr);
3378fc6e4ed5SAmine Khaldi 
3379fc6e4ed5SAmine Khaldi     hr = CoRevokeInitializeSpy(init_cookies[2]);
3380fc6e4ed5SAmine Khaldi     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3381fc6e4ed5SAmine Khaldi 
3382fc6e4ed5SAmine Khaldi     CoUninitialize();
3383fc6e4ed5SAmine Khaldi     return 0;
3384fc6e4ed5SAmine Khaldi }
3385fc6e4ed5SAmine Khaldi 
test_IInitializeSpy(BOOL mt)3386fc6e4ed5SAmine Khaldi static void test_IInitializeSpy(BOOL mt)
3387fc6e4ed5SAmine Khaldi {
3388fc6e4ed5SAmine Khaldi     HRESULT hr;
3389fc6e4ed5SAmine Khaldi 
3390fc6e4ed5SAmine Khaldi     if (mt)
3391fc6e4ed5SAmine Khaldi     {
3392fc6e4ed5SAmine Khaldi         hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
3393fc6e4ed5SAmine Khaldi         ok(hr == S_OK, "CoInitializeEx failed: %#x\n", hr);
3394fc6e4ed5SAmine Khaldi     }
3395fc6e4ed5SAmine Khaldi 
3396c2c66affSColin Finck     hr = CoRegisterInitializeSpy(NULL, NULL);
3397c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3398c2c66affSColin Finck 
3399fc6e4ed5SAmine Khaldi     init_cookies[0].QuadPart = 1;
3400fc6e4ed5SAmine Khaldi     hr = CoRegisterInitializeSpy(NULL, &init_cookies[0]);
3401c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3402fc6e4ed5SAmine Khaldi     ok(init_cookies[0].QuadPart == 1, "got wrong cookie\n");
3403c2c66affSColin Finck 
3404c2c66affSColin Finck     hr = CoRegisterInitializeSpy(&testinitialize, NULL);
3405c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3406c2c66affSColin Finck 
3407fc6e4ed5SAmine Khaldi     init_cookies[0].HighPart = 0;
3408fc6e4ed5SAmine Khaldi     init_cookies[0].LowPart = 1;
3409fc6e4ed5SAmine Khaldi     hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[0]);
3410c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3411fc6e4ed5SAmine Khaldi     ok(init_cookies[0].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[0].HighPart,
3412c2c66affSColin Finck         GetCurrentThreadId());
3413fc6e4ed5SAmine Khaldi     if (!mt) ok(init_cookies[0].LowPart == 0, "got wrong low part 0x%x\n", init_cookies[0].LowPart);
3414fc6e4ed5SAmine Khaldi 
3415c2c66affSColin Finck     /* register same instance one more time */
3416fc6e4ed5SAmine Khaldi     init_cookies[1].HighPart = 0;
3417fc6e4ed5SAmine Khaldi     init_cookies[1].LowPart = 0;
3418fc6e4ed5SAmine Khaldi     hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[1]);
3419c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3420fc6e4ed5SAmine Khaldi     ok(init_cookies[1].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[1].HighPart,
3421c2c66affSColin Finck         GetCurrentThreadId());
3422fc6e4ed5SAmine Khaldi     if (!mt) ok(init_cookies[1].LowPart == 1, "got wrong low part 0x%x\n", init_cookies[1].LowPart);
3423fc6e4ed5SAmine Khaldi 
3424fc6e4ed5SAmine Khaldi     init_cookies[2].HighPart = 0;
3425fc6e4ed5SAmine Khaldi     init_cookies[2].LowPart = 0;
3426fc6e4ed5SAmine Khaldi     hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[2]);
3427c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3428fc6e4ed5SAmine Khaldi     ok(init_cookies[2].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[2].HighPart,
3429c2c66affSColin Finck         GetCurrentThreadId());
3430fc6e4ed5SAmine Khaldi     if (!mt) ok(init_cookies[2].LowPart == 2, "got wrong low part 0x%x\n", init_cookies[2].LowPart);
3431fc6e4ed5SAmine Khaldi 
3432fc6e4ed5SAmine Khaldi     hr = CoRevokeInitializeSpy(init_cookies[1]);
3433c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3434c2c66affSColin Finck 
3435fc6e4ed5SAmine Khaldi     hr = CoRevokeInitializeSpy(init_cookies[1]);
3436c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3437c2c66affSColin Finck 
3438fc6e4ed5SAmine Khaldi     init_cookies[1].HighPart = 0;
3439fc6e4ed5SAmine Khaldi     init_cookies[1].LowPart = 0;
3440fc6e4ed5SAmine Khaldi     hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[1]);
3441c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3442fc6e4ed5SAmine Khaldi     ok(init_cookies[1].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[1].HighPart,
3443c2c66affSColin Finck         GetCurrentThreadId());
3444fc6e4ed5SAmine Khaldi     if (!mt) ok(init_cookies[1].LowPart == 1, "got wrong low part 0x%x\n", init_cookies[1].LowPart);
3445fc6e4ed5SAmine Khaldi 
3446fc6e4ed5SAmine Khaldi     SET_EXPECT(PreInitialize);
3447fc6e4ed5SAmine Khaldi     SET_EXPECT(PostInitialize);
3448fc6e4ed5SAmine Khaldi     hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE));
3449fc6e4ed5SAmine Khaldi     ok(hr == (mt ? S_FALSE : S_OK), "Failed to initialize COM, hr %#x.\n", hr);
3450fc6e4ed5SAmine Khaldi     CHECK_CALLED(PreInitialize, 3);
3451fc6e4ed5SAmine Khaldi     CHECK_CALLED(PostInitialize, 3);
3452fc6e4ed5SAmine Khaldi 
3453fc6e4ed5SAmine Khaldi     if (mt)
3454fc6e4ed5SAmine Khaldi     {
3455fc6e4ed5SAmine Khaldi         HANDLE thread;
3456fc6e4ed5SAmine Khaldi         thread = CreateThread(NULL, 0, test_init_spies_proc, NULL, 0, NULL);
3457fc6e4ed5SAmine Khaldi         ok(thread != NULL, "CreateThread failed: %u\n", GetLastError());
3458fc6e4ed5SAmine Khaldi         ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
3459c2c66affSColin Finck     }
3460c2c66affSColin Finck 
3461fc6e4ed5SAmine Khaldi     SET_EXPECT(PreInitialize);
3462fc6e4ed5SAmine Khaldi     SET_EXPECT(PostInitialize);
3463fc6e4ed5SAmine Khaldi     hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE));
3464fc6e4ed5SAmine Khaldi     ok(hr == S_FALSE, "Failed to initialize COM, hr %#x.\n", hr);
3465fc6e4ed5SAmine Khaldi     CHECK_CALLED(PreInitialize, 3);
3466fc6e4ed5SAmine Khaldi     CHECK_CALLED(PostInitialize, 3);
3467c2c66affSColin Finck 
3468fc6e4ed5SAmine Khaldi     SET_EXPECT(PreUninitialize);
3469fc6e4ed5SAmine Khaldi     SET_EXPECT(PostUninitialize);
3470fc6e4ed5SAmine Khaldi     CoUninitialize();
3471fc6e4ed5SAmine Khaldi     CHECK_CALLED(PreUninitialize, 3);
3472fc6e4ed5SAmine Khaldi     CHECK_CALLED(PostUninitialize, 3);
3473fc6e4ed5SAmine Khaldi 
3474fc6e4ed5SAmine Khaldi     SET_EXPECT(PreUninitialize);
3475fc6e4ed5SAmine Khaldi     SET_EXPECT(PostUninitialize);
3476fc6e4ed5SAmine Khaldi     CoUninitialize();
3477fc6e4ed5SAmine Khaldi     CHECK_CALLED(PreUninitialize, 3);
3478fc6e4ed5SAmine Khaldi     CHECK_CALLED(PostUninitialize, 3);
3479fc6e4ed5SAmine Khaldi 
3480fc6e4ed5SAmine Khaldi     if (mt)
3481fc6e4ed5SAmine Khaldi     {
3482fc6e4ed5SAmine Khaldi         SET_EXPECT(PreUninitialize);
3483fc6e4ed5SAmine Khaldi         SET_EXPECT(PostUninitialize);
3484fc6e4ed5SAmine Khaldi         CoUninitialize();
3485fc6e4ed5SAmine Khaldi         CHECK_CALLED(PreUninitialize, 3);
3486fc6e4ed5SAmine Khaldi         CHECK_CALLED(PostUninitialize, 3);
3487fc6e4ed5SAmine Khaldi     }
3488fc6e4ed5SAmine Khaldi 
3489fc6e4ed5SAmine Khaldi     SET_EXPECT(PreInitialize);
3490fc6e4ed5SAmine Khaldi     SET_EXPECT(PostInitialize);
3491fc6e4ed5SAmine Khaldi     hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE));
3492fc6e4ed5SAmine Khaldi     ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr);
3493fc6e4ed5SAmine Khaldi     CHECK_CALLED(PreInitialize, 3);
3494fc6e4ed5SAmine Khaldi     CHECK_CALLED(PostInitialize, 3);
3495fc6e4ed5SAmine Khaldi 
3496fc6e4ed5SAmine Khaldi     SET_EXPECT(PreUninitialize);
3497fc6e4ed5SAmine Khaldi     revoke_spies_on_uninit = TRUE;
3498fc6e4ed5SAmine Khaldi     CoUninitialize();
3499fc6e4ed5SAmine Khaldi     CHECK_CALLED(PreUninitialize, 1);
3500c2c66affSColin Finck }
3501c2c66affSColin Finck 
3502c2c66affSColin Finck static HRESULT g_persistfile_qi_ret;
3503c2c66affSColin Finck static HRESULT g_persistfile_load_ret;
testinstance_QI(IPersistFile * iface,REFIID riid,void ** obj)3504c2c66affSColin Finck static HRESULT WINAPI testinstance_QI(IPersistFile *iface, REFIID riid, void **obj)
3505c2c66affSColin Finck {
3506c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IUnknown)) {
3507c2c66affSColin Finck         *obj = iface;
3508c2c66affSColin Finck         IUnknown_AddRef(iface);
3509c2c66affSColin Finck         return S_OK;
3510c2c66affSColin Finck     }
3511c2c66affSColin Finck 
3512c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IPersistFile)) {
3513c2c66affSColin Finck         if (SUCCEEDED(g_persistfile_qi_ret)) {
3514c2c66affSColin Finck             *obj = iface;
3515c2c66affSColin Finck             IUnknown_AddRef(iface);
3516c2c66affSColin Finck         }
3517c2c66affSColin Finck         else
3518c2c66affSColin Finck             *obj = NULL;
3519c2c66affSColin Finck         return g_persistfile_qi_ret;
3520c2c66affSColin Finck     }
3521c2c66affSColin Finck 
3522c2c66affSColin Finck     ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
3523c2c66affSColin Finck     *obj = NULL;
3524c2c66affSColin Finck     return E_NOINTERFACE;
3525c2c66affSColin Finck }
3526c2c66affSColin Finck 
testinstance_AddRef(IPersistFile * iface)3527c2c66affSColin Finck static ULONG WINAPI testinstance_AddRef(IPersistFile *iface)
3528c2c66affSColin Finck {
3529c2c66affSColin Finck     return 2;
3530c2c66affSColin Finck }
3531c2c66affSColin Finck 
testinstance_Release(IPersistFile * iface)3532c2c66affSColin Finck static ULONG WINAPI testinstance_Release(IPersistFile *iface)
3533c2c66affSColin Finck {
3534c2c66affSColin Finck     return 1;
3535c2c66affSColin Finck }
3536c2c66affSColin Finck 
testinstance_GetClassID(IPersistFile * iface,CLSID * clsid)3537c2c66affSColin Finck static HRESULT WINAPI testinstance_GetClassID(IPersistFile *iface, CLSID *clsid)
3538c2c66affSColin Finck {
3539c2c66affSColin Finck     ok(0, "unexpected call\n");
3540c2c66affSColin Finck     return E_NOTIMPL;
3541c2c66affSColin Finck }
3542c2c66affSColin Finck 
testinstance_IsDirty(IPersistFile * iface)3543c2c66affSColin Finck static HRESULT WINAPI testinstance_IsDirty(IPersistFile *iface)
3544c2c66affSColin Finck {
3545c2c66affSColin Finck     ok(0, "unexpected call\n");
3546c2c66affSColin Finck     return E_NOTIMPL;
3547c2c66affSColin Finck }
3548c2c66affSColin Finck 
testinstance_Load(IPersistFile * iface,LPCOLESTR filename,DWORD mode)3549c2c66affSColin Finck static HRESULT WINAPI testinstance_Load(IPersistFile *iface, LPCOLESTR filename, DWORD mode)
3550c2c66affSColin Finck {
3551c2c66affSColin Finck     return g_persistfile_load_ret;
3552c2c66affSColin Finck }
3553c2c66affSColin Finck 
testinstance_Save(IPersistFile * iface,LPCOLESTR filename,BOOL remember)3554c2c66affSColin Finck static HRESULT WINAPI testinstance_Save(IPersistFile *iface, LPCOLESTR filename, BOOL remember)
3555c2c66affSColin Finck {
3556c2c66affSColin Finck     return E_NOTIMPL;
3557c2c66affSColin Finck }
3558c2c66affSColin Finck 
testinstance_SaveCompleted(IPersistFile * iface,LPCOLESTR filename)3559c2c66affSColin Finck static HRESULT WINAPI testinstance_SaveCompleted(IPersistFile *iface, LPCOLESTR filename)
3560c2c66affSColin Finck {
3561c2c66affSColin Finck     ok(0, "unexpected call\n");
3562c2c66affSColin Finck     return E_NOTIMPL;
3563c2c66affSColin Finck }
3564c2c66affSColin Finck 
testinstance_GetCurFile(IPersistFile * iface,LPOLESTR * filename)3565c2c66affSColin Finck static HRESULT WINAPI testinstance_GetCurFile(IPersistFile *iface, LPOLESTR *filename)
3566c2c66affSColin Finck {
3567c2c66affSColin Finck     ok(0, "unexpected call\n");
3568c2c66affSColin Finck     return E_NOTIMPL;
3569c2c66affSColin Finck }
3570c2c66affSColin Finck 
3571c2c66affSColin Finck static const IPersistFileVtbl testpersistfilevtbl = {
3572c2c66affSColin Finck     testinstance_QI,
3573c2c66affSColin Finck     testinstance_AddRef,
3574c2c66affSColin Finck     testinstance_Release,
3575c2c66affSColin Finck     testinstance_GetClassID,
3576c2c66affSColin Finck     testinstance_IsDirty,
3577c2c66affSColin Finck     testinstance_Load,
3578c2c66affSColin Finck     testinstance_Save,
3579c2c66affSColin Finck     testinstance_SaveCompleted,
3580c2c66affSColin Finck     testinstance_GetCurFile
3581c2c66affSColin Finck };
3582c2c66affSColin Finck 
3583c2c66affSColin Finck static IPersistFile testpersistfile = { &testpersistfilevtbl };
3584c2c66affSColin Finck 
getinstance_cf_QI(IClassFactory * iface,REFIID riid,void ** obj)3585c2c66affSColin Finck static HRESULT WINAPI getinstance_cf_QI(IClassFactory *iface, REFIID riid, void **obj)
3586c2c66affSColin Finck {
3587c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) {
3588c2c66affSColin Finck         *obj = iface;
3589c2c66affSColin Finck         IClassFactory_AddRef(iface);
3590c2c66affSColin Finck         return S_OK;
3591c2c66affSColin Finck     }
3592c2c66affSColin Finck 
3593c2c66affSColin Finck     *obj = NULL;
3594c2c66affSColin Finck     return E_NOINTERFACE;
3595c2c66affSColin Finck }
3596c2c66affSColin Finck 
getinstance_cf_AddRef(IClassFactory * iface)3597c2c66affSColin Finck static ULONG WINAPI getinstance_cf_AddRef(IClassFactory *iface)
3598c2c66affSColin Finck {
3599c2c66affSColin Finck     return 2;
3600c2c66affSColin Finck }
3601c2c66affSColin Finck 
getinstance_cf_Release(IClassFactory * iface)3602c2c66affSColin Finck static ULONG WINAPI getinstance_cf_Release(IClassFactory *iface)
3603c2c66affSColin Finck {
3604c2c66affSColin Finck     return 1;
3605c2c66affSColin Finck }
3606c2c66affSColin Finck 
getinstance_cf_CreateInstance(IClassFactory * iface,IUnknown * outer,REFIID riid,void ** obj)3607c2c66affSColin Finck static HRESULT WINAPI getinstance_cf_CreateInstance(IClassFactory *iface, IUnknown *outer,
3608c2c66affSColin Finck     REFIID riid, void **obj)
3609c2c66affSColin Finck {
3610c2c66affSColin Finck     if (IsEqualIID(riid, &IID_IUnknown)) {
3611c2c66affSColin Finck         *obj = &testpersistfile;
3612c2c66affSColin Finck         return S_OK;
3613c2c66affSColin Finck     }
3614c2c66affSColin Finck 
3615c2c66affSColin Finck     ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid));
3616c2c66affSColin Finck     *obj = NULL;
3617c2c66affSColin Finck     return E_NOTIMPL;
3618c2c66affSColin Finck }
3619c2c66affSColin Finck 
getinstance_cf_LockServer(IClassFactory * iface,BOOL lock)3620c2c66affSColin Finck static HRESULT WINAPI getinstance_cf_LockServer(IClassFactory *iface, BOOL lock)
3621c2c66affSColin Finck {
3622c2c66affSColin Finck     ok(0, "unexpected call\n");
3623c2c66affSColin Finck     return E_NOTIMPL;
3624c2c66affSColin Finck }
3625c2c66affSColin Finck 
3626c2c66affSColin Finck static const IClassFactoryVtbl getinstance_cf_vtbl = {
3627c2c66affSColin Finck     getinstance_cf_QI,
3628c2c66affSColin Finck     getinstance_cf_AddRef,
3629c2c66affSColin Finck     getinstance_cf_Release,
3630c2c66affSColin Finck     getinstance_cf_CreateInstance,
3631c2c66affSColin Finck     getinstance_cf_LockServer
3632c2c66affSColin Finck };
3633c2c66affSColin Finck 
3634c2c66affSColin Finck static IClassFactory getinstance_cf = { &getinstance_cf_vtbl  };
3635c2c66affSColin Finck 
test_CoGetInstanceFromFile(void)3636c2c66affSColin Finck static void test_CoGetInstanceFromFile(void)
3637c2c66affSColin Finck {
3638c2c66affSColin Finck     static const WCHAR filenameW[] = {'d','u','m','m','y','p','a','t','h',0};
3639c2c66affSColin Finck     CLSID *clsid = (CLSID*)&CLSID_testclsid;
3640c2c66affSColin Finck     MULTI_QI mqi[2];
3641c2c66affSColin Finck     DWORD cookie;
3642c2c66affSColin Finck     HRESULT hr;
3643c2c66affSColin Finck 
3644c2c66affSColin Finck     hr = pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3645c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3646c2c66affSColin Finck 
3647c2c66affSColin Finck     /* CLSID is not specified, file does not exist */
3648c2c66affSColin Finck     mqi[0].pIID = &IID_IUnknown;
3649c2c66affSColin Finck     mqi[0].pItf = NULL;
3650c2c66affSColin Finck     mqi[0].hr = E_NOTIMPL;
3651c2c66affSColin Finck     hr = CoGetInstanceFromFile(NULL, NULL, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3652c2c66affSColin Finck todo_wine
3653c2c66affSColin Finck     ok(hr == MK_E_CANTOPENFILE, "got 0x%08x\n", hr);
3654c2c66affSColin Finck     ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3655c2c66affSColin Finck     ok(mqi[0].hr == E_NOINTERFACE, "got 0x%08x\n", mqi[0].hr);
3656c2c66affSColin Finck 
3657c2c66affSColin Finck     /* class is not available */
3658c2c66affSColin Finck     mqi[0].pIID = &IID_IUnknown;
3659c2c66affSColin Finck     mqi[0].pItf = NULL;
3660c2c66affSColin Finck     mqi[0].hr = E_NOTIMPL;
3661c2c66affSColin Finck     hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3662c2c66affSColin Finck     ok(hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", hr);
3663c2c66affSColin Finck     ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3664c2c66affSColin Finck     ok(mqi[0].hr == REGDB_E_CLASSNOTREG, "got 0x%08x\n", mqi[0].hr);
3665c2c66affSColin Finck 
3666c2c66affSColin Finck     hr = CoRegisterClassObject(clsid, (IUnknown*)&getinstance_cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE,
3667c2c66affSColin Finck         &cookie);
3668c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3669c2c66affSColin Finck 
3670c2c66affSColin Finck     mqi[0].pIID = &IID_IUnknown;
3671c2c66affSColin Finck     mqi[0].pItf = (void*)0xdeadbeef;
3672c2c66affSColin Finck     mqi[0].hr = S_OK;
3673c2c66affSColin Finck     hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3674c2c66affSColin Finck todo_wine {
3675c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3676c2c66affSColin Finck     ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf);
3677c2c66affSColin Finck }
3678c2c66affSColin Finck     ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3679c2c66affSColin Finck 
3680c2c66affSColin Finck     mqi[0].pIID = &IID_IUnknown;
3681c2c66affSColin Finck     mqi[0].pItf = (void*)0xdeadbeef;
3682c2c66affSColin Finck     mqi[0].hr = E_NOTIMPL;
3683c2c66affSColin Finck     hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3684c2c66affSColin Finck todo_wine {
3685c2c66affSColin Finck     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3686c2c66affSColin Finck     ok(mqi[0].pItf == (void*)0xdeadbeef, "got %p\n", mqi[0].pItf);
3687c2c66affSColin Finck     ok(mqi[0].hr == E_NOTIMPL, "got 0x%08x\n", mqi[0].hr);
3688c2c66affSColin Finck }
3689c2c66affSColin Finck     mqi[0].pIID = &IID_IUnknown;
3690c2c66affSColin Finck     mqi[0].pItf = NULL;
3691c2c66affSColin Finck     mqi[0].hr = E_NOTIMPL;
3692c2c66affSColin Finck     hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3693c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3694c2c66affSColin Finck     ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3695c2c66affSColin Finck     ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3696c2c66affSColin Finck 
3697c2c66affSColin Finck     mqi[0].pIID = &IID_IUnknown;
3698c2c66affSColin Finck     mqi[0].pItf = NULL;
3699c2c66affSColin Finck     mqi[0].hr = S_OK;
3700c2c66affSColin Finck     hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3701c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3702c2c66affSColin Finck     ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3703c2c66affSColin Finck     ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3704c2c66affSColin Finck 
3705c2c66affSColin Finck     mqi[0].pIID = &IID_IUnknown;
3706c2c66affSColin Finck     mqi[0].pItf = NULL;
3707c2c66affSColin Finck     mqi[0].hr = S_OK;
3708c2c66affSColin Finck     g_persistfile_qi_ret = S_FALSE;
3709c2c66affSColin Finck     hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 1, mqi);
3710c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3711c2c66affSColin Finck     ok(mqi[0].pItf != NULL, "got %p\n", mqi[0].pItf);
3712c2c66affSColin Finck     ok(mqi[0].hr == S_OK, "got 0x%08x\n", mqi[0].hr);
3713c2c66affSColin Finck     g_persistfile_qi_ret = S_OK;
3714c2c66affSColin Finck 
3715c2c66affSColin Finck     mqi[0].pIID = &IID_IUnknown;
3716c2c66affSColin Finck     mqi[0].pItf = NULL;
3717c2c66affSColin Finck     mqi[0].hr = S_OK;
3718c2c66affSColin Finck     mqi[1].pIID = &IID_IUnknown;
3719c2c66affSColin Finck     mqi[1].pItf = NULL;
3720c2c66affSColin Finck     mqi[1].hr = S_OK;
3721c2c66affSColin Finck     g_persistfile_qi_ret = 0x8000efef;
3722c2c66affSColin Finck     hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi);
3723c2c66affSColin Finck     ok(hr == 0x8000efef, "got 0x%08x\n", hr);
3724c2c66affSColin Finck     ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3725c2c66affSColin Finck     ok(mqi[0].hr == 0x8000efef, "got 0x%08x\n", mqi[0].hr);
3726c2c66affSColin Finck     ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf);
3727c2c66affSColin Finck     ok(mqi[1].hr == 0x8000efef, "got 0x%08x\n", mqi[1].hr);
3728c2c66affSColin Finck     g_persistfile_qi_ret = S_OK;
3729c2c66affSColin Finck 
3730c2c66affSColin Finck     mqi[0].pIID = &IID_IUnknown;
3731c2c66affSColin Finck     mqi[0].pItf = NULL;
3732c2c66affSColin Finck     mqi[0].hr = S_OK;
3733c2c66affSColin Finck     mqi[1].pIID = &IID_IUnknown;
3734c2c66affSColin Finck     mqi[1].pItf = NULL;
3735c2c66affSColin Finck     mqi[1].hr = S_OK;
3736c2c66affSColin Finck     g_persistfile_load_ret = 0x8000fefe;
3737c2c66affSColin Finck     hr = CoGetInstanceFromFile(NULL, clsid, NULL, CLSCTX_INPROC_SERVER, STGM_READ, (OLECHAR*)filenameW, 2, mqi);
3738c2c66affSColin Finck     ok(hr == 0x8000fefe, "got 0x%08x\n", hr);
3739c2c66affSColin Finck     ok(mqi[0].pItf == NULL, "got %p\n", mqi[0].pItf);
3740c2c66affSColin Finck     ok(mqi[0].hr == 0x8000fefe, "got 0x%08x\n", mqi[0].hr);
3741c2c66affSColin Finck     ok(mqi[1].pItf == NULL, "got %p\n", mqi[1].pItf);
3742c2c66affSColin Finck     ok(mqi[1].hr == 0x8000fefe, "got 0x%08x\n", mqi[1].hr);
3743c2c66affSColin Finck     g_persistfile_load_ret = S_OK;
3744c2c66affSColin Finck 
3745c2c66affSColin Finck     hr = CoRevokeClassObject(cookie);
3746c2c66affSColin Finck     ok(hr == S_OK, "got 0x%08x\n", hr);
3747c2c66affSColin Finck 
3748c2c66affSColin Finck     CoUninitialize();
3749c2c66affSColin Finck }
3750c2c66affSColin Finck 
test_GlobalOptions(void)3751c2c66affSColin Finck static void test_GlobalOptions(void)
3752c2c66affSColin Finck {
3753c2c66affSColin Finck     IGlobalOptions *global_options;
3754c2c66affSColin Finck     HRESULT hres;
3755c2c66affSColin Finck 
3756c2c66affSColin Finck     CoInitialize(NULL);
3757c2c66affSColin Finck 
3758c2c66affSColin Finck     hres = CoCreateInstance(&CLSID_GlobalOptions, NULL, CLSCTX_INPROC_SERVER,
3759c2c66affSColin Finck             &IID_IGlobalOptions, (void**)&global_options);
3760c2c66affSColin Finck     ok(hres == S_OK || broken(hres == E_NOINTERFACE), "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres);
3761c2c66affSColin Finck     if(FAILED(hres))
3762c2c66affSColin Finck     {
3763c2c66affSColin Finck         win_skip("CLSID_GlobalOptions not available\n");
3764c2c66affSColin Finck         CoUninitialize();
3765c2c66affSColin Finck         return;
3766c2c66affSColin Finck     }
3767c2c66affSColin Finck 
3768c2c66affSColin Finck     IGlobalOptions_Release(global_options);
3769c2c66affSColin Finck 
3770c2c66affSColin Finck     hres = CoCreateInstance(&CLSID_GlobalOptions, (IUnknown*)0xdeadbeef, CLSCTX_INPROC_SERVER,
3771c2c66affSColin Finck             &IID_IGlobalOptions, (void**)&global_options);
3772c2c66affSColin Finck     ok(hres == E_INVALIDARG, "CoCreateInstance(CLSID_GlobalOptions) failed: %08x\n", hres);
3773c2c66affSColin Finck 
3774c2c66affSColin Finck     CoUninitialize();
3775c2c66affSColin Finck }
3776c2c66affSColin Finck 
init_funcs(void)3777c2c66affSColin Finck static void init_funcs(void)
3778c2c66affSColin Finck {
3779c2c66affSColin Finck     HMODULE hOle32 = GetModuleHandleA("ole32");
3780c2c66affSColin Finck     HMODULE hAdvapi32 = GetModuleHandleA("advapi32");
3781c2c66affSColin Finck     HMODULE hkernel32 = GetModuleHandleA("kernel32");
3782c2c66affSColin Finck 
3783c2c66affSColin Finck     pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
3784c2c66affSColin Finck     pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
3785c2c66affSColin Finck     pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
3786c2c66affSColin Finck     pCoTreatAsClass = (void*)GetProcAddress(hOle32,"CoTreatAsClass");
3787c2c66affSColin Finck     pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
3788c2c66affSColin Finck     pCoGetApartmentType = (void*)GetProcAddress(hOle32, "CoGetApartmentType");
3789c2c66affSColin Finck     pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA");
3790c2c66affSColin Finck     pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
3791c2c66affSColin Finck     pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
3792c2c66affSColin Finck 
3793c2c66affSColin Finck     pActivateActCtx = (void*)GetProcAddress(hkernel32, "ActivateActCtx");
3794c2c66affSColin Finck     pCreateActCtxW = (void*)GetProcAddress(hkernel32, "CreateActCtxW");
3795c2c66affSColin Finck     pDeactivateActCtx = (void*)GetProcAddress(hkernel32, "DeactivateActCtx");
3796c2c66affSColin Finck     pIsWow64Process = (void*)GetProcAddress(hkernel32, "IsWow64Process");
3797c2c66affSColin Finck     pReleaseActCtx = (void*)GetProcAddress(hkernel32, "ReleaseActCtx");
3798c2c66affSColin Finck }
3799c2c66affSColin Finck 
implicit_mta_proc(void * param)3800a6cdf4ffSAmine Khaldi static DWORD CALLBACK implicit_mta_proc(void *param)
3801a6cdf4ffSAmine Khaldi {
3802a6cdf4ffSAmine Khaldi     IComThreadingInfo *threading_info;
3803a6cdf4ffSAmine Khaldi     ULONG_PTR token;
3804a6cdf4ffSAmine Khaldi     IUnknown *unk;
3805a6cdf4ffSAmine Khaldi     DWORD cookie;
3806a6cdf4ffSAmine Khaldi     CLSID clsid;
3807a6cdf4ffSAmine Khaldi     HRESULT hr;
3808a6cdf4ffSAmine Khaldi 
3809a6cdf4ffSAmine Khaldi     test_apt_type(APTTYPE_MTA, APTTYPEQUALIFIER_IMPLICIT_MTA);
3810a6cdf4ffSAmine Khaldi 
3811a6cdf4ffSAmine Khaldi     hr = CoCreateInstance(&CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
3812a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoCreateInstance");
3813a6cdf4ffSAmine Khaldi     IUnknown_Release(unk);
3814a6cdf4ffSAmine Khaldi 
3815a6cdf4ffSAmine Khaldi     hr = CoGetClassObject(&CLSID_InternetZoneManager, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void **)&unk);
3816a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoGetClassObject");
3817a6cdf4ffSAmine Khaldi     IUnknown_Release(unk);
3818a6cdf4ffSAmine Khaldi 
3819a6cdf4ffSAmine Khaldi     hr = CoGetObjectContext(&IID_IComThreadingInfo, (void **)&threading_info);
3820a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoGetObjectContext");
3821a6cdf4ffSAmine Khaldi     IComThreadingInfo_Release(threading_info);
3822a6cdf4ffSAmine Khaldi 
3823a6cdf4ffSAmine Khaldi     hr = CoGetContextToken(&token);
3824a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoGetContextToken");
3825a6cdf4ffSAmine Khaldi 
3826a6cdf4ffSAmine Khaldi     hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
3827a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoRegisterPSClsid");
3828a6cdf4ffSAmine Khaldi 
3829a6cdf4ffSAmine Khaldi     hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
3830a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoGetPSClsid");
3831a6cdf4ffSAmine Khaldi 
3832a6cdf4ffSAmine Khaldi     hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory,
3833a6cdf4ffSAmine Khaldi                                CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie);
3834a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoRegisterClassObject");
3835a6cdf4ffSAmine Khaldi 
3836a6cdf4ffSAmine Khaldi     hr = CoRevokeClassObject(cookie);
3837a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoRevokeClassObject");
3838a6cdf4ffSAmine Khaldi 
3839a6cdf4ffSAmine Khaldi     hr = CoRegisterMessageFilter(NULL, NULL);
3840a6cdf4ffSAmine Khaldi     ok(hr == CO_E_NOT_SUPPORTED, "got %#x\n", hr);
3841a6cdf4ffSAmine Khaldi 
3842fc6e4ed5SAmine Khaldi     hr = CoLockObjectExternal(&Test_Unknown, TRUE, TRUE);
3843a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoLockObjectExternal");
3844a6cdf4ffSAmine Khaldi 
3845fc6e4ed5SAmine Khaldi     hr = CoDisconnectObject(&Test_Unknown, 0);
3846a6cdf4ffSAmine Khaldi     ok_ole_success(hr, "CoDisconnectObject");
3847a6cdf4ffSAmine Khaldi 
3848a6cdf4ffSAmine Khaldi     return 0;
3849a6cdf4ffSAmine Khaldi }
3850a6cdf4ffSAmine Khaldi 
3851a6cdf4ffSAmine Khaldi /* Some COM functions (perhaps even all of them?) can make use of an "implicit"
3852a6cdf4ffSAmine Khaldi  * multi-threaded apartment created by another thread in the same process. */
test_implicit_mta(void)3853a6cdf4ffSAmine Khaldi static void test_implicit_mta(void)
3854a6cdf4ffSAmine Khaldi {
3855a6cdf4ffSAmine Khaldi     HANDLE thread;
3856a6cdf4ffSAmine Khaldi 
3857a6cdf4ffSAmine Khaldi     CoInitializeEx(NULL, COINIT_MULTITHREADED);
3858a6cdf4ffSAmine Khaldi 
3859a6cdf4ffSAmine Khaldi     thread = CreateThread(NULL, 0, implicit_mta_proc, NULL, 0, NULL);
3860a6cdf4ffSAmine Khaldi     ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
3861a6cdf4ffSAmine Khaldi 
3862a6cdf4ffSAmine Khaldi     CoUninitialize();
3863a6cdf4ffSAmine Khaldi }
3864a6cdf4ffSAmine Khaldi 
START_TEST(compobj)3865c2c66affSColin Finck START_TEST(compobj)
3866c2c66affSColin Finck {
3867c2c66affSColin Finck     init_funcs();
3868c2c66affSColin Finck 
3869c2c66affSColin Finck     if (!pCoInitializeEx)
3870c2c66affSColin Finck     {
3871c2c66affSColin Finck         trace("You need DCOM95 installed to run this test\n");
3872c2c66affSColin Finck         return;
3873c2c66affSColin Finck     }
3874c2c66affSColin Finck 
3875c2c66affSColin Finck     if (!pCreateActCtxW)
3876c2c66affSColin Finck         win_skip("Activation contexts are not supported, some tests will be skipped.\n");
3877c2c66affSColin Finck 
3878c2c66affSColin Finck     test_ProgIDFromCLSID();
3879c2c66affSColin Finck     test_CLSIDFromProgID();
3880c2c66affSColin Finck     test_CLSIDFromString();
3881c2c66affSColin Finck     test_IIDFromString();
3882c2c66affSColin Finck     test_StringFromGUID2();
3883c2c66affSColin Finck     test_CoCreateInstance();
3884c2c66affSColin Finck     test_ole_menu();
3885c2c66affSColin Finck     test_CoGetClassObject();
3886c2c66affSColin Finck     test_CoCreateInstanceEx();
3887c2c66affSColin Finck     test_CoRegisterMessageFilter();
3888c2c66affSColin Finck     test_CoRegisterPSClsid();
3889c2c66affSColin Finck     test_CoGetPSClsid();
3890c2c66affSColin Finck     test_CoUnmarshalInterface();
3891c2c66affSColin Finck     test_CoGetInterfaceAndReleaseStream();
3892c2c66affSColin Finck     test_CoMarshalInterface();
3893c2c66affSColin Finck     test_CoMarshalInterThreadInterfaceInStream();
3894c2c66affSColin Finck     test_CoRegisterClassObject();
3895c2c66affSColin Finck     test_registered_object_thread_affinity();
3896c2c66affSColin Finck     test_CoFreeUnusedLibraries();
3897c2c66affSColin Finck     test_CoGetObjectContext();
3898c2c66affSColin Finck     test_CoGetCallContext();
3899c2c66affSColin Finck     test_CoGetContextToken();
3900c2c66affSColin Finck     test_TreatAsClass();
3901c2c66affSColin Finck     test_CoInitializeEx();
3902c2c66affSColin Finck     test_OleInitialize_InitCounting();
3903c2c66affSColin Finck     test_OleRegGetMiscStatus();
3904c2c66affSColin Finck     test_CoCreateGuid();
3905c2c66affSColin Finck     test_CoWaitForMultipleHandles();
3906c2c66affSColin Finck     test_CoGetMalloc();
3907c2c66affSColin Finck     test_OleRegGetUserType();
3908c2c66affSColin Finck     test_CoGetApartmentType();
3909c2c66affSColin Finck     test_IMallocSpy();
3910c2c66affSColin Finck     test_CoGetCurrentLogicalThreadId();
3911fc6e4ed5SAmine Khaldi     test_IInitializeSpy(FALSE);
3912fc6e4ed5SAmine Khaldi     test_IInitializeSpy(TRUE);
3913c2c66affSColin Finck     test_CoGetInstanceFromFile();
3914c2c66affSColin Finck     test_GlobalOptions();
3915a6cdf4ffSAmine Khaldi     test_implicit_mta();
3916c2c66affSColin Finck }
3917