1 /*
2  * Copyright 2012 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <stdarg.h>
20 #include <stdio.h>
21 
22 #define COBJMACROS
23 #define CONST_VTABLE
24 
25 #include <windef.h>
26 #include <winbase.h>
27 #include <winuser.h>
28 #include <exdisp.h>
29 
30 #include <wine/atlbase.h>
31 #include <mshtml.h>
32 
33 #include <wine/test.h>
34 
35 static const GUID CLSID_Test =
36     {0x178fc163,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
37 #define CLSID_TEST_STR "178fc163-0000-0000-0000-000000000046"
38 
39 static const GUID CATID_CatTest1 =
40     {0x178fc163,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x46}};
41 #define CATID_CATTEST1_STR "178fc163-0000-0000-0000-000000000146"
42 
43 static const GUID CATID_CatTest2 =
44     {0x178fc163,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x46}};
45 #define CATID_CATTEST2_STR "178fc163-0000-0000-0000-000000000246"
46 
47 static const WCHAR emptyW[] = {'\0'};
48 static const WCHAR randomW[] = {'r','a','n','d','o','m','\0'};
49 static const WCHAR progid1W[] = {'S','h','e','l','l','.','E','x','p','l','o','r','e','r','.','2','\0'};
50 static const WCHAR clsid1W[] = {'{','8','8','5','6','f','9','6','1','-','3','4','0','a','-',
51                                 '1','1','d','0','-','a','9','6','b','-',
52                                 '0','0','c','0','4','f','d','7','0','5','a','2','}','\0'};
53 static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q',
54                               '.','o','r','g','/','t','e','s','t','s','/','w','i','n','e','h','q','_',
55                               's','n','a','p','s','h','o','t','/','\0'};
56 static const WCHAR mshtml1W[] = {'m','s','h','t','m','l',':','<','h','t','m','l','>','<','b','o','d','y','>',
57                                  't','e','s','t','<','/','b','o','d','y','>','<','/','h','t','m','l','>','\0'};
58 static const WCHAR mshtml2W[] = {'M','S','H','T','M','L',':','<','h','t','m','l','>','<','b','o','d','y','>',
59                                  't','e','s','t','<','/','b','o','d','y','>','<','/','h','t','m','l','>','\0'};
60 static const WCHAR mshtml3W[] = {'<','h','t','m','l','>','<','b','o','d','y','>', 't','e','s','t',
61                                  '<','/','b','o','d','y','>','<','/','h','t','m','l','>','\0'};
62 static const WCHAR fileW[] = {'f','i','l','e',':','/','/','/','\0'};
63 static const WCHAR html_fileW[] = {'t','e','s','t','.','h','t','m','l','\0'};
64 static const char html_str[] = "<html><body>test</body><html>";
65 
is_token_admin(HANDLE token)66 static BOOL is_token_admin(HANDLE token)
67 {
68     PSID administrators = NULL;
69     SID_IDENTIFIER_AUTHORITY nt_authority = { SECURITY_NT_AUTHORITY };
70     DWORD groups_size;
71     PTOKEN_GROUPS groups;
72     DWORD group_index;
73 
74     /* Create a well-known SID for the Administrators group. */
75     if (! AllocateAndInitializeSid(&nt_authority, 2, SECURITY_BUILTIN_DOMAIN_RID,
76                                    DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
77                                    &administrators))
78         return FALSE;
79 
80     /* Get the group info from the token */
81     groups_size = 0;
82     GetTokenInformation(token, TokenGroups, NULL, 0, &groups_size);
83     groups = HeapAlloc(GetProcessHeap(), 0, groups_size);
84     if (groups == NULL)
85     {
86         FreeSid(administrators);
87         return FALSE;
88     }
89     if (! GetTokenInformation(token, TokenGroups, groups, groups_size, &groups_size))
90     {
91         HeapFree(GetProcessHeap(), 0, groups);
92         FreeSid(administrators);
93         return FALSE;
94     }
95 
96     /* Now check if the token groups include the Administrators group */
97     for (group_index = 0; group_index < groups->GroupCount; group_index++)
98     {
99         if (EqualSid(groups->Groups[group_index].Sid, administrators))
100         {
101             HeapFree(GetProcessHeap(), 0, groups);
102             FreeSid(administrators);
103             return TRUE;
104         }
105     }
106 
107     /* If we end up here we didn't find the Administrators group */
108     HeapFree(GetProcessHeap(), 0, groups);
109     FreeSid(administrators);
110     return FALSE;
111 }
112 
is_process_limited(void)113 static BOOL is_process_limited(void)
114 {
115     static BOOL (WINAPI *pOpenProcessToken)(HANDLE, DWORD, PHANDLE) = NULL;
116     HANDLE token;
117     BOOL result=FALSE;
118 
119     if (!pOpenProcessToken)
120     {
121         HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
122         pOpenProcessToken = (void*)GetProcAddress(hadvapi32, "OpenProcessToken");
123         if (!pOpenProcessToken)
124             return FALSE;
125     }
126 
127     if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
128     {
129         BOOL ret;
130         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
131         DWORD size;
132 
133         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
134         if (ret)
135         {
136             if (type == TokenElevationTypeDefault)
137                 /* UAC is disabled, check for administrators group */
138                 result = !is_token_admin(token);
139             else if (type == TokenElevationTypeFull)
140                 result = FALSE;
141             else if (type == TokenElevationTypeLimited)
142                 result = TRUE;
143         }
144         CloseHandle(token);
145     }
146     return result;
147 }
148 
test_winmodule(void)149 static void test_winmodule(void)
150 {
151     _AtlCreateWndData create_data[3];
152     _ATL_WIN_MODULE winmod;
153     void *p;
154     HRESULT hres;
155 
156     winmod.cbSize = 0xdeadbeef;
157     hres = AtlWinModuleInit(&winmod);
158     ok(hres == E_INVALIDARG, "AtlWinModuleInit failed: %08x\n", hres);
159 
160     winmod.cbSize = sizeof(winmod);
161     winmod.m_pCreateWndList = (void*)0xdeadbeef;
162     winmod.m_csWindowCreate.LockCount = 0xdeadbeef;
163     winmod.m_rgWindowClassAtoms.m_aT = (void*)0xdeadbeef;
164     winmod.m_rgWindowClassAtoms.m_nSize = 0xdeadbeef;
165     winmod.m_rgWindowClassAtoms.m_nAllocSize = 0xdeadbeef;
166     hres = AtlWinModuleInit(&winmod);
167     ok(hres == S_OK, "AtlWinModuleInit failed: %08x\n", hres);
168     ok(!winmod.m_pCreateWndList, "winmod.m_pCreateWndList = %p\n", winmod.m_pCreateWndList);
169     ok(winmod.m_csWindowCreate.LockCount == -1, "winmod.m_csWindowCreate.LockCount = %d\n",
170        winmod.m_csWindowCreate.LockCount);
171     ok(winmod.m_rgWindowClassAtoms.m_aT == (void*)0xdeadbeef, "winmod.m_rgWindowClassAtoms.m_aT = %p\n",
172        winmod.m_rgWindowClassAtoms.m_aT);
173     ok(winmod.m_rgWindowClassAtoms.m_nSize == 0xdeadbeef, "winmod.m_rgWindowClassAtoms.m_nSize = %d\n",
174        winmod.m_rgWindowClassAtoms.m_nSize);
175     ok(winmod.m_rgWindowClassAtoms.m_nAllocSize == 0xdeadbeef, "winmod.m_rgWindowClassAtoms.m_nAllocSize = %d\n",
176        winmod.m_rgWindowClassAtoms.m_nAllocSize);
177 
178     InitializeCriticalSection(&winmod.m_csWindowCreate);
179 
180     AtlWinModuleAddCreateWndData(&winmod, create_data, (void*)0xdead0001);
181     ok(winmod.m_pCreateWndList == create_data, "winmod.m_pCreateWndList != create_data\n");
182     ok(create_data[0].m_pThis == (void*)0xdead0001, "unexpected create_data[0].m_pThis %p\n", create_data[0].m_pThis);
183     ok(create_data[0].m_dwThreadID == GetCurrentThreadId(), "unexpected create_data[0].m_dwThreadID %x\n",
184        create_data[0].m_dwThreadID);
185     ok(!create_data[0].m_pNext, "unexpected create_data[0].m_pNext %p\n", create_data[0].m_pNext);
186 
187     AtlWinModuleAddCreateWndData(&winmod, create_data+1, (void*)0xdead0002);
188     ok(winmod.m_pCreateWndList == create_data+1, "winmod.m_pCreateWndList != create_data\n");
189     ok(create_data[1].m_pThis == (void*)0xdead0002, "unexpected create_data[1].m_pThis %p\n", create_data[1].m_pThis);
190     ok(create_data[1].m_dwThreadID == GetCurrentThreadId(), "unexpected create_data[1].m_dwThreadID %x\n",
191        create_data[1].m_dwThreadID);
192     ok(create_data[1].m_pNext == create_data, "unexpected create_data[1].m_pNext %p\n", create_data[1].m_pNext);
193 
194     AtlWinModuleAddCreateWndData(&winmod, create_data+2, (void*)0xdead0003);
195     ok(winmod.m_pCreateWndList == create_data+2, "winmod.m_pCreateWndList != create_data\n");
196     ok(create_data[2].m_pThis == (void*)0xdead0003, "unexpected create_data[2].m_pThis %p\n", create_data[2].m_pThis);
197     ok(create_data[2].m_dwThreadID == GetCurrentThreadId(), "unexpected create_data[2].m_dwThreadID %x\n",
198        create_data[2].m_dwThreadID);
199     ok(create_data[2].m_pNext == create_data+1, "unexpected create_data[2].m_pNext %p\n", create_data[2].m_pNext);
200 
201     p = AtlWinModuleExtractCreateWndData(&winmod);
202     ok(p == (void*)0xdead0003, "unexpected AtlWinModuleExtractCreateWndData result %p\n", p);
203     ok(winmod.m_pCreateWndList == create_data+1, "winmod.m_pCreateWndList != create_data\n");
204     ok(create_data[2].m_pNext == create_data+1, "unexpected create_data[2].m_pNext %p\n", create_data[2].m_pNext);
205 
206     create_data[1].m_dwThreadID = 0xdeadbeef;
207 
208     p = AtlWinModuleExtractCreateWndData(&winmod);
209     ok(p == (void*)0xdead0001, "unexpected AtlWinModuleExtractCreateWndData result %p\n", p);
210     ok(winmod.m_pCreateWndList == create_data+1, "winmod.m_pCreateWndList != create_data\n");
211     ok(!create_data[0].m_pNext, "unexpected create_data[0].m_pNext %p\n", create_data[0].m_pNext);
212     ok(!create_data[1].m_pNext, "unexpected create_data[1].m_pNext %p\n", create_data[1].m_pNext);
213 
214     p = AtlWinModuleExtractCreateWndData(&winmod);
215     ok(!p, "unexpected AtlWinModuleExtractCreateWndData result %p\n", p);
216     ok(winmod.m_pCreateWndList == create_data+1, "winmod.m_pCreateWndList != create_data\n");
217 }
218 
219 #define test_key_exists(a,b) _test_key_exists(__LINE__,a,b)
_test_key_exists(unsigned line,HKEY root,const char * key_name)220 static void _test_key_exists(unsigned line, HKEY root, const char *key_name)
221 {
222     HKEY key;
223     DWORD res;
224 
225     res = RegOpenKeyA(root, key_name, &key);
226     ok_(__FILE__,line)(res == ERROR_SUCCESS, "Could not open key %s\n", key_name);
227     if(res == ERROR_SUCCESS)
228         RegCloseKey(key);
229 }
230 
231 #define test_key_not_exists(a,b) _test_key_not_exists(__LINE__,a,b)
_test_key_not_exists(unsigned line,HKEY root,const char * key_name)232 static void _test_key_not_exists(unsigned line, HKEY root, const char *key_name)
233 {
234     HKEY key;
235     DWORD res;
236 
237     res = RegOpenKeyA(root, key_name, &key);
238     ok_(__FILE__,line)(res == ERROR_FILE_NOT_FOUND, "Attempting to open %s returned %u\n", key_name, res);
239     if(res == ERROR_SUCCESS)
240         RegCloseKey(key);
241 }
242 
test_regcat(void)243 static void test_regcat(void)
244 {
245     unsigned char b;
246     HRESULT hres;
247 
248     const struct _ATL_CATMAP_ENTRY catmap[] = {
249         {_ATL_CATMAP_ENTRY_IMPLEMENTED, &CATID_CatTest1},
250         {_ATL_CATMAP_ENTRY_REQUIRED, &CATID_CatTest2},
251         {_ATL_CATMAP_ENTRY_END}
252     };
253 
254     if (is_process_limited())
255     {
256         skip("process is limited\n");
257         return;
258     }
259 
260     hres = AtlRegisterClassCategoriesHelper(&CLSID_Test, catmap, TRUE);
261     ok(hres == S_OK, "AtlRegisterClassCategoriesHelper failed: %08x\n", hres);
262 
263     test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}");
264     test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Implemented Categories\\{" CATID_CATTEST1_STR "}");
265     test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Required Categories\\{" CATID_CATTEST2_STR "}");
266 
267     hres = AtlRegisterClassCategoriesHelper(&CLSID_Test, catmap, FALSE);
268     ok(hres == S_OK, "AtlRegisterClassCategoriesHelper failed: %08x\n", hres);
269 
270     test_key_not_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Implemented Categories");
271     test_key_not_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Required Categories");
272     test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}");
273 
274     ok(RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}") == ERROR_SUCCESS, "Could not delete key\n");
275 
276     hres = AtlRegisterClassCategoriesHelper(&CLSID_Test, NULL, TRUE);
277     ok(hres == S_OK, "AtlRegisterClassCategoriesHelper failed: %08x\n", hres);
278 
279     test_key_not_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}");
280 
281     b = 10;
282     hres = AtlGetPerUserRegistration(&b);
283     ok(hres == S_OK, "AtlGetPerUserRegistration failed: %08x\n", hres);
284     ok(!b, "AtlGetPerUserRegistration returned %x\n", b);
285 }
286 
test_typelib(void)287 static void test_typelib(void)
288 {
289     ITypeLib *typelib;
290     HINSTANCE inst;
291     size_t len;
292     BSTR path;
293     HRESULT hres;
294 
295     static const WCHAR scrrun_dll_suffixW[] = {'\\','s','c','r','r','u','n','.','d','l','l',0};
296     static const WCHAR mshtml_tlb_suffixW[] = {'\\','m','s','h','t','m','l','.','t','l','b',0};
297 
298     inst = LoadLibraryA("scrrun.dll");
299     ok(inst != NULL, "Could not load scrrun.dll\n");
300 
301     typelib = NULL;
302     hres = AtlLoadTypeLib(inst, NULL, &path, &typelib);
303     ok(hres == S_OK, "AtlLoadTypeLib failed: %08x\n", hres);
304     FreeLibrary(inst);
305 
306     len = SysStringLen(path);
307     ok(len > ARRAY_SIZE(scrrun_dll_suffixW)
308        && lstrcmpiW(path+len-ARRAY_SIZE(scrrun_dll_suffixW), scrrun_dll_suffixW),
309        "unexpected path %s\n", wine_dbgstr_w(path));
310     SysFreeString(path);
311     ok(typelib != NULL, "typelib == NULL\n");
312     ITypeLib_Release(typelib);
313 
314     inst = LoadLibraryA("mshtml.dll");
315     ok(inst != NULL, "Could not load mshtml.dll\n");
316 
317     typelib = NULL;
318     hres = AtlLoadTypeLib(inst, NULL, &path, &typelib);
319     ok(hres == S_OK, "AtlLoadTypeLib failed: %08x\n", hres);
320     FreeLibrary(inst);
321 
322     len = SysStringLen(path);
323     ok(len > ARRAY_SIZE(mshtml_tlb_suffixW)
324        && lstrcmpiW(path+len-ARRAY_SIZE(mshtml_tlb_suffixW), mshtml_tlb_suffixW),
325        "unexpected path %s\n", wine_dbgstr_w(path));
326     SysFreeString(path);
327     ok(typelib != NULL, "typelib == NULL\n");
328     ITypeLib_Release(typelib);
329 }
330 
ConnectionPoint_QueryInterface(IConnectionPoint * iface,REFIID riid,void ** ppv)331 static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface, REFIID riid, void **ppv)
332 {
333     if(IsEqualGUID(&IID_IConnectionPoint, riid)) {
334         *ppv = iface;
335         return S_OK;
336     }
337 
338     ok(0, "unexpected call\n");
339     return E_NOINTERFACE;
340 }
341 
ConnectionPoint_AddRef(IConnectionPoint * iface)342 static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
343 {
344     return 2;
345 }
346 
ConnectionPoint_Release(IConnectionPoint * iface)347 static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
348 {
349     return 1;
350 }
351 
ConnectionPoint_GetConnectionInterface(IConnectionPoint * iface,IID * pIID)352 static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID)
353 {
354     ok(0, "unexpected call\n");
355     return E_NOTIMPL;
356 }
357 
ConnectionPoint_GetConnectionPointContainer(IConnectionPoint * iface,IConnectionPointContainer ** ppCPC)358 static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
359         IConnectionPointContainer **ppCPC)
360 {
361     ok(0, "unexpected call\n");
362     return E_NOTIMPL;
363 }
364 
365 static int advise_cnt;
366 
ConnectionPoint_Advise(IConnectionPoint * iface,IUnknown * pUnkSink,DWORD * pdwCookie)367 static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
368                                              DWORD *pdwCookie)
369 {
370     ok(pUnkSink == (IUnknown*)0xdead0000, "pUnkSink = %p\n", pUnkSink);
371     *pdwCookie = 0xdeadbeef;
372     advise_cnt++;
373     return S_OK;
374 }
375 
ConnectionPoint_Unadvise(IConnectionPoint * iface,DWORD dwCookie)376 static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
377 {
378     ok(dwCookie == 0xdeadbeef, "dwCookie = %x\n", dwCookie);
379     advise_cnt--;
380     return S_OK;
381 }
382 
ConnectionPoint_EnumConnections(IConnectionPoint * iface,IEnumConnections ** ppEnum)383 static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
384                                                       IEnumConnections **ppEnum)
385 {
386     ok(0, "unexpected call\n");
387     return E_NOTIMPL;
388 }
389 
390 static const IConnectionPointVtbl ConnectionPointVtbl =
391 {
392     ConnectionPoint_QueryInterface,
393     ConnectionPoint_AddRef,
394     ConnectionPoint_Release,
395     ConnectionPoint_GetConnectionInterface,
396     ConnectionPoint_GetConnectionPointContainer,
397     ConnectionPoint_Advise,
398     ConnectionPoint_Unadvise,
399     ConnectionPoint_EnumConnections
400 };
401 
402 static IConnectionPoint ConnectionPoint = { &ConnectionPointVtbl };
403 
ConnectionPointContainer_QueryInterface(IConnectionPointContainer * iface,REFIID riid,void ** ppv)404 static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
405         REFIID riid, void **ppv)
406 {
407     if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) {
408         *ppv = iface;
409         return S_OK;
410     }
411 
412     ok(0, "unexpected call\n");
413     return E_NOTIMPL;
414 }
415 
ConnectionPointContainer_AddRef(IConnectionPointContainer * iface)416 static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
417 {
418     return 2;
419 }
420 
ConnectionPointContainer_Release(IConnectionPointContainer * iface)421 static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
422 {
423     return 1;
424 }
425 
ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer * iface,IEnumConnectionPoints ** ppEnum)426 static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
427         IEnumConnectionPoints **ppEnum)
428 {
429     ok(0, "unexpected call\n");
430     return E_NOTIMPL;
431 }
432 
ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer * iface,REFIID riid,IConnectionPoint ** ppCP)433 static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
434         REFIID riid, IConnectionPoint **ppCP)
435 {
436     ok(IsEqualGUID(riid, &CLSID_Test), "unexpected riid\n");
437     *ppCP = &ConnectionPoint;
438     return S_OK;
439 }
440 
441 static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl = {
442     ConnectionPointContainer_QueryInterface,
443     ConnectionPointContainer_AddRef,
444     ConnectionPointContainer_Release,
445     ConnectionPointContainer_EnumConnectionPoints,
446     ConnectionPointContainer_FindConnectionPoint
447 };
448 
449 static IConnectionPointContainer ConnectionPointContainer = { &ConnectionPointContainerVtbl };
450 
test_cp(void)451 static void test_cp(void)
452 {
453     DWORD cookie = 0;
454     HRESULT hres;
455 
456     hres = AtlAdvise(NULL, (IUnknown*)0xdeed0000, &CLSID_Test, &cookie);
457     ok(hres == E_INVALIDARG, "expect E_INVALIDARG, returned %08x\n", hres);
458 
459     hres = AtlUnadvise(NULL, &CLSID_Test, 0xdeadbeef);
460     ok(hres == E_INVALIDARG, "expect E_INVALIDARG, returned %08x\n", hres);
461 
462     hres = AtlAdvise((IUnknown*)&ConnectionPointContainer, (IUnknown*)0xdead0000, &CLSID_Test, &cookie);
463     ok(hres == S_OK, "AtlAdvise failed: %08x\n", hres);
464     ok(cookie == 0xdeadbeef, "cookie = %x\n", cookie);
465     ok(advise_cnt == 1, "advise_cnt = %d\n", advise_cnt);
466 
467     hres = AtlUnadvise((IUnknown*)&ConnectionPointContainer, &CLSID_Test, 0xdeadbeef);
468     ok(hres == S_OK, "AtlUnadvise failed: %08x\n", hres);
469     ok(!advise_cnt, "advise_cnt = %d\n", advise_cnt);
470 }
471 
472 static CLSID persist_clsid;
473 
Persist_QueryInterface(IPersist * iface,REFIID riid,void ** ppv)474 static HRESULT WINAPI Persist_QueryInterface(IPersist *iface, REFIID riid, void **ppv)
475 {
476     ok(0, "unexpected call\n");
477     return E_NOINTERFACE;
478 }
479 
Persist_AddRef(IPersist * iface)480 static ULONG WINAPI Persist_AddRef(IPersist *iface)
481 {
482     return 2;
483 }
484 
Persist_Release(IPersist * iface)485 static ULONG WINAPI Persist_Release(IPersist *iface)
486 {
487     return 1;
488 }
489 
Persist_GetClassID(IPersist * iface,CLSID * pClassID)490 static HRESULT WINAPI Persist_GetClassID(IPersist *iface, CLSID *pClassID)
491 {
492     *pClassID = persist_clsid;
493     return S_OK;
494 }
495 
496 static const IPersistVtbl PersistVtbl = {
497     Persist_QueryInterface,
498     Persist_AddRef,
499     Persist_Release,
500     Persist_GetClassID
501 };
502 
503 static IPersist Persist = { &PersistVtbl };
504 
ProvideClassInfo2_QueryInterface(IProvideClassInfo2 * iface,REFIID riid,void ** ppv)505 static HRESULT WINAPI ProvideClassInfo2_QueryInterface(IProvideClassInfo2 *iface, REFIID riid, void **ppv)
506 {
507     ok(0, "unexpected call\n");
508     return E_NOINTERFACE;
509 }
510 
ProvideClassInfo2_AddRef(IProvideClassInfo2 * iface)511 static ULONG WINAPI ProvideClassInfo2_AddRef(IProvideClassInfo2 *iface)
512 {
513     return 2;
514 }
515 
ProvideClassInfo2_Release(IProvideClassInfo2 * iface)516 static ULONG WINAPI ProvideClassInfo2_Release(IProvideClassInfo2 *iface)
517 {
518     return 1;
519 }
520 
ProvideClassInfo2_GetClassInfo(IProvideClassInfo2 * iface,ITypeInfo ** ppTI)521 static HRESULT WINAPI ProvideClassInfo2_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI)
522 {
523     ok(0, "unexpected call\n");
524     return E_NOTIMPL;
525 }
526 
ProvideClassInfo2_GetGUID(IProvideClassInfo2 * iface,DWORD dwGuidKind,GUID * pGUID)527 static HRESULT WINAPI ProvideClassInfo2_GetGUID(IProvideClassInfo2 *iface, DWORD dwGuidKind, GUID *pGUID)
528 {
529     ok(dwGuidKind == GUIDKIND_DEFAULT_SOURCE_DISP_IID, "unexpected dwGuidKind %x\n", dwGuidKind);
530     *pGUID = DIID_DispHTMLBody;
531     return S_OK;
532 }
533 
534 static const IProvideClassInfo2Vtbl ProvideClassInfo2Vtbl = {
535     ProvideClassInfo2_QueryInterface,
536     ProvideClassInfo2_AddRef,
537     ProvideClassInfo2_Release,
538     ProvideClassInfo2_GetClassInfo,
539     ProvideClassInfo2_GetGUID
540 };
541 
542 static IProvideClassInfo2 ProvideClassInfo2 = { &ProvideClassInfo2Vtbl };
543 static BOOL support_classinfo2;
544 
Dispatch_QueryInterface(IDispatch * iface,REFIID riid,void ** ppv)545 static HRESULT WINAPI Dispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
546 {
547     *ppv = NULL;
548 
549     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid)) {
550         *ppv = iface;
551         return S_OK;
552     }
553 
554     if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) {
555         if(!support_classinfo2)
556             return E_NOINTERFACE;
557         *ppv = &ProvideClassInfo2;
558         return S_OK;
559     }
560 
561     if(IsEqualGUID(&IID_IPersist, riid)) {
562         *ppv = &Persist;
563         return S_OK;
564     }
565 
566     ok(0, "unexpected riid: %s\n", wine_dbgstr_guid(riid));
567     return E_NOINTERFACE;
568 }
569 
Dispatch_AddRef(IDispatch * iface)570 static ULONG WINAPI Dispatch_AddRef(IDispatch *iface)
571 {
572     return 2;
573 }
574 
Dispatch_Release(IDispatch * iface)575 static ULONG WINAPI Dispatch_Release(IDispatch *iface)
576 {
577     return 1;
578 }
579 
Dispatch_GetTypeInfoCount(IDispatch * iface,UINT * pctinfo)580 static HRESULT WINAPI Dispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
581 {
582     ok(0, "unexpected call\n");
583     return E_NOTIMPL;
584 }
585 
Dispatch_GetTypeInfo(IDispatch * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)586 static HRESULT WINAPI Dispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid,
587         ITypeInfo **ppTInfo)
588 {
589     ITypeLib *typelib;
590     HRESULT hres;
591 
592     static const WCHAR mshtml_tlbW[] = {'m','s','h','t','m','l','.','t','l','b',0};
593 
594     ok(!iTInfo, "iTInfo = %d\n", iTInfo);
595     ok(!lcid, "lcid = %x\n", lcid);
596 
597     hres = LoadTypeLib(mshtml_tlbW, &typelib);
598     ok(hres == S_OK, "LoadTypeLib failed: %08x\n", hres);
599 
600     hres = ITypeLib_GetTypeInfoOfGuid(typelib, &IID_IHTMLElement, ppTInfo);
601     ok(hres == S_OK, "GetTypeInfoOfGuid failed: %08x\n", hres);
602 
603     ITypeLib_Release(typelib);
604     return S_OK;
605 }
606 
Dispatch_GetIDsOfNames(IDispatch * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)607 static HRESULT WINAPI Dispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
608         UINT cNames, LCID lcid, DISPID *rgDispId)
609 {
610     ok(0, "unexpected call\n");
611     return E_NOTIMPL;
612 }
613 
Dispatch_Invoke(IDispatch * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)614 static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid,
615         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
616         EXCEPINFO *pExcepInfo, UINT *puArgErr)
617 {
618     ok(0, "unexpected call\n");
619     return E_NOTIMPL;
620 }
621 
622 static const IDispatchVtbl DispatchVtbl = {
623     Dispatch_QueryInterface,
624     Dispatch_AddRef,
625     Dispatch_Release,
626     Dispatch_GetTypeInfoCount,
627     Dispatch_GetTypeInfo,
628     Dispatch_GetIDsOfNames,
629     Dispatch_Invoke
630 };
631 
632 static IDispatch Dispatch = { &DispatchVtbl };
633 
test_source_iface(void)634 static void test_source_iface(void)
635 {
636     unsigned short maj_ver, min_ver;
637     IID libid, iid;
638     HRESULT hres;
639 
640     support_classinfo2 = TRUE;
641 
642     maj_ver = min_ver = 0xdead;
643     hres = AtlGetObjectSourceInterface((IUnknown*)&Dispatch, &libid, &iid, &maj_ver, &min_ver);
644     ok(hres == S_OK, "AtlGetObjectSourceInterface failed: %08x\n", hres);
645     ok(IsEqualGUID(&libid, &LIBID_MSHTML), "libid = %s\n", wine_dbgstr_guid(&libid));
646     ok(IsEqualGUID(&iid, &DIID_DispHTMLBody), "iid = %s\n", wine_dbgstr_guid(&iid));
647     ok(maj_ver == 4 && min_ver == 0, "ver = %d.%d\n", maj_ver, min_ver);
648 
649     support_classinfo2 = FALSE;
650     persist_clsid = CLSID_HTMLDocument;
651 
652     maj_ver = min_ver = 0xdead;
653     hres = AtlGetObjectSourceInterface((IUnknown*)&Dispatch, &libid, &iid, &maj_ver, &min_ver);
654     ok(hres == S_OK, "AtlGetObjectSourceInterface failed: %08x\n", hres);
655     ok(IsEqualGUID(&libid, &LIBID_MSHTML), "libid = %s\n", wine_dbgstr_guid(&libid));
656     ok(IsEqualGUID(&iid, &DIID_HTMLDocumentEvents), "iid = %s\n", wine_dbgstr_guid(&iid));
657     ok(maj_ver == 4 && min_ver == 0, "ver = %d.%d\n", maj_ver, min_ver);
658 
659     persist_clsid = CLSID_HTMLStyle;
660 
661     maj_ver = min_ver = 0xdead;
662     hres = AtlGetObjectSourceInterface((IUnknown*)&Dispatch, &libid, &iid, &maj_ver, &min_ver);
663     ok(hres == S_OK, "AtlGetObjectSourceInterface failed: %08x\n", hres);
664     ok(IsEqualGUID(&libid, &LIBID_MSHTML), "libid = %s\n", wine_dbgstr_guid(&libid));
665     ok(IsEqualGUID(&iid, &IID_NULL), "iid = %s\n", wine_dbgstr_guid(&iid));
666     ok(maj_ver == 4 && min_ver == 0, "ver = %d.%d\n", maj_ver, min_ver);
667 }
668 
test_ax_win(void)669 static void test_ax_win(void)
670 {
671     DWORD ret, ret_size, i;
672     HRESULT res;
673     HWND hwnd;
674     HANDLE hfile;
675     IUnknown *control;
676     WNDPROC wndproc[2] = {NULL, NULL};
677     WCHAR file_uri1W[MAX_PATH], pathW[MAX_PATH];
678     WNDCLASSEXW wcex;
679     static HMODULE hinstance = 0;
680     static const WCHAR cls_names[][16] =
681     {
682         {'A','t','l','A','x','W','i','n','1','0','0',0},
683         {'A','t','l','A','x','W','i','n','L','i','c','1','0','0',0}
684     };
685 
686     ret = AtlAxWinInit();
687     ok(ret, "AtlAxWinInit failed\n");
688 
689     hinstance = GetModuleHandleA(NULL);
690 
691     for (i = 0; i < 2; i++)
692     {
693         memset(&wcex, 0, sizeof(wcex));
694         wcex.cbSize = sizeof(wcex);
695         ret = GetClassInfoExW(hinstance, cls_names[i], &wcex);
696         ok(ret, "%s has not registered\n", wine_dbgstr_w(cls_names[i]));
697         ok(wcex.style == (CS_GLOBALCLASS | CS_DBLCLKS), "wcex.style %08x\n", wcex.style);
698         wndproc[i] = wcex.lpfnWndProc;
699 
700         hwnd = CreateWindowW(cls_names[i], NULL, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
701         ok(hwnd != NULL, "CreateWindow failed!\n");
702         control = (IUnknown *)0xdeadbeef;
703         res = AtlAxGetControl(hwnd, &control);
704         ok(res == E_FAIL, "Expected E_FAIL, returned %08x\n", res);
705         ok(!control, "returned %p\n", control);
706         if (control) IUnknown_Release(control);
707         DestroyWindow(hwnd);
708 
709         hwnd = CreateWindowW(cls_names[i], emptyW, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
710         ok(hwnd != NULL, "CreateWindow failed!\n");
711         control = (IUnknown *)0xdeadbeef;
712         res = AtlAxGetControl(hwnd, &control);
713         ok(res == E_FAIL, "Expected E_FAIL, returned %08x\n", res);
714         ok(!control, "returned %p\n", control);
715         if (control) IUnknown_Release(control);
716         DestroyWindow(hwnd);
717 
718         hwnd = CreateWindowW(cls_names[i], randomW, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
719         todo_wine ok(!hwnd, "returned %p\n", hwnd);
720         if(hwnd) DestroyWindow(hwnd);
721 
722         hwnd = CreateWindowW(cls_names[i], progid1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
723         ok(hwnd != NULL, "CreateWindow failed!\n");
724         control = NULL;
725         res = AtlAxGetControl(hwnd, &control);
726         ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
727         ok(control != NULL, "AtlAxGetControl failed!\n");
728         IUnknown_Release(control);
729         DestroyWindow(hwnd);
730 
731         hwnd = CreateWindowW(cls_names[i], clsid1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
732         ok(hwnd != NULL, "CreateWindow failed!\n");
733         control = NULL;
734         res = AtlAxGetControl(hwnd, &control);
735         ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
736         ok(control != NULL, "AtlAxGetControl failed!\n");
737         IUnknown_Release(control);
738         DestroyWindow(hwnd);
739 
740         hwnd = CreateWindowW(cls_names[i], url1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
741         ok(hwnd != NULL, "CreateWindow failed!\n");
742         control = NULL;
743         res = AtlAxGetControl(hwnd, &control);
744         ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
745         ok(control != NULL, "AtlAxGetControl failed!\n");
746         IUnknown_Release(control);
747         DestroyWindow(hwnd);
748 
749         /* test html stream with "MSHTML:" prefix */
750         hwnd = CreateWindowW(cls_names[i], mshtml1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
751         ok(hwnd != NULL, "CreateWindow failed!\n");
752         control = NULL;
753         res = AtlAxGetControl(hwnd, &control);
754         ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
755         ok(control != NULL, "AtlAxGetControl failed!\n");
756         IUnknown_Release(control);
757         DestroyWindow(hwnd);
758 
759         hwnd = CreateWindowW(cls_names[i], mshtml2W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
760         ok(hwnd != NULL, "CreateWindow failed!\n");
761         control = NULL;
762         res = AtlAxGetControl(hwnd, &control);
763         ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
764         ok(control != NULL, "AtlAxGetControl failed!\n");
765         IUnknown_Release(control);
766         DestroyWindow(hwnd);
767 
768         /* test html stream without "MSHTML:" prefix */
769         hwnd = CreateWindowW(cls_names[i], mshtml3W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
770         todo_wine ok(!hwnd, "returned %p\n", hwnd);
771         if(hwnd) DestroyWindow(hwnd);
772 
773         ret = GetTempPathW(MAX_PATH, pathW);
774         ok(ret, "GetTempPath failed!\n");
775         lstrcatW(pathW, html_fileW);
776         hfile = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
777         ok(hfile != INVALID_HANDLE_VALUE, "failed to create file\n");
778         ret = WriteFile(hfile, html_str, sizeof(html_str), &ret_size, NULL);
779         ok(ret, "WriteFile failed\n");
780         CloseHandle(hfile);
781 
782         /* test C:// scheme */
783         hwnd = CreateWindowW(cls_names[i], pathW, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
784         ok(hwnd != NULL, "CreateWindow failed!\n");
785         control = NULL;
786         res = AtlAxGetControl(hwnd, &control);
787         ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
788         ok(control != NULL, "AtlAxGetControl failed!\n");
789         IUnknown_Release(control);
790         DestroyWindow(hwnd);
791 
792         /* test file:// scheme */
793         lstrcpyW(file_uri1W, fileW);
794         lstrcatW(file_uri1W, pathW);
795         hwnd = CreateWindowW(cls_names[i], file_uri1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
796         ok(hwnd != NULL, "CreateWindow failed!\n");
797         control = NULL;
798         res = AtlAxGetControl(hwnd, &control);
799         ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
800         ok(control != NULL, "AtlAxGetControl failed!\n");
801         IUnknown_Release(control);
802         DestroyWindow(hwnd);
803 
804         /* test file:// scheme on non-existent file */
805         ret = DeleteFileW(pathW);
806         ok(ret, "DeleteFile failed!\n");
807         hwnd = CreateWindowW(cls_names[i], file_uri1W, 0, 100, 100, 100, 100, NULL, NULL, NULL, NULL);
808         ok(hwnd != NULL, "CreateWindow failed!\n");
809         control = NULL;
810         res = AtlAxGetControl(hwnd, &control);
811         ok(res == S_OK, "AtlAxGetControl failed with res %08x\n", res);
812         ok(control != NULL, "AtlAxGetControl failed!\n");
813         IUnknown_Release(control);
814         DestroyWindow(hwnd);
815     }
816     todo_wine ok(wndproc[0] != wndproc[1], "expected different proc!\n");
817 }
818 
register_class(void)819 static ATOM register_class(void)
820 {
821     WNDCLASSA wndclassA;
822 
823     wndclassA.style = 0;
824     wndclassA.lpfnWndProc = DefWindowProcA;
825     wndclassA.cbClsExtra = 0;
826     wndclassA.cbWndExtra = 0;
827     wndclassA.hInstance = GetModuleHandleA(NULL);
828     wndclassA.hIcon = NULL;
829     wndclassA.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
830     wndclassA.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
831     wndclassA.lpszMenuName = NULL;
832     wndclassA.lpszClassName = "WineAtlTestClass";
833 
834     return RegisterClassA(&wndclassA);
835 }
836 
create_container_window(void)837 static HWND create_container_window(void)
838 {
839     return CreateWindowA("WineAtlTestClass", "Wine ATL Test Window", 0,
840                               CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
841                               CW_USEDEFAULT, NULL, NULL, NULL, NULL);
842 }
843 
test_AtlAxAttachControl(void)844 static void test_AtlAxAttachControl(void)
845 {
846     HWND hwnd;
847     HRESULT hr;
848     IUnknown *control, *container;
849     LONG val;
850 
851     hr = AtlAxAttachControl(NULL, NULL, NULL);
852     ok(hr == E_INVALIDARG, "Expected AtlAxAttachControl to return E_INVALIDARG, got 0x%08x\n", hr);
853 
854     container = (IUnknown *)0xdeadbeef;
855     hr = AtlAxAttachControl(NULL, NULL, &container);
856     ok(hr == E_INVALIDARG, "Expected AtlAxAttachControl to return E_INVALIDARG, got 0x%08x\n", hr);
857     ok(container == (IUnknown *)0xdeadbeef,
858        "Expected the output container pointer to be untouched, got %p\n", container);
859 
860     hwnd = create_container_window();
861     hr = AtlAxAttachControl(NULL, hwnd, NULL);
862     ok(hr == E_INVALIDARG, "Expected AtlAxAttachControl to return E_INVALIDARG, got 0x%08x\n", hr);
863     DestroyWindow(hwnd);
864 
865     hwnd = create_container_window();
866     container = (IUnknown *)0xdeadbeef;
867     hr = AtlAxAttachControl(NULL, hwnd, &container);
868     ok(hr == E_INVALIDARG, "Expected AtlAxAttachControl to return E_INVALIDARG, got 0x%08x\n", hr);
869     ok(container == (IUnknown *)0xdeadbeef, "returned %p\n", container);
870     DestroyWindow(hwnd);
871 
872     hr = CoCreateInstance(&CLSID_WebBrowser, NULL, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER,
873                           &IID_IOleObject, (void **)&control);
874     ok(hr == S_OK, "Expected CoCreateInstance to return S_OK, got 0x%08x\n", hr);
875 
876     if (FAILED(hr))
877     {
878         skip("Couldn't obtain a test IOleObject instance\n");
879         return;
880     }
881 
882     hr = AtlAxAttachControl(control, NULL, NULL);
883     ok(hr == S_FALSE, "Expected AtlAxAttachControl to return S_FALSE, got 0x%08x\n", hr);
884 
885     container = NULL;
886     hr = AtlAxAttachControl(control, NULL, &container);
887     ok(hr == S_FALSE, "Expected AtlAxAttachControl to return S_FALSE, got 0x%08x\n", hr);
888     ok(container != NULL, "got %p\n", container);
889     IUnknown_Release(container);
890 
891     hwnd = create_container_window();
892     SetWindowLongW(hwnd, GWLP_USERDATA, 0xdeadbeef);
893     hr = AtlAxAttachControl(control, hwnd, NULL);
894     ok(hr == S_OK, "Expected AtlAxAttachControl to return S_OK, got 0x%08x\n", hr);
895     val = GetWindowLongW(hwnd, GWLP_USERDATA);
896     ok(val == 0xdeadbeef, "returned %08x\n", val);
897     DestroyWindow(hwnd);
898 
899     hwnd = create_container_window();
900     SetWindowLongW(hwnd, GWLP_USERDATA, 0xdeadbeef);
901     container = NULL;
902     hr = AtlAxAttachControl(control, hwnd, &container);
903     ok(hr == S_OK, "Expected AtlAxAttachControl to return S_OK, got 0x%08x\n", hr);
904     ok(container != NULL, "Expected not NULL!\n");
905     IUnknown_Release(container);
906     val = GetWindowLongW(hwnd, GWLP_USERDATA);
907     ok(val == 0xdeadbeef, "Expected unchanged, returned %08x\n", val);
908     DestroyWindow(hwnd);
909 
910     IUnknown_Release(control);
911 }
912 
test_AtlAxCreateControl(void)913 static void test_AtlAxCreateControl(void)
914 {
915     HWND hwnd;
916     IUnknown *control, *container;
917     HRESULT hr;
918     DWORD ret, ret_size;
919     HANDLE hfile;
920     WCHAR file_uri1W[MAX_PATH], pathW[MAX_PATH];
921 
922     container = NULL;
923     control = (IUnknown *)0xdeadbeef;
924     hr = AtlAxCreateControlEx(NULL, NULL, NULL, &container, &control, NULL, NULL);
925     todo_wine ok(hr == S_FALSE, "got 0x%08x\n", hr);
926     todo_wine ok(container != NULL, "returned %p\n", container);
927     ok(!control, "returned %p\n", control);
928 
929     container = NULL;
930     control = (IUnknown *)0xdeadbeef;
931     hwnd = create_container_window();
932     ok(hwnd != NULL, "create window failed!\n");
933     hr = AtlAxCreateControlEx(NULL, hwnd, NULL, &container, &control, &IID_NULL, NULL);
934     ok(hr == S_OK, "got 0x%08x\n", hr);
935     todo_wine ok(container != NULL, "returned %p!\n", container);
936     ok(!control, "returned %p\n", control);
937     DestroyWindow(hwnd);
938 
939     container = NULL;
940     control = (IUnknown *)0xdeadbeef;
941     hwnd = create_container_window();
942     ok(hwnd != NULL, "create window failed!\n");
943     hr = AtlAxCreateControlEx(emptyW, hwnd, NULL, &container, &control, &IID_NULL, NULL);
944     ok(hr == S_OK, "got 0x%08x\n", hr);
945     todo_wine ok(container != NULL, "returned %p!\n", container);
946     ok(!control, "returned %p\n", control);
947     DestroyWindow(hwnd);
948 
949     container = (IUnknown *)0xdeadbeef;
950     control = (IUnknown *)0xdeadbeef;
951     hwnd = create_container_window();
952     ok(hwnd != NULL, "create window failed!\n");
953     hr = AtlAxCreateControlEx(randomW, hwnd, NULL, &container, &control, &IID_NULL, NULL);
954     ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
955     ok(!container, "returned %p!\n", container);
956     ok(!control, "returned %p\n", control);
957     DestroyWindow(hwnd);
958 
959     container = NULL;
960     control = NULL;
961     hwnd = create_container_window();
962     ok(hwnd != NULL, "create window failed!\n");
963     hr = AtlAxCreateControlEx(progid1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
964     ok(hr == S_OK, "got 0x%08x\n", hr);
965     ok(container != NULL, "returned %p!\n", container);
966     ok(control != NULL, "returned %p\n", control);
967     IUnknown_Release(container);
968     IUnknown_Release(control);
969     DestroyWindow(hwnd);
970 
971     container = NULL;
972     control = NULL;
973     hwnd = create_container_window();
974     ok(hwnd != NULL, "create window failed!\n");
975     hr = AtlAxCreateControlEx(clsid1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
976     ok(hr == S_OK, "got 0x%08x\n", hr);
977     ok(container != NULL, "returned %p!\n", container);
978     ok(control != NULL, "returned %p\n", control);
979     IUnknown_Release(container);
980     IUnknown_Release(control);
981     DestroyWindow(hwnd);
982 
983     container = NULL;
984     control = NULL;
985     hwnd = create_container_window();
986     ok(hwnd != NULL, "create window failed!\n");
987     hr = AtlAxCreateControlEx(url1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
988     ok(hr == S_OK, "got 0x%08x\n", hr);
989     ok(container != NULL, "returned %p!\n", container);
990     ok(control != NULL, "returned %p\n", control);
991     IUnknown_Release(container);
992     IUnknown_Release(control);
993     DestroyWindow(hwnd);
994 
995     container = NULL;
996     control = NULL;
997     hwnd = create_container_window();
998     ok(hwnd != NULL, "create window failed!\n");
999     hr = AtlAxCreateControlEx(mshtml1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
1000     ok(hr == S_OK, "got 0x%08x\n", hr);
1001     ok(container != NULL, "returned %p!\n", container);
1002     ok(control != NULL, "returned %p\n", control);
1003     IUnknown_Release(container);
1004     IUnknown_Release(control);
1005     DestroyWindow(hwnd);
1006 
1007     container = NULL;
1008     control = NULL;
1009     hwnd = create_container_window();
1010     ok(hwnd != NULL, "create window failed!\n");
1011     hr = AtlAxCreateControlEx(mshtml2W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
1012     ok(hr == S_OK, "got 0x%08x\n", hr);
1013     ok(container != NULL, "returned %p!\n", container);
1014     ok(control != NULL, "returned %p\n", control);
1015     IUnknown_Release(container);
1016     IUnknown_Release(control);
1017     DestroyWindow(hwnd);
1018 
1019     container = (IUnknown *)0xdeadbeef;
1020     control = (IUnknown *)0xdeadbeef;
1021     hwnd = create_container_window();
1022     ok(hwnd != NULL, "create window failed!\n");
1023     hr = AtlAxCreateControlEx(mshtml3W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
1024     ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
1025     ok(!container, "returned %p!\n", container);
1026     ok(!control, "returned %p\n", control);
1027     DestroyWindow(hwnd);
1028 
1029     ret = GetTempPathW(MAX_PATH, pathW);
1030     ok(ret, "GetTempPath failed!\n");
1031     lstrcatW(pathW, html_fileW);
1032     hfile = CreateFileW(pathW, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
1033     ok(hfile != INVALID_HANDLE_VALUE, "failed to create file\n");
1034     ret = WriteFile(hfile, html_str, sizeof(html_str), &ret_size, NULL);
1035     ok(ret, "WriteFile failed\n");
1036     CloseHandle(hfile);
1037 
1038     /* test C:// scheme */
1039     container = NULL;
1040     control = NULL;
1041     hwnd = create_container_window();
1042     ok(hwnd != NULL, "create window failed!\n");
1043     hr = AtlAxCreateControlEx(pathW, hwnd, NULL, &container, &control, &IID_NULL, NULL);
1044     ok(hr == S_OK, "got 0x%08x\n", hr);
1045     ok(container != NULL, "returned %p!\n", container);
1046     ok(control != NULL, "returned %p\n", control);
1047     IUnknown_Release(container);
1048     IUnknown_Release(control);
1049     DestroyWindow(hwnd);
1050 
1051     /* test file:// scheme */
1052     lstrcpyW(file_uri1W, fileW);
1053     lstrcatW(file_uri1W, pathW);
1054     container = NULL;
1055     control = NULL;
1056     hwnd = create_container_window();
1057     ok(hwnd != NULL, "create window failed!\n");
1058     hr = AtlAxCreateControlEx(file_uri1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
1059     ok(hr == S_OK, "got 0x%08x\n", hr);
1060     ok(container != NULL, "returned %p!\n", container);
1061     ok(control != NULL, "returned %p\n", control);
1062     IUnknown_Release(container);
1063     IUnknown_Release(control);
1064     DestroyWindow(hwnd);
1065 
1066     /* test file:// scheme on non-existent file. */
1067     ret = DeleteFileW(pathW);
1068     ok(ret, "DeleteFile failed!\n");
1069     container = NULL;
1070     control = NULL;
1071     hwnd = create_container_window();
1072     ok(hwnd != NULL, "create window failed!\n");
1073     hr = AtlAxCreateControlEx(file_uri1W, hwnd, NULL, &container, &control, &IID_NULL, NULL);
1074     ok(hr == S_OK, "got 0x%08x\n", hr);
1075     ok(container != NULL, "returned %p!\n", container);
1076     ok(control != NULL, "returned %p\n", control);
1077     IUnknown_Release(container);
1078     IUnknown_Release(control);
1079     DestroyWindow(hwnd);
1080 }
1081 
START_TEST(atl)1082 START_TEST(atl)
1083 {
1084     if (!register_class())
1085         return;
1086 
1087     CoInitialize(NULL);
1088 
1089     test_winmodule();
1090     test_regcat();
1091     test_typelib();
1092     test_cp();
1093     test_source_iface();
1094     test_ax_win();
1095     test_AtlAxAttachControl();
1096     test_AtlAxCreateControl();
1097 
1098     CoUninitialize();
1099 }
1100