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