urlmon: Add some more tests for FindMimeFromData().
[wine] / dlls / urlmon / tests / sec_mgr.c
1 /*
2  * Copyright 2005-2006 Jacek Caban for CodeWeavers
3  * Copyright 2009-2011 Detlef Riekenberg
4  * Copyright 2011 Thomas Mullaly for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22 #define CONST_VTABLE
23 #define NONAMELESSUNION
24
25 /* needed for IInternetZoneManagerEx2 */
26 #define _WIN32_IE 0x0700
27
28 #include <wine/test.h>
29 #include <stdarg.h>
30 #include <stddef.h>
31 #include <stdio.h>
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "ole2.h"
36 #include "urlmon.h"
37
38 #include "initguid.h"
39
40 #define URLZONE_CUSTOM  URLZONE_USER_MIN+1
41 #define URLZONE_CUSTOM2 URLZONE_CUSTOM+1
42
43 #define DEFINE_EXPECT(func) \
44     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
45
46 #define SET_EXPECT(func) \
47     expect_ ## func = TRUE
48
49 #define CHECK_EXPECT(func) \
50     do { \
51         ok(expect_ ##func, "unexpected call " #func "\n"); \
52         expect_ ## func = FALSE; \
53         called_ ## func = TRUE; \
54     }while(0)
55
56 #define CHECK_EXPECT2(func) \
57     do { \
58         ok(expect_ ##func, "unexpected call " #func "\n"); \
59         called_ ## func = TRUE; \
60     }while(0)
61
62 #define CHECK_CALLED(func) \
63     do { \
64         ok(called_ ## func, "expected " #func "\n"); \
65         expect_ ## func = called_ ## func = FALSE; \
66     }while(0)
67
68 DEFINE_EXPECT(ParseUrl_SECURITY_URL_input);
69 DEFINE_EXPECT(ParseUrl_SECURITY_URL_input2);
70 DEFINE_EXPECT(ParseUrl_SECURITY_URL_expected);
71 DEFINE_EXPECT(ParseUrl_SECURITY_URL_http);
72 DEFINE_EXPECT(ParseUrl_SECURITY_DOMAIN_expected);
73 DEFINE_EXPECT(ProcessUrlAction);
74
75 static HRESULT (WINAPI *pCoInternetCreateSecurityManager)(IServiceProvider *, IInternetSecurityManager**, DWORD);
76 static HRESULT (WINAPI *pCoInternetCreateZoneManager)(IServiceProvider *, IInternetZoneManager**, DWORD);
77 static HRESULT (WINAPI *pCoInternetGetSecurityUrl)(LPCWSTR, LPWSTR*, PSUACTION, DWORD);
78 static HRESULT (WINAPI *pCoInternetGetSecurityUrlEx)(IUri*, IUri**, PSUACTION, DWORD_PTR);
79 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
80 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD, IInternetSession**, DWORD);
81 static HRESULT (WINAPI *pCoInternetIsFeatureEnabled)(INTERNETFEATURELIST, DWORD);
82 static HRESULT (WINAPI *pCoInternetIsFeatureEnabledForUrl)(INTERNETFEATURELIST, DWORD, LPCWSTR, IInternetSecurityManager*);
83 static HRESULT (WINAPI *pCoInternetIsFeatureZoneElevationEnabled)(LPCWSTR, LPCWSTR, IInternetSecurityManager*, DWORD);
84
85 static const WCHAR url1[] = {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l',
86         '/','b','l','a','n','k','.','h','t','m',0};
87 static const WCHAR url2[] = {'i','n','d','e','x','.','h','t','m',0};
88 static const WCHAR url3[] = {'f','i','l','e',':','/','/','c',':','\\','I','n','d','e','x','.','h','t','m',0};
89 static const WCHAR url4[] = {'f','i','l','e',':','s','o','m','e','%','2','0','f','i','l','e',
90         '%','2','e','j','p','g',0};
91 static const WCHAR url5[] = {'h','t','t','p',':','/','/','w','w','w','.','z','o','n','e','3',
92         '.','w','i','n','e','t','e','s','t',0};
93 static const WCHAR url6[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
94 static const WCHAR url7[] = {'f','t','p',':','/','/','z','o','n','e','3',
95         '.','w','i','n','e','t','e','s','t','/','f','i','l','e','.','t','e','s','t',0};
96 static const WCHAR url8[] = {'t','e','s','t',':','1','2','3','a','b','c',0};
97 static const WCHAR url9[] = {'h','t','t','p',':','/','/','w','w','w','.','z','o','n','e','3',
98         '.','w','i','n','e','t','e','s','t', '/','s','i','t','e','/','a','b','o','u','t',0};
99 static const WCHAR url10[] = {'f','i','l','e',':','/','/','s','o','m','e','%','2','0','f','i','l','e',
100         '.','j','p','g',0};
101 static const WCHAR url11[] = {'f','i','l','e',':','/','/','c',':','/','I','n','d','e','x','.','h','t','m',0};
102 static const WCHAR url12[] = {'f','i','l','e',':','/','/','/','c',':','/','I','n','d','e','x','.','h','t','m',0};
103 static const WCHAR url13[] = {'h','t','t','p',':','g','o','o','g','l','e','.','c','o','m',0};
104 static const WCHAR url14[] = {'z','i','p',':','t','e','s','t','i','n','g','.','c','o','m','/','t','e','s','t','i','n','g',0};
105 static const WCHAR url15[] = {'h','t','t','p',':','/','/','g','o','o','g','l','e','.','c','o','m','.','u','k',0};
106 static const WCHAR url16[] = {'f','i','l','e',':','/','/','/','c',':',0};
107 static const WCHAR url17[] = {'f','i','l','e',':','/','/','/','c',':','c','\\',0};
108
109 static const WCHAR url4e[] = {'f','i','l','e',':','s','o','m','e',' ','f','i','l','e',
110         '.','j','p','g',0};
111
112 static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0};
113 static const WCHAR security_urlW[] = {'w','i','n','e','t','e','s','t',':','t','e','s','t','i','n','g',0};
114 static const WCHAR security_url2W[] = {'w','i','n','e','t','e','s','t',':','t','e','s','t','i','n','g','2',0};
115 static const WCHAR security_expectedW[] = {'w','i','n','e','t','e','s','t',':','z','i','p',0};
116 static const WCHAR winetest_to_httpW[] = {'w','i','n','e','t','e','s','t',':','h',0};
117
118 static const char *szZoneMapDomainsKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Domains";
119 static const char *szInternetSettingsKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
120
121 static const BYTE secid1[] = {'f','i','l','e',':',0,0,0,0};
122 static const BYTE secid2[] = {'*',':','i','n','d','e','x','.','h','t','m',3,0,0,0};
123 static const BYTE secid5[] = {'h','t','t','p',':','w','w','w','.','z','o','n','e','3',
124         '.','w','i','n','e','t','e','s','t',3,0,0,0};
125 static const BYTE secid6[] = {'a','b','o','u','t',':','b','l','a','n','k',3,0,0,0};
126 static const BYTE secid7[] = {'f','t','p',':','z','o','n','e','3',
127         '.','w','i','n','e','t','e','s','t',3,0,0,0};
128 static const BYTE secid10[] =
129     {'f','i','l','e',':','s','o','m','e','%','2','0','f','i','l','e','.','j','p','g',3,0,0,0};
130 static const BYTE secid14[] =
131     {'z','i','p',':','t','e','s','t','i','n','g','.','c','o','m','/','t','e','s','t','i','n','g',3,0,0,0};
132 static const BYTE secid10_2[] =
133     {'f','i','l','e',':','s','o','m','e',' ','f','i','l','e','.','j','p','g',3,0,0,0};
134 static const BYTE secid13[] = {'h','t','t','p',':','c','o','m','.','u','k',3,0,0,0};
135 static const BYTE secid13_2[] = {'h','t','t','p',':','g','o','o','g','l','e','.','c','o','m','.','u','k',3,0,0,0};
136
137 static const GUID CLSID_TestActiveX =
138     {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x06,0x46}};
139
140 /* Defined as extern in urlmon.idl, but not exported by uuid.lib */
141 const GUID GUID_CUSTOM_CONFIRMOBJECTSAFETY =
142     {0x10200490,0xfa38,0x11d0,{0xac,0x0e,0x00,0xa0,0xc9,0xf,0xff,0xc0}};
143
144 static int called_securl_http;
145 static DWORD ProcessUrlAction_policy;
146
147 static struct secmgr_test {
148     LPCWSTR url;
149     DWORD zone;
150     HRESULT zone_hres;
151     DWORD secid_size;
152     const BYTE *secid;
153     HRESULT secid_hres;
154 } secmgr_tests[] = {
155     {url1, 0,   S_OK, sizeof(secid1), secid1, S_OK},
156     {url2, 100, 0x80041001, 0, NULL, E_INVALIDARG},
157     {url3, 0,   S_OK, sizeof(secid1), secid1, S_OK},
158     {url5, 3,   S_OK, sizeof(secid5), secid5, S_OK},
159     {url6, 3,   S_OK, sizeof(secid6), secid6, S_OK},
160     {url7, 3,   S_OK, sizeof(secid7), secid7, S_OK},
161     {url11,0,   S_OK, sizeof(secid1), secid1, S_OK},
162     {url12,0,   S_OK, sizeof(secid1), secid1, S_OK},
163     {url16,0,   S_OK, sizeof(secid1), secid1, S_OK},
164     {url17,0,   S_OK, sizeof(secid1), secid1, S_OK}
165 };
166
167 static int strcmp_w(const WCHAR *str1, const WCHAR *str2)
168 {
169     DWORD len1 = lstrlenW(str1);
170     DWORD len2 = lstrlenW(str2);
171
172     if(len1!=len2) return 1;
173     return memcmp(str1, str2, len1*sizeof(WCHAR));
174 }
175
176 static inline void heap_free(void *mem)
177 {
178     HeapFree(GetProcessHeap(), 0, mem);
179 }
180
181 static inline LPWSTR a2w(LPCSTR str)
182 {
183     LPWSTR ret = NULL;
184
185     if(str) {
186         DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
187         ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
188         MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
189     }
190
191     return ret;
192 }
193
194 static inline DWORD strcmp_aw(LPCSTR strA, LPCWSTR strB) {
195     LPWSTR strAW = a2w(strA);
196     DWORD ret = lstrcmpW(strAW, strB);
197     heap_free(strAW);
198     return ret;
199 }
200
201
202 /* Based on RegDeleteTreeW from dlls/advapi32/registry.c */
203 static LONG myRegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
204 {
205     LONG ret;
206     DWORD dwMaxSubkeyLen, dwMaxValueLen;
207     DWORD dwMaxLen, dwSize;
208     CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
209     HKEY hSubKey = hKey;
210
211     if(lpszSubKey)
212     {
213         ret = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
214         if (ret) return ret;
215     }
216
217     /* Get highest length for keys, values */
218     ret = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
219             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
220     if (ret) goto cleanup;
221
222     dwMaxSubkeyLen++;
223     dwMaxValueLen++;
224     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
225     if (dwMaxLen > sizeof(szNameBuf)/sizeof(CHAR))
226     {
227         /* Name too big: alloc a buffer for it */
228         if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(CHAR))))
229         {
230             ret = ERROR_NOT_ENOUGH_MEMORY;
231             goto cleanup;
232         }
233     }
234
235     /* Recursively delete all the subkeys */
236     while (TRUE)
237     {
238         dwSize = dwMaxLen;
239         if (RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL,
240                           NULL, NULL, NULL)) break;
241
242         ret = myRegDeleteTreeA(hSubKey, lpszName);
243         if (ret) goto cleanup;
244     }
245
246     if (lpszSubKey)
247         ret = RegDeleteKeyA(hKey, lpszSubKey);
248     else
249         while (TRUE)
250         {
251             dwSize = dwMaxLen;
252             if (RegEnumValueA(hKey, 0, lpszName, &dwSize,
253                   NULL, NULL, NULL, NULL)) break;
254
255             ret = RegDeleteValueA(hKey, lpszName);
256             if (ret) goto cleanup;
257         }
258
259 cleanup:
260     /* Free buffer if allocated */
261     if (lpszName != szNameBuf)
262         heap_free(lpszName);
263     if(lpszSubKey)
264         RegCloseKey(hSubKey);
265     return ret;
266 }
267
268 static HRESULT WINAPI SecurityManager_QueryInterface(IInternetSecurityManager* This,
269         REFIID riid, void **ppvObject)
270 {
271     ok(0, "unexpected call\n");
272     return E_NOTIMPL;
273 }
274
275 static ULONG WINAPI SecurityManager_AddRef(IInternetSecurityManager* This)
276 {
277     return 2;
278 }
279
280 static ULONG WINAPI SecurityManager_Release(IInternetSecurityManager* This)
281 {
282     return 1;
283 }
284
285 static HRESULT WINAPI SecurityManager_SetSecuritySite(IInternetSecurityManager* This,
286         IInternetSecurityMgrSite *pSite)
287 {
288     ok(0, "unexpected call\n");
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI SecurityManager_GetSecuritySite(IInternetSecurityManager* This,
293         IInternetSecurityMgrSite **ppSite)
294 {
295     ok(0, "unexpected call\n");
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI SecurityManager_MapUrlToZone(IInternetSecurityManager* This,
300         LPCWSTR pwszUrl, DWORD *pdwZone, DWORD dwFlags)
301 {
302     ok(0, "unexpected call\n");
303     return E_NOTIMPL;
304 }
305
306 static HRESULT WINAPI SecurityManager_GetSecurityId(IInternetSecurityManager* This,
307         LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
308 {
309     ok(0, "unexpected call\n");
310     return E_NOTIMPL;
311 }
312
313 static HRESULT WINAPI SecurityManager_ProcessUrlAction(IInternetSecurityManager* This,
314         LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy,
315         BYTE *pContext, DWORD cbContext, DWORD dwFlags, DWORD dwReserved)
316 {
317     CHECK_EXPECT(ProcessUrlAction);
318     ok(dwAction == URLACTION_FEATURE_ZONE_ELEVATION, "dwAction = %x\n", dwAction);
319     ok(cbPolicy == sizeof(DWORD), "cbPolicy = %d\n", cbPolicy);
320     ok(!pContext, "pContext != NULL\n");
321     ok(dwFlags == PUAF_NOUI, "dwFlags = %x\n", dwFlags);
322     ok(dwReserved == 0, "dwReserved = %x\n", dwReserved);
323
324     *pPolicy = ProcessUrlAction_policy;
325     return ProcessUrlAction_policy==URLPOLICY_ALLOW ? S_OK : S_FALSE;
326 }
327
328 static HRESULT WINAPI SecurityManager_QueryCustomPolicy(IInternetSecurityManager* This,
329         LPCWSTR pwszUrl, REFGUID guidKey, BYTE **ppPolicy, DWORD *pcbPolicy,
330         BYTE *pContext, DWORD cbContext, DWORD dwReserved)
331 {
332     ok(0, "unexpected call\n");
333     return E_NOTIMPL;
334 }
335
336 static HRESULT WINAPI SecurityManager_SetZoneMapping(IInternetSecurityManager* This,
337         DWORD dwZone, LPCWSTR lpszPattern, DWORD dwFlags)
338 {
339     ok(0, "unexpected call\n");
340     return E_NOTIMPL;
341 }
342
343 static HRESULT WINAPI SecurityManager_GetZoneMappings(IInternetSecurityManager* This,
344         DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
345 {
346     ok(0, "unexpected call\n");
347     return E_NOTIMPL;
348 }
349
350 static const IInternetSecurityManagerVtbl SecurityManagerVtbl = {
351     SecurityManager_QueryInterface,
352     SecurityManager_AddRef,
353     SecurityManager_Release,
354     SecurityManager_SetSecuritySite,
355     SecurityManager_GetSecuritySite,
356     SecurityManager_MapUrlToZone,
357     SecurityManager_GetSecurityId,
358     SecurityManager_ProcessUrlAction,
359     SecurityManager_QueryCustomPolicy,
360     SecurityManager_SetZoneMapping,
361     SecurityManager_GetZoneMappings
362 };
363
364 static IInternetSecurityManager security_manager = { &SecurityManagerVtbl };
365
366 static void test_SecurityManager(void)
367 {
368     int i;
369     IInternetSecurityManager *secmgr = NULL;
370     BYTE buf[512];
371     DWORD zone, size, policy;
372     HRESULT hres;
373
374     if(!pCoInternetCreateSecurityManager) {
375         return;
376     }
377
378     trace("Testing security manager...\n");
379
380     hres = pCoInternetCreateSecurityManager(NULL, &secmgr, 0);
381     ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres);
382     if(FAILED(hres))
383         return;
384
385     for(i=0; i < sizeof(secmgr_tests)/sizeof(secmgr_tests[0]); i++) {
386         zone = 100;
387         hres = IInternetSecurityManager_MapUrlToZone(secmgr, secmgr_tests[i].url,
388                                                      &zone, 0);
389         ok(hres == secmgr_tests[i].zone_hres /* IE <=6 */
390            || (FAILED(secmgr_tests[i].zone_hres) && hres == E_INVALIDARG), /* IE7 */
391            "[%d] MapUrlToZone failed: %08x, expected %08x\n",
392                 i, hres, secmgr_tests[i].zone_hres);
393         if(SUCCEEDED(hres))
394             ok(zone == secmgr_tests[i].zone, "[%d] zone=%d, expected %d\n", i, zone,
395                secmgr_tests[i].zone);
396         else
397             ok(zone == secmgr_tests[i].zone || zone == -1, "[%d] zone=%d\n", i, zone);
398
399         size = sizeof(buf);
400         memset(buf, 0xf0, sizeof(buf));
401         hres = IInternetSecurityManager_GetSecurityId(secmgr, secmgr_tests[i].url,
402                 buf, &size, 0);
403         ok(hres == secmgr_tests[i].secid_hres,
404            "[%d] GetSecurityId failed: %08x, expected %08x\n",
405            i, hres, secmgr_tests[i].secid_hres);
406         if(secmgr_tests[i].secid) {
407             ok(size == secmgr_tests[i].secid_size, "[%d] size=%d, expected %d\n",
408                     i, size, secmgr_tests[i].secid_size);
409             ok(!memcmp(buf, secmgr_tests[i].secid, size), "[%d] wrong secid\n", i);
410         }
411     }
412
413     zone = 100;
414     hres = IInternetSecurityManager_MapUrlToZone(secmgr, url10, &zone, 0);
415     ok(hres == S_OK, "MapUrlToZone failed: %08x, expected S_OK\n", hres);
416     ok(zone == 3, "zone=%d, expected 3\n", zone);
417
418     /* win2k3 translates %20 into a space */
419     size = sizeof(buf);
420     memset(buf, 0xf0, sizeof(buf));
421     hres = IInternetSecurityManager_GetSecurityId(secmgr, url10, buf, &size, 0);
422     ok(hres == S_OK, "GetSecurityId failed: %08x, expected S_OK\n", hres);
423     ok(size == sizeof(secid10) ||
424        size == sizeof(secid10_2), /* win2k3 */
425        "size=%d\n", size);
426     ok(!memcmp(buf, secid10, size) ||
427        !memcmp(buf, secid10_2, size), /* win2k3 */
428        "wrong secid\n");
429
430     zone = 100;
431     hres = IInternetSecurityManager_MapUrlToZone(secmgr, url13, &zone, 0);
432     ok(hres == S_OK, "MapUrlToZone failed: %08x\n", hres);
433     ok(zone == URLZONE_INVALID || broken(zone == URLZONE_INTERNET), "zone=%d\n", zone);
434
435     size = sizeof(buf);
436     memset(buf, 0xf0, sizeof(buf));
437     hres = IInternetSecurityManager_GetSecurityId(secmgr, url13, buf, &size, 0);
438     ok(hres == E_INVALIDARG || broken(hres == S_OK), "GetSecurityId failed: %08x\n", hres);
439
440     zone = 100;
441     hres = IInternetSecurityManager_MapUrlToZone(secmgr, url14, &zone, 0);
442     ok(hres == S_OK, "MapUrlToZone failed: %08x, expected S_OK\n", hres);
443     ok(zone == URLZONE_INTERNET, "zone=%d\n", zone);
444
445     size = sizeof(buf);
446     memset(buf, 0xf0, sizeof(buf));
447     hres = IInternetSecurityManager_GetSecurityId(secmgr, url14, buf, &size, 0);
448     ok(hres == S_OK, "GetSecurityId failed: %08x, expected S_OK\n", hres);
449     ok(size == sizeof(secid14), "size=%d\n", size);
450     ok(!memcmp(buf, secid14, size), "wrong secid\n");
451
452     zone = 100;
453     hres = IInternetSecurityManager_MapUrlToZone(secmgr, NULL, &zone, 0);
454     ok(hres == E_INVALIDARG, "MapUrlToZone failed: %08x, expected E_INVALIDARG\n", hres);
455     ok(zone == 100 || zone == -1, "zone=%d\n", zone);
456
457     size = sizeof(buf);
458     hres = IInternetSecurityManager_GetSecurityId(secmgr, NULL, buf, &size, 0);
459     ok(hres == E_INVALIDARG,
460        "GetSecurityId failed: %08x, expected E_INVALIDARG\n", hres);
461     hres = IInternetSecurityManager_GetSecurityId(secmgr, secmgr_tests[1].url,
462                                                   NULL, &size, 0);
463     ok(hres == E_INVALIDARG,
464        "GetSecurityId failed: %08x, expected E_INVALIDARG\n", hres);
465     hres = IInternetSecurityManager_GetSecurityId(secmgr, secmgr_tests[1].url,
466                                                   buf, NULL, 0);
467     ok(hres == E_INVALIDARG,
468        "GetSecurityId failed: %08x, expected E_INVALIDARG\n", hres);
469
470     hres = IInternetSecurityManager_ProcessUrlAction(secmgr, NULL, URLACTION_SCRIPT_RUN, (BYTE*)&policy,
471             sizeof(WCHAR), NULL, 0, 0, 0);
472     ok(hres == E_INVALIDARG, "ProcessUrlAction failed: %08x, expected E_INVALIDARG\n", hres);
473
474     IInternetSecurityManager_Release(secmgr);
475 }
476
477 /* Check if Internet Explorer is configured to run in "Enhanced Security Configuration" (aka hardened mode) */
478 /* Note: this code is duplicated in dlls/mshtml/tests/mshtml_test.h and dlls/urlmon/tests/sec_mgr.c */
479 static BOOL is_ie_hardened(void)
480 {
481     HKEY zone_map;
482     DWORD ie_harden, type, size;
483
484     ie_harden = 0;
485     if(RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap",
486                     0, KEY_QUERY_VALUE, &zone_map) == ERROR_SUCCESS) {
487         size = sizeof(DWORD);
488         if (RegQueryValueExA(zone_map, "IEHarden", NULL, &type, (LPBYTE) &ie_harden, &size) != ERROR_SUCCESS ||
489             type != REG_DWORD) {
490             ie_harden = 0;
491         }
492         RegCloseKey(zone_map);
493     }
494
495     return ie_harden != 0;
496 }
497
498 static void test_url_action(IInternetSecurityManager *secmgr, IInternetZoneManager *zonemgr, DWORD action)
499 {
500     DWORD res, size, policy, reg_policy;
501     char buf[10];
502     HKEY hkey;
503     HRESULT hres;
504
505     /* FIXME: HKEY_CURRENT_USER is most of the time the default but this can be changed on a system.
506      * The test should be changed to cope with that, if need be.
507      */
508     res = RegOpenKeyA(HKEY_CURRENT_USER,
509             "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3", &hkey);
510     if(res != ERROR_SUCCESS) {
511         ok(0, "Could not open zone key\n");
512         return;
513     }
514
515     wsprintf(buf, "%X", action);
516     size = sizeof(DWORD);
517     res = RegQueryValueExA(hkey, buf, NULL, NULL, (BYTE*)&reg_policy, &size);
518     RegCloseKey(hkey);
519     if(res != ERROR_SUCCESS || size != sizeof(DWORD)) {
520         policy = 0xdeadbeef;
521         hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url9, action, (BYTE*)&policy,
522                 sizeof(WCHAR), NULL, 0, 0, 0);
523         ok(hres == E_FAIL || broken(hres == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)),
524             "(0x%x) got 0x%x (expected E_FAIL)\n", action, hres);
525         ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy);
526
527         policy = 0xdeadbeef;
528         hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, (BYTE*)&policy,
529                 sizeof(DWORD), URLZONEREG_DEFAULT);
530         ok(hres == E_FAIL || broken(hres == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)),
531             "(0x%x) got 0x%x (expected E_FAIL)\n", action, hres);
532         ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy);
533         return;
534     }
535
536     policy = 0xdeadbeef;
537     hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, (BYTE*)&policy,
538             sizeof(DWORD), URLZONEREG_DEFAULT);
539     ok(hres == S_OK, "GetZoneActionPolicy failed: %08x\n", hres);
540     ok(policy == reg_policy, "(%x) policy=%x, expected %x\n", action, policy, reg_policy);
541
542     if(policy != URLPOLICY_QUERY) {
543         if(winetest_interactive || ! is_ie_hardened()) {
544             BOOL expect_parse_call = !called_securl_http;
545
546             policy = 0xdeadbeef;
547             hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url9, action, (BYTE*)&policy,
548                     sizeof(WCHAR), NULL, 0, 0, 0);
549             if(reg_policy == URLPOLICY_DISALLOW)
550                 ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres);
551             else
552                 ok(hres == S_OK, "ProcessUrlAction(%x) failed: %08x\n", action, hres);
553             ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy);
554
555             policy = 0xdeadbeef;
556             hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url9, action, (BYTE*)&policy,
557                     2, NULL, 0, 0, 0);
558             if(reg_policy == URLPOLICY_DISALLOW)
559                 ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres);
560             else
561                 ok(hres == S_OK, "ProcessUrlAction(%x) failed: %08x\n", action, hres);
562             ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy);
563
564             policy = 0xdeadbeef;
565             hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url9, action, (BYTE*)&policy,
566                     sizeof(DWORD), NULL, 0, 0, 0);
567             if(reg_policy == URLPOLICY_DISALLOW)
568                 ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres);
569             else
570                 ok(hres == S_OK, "ProcessUrlAction(%x) failed: %08x\n", action, hres);
571             ok(policy == reg_policy, "(%x) policy=%x\n", action, policy);
572
573             policy = 0xdeadbeef;
574             hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url9, action, (BYTE*)&policy,
575                     sizeof(WCHAR), (BYTE*)0xdeadbeef, 16, 0, 0);
576             if(reg_policy == URLPOLICY_DISALLOW)
577                 ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres);
578             else
579                 ok(hres == S_OK, "ProcessUrlAction(%x) failed: %08x\n", action, hres);
580             ok(policy == 0xdeadbeef, "(%x) policy=%x\n", action, policy);
581
582             policy = 0xdeadbeef;
583             if(expect_parse_call)
584                 SET_EXPECT(ParseUrl_SECURITY_URL_http);
585             hres = IInternetSecurityManager_ProcessUrlAction(secmgr, winetest_to_httpW, action, (BYTE*)&policy,
586                     sizeof(DWORD), NULL, 0, 0, 0);
587             if(expect_parse_call)
588                 CHECK_CALLED(ParseUrl_SECURITY_URL_http);
589             if(reg_policy == URLPOLICY_DISALLOW)
590                 ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres);
591             else
592                 ok(hres == S_OK, "ProcessUrlAction(%x) failed: %08x\n", action, hres);
593             ok(policy == reg_policy, "(%x) policy=%x\n", action, policy);
594         }else {
595             skip("IE running in Enhanced Security Configuration\n");
596         }
597     }
598 }
599
600 static void test_special_url_action(IInternetSecurityManager *secmgr, IInternetZoneManager *zonemgr, DWORD action)
601 {
602     DWORD policy;
603     HRESULT hres;
604
605     policy = 0xdeadbeef;
606     hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, (BYTE*)&policy,
607             sizeof(DWORD), URLZONEREG_DEFAULT);
608     ok(hres == S_OK, "GetZoneActionPolicy failed: %08x\n", hres);
609     ok(policy == URLPOLICY_DISALLOW, "(%x) policy=%x, expected URLPOLICY_DISALLOW\n", action, policy);
610
611     policy = 0xdeadbeef;
612     hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url1, action, (BYTE*)&policy,
613             sizeof(WCHAR), NULL, 0, 0, 0);
614     ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres);
615
616     policy = 0xdeadbeef;
617     hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url1, action, (BYTE*)&policy,
618             sizeof(DWORD), NULL, 0, 0, 0);
619     ok(hres == S_FALSE, "ProcessUrlAction(%x) failed: %08x, expected S_FALSE\n", action, hres);
620     ok(policy == URLPOLICY_DISALLOW, "policy = %x\n", policy);
621 }
622
623 static void test_activex(IInternetSecurityManager *secmgr)
624 {
625     DWORD policy, policy_size;
626     struct CONFIRMSAFETY cs;
627     BYTE *ppolicy;
628     HRESULT hres;
629
630     policy = 0xdeadbeef;
631     hres = IInternetSecurityManager_ProcessUrlAction(secmgr, url1, URLACTION_ACTIVEX_RUN, (BYTE*)&policy,
632             sizeof(DWORD), (BYTE*)&CLSID_TestActiveX, sizeof(CLSID), 0, 0);
633     ok(hres == S_OK, "ProcessUrlAction(URLACTION_ACTIVEX_RUN) failed: %08x\n", hres);
634     ok(policy == URLPOLICY_ALLOW || policy == URLPOLICY_DISALLOW, "policy = %x\n", policy);
635
636     cs.clsid = CLSID_TestActiveX;
637     cs.pUnk = (IUnknown*)0xdeadbeef;
638     cs.dwFlags = 0;
639     hres = IInternetSecurityManager_QueryCustomPolicy(secmgr, url1, &GUID_CUSTOM_CONFIRMOBJECTSAFETY,
640             &ppolicy, &policy_size, (BYTE*)&cs, sizeof(cs), 0);
641     ok(hres == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "QueryCusromPolicy failed: %08x\n", hres);
642 }
643
644 static void test_polices(void)
645 {
646     IInternetZoneManager *zonemgr = NULL;
647     IInternetSecurityManager *secmgr = NULL;
648     HRESULT hres;
649
650     trace("testing polices...\n");
651
652     hres = pCoInternetCreateSecurityManager(NULL, &secmgr, 0);
653     ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres);
654     hres = pCoInternetCreateZoneManager(NULL, &zonemgr, 0);
655     ok(hres == S_OK, "CoInternetCreateZoneManager failed: %08x\n", hres);
656
657     test_url_action(secmgr, zonemgr, URLACTION_SCRIPT_RUN);
658     test_url_action(secmgr, zonemgr, URLACTION_ACTIVEX_RUN);
659     test_url_action(secmgr, zonemgr, URLACTION_ACTIVEX_OVERRIDE_OBJECT_SAFETY);
660     test_url_action(secmgr, zonemgr, URLACTION_CHANNEL_SOFTDIST_PERMISSIONS);
661     test_url_action(secmgr, zonemgr, 0xdeadbeef);
662
663     test_special_url_action(secmgr, zonemgr, URLACTION_SCRIPT_OVERRIDE_SAFETY);
664     test_special_url_action(secmgr, zonemgr, URLACTION_ACTIVEX_OVERRIDE_SCRIPT_SAFETY);
665
666     test_activex(secmgr);
667
668     IInternetSecurityManager_Release(secmgr);
669     IInternetZoneManager_Release(zonemgr);
670 }
671
672 /* IE (or at least newer versions of it) seem to cache the keys in ZoneMap
673  * when urlmon.dll is loaded and it doesn't seem to update its cache, unless
674  * SetZoneMapping is used.
675  */
676 static void test_zone_domain_cache(void)
677 {
678     HRESULT hres;
679     DWORD res, zone;
680     IInternetSecurityManager *secmgr = NULL;
681     HKEY domains, domain;
682
683     static const WCHAR testing_domain_urlW[] = {'h','t','t','p',':','/','/','t','e','s','t','i','n','g','.',
684             'd','o','m','a','i','n','/',0};
685
686     res = RegOpenKeyA(HKEY_CURRENT_USER, szZoneMapDomainsKey, &domains);
687     ok(res == ERROR_SUCCESS, "RegOpenKey failed: %d\n", res);
688     if(res != ERROR_SUCCESS)
689         return;
690
691     res = RegCreateKeyA(domains, "testing.domain", &domain);
692     ok(res == ERROR_SUCCESS, "RegCreateKey failed: %d\n", res);
693     if(res != ERROR_SUCCESS) {
694         RegCloseKey(domains);
695         return;
696     }
697
698     zone = URLZONE_CUSTOM;
699     res = RegSetValueExA(domain, "http", 0, REG_DWORD, (BYTE*)&zone, sizeof(DWORD));
700     ok(res == ERROR_SUCCESS, "RegSetValueEx failed: %d\n", res);
701
702     RegCloseKey(domain);
703
704     hres = pCoInternetCreateSecurityManager(NULL, &secmgr, 0);
705     ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres);
706
707     zone = URLZONE_INVALID;
708     hres = IInternetSecurityManager_MapUrlToZone(secmgr, testing_domain_urlW, &zone, 0);
709     ok(hres == S_OK, "MapUrlToZone failed: %08x\n", hres);
710     todo_wine ok(zone == URLZONE_INTERNET, "Got %d, expected URLZONE_INTERNET\n", zone);
711
712     /* FIXME: Play nice with ZoneMaps that existed before the test is run. */
713     res = RegDeleteKeyA(domains, "testing.domain");
714     ok(res == ERROR_SUCCESS, "RegDeleteKey failed: %d\n", res);
715
716     RegCloseKey(domains);
717     IInternetSecurityManager_Release(secmgr);
718 }
719
720 typedef struct {
721     const char  *domain;
722     const char  *subdomain;
723     const char  *scheme;
724     DWORD       zone;
725 } zone_domain_mapping;
726
727 /* FIXME: Move these into SetZoneMapping tests when the day comes... */
728 static const zone_domain_mapping zone_domain_mappings[] = {
729     /* Implicitly means "*.yabadaba.do". */
730     {"yabadaba.do",NULL,"http",URLZONE_CUSTOM},
731     /* The '*' doesn't count as a wildcard, since its not the first component of the subdomain. */
732     {"super.cool","testing.*","ftp",URLZONE_CUSTOM2},
733     /* The '*' counts since it's the first component of the subdomain. */
734     {"super.cool","*.testing","ftp",URLZONE_CUSTOM2},
735     /* All known scheme types apply to wildcard schemes. */
736     {"tests.test",NULL,"*",URLZONE_CUSTOM},
737     /* Due to a defect with how windows checks the mappings, unknown scheme types
738      * never seem to get mapped properly. */
739     {"tests.test",NULL,"zip",URLZONE_CUSTOM},
740     {"www.testing.com",NULL,"http",URLZONE_CUSTOM},
741     {"www.testing.com","testing","http",URLZONE_CUSTOM2},
742     {"org",NULL,"http",URLZONE_CUSTOM},
743     {"org","testing","http",URLZONE_CUSTOM2},
744     {"wine.testing",NULL,"*",URLZONE_CUSTOM2}
745 };
746
747 static void register_zone_domains(void)
748 {
749     HKEY domains;
750     DWORD res, i;
751
752     /* Some Windows versions don't seem to have a "Domains" key in their HKLM. */
753     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, szZoneMapDomainsKey, &domains);
754     ok(res == ERROR_SUCCESS || broken(res == ERROR_FILE_NOT_FOUND), "RegOpenKey failed: %d\n", res);
755     if(res == ERROR_SUCCESS) {
756         HKEY domain;
757         DWORD zone = URLZONE_CUSTOM;
758
759         res = RegCreateKeyA(domains, "local.machine", &domain);
760         ok(res == ERROR_SUCCESS, "RegCreateKey failed: %d\n", res);
761
762         res = RegSetValueExA(domain, "http", 0, REG_DWORD, (BYTE*)&zone, sizeof(DWORD));
763         ok(res == ERROR_SUCCESS, "RegSetValueEx failed: %d\n", res);
764
765         RegCloseKey(domain);
766         RegCloseKey(domains);
767     }
768
769     res = RegOpenKeyA(HKEY_CURRENT_USER, szZoneMapDomainsKey, &domains);
770     ok(res == ERROR_SUCCESS, "RegOpenKey failed: %d\n", res);
771
772     for(i = 0; i < sizeof(zone_domain_mappings)/sizeof(zone_domain_mappings[0]); ++i) {
773         const zone_domain_mapping *test = zone_domain_mappings+i;
774         HKEY domain;
775
776         res = RegCreateKeyA(domains, test->domain, &domain);
777         ok(res == ERROR_SUCCESS, "RegCreateKey failed with %d on test %d\n", res, i);
778
779         /* Only set the value if there's no subdomain. */
780         if(!test->subdomain) {
781             res = RegSetValueExA(domain, test->scheme, 0, REG_DWORD, (BYTE*)&test->zone, sizeof(DWORD));
782             ok(res == ERROR_SUCCESS, "RegSetValueEx failed with %d on test %d\n", res, i);
783         } else {
784             HKEY subdomain;
785
786             res = RegCreateKeyA(domain, test->subdomain, &subdomain);
787             ok(res == ERROR_SUCCESS, "RegCreateKey failed with %d on test %d\n", res, i);
788
789             res = RegSetValueExA(subdomain, test->scheme, 0, REG_DWORD, (BYTE*)&test->zone, sizeof(DWORD));
790             ok(res == ERROR_SUCCESS, "RegSetValueEx failed with %d on test %d\n", res, i);
791
792             RegCloseKey(subdomain);
793         }
794
795         RegCloseKey(domain);
796     }
797
798     RegCloseKey(domains);
799 }
800
801 static void unregister_zone_domains(void)
802 {
803     HKEY domains;
804     DWORD res, i;
805
806     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, szZoneMapDomainsKey, &domains);
807     ok(res == ERROR_SUCCESS || broken(res == ERROR_FILE_NOT_FOUND), "RegOpenKey failed: %d\n", res);
808     if(res == ERROR_SUCCESS) {
809         RegDeleteKeyA(domains, "local.machine");
810         RegCloseKey(domains);
811     }
812
813     res = RegOpenKeyA(HKEY_CURRENT_USER, szZoneMapDomainsKey, &domains);
814     ok(res == ERROR_SUCCESS, "RegOpenKey failed: %d\n", res);
815
816     for(i = 0; i < sizeof(zone_domain_mappings)/sizeof(zone_domain_mappings[0]); ++i) {
817         const zone_domain_mapping *test = zone_domain_mappings+i;
818
819         /* FIXME: Uses the "cludge" approach to remove the test data from the registry!
820          *        Although, if domain names are... unique, this shouldn't cause any harm
821          *        to keys (if any) that existed before the tests.
822          */
823         if(test->subdomain) {
824             HKEY domain;
825
826             res = RegOpenKeyA(domains, test->domain, &domain);
827             if(res == ERROR_SUCCESS) {
828                 RegDeleteKeyA(domain, test->subdomain);
829                 RegCloseKey(domain);
830             }
831         }
832         RegDeleteKeyA(domains, test->domain);
833     }
834
835     RegCloseKey(domains);
836 }
837
838 static void run_child_process(void)
839 {
840     char cmdline[MAX_PATH];
841     char path[MAX_PATH];
842     char **argv;
843     PROCESS_INFORMATION pi;
844     STARTUPINFO si = { 0 };
845     BOOL ret;
846
847     GetModuleFileNameA(NULL, path, MAX_PATH);
848
849     si.cb = sizeof(si);
850     winetest_get_mainargs(&argv);
851     sprintf(cmdline, "\"%s\" %s domain_tests", argv[0], argv[1]);
852     ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
853     ok(ret, "Failed to spawn child process: %u\n", GetLastError());
854     winetest_wait_child_process(pi.hProcess);
855     CloseHandle(pi.hThread);
856     CloseHandle(pi.hProcess);
857 }
858
859 typedef struct {
860     const char  *url;
861     DWORD       zone;
862     BOOL        todo;
863     DWORD       broken_zone;
864 } zone_mapping_test;
865
866 static const zone_mapping_test zone_mapping_tests[] = {
867     /* Tests for "yabadaba.do" zone mappings. */
868     {"http://yabadaba.do/",URLZONE_CUSTOM},
869     {"http://google.yabadaba.do/",URLZONE_CUSTOM},
870     {"zip://yabadaba.do/",URLZONE_INTERNET},
871     /* Tests for "super.cool" zone mappings. */
872     {"ftp://testing.google.super.cool/",URLZONE_INTERNET},
873     {"ftp://testing.*.super.cool/",URLZONE_CUSTOM2},
874     {"ftp://google.testing.super.cool/",URLZONE_CUSTOM2},
875     /* Tests for "tests.test" zone mappings. */
876     {"http://tests.test/",URLZONE_CUSTOM},
877     {"http://www.tests.test/",URLZONE_CUSTOM},
878     {"ftp://tests.test/",URLZONE_CUSTOM},
879     {"ftp://www.tests.test/",URLZONE_CUSTOM},
880     {"test://www.tests.test/",URLZONE_INTERNET},
881     {"test://tests.test/",URLZONE_INTERNET},
882     {"zip://www.tests.test/",URLZONE_INTERNET},
883     {"zip://tests.test/",URLZONE_INTERNET},
884     /* Tests for "www.testing.com" zone mappings. */
885     {"http://google.www.testing.com/",URLZONE_INTERNET},
886     {"http://www.testing.com/",URLZONE_CUSTOM,FALSE,URLZONE_INTERNET},
887     {"http://testing.www.testing.com/",URLZONE_CUSTOM2,FALSE,URLZONE_INTERNET},
888     /* Tests for "org" zone mappings. */
889     {"http://google.org/",URLZONE_INTERNET,FALSE,URLZONE_CUSTOM},
890     {"http://org/",URLZONE_CUSTOM},
891     {"http://testing.org/",URLZONE_CUSTOM2},
892     /* Tests for "wine.testing" mapping */
893     {"*:wine.testing/test",URLZONE_CUSTOM2},
894     {"http://wine.testing/testing",URLZONE_CUSTOM2}
895 };
896
897 static void test_zone_domain_mappings(void)
898 {
899     HRESULT hres;
900     DWORD i, res;
901     IInternetSecurityManager *secmgr = NULL;
902     HKEY domains;
903     DWORD zone = URLZONE_INVALID;
904
905     trace("testing zone domain mappings...\n");
906
907     hres = pCoInternetCreateSecurityManager(NULL, &secmgr, 0);
908     ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres);
909
910     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, szZoneMapDomainsKey, &domains);
911     if(res == ERROR_SUCCESS) {
912         static const WCHAR local_machineW[] = {'h','t','t','p',':','/','/','t','e','s','t','.','l','o','c','a','l',
913                 '.','m','a','c','h','i','n','e','/',0};
914
915         hres = IInternetSecurityManager_MapUrlToZone(secmgr, local_machineW, &zone, 0);
916         ok(hres == S_OK, "MapUrlToZone failed: %08x\n", hres);
917         ok(zone == URLZONE_CUSTOM, "Expected URLZONE_CUSTOM, but got %d\n", zone);
918
919         RegCloseKey(domains);
920     }
921
922     for(i = 0; i < sizeof(zone_mapping_tests)/sizeof(zone_mapping_tests[0]); ++i) {
923         const zone_mapping_test *test = zone_mapping_tests+i;
924         LPWSTR urlW = a2w(test->url);
925         zone = URLZONE_INVALID;
926
927         hres = IInternetSecurityManager_MapUrlToZone(secmgr, urlW, &zone, 0);
928         ok(hres == S_OK, "MapUrlToZone failed: %08x\n", hres);
929         if(test->todo)
930             todo_wine
931                 ok(zone == test->zone || broken(test->broken_zone == zone),
932                     "Expected %d, but got %d on test %d\n", test->zone, zone, i);
933         else
934             ok(zone == test->zone || broken(test->broken_zone == zone),
935                 "Expected %d, but got %d on test %d\n", test->zone, zone, i);
936
937         heap_free(urlW);
938     }
939
940     IInternetSecurityManager_Release(secmgr);
941 }
942
943 static void test_zone_domains(void)
944 {
945     if(is_ie_hardened()) {
946         skip("IE running in Enhanced Security Configuration\n");
947         return;
948     } else if(!pCreateUri) {
949         win_skip("Skipping zone domain tests, IE too old\n");
950         return;
951     }
952
953     trace("testing zone domains...\n");
954
955     test_zone_domain_cache();
956
957     register_zone_domains();
958     run_child_process();
959     unregister_zone_domains();
960 }
961
962 static void test_CoInternetCreateZoneManager(void)
963 {
964     IInternetZoneManager *zonemgr = NULL;
965     IUnknown *punk = NULL;
966     HRESULT hr;
967
968     trace("simple zone manager tests...\n");
969
970     hr = pCoInternetCreateZoneManager(NULL, &zonemgr, 0);
971     ok(hr == S_OK, "CoInternetCreateZoneManager result: 0x%x\n", hr);
972     if (FAILED(hr))
973         return;
974
975     hr = IInternetZoneManager_QueryInterface(zonemgr, &IID_IUnknown, (void **) &punk);
976     ok(SUCCEEDED(hr), "got 0x%x with %p (expected Success)\n", hr, punk);
977     if (punk)
978         IUnknown_Release(punk);
979
980     hr = IInternetZoneManager_QueryInterface(zonemgr, &IID_IInternetZoneManager, (void **) &punk);
981     ok(SUCCEEDED(hr), "got 0x%x with %p (expected Success)\n", hr, punk);
982     if (punk)
983         IUnknown_Release(punk);
984
985
986     hr = IInternetZoneManager_QueryInterface(zonemgr, &IID_IInternetZoneManagerEx, (void **) &punk);
987     if (SUCCEEDED(hr)) {
988         IUnknown_Release(punk);
989
990         hr = IInternetZoneManager_QueryInterface(zonemgr, &IID_IInternetZoneManagerEx2, (void **) &punk);
991         ok(hr == S_OK || broken(hr == E_NOINTERFACE /* some W2K3 */),
992            "got 0x%x (expected S_OK)\n", hr);
993         if (punk)
994             IUnknown_Release(punk);
995         else
996             win_skip("InternetZoneManagerEx2 not supported\n");
997
998     }
999     else
1000         win_skip("InternetZoneManagerEx not supported\n");
1001
1002     hr = IInternetZoneManager_Release(zonemgr);
1003     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1004
1005 }
1006
1007 static void test_CreateZoneEnumerator(void)
1008 {
1009     IInternetZoneManager *zonemgr = NULL;
1010     HRESULT hr;
1011     DWORD dwEnum;
1012     DWORD dwEnum2;
1013     DWORD dwCount;
1014     DWORD dwCount2;
1015
1016     trace("testing zone enumerator...\n");
1017
1018     hr = pCoInternetCreateZoneManager(NULL, &zonemgr, 0);
1019     ok(hr == S_OK, "CoInternetCreateZoneManager result: 0x%x\n", hr);
1020     if (FAILED(hr))
1021         return;
1022
1023     dwEnum=0xdeadbeef;
1024     hr = IInternetZoneManager_CreateZoneEnumerator(zonemgr, &dwEnum, NULL, 0);
1025     ok((hr == E_INVALIDARG) && (dwEnum == 0xdeadbeef),
1026         "got 0x%x with 0x%x (expected E_INVALIDARG with 0xdeadbeef)\n", hr, dwEnum);
1027
1028     dwCount=0xdeadbeef;
1029     hr = IInternetZoneManager_CreateZoneEnumerator(zonemgr, NULL, &dwCount, 0);
1030     ok((hr == E_INVALIDARG) && (dwCount == 0xdeadbeef),
1031         "got 0x%x and 0x%x (expected E_INVALIDARG and 0xdeadbeef)\n", hr, dwCount);
1032
1033     dwEnum=0xdeadbeef;
1034     dwCount=0xdeadbeef;
1035     hr = IInternetZoneManager_CreateZoneEnumerator(zonemgr, &dwEnum, &dwCount, 0xffffffff);
1036     ok((hr == E_INVALIDARG) && (dwEnum == 0xdeadbeef) && (dwCount == 0xdeadbeef),
1037         "got 0x%x with 0x%x and 0x%x (expected E_INVALIDARG with 0xdeadbeef and 0xdeadbeef)\n",
1038         hr, dwEnum, dwCount);
1039
1040     dwEnum=0xdeadbeef;
1041     dwCount=0xdeadbeef;
1042     hr = IInternetZoneManager_CreateZoneEnumerator(zonemgr, &dwEnum, &dwCount, 1);
1043     ok((hr == E_INVALIDARG) && (dwEnum == 0xdeadbeef) && (dwCount == 0xdeadbeef),
1044         "got 0x%x with 0x%x and 0x%x (expected E_INVALIDARG with 0xdeadbeef and 0xdeadbeef)\n",
1045         hr, dwEnum, dwCount);
1046
1047     dwEnum=0xdeadbeef;
1048     dwCount=0xdeadbeef;
1049     /* Normal use */
1050     hr = IInternetZoneManager_CreateZoneEnumerator(zonemgr, &dwEnum, &dwCount, 0);
1051     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1052
1053     if (SUCCEEDED(hr)) {
1054         dwEnum2=0xdeadbeef;
1055         dwCount2=0xdeadbeef;
1056         hr = IInternetZoneManager_CreateZoneEnumerator(zonemgr, &dwEnum2, &dwCount2, 0);
1057         ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1058         if (SUCCEEDED(hr)) {
1059             /* native urlmon has an incrementing counter for dwEnum */
1060             hr = IInternetZoneManager_DestroyZoneEnumerator(zonemgr, dwEnum2);
1061             ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1062         }
1063
1064         hr = IInternetZoneManager_DestroyZoneEnumerator(zonemgr, dwEnum);
1065         ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1066
1067         /* Destroy the Enumerator twice is detected and handled in native urlmon */
1068         hr = IInternetZoneManager_DestroyZoneEnumerator(zonemgr, dwEnum);
1069         ok((hr == E_INVALIDARG), "got 0x%x (expected E_INVALIDARG)\n", hr);
1070     }
1071
1072     /* ::Release succeed also, when a ::DestroyZoneEnumerator is missing */
1073     hr = IInternetZoneManager_Release(zonemgr);
1074     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1075 }
1076
1077 static void test_GetZoneActionPolicy(void)
1078 {
1079     IInternetZoneManager *zonemgr = NULL;
1080     BYTE buf[32];
1081     HRESULT hres;
1082     DWORD action = URLACTION_CREDENTIALS_USE; /* Implemented on all IE versions */
1083
1084     trace("testing GetZoneActionPolixy...\n");
1085
1086     hres = pCoInternetCreateZoneManager(NULL, &zonemgr, 0);
1087     ok(hres == S_OK, "CoInternetCreateZoneManager failed: %08x\n", hres);
1088     if(FAILED(hres))
1089         return;
1090
1091     hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, buf,
1092             sizeof(DWORD), URLZONEREG_DEFAULT);
1093     ok(hres == S_OK, "GetZoneActionPolicy failed: %08x\n", hres);
1094     ok(*(DWORD*)buf == URLPOLICY_CREDENTIALS_SILENT_LOGON_OK ||
1095             *(DWORD*)buf == URLPOLICY_CREDENTIALS_MUST_PROMPT_USER ||
1096             *(DWORD*)buf == URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT ||
1097             *(DWORD*)buf == URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY,
1098             "unexpected policy=%d\n", *(DWORD*)buf);
1099
1100     hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, NULL,
1101             sizeof(DWORD), URLZONEREG_DEFAULT);
1102     ok(hres == E_INVALIDARG, "GetZoneActionPolicy failed: %08x, expected E_INVALIDARG\n", hres);
1103
1104     hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, action, buf,
1105             2, URLZONEREG_DEFAULT);
1106     ok(hres == E_INVALIDARG, "GetZoneActionPolicy failed: %08x, expected E_INVALIDARG\n", hres);
1107
1108     hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 3, 0x1fff, buf,
1109             sizeof(DWORD), URLZONEREG_DEFAULT);
1110     ok(hres == E_FAIL || broken(hres == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)),
1111             "(0x%x) got 0x%x (expected E_FAIL)\n", action, hres);
1112
1113     hres = IInternetZoneManager_GetZoneActionPolicy(zonemgr, 13, action, buf,
1114             sizeof(DWORD), URLZONEREG_DEFAULT);
1115     ok(hres == E_INVALIDARG, "GetZoneActionPolicy failed: %08x, expected E_INVALIDARG\n", hres);
1116
1117     IInternetZoneManager_Release(zonemgr);
1118 }
1119
1120 static void test_GetZoneAt(void)
1121 {
1122     IInternetZoneManager *zonemgr = NULL;
1123     HRESULT hr;
1124     DWORD dwEnum;
1125     DWORD dwCount;
1126     DWORD dwZone;
1127     DWORD i;
1128
1129     trace("testing GetZoneAt...\n");
1130
1131     hr = pCoInternetCreateZoneManager(NULL, &zonemgr, 0);
1132     ok(hr == S_OK, "CoInternetCreateZoneManager result: 0x%x\n", hr);
1133     if (FAILED(hr))
1134         return;
1135
1136     hr = IInternetZoneManager_CreateZoneEnumerator(zonemgr, &dwEnum, &dwCount, 0);
1137     if (FAILED(hr))
1138         goto cleanup;
1139
1140     if (0) {
1141         /* this crashes with native urlmon */
1142         IInternetZoneManager_GetZoneAt(zonemgr, dwEnum, 0, NULL);
1143     }
1144
1145     dwZone = 0xdeadbeef;
1146     hr = IInternetZoneManager_GetZoneAt(zonemgr, 0xdeadbeef, 0, &dwZone);
1147     ok(hr == E_INVALIDARG,
1148         "got 0x%x with 0x%x (expected E_INVALIDARG)\n", hr, dwZone);
1149
1150     for (i = 0; i < dwCount; i++)
1151     {
1152         dwZone = 0xdeadbeef;
1153         hr = IInternetZoneManager_GetZoneAt(zonemgr, dwEnum, i, &dwZone);
1154         ok(hr == S_OK, "#%d: got x%x with %d (expected S_OK)\n", i, hr, dwZone);
1155     }
1156
1157     dwZone = 0xdeadbeef;
1158     /* MSDN (index .. must be .. less than or equal to) is wrong */
1159     hr = IInternetZoneManager_GetZoneAt(zonemgr, dwEnum, dwCount, &dwZone);
1160     ok(hr == E_INVALIDARG,
1161         "got 0x%x with 0x%x (expected E_INVALIDARG)\n", hr, dwZone);
1162
1163     hr = IInternetZoneManager_DestroyZoneEnumerator(zonemgr, dwEnum);
1164     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1165
1166 cleanup:
1167     hr = IInternetZoneManager_Release(zonemgr);
1168     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1169 }
1170
1171 static void test_GetZoneAttributes(void)
1172 {
1173     IInternetZoneManager *zonemgr = NULL;
1174     CHAR buffer [sizeof(ZONEATTRIBUTES) + 32];
1175     ZONEATTRIBUTES* pZA = (ZONEATTRIBUTES*) buffer;
1176     HRESULT hr;
1177     DWORD i;
1178
1179     trace("testing GetZoneAttributes...\n");
1180
1181     hr = pCoInternetCreateZoneManager(NULL, &zonemgr, 0);
1182     ok(hr == S_OK, "CoInternetCreateZoneManager result: 0x%x\n", hr);
1183     if (FAILED(hr))
1184         return;
1185
1186     /* native urlmon has Zone "0" up to Zone "4" since IE4 */
1187     for (i = 0; i < 5; i++) {
1188         memset(buffer, -1, sizeof(buffer));
1189         hr = IInternetZoneManager_GetZoneAttributes(zonemgr, i, pZA);
1190         ok(hr == S_OK, "#%d: got 0x%x (expected S_OK)\n", i, hr);
1191     }
1192
1193     /* IE8 no longer set cbSize */
1194     memset(buffer, -1, sizeof(buffer));
1195     pZA->cbSize = 0;
1196     hr = IInternetZoneManager_GetZoneAttributes(zonemgr, 0, pZA);
1197     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1198     ok((pZA->cbSize == 0) || (pZA->cbSize == sizeof(ZONEATTRIBUTES)),
1199         "got cbSize = %d (expected 0)\n", pZA->cbSize);
1200
1201     memset(buffer, -1, sizeof(buffer));
1202     pZA->cbSize = 64;
1203     hr = IInternetZoneManager_GetZoneAttributes(zonemgr, 0, pZA);
1204     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1205     ok((pZA->cbSize == 64) || (pZA->cbSize == sizeof(ZONEATTRIBUTES)),
1206         "got cbSize = %d (expected 64)\n", pZA->cbSize);
1207
1208     memset(buffer, -1, sizeof(buffer));
1209     hr = IInternetZoneManager_GetZoneAttributes(zonemgr, 0, pZA);
1210     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1211     ok((pZA->cbSize == 0xffffffff) || (pZA->cbSize == sizeof(ZONEATTRIBUTES)),
1212         "got cbSize = 0x%x (expected 0xffffffff)\n", pZA->cbSize);
1213
1214     /* IE8 no longer fail on invalid zones */
1215     memset(buffer, -1, sizeof(buffer));
1216     hr = IInternetZoneManager_GetZoneAttributes(zonemgr, 0xdeadbeef, pZA);
1217     ok(hr == S_OK || (hr == E_FAIL),
1218         "got 0x%x (expected S_OK or E_FAIL)\n", hr);
1219
1220     hr = IInternetZoneManager_GetZoneAttributes(zonemgr, 0, NULL);
1221     ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
1222
1223     hr = IInternetZoneManager_Release(zonemgr);
1224     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1225 }
1226
1227 static void test_SetZoneAttributes(void)
1228 {
1229     IInternetZoneManager *zonemgr = NULL;
1230     CHAR buffer [sizeof(ZONEATTRIBUTES) + 16];
1231     ZONEATTRIBUTES* pZA = (ZONEATTRIBUTES*) buffer;
1232     CHAR regpath[MAX_PATH];
1233     HKEY hkey;
1234     HRESULT hr;
1235     DWORD res;
1236
1237     trace("testing SetZoneAttributes...\n");
1238     hr = pCoInternetCreateZoneManager(NULL, &zonemgr, 0);
1239     ok(hr == S_OK, "CoInternetCreateZoneManager result: 0x%x\n", hr);
1240     if (FAILED(hr))
1241         return;
1242
1243     memset(buffer, -1, sizeof(buffer));
1244     hr = IInternetZoneManager_GetZoneAttributes(zonemgr, URLZONE_LOCAL_MACHINE, pZA);
1245     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1246
1247     sprintf(regpath, "%s\\Zones\\%d", szInternetSettingsKey, URLZONE_CUSTOM);
1248     res = RegCreateKeyA(HKEY_CURRENT_USER, regpath, &hkey);
1249     RegCloseKey(hkey);
1250
1251     ok(res == ERROR_SUCCESS, "got %d (expected ERROR_SUCCESS)\n", res);
1252     if (res != ERROR_SUCCESS)
1253         goto cleanup;
1254
1255     pZA->cbSize = sizeof(ZONEATTRIBUTES);
1256     hr = IInternetZoneManager_SetZoneAttributes(zonemgr, URLZONE_CUSTOM, NULL);
1257     ok(hr == E_INVALIDARG, "got 0x%x (expected E_INVALIDARG)\n", hr);
1258
1259     /* normal use */
1260     hr = IInternetZoneManager_SetZoneAttributes(zonemgr, URLZONE_CUSTOM, pZA);
1261     if (hr == E_FAIL) {
1262         win_skip("SetZoneAttributes not supported: IE too old\n");
1263         goto cleanup;
1264     }
1265     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1266
1267     /* native urlmon ignores cbSize */
1268     pZA->cbSize = sizeof(ZONEATTRIBUTES) + sizeof(DWORD);
1269     hr = IInternetZoneManager_SetZoneAttributes(zonemgr, URLZONE_CUSTOM, pZA);
1270     ok(hr == S_OK, "got 0x%x for sizeof(ZONEATTRIBUTES) + sizeof(DWORD) (expected S_OK)\n", hr);
1271
1272     pZA->cbSize = sizeof(ZONEATTRIBUTES) - sizeof(DWORD);
1273     hr = IInternetZoneManager_SetZoneAttributes(zonemgr, URLZONE_CUSTOM, pZA);
1274     ok(hr == S_OK, "got 0x%x for sizeof(ZONEATTRIBUTES) - sizeof(DWORD) (expected S_OK)\n", hr);
1275
1276     pZA->cbSize = 0;
1277     hr = IInternetZoneManager_SetZoneAttributes(zonemgr, URLZONE_CUSTOM, pZA);
1278     ok(hr == S_OK, "got 0x%x for size 0 (expected S_OK)\n", hr);
1279
1280     /* The key for the zone must be present, when calling SetZoneAttributes */
1281     myRegDeleteTreeA(HKEY_CURRENT_USER, regpath);
1282     /* E_FAIL is returned from IE6 here, which is reasonable.
1283        All newer IE return S_OK without saving the zone attributes to the registry.
1284        This is a Windows bug, but we have to accept that as standard */
1285     hr = IInternetZoneManager_SetZoneAttributes(zonemgr, URLZONE_CUSTOM, pZA);
1286     ok((hr == S_OK) || broken(hr == E_FAIL), "got 0x%x (expected S_OK)\n", hr);
1287
1288     /* SetZoneAttributes did not create the directory */
1289     res = RegOpenKeyA(HKEY_CURRENT_USER, regpath, &hkey);
1290     ok((res == ERROR_FILE_NOT_FOUND) && (hkey == NULL),
1291         "got %u with %p (expected ERROR_FILE_NOT_FOUND with NULL)\n", res, hkey);
1292
1293     if (hkey) RegCloseKey(hkey);
1294
1295 cleanup:
1296     /* delete zone settings in the registry */
1297     myRegDeleteTreeA(HKEY_CURRENT_USER, regpath);
1298
1299     hr = IInternetZoneManager_Release(zonemgr);
1300     ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr);
1301 }
1302
1303
1304 static void test_InternetSecurityMarshalling(void)
1305 {
1306     IInternetSecurityManager *secmgr = NULL;
1307     IUnknown *unk;
1308     IStream *stream;
1309     HRESULT hres;
1310
1311     trace("testing marshalling...\n");
1312
1313     hres = pCoInternetCreateSecurityManager(NULL, &secmgr, 0);
1314     ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres);
1315     if(FAILED(hres))
1316         return;
1317
1318     hres = IInternetSecurityManager_QueryInterface(secmgr, &IID_IUnknown, (void**)&unk);
1319     ok(hres == S_OK, "QueryInterface returned: %08x\n", hres);
1320
1321     hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1322     ok(hres == S_OK, "CreateStreamOnHGlobal returned: %08x\n", hres);
1323
1324     hres = CoMarshalInterface(stream, &IID_IInternetSecurityManager, unk, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1325     /* Not supported in W98 */
1326     ok(hres == S_OK || broken(hres == REGDB_E_IIDNOTREG),
1327         "CoMarshalInterface returned: %08x\n", hres);
1328
1329     IStream_Release(stream);
1330     IUnknown_Release(unk);
1331     IInternetSecurityManager_Release(secmgr);
1332 }
1333
1334 static void test_InternetGetSecurityUrl(void)
1335 {
1336     const WCHAR url5_out[] = {'h','t','t','p',':','w','w','w','.','z','o','n','e','3',
1337                               '.','w','i','n','e','t','e','s','t',0};
1338     const WCHAR url7_out[] = {'f','t','p',':','z','o','n','e','3','.','w','i','n','e','t','e','s','t',0};
1339
1340     const WCHAR *in[] = {url2, url3, url4, url5, url7, url8, url9, url10};
1341     const WCHAR *out_default[] = {url2, url3, url4, url5_out, url7_out, url8, url5_out, url10};
1342     const WCHAR *out_securl[] = {url2, url3, url4, url5, url7, url8, url9, url10};
1343
1344     WCHAR *sec;
1345     DWORD i;
1346     HRESULT hres;
1347
1348     trace("testing CoInternetGetSecurityUrl...\n");
1349
1350     for(i=0; i<sizeof(in)/sizeof(WCHAR*); i++) {
1351         hres = pCoInternetGetSecurityUrl(in[i], &sec, PSU_DEFAULT, 0);
1352         ok(hres == S_OK, "(%d) CoInternetGetSecurityUrl returned: %08x\n", i, hres);
1353         if(hres == S_OK) {
1354             ok(!strcmp_w(sec, out_default[i]), "(%d) Got %s, expected %s\n",
1355                     i, wine_dbgstr_w(sec), wine_dbgstr_w(out_default[i]));
1356             CoTaskMemFree(sec);
1357         }
1358
1359         hres = pCoInternetGetSecurityUrl(in[i], &sec, PSU_SECURITY_URL_ONLY, 0);
1360         ok(hres == S_OK, "(%d) CoInternetGetSecurityUrl returned: %08x\n", i, hres);
1361         if(hres == S_OK) {
1362             ok(!strcmp_w(sec, out_securl[i]), "(%d) Got %s, expected %s\n",
1363                     i, wine_dbgstr_w(sec), wine_dbgstr_w(out_securl[i]));
1364             CoTaskMemFree(sec);
1365         }
1366     }
1367
1368     SET_EXPECT(ParseUrl_SECURITY_URL_input2);
1369     SET_EXPECT(ParseUrl_SECURITY_URL_expected);
1370     SET_EXPECT(ParseUrl_SECURITY_DOMAIN_expected);
1371
1372     hres = pCoInternetGetSecurityUrl(security_url2W, &sec, PSU_DEFAULT, 0);
1373     ok(hres == S_OK, "CoInternetGetSecurityUrl returned 0x%08x, expected S_OK\n", hres);
1374
1375     CHECK_CALLED(ParseUrl_SECURITY_URL_input2);
1376     CHECK_CALLED(ParseUrl_SECURITY_URL_expected);
1377     CHECK_CALLED(ParseUrl_SECURITY_DOMAIN_expected);
1378
1379     ok(!lstrcmpW(security_expectedW, sec), "Expected %s but got %s\n",
1380        wine_dbgstr_w(security_expectedW), wine_dbgstr_w(sec));
1381     CoTaskMemFree(sec);
1382 }
1383
1384 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
1385                                                           REFIID riid, void **ppv)
1386 {
1387     ok(0, "unexpected call\n");
1388     return E_NOINTERFACE;
1389 }
1390
1391 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
1392 {
1393     return 2;
1394 }
1395
1396 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
1397 {
1398     return 1;
1399 }
1400
1401 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
1402         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
1403         DWORD *pcchResult, DWORD dwReserved)
1404 {
1405     const WCHAR *ret = NULL;
1406
1407     ok(pwzResult != NULL, "pwzResult == NULL\n");
1408     ok(pcchResult != NULL, "pcchResult == NULL\n");
1409     ok(!dwParseFlags, "Expected 0, but got 0x%08x\n", dwParseFlags);
1410
1411     switch(ParseAction) {
1412     case PARSE_SECURITY_URL:
1413         if(!strcmp_w(pwzUrl, security_urlW)) {
1414             CHECK_EXPECT(ParseUrl_SECURITY_URL_input);
1415             ok(cchResult == lstrlenW(pwzUrl)+1, "Got %d\n", cchResult);
1416             ret = security_expectedW;
1417         } else if(!strcmp_w(pwzUrl, security_url2W)) {
1418             CHECK_EXPECT(ParseUrl_SECURITY_URL_input2);
1419             ok(cchResult == lstrlenW(pwzUrl)+1, "Got %d\n", cchResult);
1420             ret = security_expectedW;
1421         } else if(!strcmp_w(pwzUrl, security_expectedW)) {
1422             CHECK_EXPECT(ParseUrl_SECURITY_URL_expected);
1423             ok(cchResult == lstrlenW(pwzUrl)+1, "Got %d\n", cchResult);
1424             ret = security_expectedW;
1425         } else if(!strcmp_w(pwzUrl, winetest_to_httpW)) {
1426             switch(++called_securl_http) {
1427             case 1:
1428                 ok(cchResult == lstrlenW(pwzUrl)+1, "Got %d\n", cchResult);
1429                 break;
1430             case 2:
1431                 CHECK_EXPECT(ParseUrl_SECURITY_URL_http);
1432                 ok(cchResult == lstrlenW(url9)+1, "Got %d\n", cchResult);
1433                 break;
1434             default:
1435                 todo_wine CHECK_EXPECT(ParseUrl_SECURITY_URL_http);
1436             }
1437             ret = url9;
1438         } else
1439             ok(0, "Unexpected call, pwzUrl=%s\n", wine_dbgstr_w(pwzUrl));
1440
1441         break;
1442     case PARSE_SECURITY_DOMAIN:
1443
1444         CHECK_EXPECT(ParseUrl_SECURITY_DOMAIN_expected);
1445
1446         ok(!strcmp_w(pwzUrl, security_expectedW), "Expected %s but got %s\n",
1447             wine_dbgstr_w(security_expectedW), wine_dbgstr_w(pwzUrl));
1448         ok(cchResult == lstrlenW(pwzUrl)+1, "Got %d\n", cchResult);
1449         ret = security_expectedW;
1450         break;
1451     default:
1452         ok(0, "Unexpected call, ParseAction=%d pwzUrl=%s\n", ParseAction,
1453             wine_dbgstr_w(pwzUrl));
1454     }
1455
1456     if(!ret)
1457         return E_FAIL;
1458
1459     *pcchResult = lstrlenW(ret)+1;
1460     if(*pcchResult > cchResult)
1461         return S_FALSE;
1462     memcpy(pwzResult, ret, (*pcchResult)*sizeof(WCHAR));
1463     return S_OK;
1464 }
1465
1466 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
1467         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
1468         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
1469 {
1470     ok(0, "unexpected call\n");
1471     return E_NOTIMPL;
1472 }
1473
1474 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
1475         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
1476 {
1477     ok(0, "unexpected call\n");
1478     return E_NOTIMPL;
1479 }
1480
1481 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
1482         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
1483         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
1484 {
1485     ok(0, "unexpected call\n");
1486     return E_NOTIMPL;
1487 }
1488
1489 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
1490     InternetProtocolInfo_QueryInterface,
1491     InternetProtocolInfo_AddRef,
1492     InternetProtocolInfo_Release,
1493     InternetProtocolInfo_ParseUrl,
1494     InternetProtocolInfo_CombineUrl,
1495     InternetProtocolInfo_CompareUrl,
1496     InternetProtocolInfo_QueryInfo
1497 };
1498
1499 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
1500
1501 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
1502 {
1503     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
1504         *ppv = &protocol_info;
1505         return S_OK;
1506     }
1507
1508     ok(0, "unexpected call\n");
1509     return E_NOINTERFACE;
1510 }
1511
1512 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
1513 {
1514     return 2;
1515 }
1516
1517 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
1518 {
1519     return 1;
1520 }
1521
1522 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1523                                         REFIID riid, void **ppv)
1524 {
1525     ok(0, "unexpected call\n");
1526     return E_NOTIMPL;
1527 }
1528
1529 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
1530 {
1531     ok(0, "unexpected call\n");
1532     return S_OK;
1533 }
1534
1535 static const IClassFactoryVtbl ClassFactoryVtbl = {
1536     ClassFactory_QueryInterface,
1537     ClassFactory_AddRef,
1538     ClassFactory_Release,
1539     ClassFactory_CreateInstance,
1540     ClassFactory_LockServer
1541 };
1542
1543 static IClassFactory protocol_cf = { &ClassFactoryVtbl };
1544
1545 static void register_protocols(void)
1546 {
1547     IInternetSession *session;
1548     HRESULT hres;
1549
1550     hres = pCoInternetGetSession(0, &session, 0);
1551     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
1552     if(FAILED(hres))
1553         return;
1554
1555     hres = IInternetSession_RegisterNameSpace(session, &protocol_cf, &IID_NULL,
1556             winetestW, 0, NULL, 0);
1557     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
1558
1559     IInternetSession_Release(session);
1560 }
1561
1562 static void unregister_protocols(void) {
1563     IInternetSession *session;
1564     HRESULT hr;
1565
1566     hr = pCoInternetGetSession(0, &session, 0);
1567     ok(hr == S_OK, "CoInternetGetSession failed: 0x%08x\n", hr);
1568     if(FAILED(hr))
1569         return;
1570
1571     hr = IInternetSession_UnregisterNameSpace(session, &protocol_cf, winetestW);
1572     ok(hr == S_OK, "UnregisterNameSpace failed: 0x%08x\n", hr);
1573
1574     IInternetSession_Release(session);
1575 }
1576
1577 static const struct {
1578     const char  *uri;
1579     DWORD       create_flags;
1580     const char  *security_uri;
1581     HRESULT     security_hres;
1582     const char  *default_uri;
1583     HRESULT     default_hres;
1584     BOOL        todo;
1585 } sec_url_ex_tests[] = {
1586     {"index.htm",Uri_CREATE_ALLOW_RELATIVE,"*:index.html",S_OK,"*:index.htm",S_OK},
1587     {"file://c:\\Index.htm",Uri_CREATE_FILE_USE_DOS_PATH,"file:///c:/Index.htm",S_OK,"file:///c:/Index.htm",S_OK},
1588     {"file:some%20file%2ejpg",0,NULL,E_INVALIDARG,NULL,E_INVALIDARG},
1589     {"file:some file.jpg",0,NULL,E_INVALIDARG,NULL,E_INVALIDARG},
1590     {"http://www.zone3.winetest/",0,"http://www.zone3.winetest/",S_OK,"http://www.zone3.winetest/",S_OK},
1591     {"about:blank",0,"about:blank",S_OK,"about:blank",S_OK},
1592     {"ftp://zone3.winetest/file.test",0,"ftp://zone3.winetest/file.test",S_OK,"ftp://zone3.winetest/file.test",S_OK},
1593     {"test:123abc",0,"test:123abc",S_OK,"test:123abc",S_OK},
1594     {"http:google.com/test.file",0,"http:google.com/test.file",S_OK,"http:google.com/test.file",S_OK},
1595     {"ftp://test@ftp.winehq.org/",0,"ftp://ftp.winehq.org/",S_OK,"ftp://ftp.winehq.org/",S_OK},
1596     {"test://google@ftp.winehq.org/",0,"test://google@ftp.winehq.org/",S_OK,"test://google@ftp.winehq.org/",S_OK}
1597 };
1598
1599 static void test_InternetGetSecurityUrlEx(void)
1600 {
1601     HRESULT hr;
1602     DWORD i;
1603     IUri *uri = NULL, *result = NULL;
1604
1605     trace("testing CoInternetGetSecurityUrlEx...\n");
1606
1607     hr = pCoInternetGetSecurityUrlEx(NULL, NULL, PSU_DEFAULT, 0);
1608     ok(hr == E_INVALIDARG, "CoInternetGetSecurityUrlEx returned 0x%08x, expected E_INVALIDARG\n", hr);
1609
1610     result = (void*) 0xdeadbeef;
1611     hr = pCoInternetGetSecurityUrlEx(NULL, &result, PSU_DEFAULT, 0);
1612     ok(hr == E_INVALIDARG, "CoInternetGetSecurityUrlEx returned 0x%08x, expected E_INVALIDARG\n", hr);
1613     ok(result == (void*) 0xdeadbeef, "'result' was %p\n", result);
1614
1615     for(i = 0; i < sizeof(sec_url_ex_tests)/sizeof(sec_url_ex_tests[0]); ++i) {
1616         LPWSTR uriW = a2w(sec_url_ex_tests[i].uri);
1617         uri = NULL;
1618
1619         hr = pCreateUri(uriW, sec_url_ex_tests[i].create_flags, 0, &uri);
1620         ok(hr == S_OK, "CreateUri returned 0x%08x on test %d\n", hr, i);
1621         if(hr == S_OK) {
1622             result = NULL;
1623
1624             hr = pCoInternetGetSecurityUrlEx(uri, &result, PSU_DEFAULT, 0);
1625             if(sec_url_ex_tests[i].todo) {
1626                 todo_wine
1627                     ok(hr == sec_url_ex_tests[i].default_hres,
1628                         "CoInternetGetSecurityUrlEx returned 0x%08x, expected 0x%08x on test %d\n",
1629                         hr, sec_url_ex_tests[i].default_hres, i);
1630             } else {
1631                 ok(hr == sec_url_ex_tests[i].default_hres,
1632                     "CoInternetGetSecurityUrlEx returned 0x%08x, expected 0x%08x on test %d\n",
1633                     hr, sec_url_ex_tests[i].default_hres, i);
1634             }
1635             if(SUCCEEDED(hr)) {
1636                 BSTR received;
1637
1638                 hr = IUri_GetDisplayUri(result, &received);
1639                 ok(hr == S_OK, "GetDisplayUri returned 0x%08x on test %d\n", hr, i);
1640                 if(hr == S_OK) {
1641                     if(sec_url_ex_tests[i].todo) {
1642                         todo_wine
1643                             ok(!strcmp_aw(sec_url_ex_tests[i].default_uri, received),
1644                                 "Expected %s but got %s on test %d\n", sec_url_ex_tests[i].default_uri,
1645                                 wine_dbgstr_w(received), i);
1646                     } else {
1647                         ok(!strcmp_aw(sec_url_ex_tests[i].default_uri, received),
1648                             "Expected %s but got %s on test %d\n", sec_url_ex_tests[i].default_uri,
1649                             wine_dbgstr_w(received), i);
1650                     }
1651                 }
1652                 SysFreeString(received);
1653             }
1654             if(result) IUri_Release(result);
1655
1656             result = NULL;
1657             hr = pCoInternetGetSecurityUrlEx(uri, &result, PSU_SECURITY_URL_ONLY, 0);
1658             if(sec_url_ex_tests[i].todo) {
1659                 todo_wine
1660                     ok(hr == sec_url_ex_tests[i].default_hres,
1661                         "CoInternetGetSecurityUrlEx returned 0x%08x, expected 0x%08x on test %d\n",
1662                         hr, sec_url_ex_tests[i].default_hres, i);
1663             } else {
1664                 ok(hr == sec_url_ex_tests[i].default_hres,
1665                     "CoInternetGetSecurityUrlEx returned 0x%08x, expected 0x%08x on test %d\n",
1666                     hr, sec_url_ex_tests[i].default_hres, i);
1667             }
1668             if(SUCCEEDED(hr)) {
1669                 BSTR received;
1670
1671                 hr = IUri_GetDisplayUri(result, &received);
1672                 ok(hr == S_OK, "GetDisplayUri returned 0x%08x on test %d\n", hr, i);
1673                 if(hr == S_OK) {
1674                     if(sec_url_ex_tests[i].todo) {
1675                         todo_wine
1676                             ok(!strcmp_aw(sec_url_ex_tests[i].default_uri, received),
1677                                 "Expected %s but got %s on test %d\n", sec_url_ex_tests[i].default_uri,
1678                                 wine_dbgstr_w(received), i);
1679                     } else {
1680                         ok(!strcmp_aw(sec_url_ex_tests[i].default_uri, received),
1681                             "Expected %s but got %s on test %d\n", sec_url_ex_tests[i].default_uri,
1682                             wine_dbgstr_w(received), i);
1683                     }
1684                 }
1685                 SysFreeString(received);
1686             }
1687             if(result) IUri_Release(result);
1688         }
1689
1690         if(uri) IUri_Release(uri);
1691         heap_free(uriW);
1692     }
1693 }
1694
1695 static void test_InternetGetSecurityUrlEx_Pluggable(void)
1696 {
1697     HRESULT hr;
1698     IUri *uri = NULL, *result;
1699
1700     trace("testing CoInternetGetSecurityUrlEx for pluggable protocols...\n");
1701
1702     hr = pCreateUri(security_urlW, 0, 0, &uri);
1703     ok(hr == S_OK, "CreateUri returned 0x%08x\n", hr);
1704     if(hr == S_OK) {
1705         SET_EXPECT(ParseUrl_SECURITY_URL_input);
1706         SET_EXPECT(ParseUrl_SECURITY_URL_expected);
1707         SET_EXPECT(ParseUrl_SECURITY_DOMAIN_expected);
1708
1709         hr = pCoInternetGetSecurityUrlEx(uri, &result, PSU_DEFAULT, 0);
1710         ok(hr == S_OK, "CoInternetGetSecurityUrlEx returned 0x%08x, expected S_OK\n", hr);
1711
1712         CHECK_CALLED(ParseUrl_SECURITY_URL_input);
1713         CHECK_CALLED(ParseUrl_SECURITY_URL_expected);
1714         CHECK_CALLED(ParseUrl_SECURITY_DOMAIN_expected);
1715
1716         if(hr == S_OK) {
1717             BSTR received = NULL;
1718
1719             hr = IUri_GetAbsoluteUri(result, &received);
1720             ok(hr == S_OK, "GetAbsoluteUri returned 0x%08x\n", hr);
1721             if(hr == S_OK) {
1722                 ok(!strcmp_w(security_expectedW, received), "Expected %s but got %s\n",
1723                     wine_dbgstr_w(security_expectedW), wine_dbgstr_w(received));
1724             }
1725             SysFreeString(received);
1726         }
1727         if(result) IUri_Release(result);
1728
1729         result = NULL;
1730
1731         SET_EXPECT(ParseUrl_SECURITY_URL_input);
1732         SET_EXPECT(ParseUrl_SECURITY_URL_expected);
1733
1734         hr = pCoInternetGetSecurityUrlEx(uri, &result, PSU_SECURITY_URL_ONLY, 0);
1735         ok(hr == S_OK, "CoInternetGetSecurityUrlEx returned 0x%08x, expected S_OK\n", hr);
1736
1737         CHECK_CALLED(ParseUrl_SECURITY_URL_input);
1738         CHECK_CALLED(ParseUrl_SECURITY_URL_expected);
1739
1740         if(hr == S_OK) {
1741             BSTR received = NULL;
1742
1743             hr = IUri_GetAbsoluteUri(result, &received);
1744             ok(hr == S_OK, "GetAbsoluteUri returned 0x%08x\n", hr);
1745             if(hr == S_OK) {
1746                 ok(!strcmp_w(security_expectedW, received), "Expected %s but got %s\n",
1747                     wine_dbgstr_w(security_expectedW), wine_dbgstr_w(received));
1748             }
1749             SysFreeString(received);
1750         }
1751         if(result) IUri_Release(result);
1752     }
1753     if(uri) IUri_Release(uri);
1754 }
1755
1756 static const BYTE secidex2_1[] = {'z','i','p',':','/','/','t','e','s','t','i','n','g','.','c','o','m','/',3,0,0,0};
1757 static const BYTE secidex2_2[] = {'z','i','p',':','t','e','s','t','i','n','g','.','c','o','m',3,0,0,0};
1758 static const BYTE secidex2_3[] = {'*',':','t','e','s','t','i','n','g','.','c','o','m',3,0,0,0};
1759
1760 static const struct {
1761     const char  *uri;
1762     DWORD       create_flags;
1763     HRESULT     map_hres;
1764     DWORD       zone;
1765     BOOL        map_todo;
1766     const BYTE  *secid;
1767     DWORD       secid_size;
1768     HRESULT     secid_hres;
1769     BOOL        secid_todo;
1770 } sec_mgr_ex2_tests[] = {
1771     {"res://mshtml.dll/blank.htm",0,S_OK,URLZONE_LOCAL_MACHINE,FALSE,secid1,sizeof(secid1),S_OK},
1772     {"index.htm",Uri_CREATE_ALLOW_RELATIVE,0,URLZONE_INTERNET,FALSE,secid2,sizeof(secid2),S_OK},
1773     {"file://c:\\Index.html",0,0,URLZONE_LOCAL_MACHINE,FALSE,secid1,sizeof(secid1),S_OK},
1774     {"http://www.zone3.winetest/",0,0,URLZONE_INTERNET,FALSE,secid5,sizeof(secid5),S_OK},
1775     {"about:blank",0,0,URLZONE_INTERNET,FALSE,secid6,sizeof(secid6),S_OK},
1776     {"ftp://zone3.winetest/file.test",0,0,URLZONE_INTERNET,FALSE,secid7,sizeof(secid7),S_OK},
1777     {"/file/testing/test.test",Uri_CREATE_ALLOW_RELATIVE,0,URLZONE_INTERNET,FALSE,NULL,0,E_INVALIDARG},
1778     {"zip://testing.com/",0,0,URLZONE_INTERNET,FALSE,secidex2_1,sizeof(secidex2_1),S_OK},
1779     {"zip:testing.com",0,0,URLZONE_INTERNET,FALSE,secidex2_2,sizeof(secidex2_2),S_OK},
1780     {"http:google.com",0,S_OK,URLZONE_INVALID,FALSE,NULL,0,E_INVALIDARG},
1781     {"http:/google.com",0,S_OK,URLZONE_INVALID,FALSE,NULL,0,E_INVALIDARG},
1782     {"*:/testing",0,S_OK,URLZONE_INTERNET,FALSE,NULL,0,E_INVALIDARG},
1783     {"*://testing.com",0,S_OK,URLZONE_INTERNET,FALSE,secidex2_3,sizeof(secidex2_3),S_OK}
1784 };
1785
1786 static void test_SecurityManagerEx2(void)
1787 {
1788     HRESULT hres;
1789     DWORD i, zone;
1790     BYTE buf[512];
1791     DWORD buf_size = sizeof(buf);
1792     IInternetSecurityManager *sec_mgr;
1793     IInternetSecurityManagerEx2 *sec_mgr2;
1794     IUri *uri = NULL;
1795
1796     static const WCHAR domainW[] = {'c','o','m','.','u','k',0};
1797
1798     if(!pCreateUri) {
1799         win_skip("Skipping SecurityManagerEx2, IE is too old\n");
1800         return;
1801     }
1802
1803     trace("Testing SecurityManagerEx2...\n");
1804
1805     hres = pCoInternetCreateSecurityManager(NULL, &sec_mgr, 0);
1806     ok(hres == S_OK, "CoInternetCreateSecurityManager failed: %08x\n", hres);
1807
1808     hres = IInternetSecurityManager_QueryInterface(sec_mgr, &IID_IInternetSecurityManagerEx2, (void**)&sec_mgr2);
1809     ok(hres == S_OK, "QueryInterface(IID_IInternetSecurityManagerEx2) failed: %08x\n", hres);
1810
1811     zone = 0xdeadbeef;
1812
1813     hres = IInternetSecurityManagerEx2_MapUrlToZoneEx2(sec_mgr2, NULL, &zone, 0, NULL, NULL);
1814     ok(hres == E_INVALIDARG, "MapUrlToZoneEx2 returned %08x, expected E_INVALIDARG\n", hres);
1815     ok(zone == URLZONE_INVALID, "zone was %d\n", zone);
1816
1817     hres = IInternetSecurityManagerEx2_GetSecurityIdEx2(sec_mgr2, NULL, buf, &buf_size, 0);
1818     ok(hres == E_INVALIDARG, "GetSecurityIdEx2 returned %08x, expected E_INVALIDARG\n", hres);
1819     ok(buf_size == sizeof(buf), "buf_size was %d\n", buf_size);
1820
1821     hres = pCreateUri(url5, 0, 0, &uri);
1822     ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
1823
1824     hres = IInternetSecurityManagerEx2_MapUrlToZoneEx2(sec_mgr2, uri, NULL, 0, NULL, NULL);
1825     ok(hres == E_INVALIDARG, "MapToUrlZoneEx2 returned %08x, expected E_INVALIDARG\n", hres);
1826
1827     buf_size = sizeof(buf);
1828     hres = IInternetSecurityManagerEx2_GetSecurityIdEx2(sec_mgr2, uri, NULL, &buf_size, 0);
1829     ok(hres == E_INVALIDARG || broken(hres == S_OK), "GetSecurityIdEx2 failed: %08x\n", hres);
1830     ok(buf_size == sizeof(buf), "bug_size was %d\n", buf_size);
1831
1832     hres = IInternetSecurityManagerEx2_GetSecurityIdEx2(sec_mgr2, uri, buf, NULL, 0);
1833     ok(hres == E_INVALIDARG, "GetSecurityIdEx2 returned %08x, expected E_INVALIDARG\n", hres);
1834
1835     IUri_Release(uri);
1836
1837     for(i = 0; i < sizeof(sec_mgr_ex2_tests)/sizeof(sec_mgr_ex2_tests[0]); ++i) {
1838         LPWSTR uriW = a2w(sec_mgr_ex2_tests[i].uri);
1839
1840         uri = NULL;
1841         zone = URLZONE_INVALID;
1842
1843         hres = pCreateUri(uriW, sec_mgr_ex2_tests[i].create_flags, 0, &uri);
1844         ok(hres == S_OK, "CreateUri returned %08x for '%s'\n", hres, sec_mgr_ex2_tests[i].uri);
1845
1846         hres = IInternetSecurityManagerEx2_MapUrlToZoneEx2(sec_mgr2, uri, &zone, 0, NULL, NULL);
1847         if(sec_mgr_ex2_tests[i].map_todo) {
1848             todo_wine
1849                 ok(hres == sec_mgr_ex2_tests[i].map_hres, "MapUrlZoneToEx2 returned %08x, expected %08x for '%s'\n",
1850                     hres, sec_mgr_ex2_tests[i].map_hres, sec_mgr_ex2_tests[i].uri);
1851             todo_wine
1852                 ok(zone == sec_mgr_ex2_tests[i].zone, "Expected zone %d, but got %d for '%s'\n", sec_mgr_ex2_tests[i].zone,
1853                     zone, sec_mgr_ex2_tests[i].uri);
1854         } else {
1855             ok(hres == sec_mgr_ex2_tests[i].map_hres, "MapUrlToZoneEx2 returned %08x, expected %08x for '%s'\n",
1856                 hres, sec_mgr_ex2_tests[i].map_hres, sec_mgr_ex2_tests[i].uri);
1857             ok(zone == sec_mgr_ex2_tests[i].zone, "Expected zone %d, but got %d for '%s'\n", sec_mgr_ex2_tests[i].zone,
1858                 zone, sec_mgr_ex2_tests[i].uri);
1859         }
1860
1861         buf_size = sizeof(buf);
1862         memset(buf, 0xf0, buf_size);
1863
1864         hres = IInternetSecurityManagerEx2_GetSecurityIdEx2(sec_mgr2, uri, buf, &buf_size, 0);
1865         if(sec_mgr_ex2_tests[i].secid_todo) {
1866             todo_wine
1867                 ok(hres == sec_mgr_ex2_tests[i].secid_hres, "GetSecurityIdEx2 returned %08x, expected %08x on test '%s'\n",
1868                     hres, sec_mgr_ex2_tests[i].secid_hres, sec_mgr_ex2_tests[i].uri);
1869             if(sec_mgr_ex2_tests[i].secid) {
1870                 todo_wine {
1871                     ok(buf_size == sec_mgr_ex2_tests[i].secid_size, "Got wrong security id size=%d, expected %d on test '%s'\n",
1872                         buf_size, sec_mgr_ex2_tests[i].secid_size, sec_mgr_ex2_tests[i].uri);
1873                     ok(!memcmp(buf, sec_mgr_ex2_tests[i].secid, sec_mgr_ex2_tests[i].secid_size), "Got wrong security id on test '%s'\n",
1874                         sec_mgr_ex2_tests[i].uri);
1875                 }
1876             }
1877         } else {
1878             ok(hres == sec_mgr_ex2_tests[i].secid_hres, "GetSecurityIdEx2 returned %08x, expected %08x on test '%s'\n",
1879                 hres, sec_mgr_ex2_tests[i].secid_hres, sec_mgr_ex2_tests[i].uri);
1880             if(sec_mgr_ex2_tests[i].secid) {
1881                 ok(buf_size == sec_mgr_ex2_tests[i].secid_size, "Got wrong security id size=%d, expected %d on test '%s'\n",
1882                     buf_size, sec_mgr_ex2_tests[i].secid_size, sec_mgr_ex2_tests[i].uri);
1883                 ok(!memcmp(buf, sec_mgr_ex2_tests[i].secid, sec_mgr_ex2_tests[i].secid_size), "Got wrong security id on test '%s'\n",
1884                     sec_mgr_ex2_tests[i].uri);
1885             }
1886         }
1887
1888         heap_free(uriW);
1889         IUri_Release(uri);
1890     }
1891
1892     hres = pCreateUri(url15, 0, 0, &uri);
1893     ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
1894
1895     buf_size = sizeof(buf);
1896     memset(buf, 0xf0, buf_size);
1897
1898     hres = IInternetSecurityManagerEx2_GetSecurityIdEx2(sec_mgr2, uri, buf, &buf_size, (DWORD_PTR)domainW);
1899     ok(hres == S_OK, "GetSecurityIdEx2 failed: %08x\n", hres);
1900     todo_wine ok(buf_size == sizeof(secid13), "buf_size was %d\n", buf_size);
1901     todo_wine ok(!memcmp(buf, secid13, sizeof(secid13)), "Got wrong secid\n");
1902
1903     buf_size = sizeof(buf);
1904     memset(buf, 0xf0, buf_size);
1905
1906     hres = IInternetSecurityManagerEx2_GetSecurityIdEx2(sec_mgr2, uri, buf, &buf_size, 0);
1907     ok(hres == S_OK, "GetSecurityIdEx2 failed: %08x\n", hres);
1908     ok(buf_size == sizeof(secid13_2), "buf_size was %d\n", buf_size);
1909     ok(!memcmp(buf, secid13_2, sizeof(secid13_2)), "Got wrong secid\n");
1910
1911     IUri_Release(uri);
1912
1913     IInternetSecurityManagerEx2_Release(sec_mgr2);
1914     IInternetSecurityManager_Release(sec_mgr);
1915 }
1916
1917 static void test_CoInternetIsFeatureZoneElevationEnabled(void)
1918 {
1919     struct {
1920         const char *url_from;
1921         const char *url_to;
1922         DWORD flags;
1923         HRESULT hres;
1924         DWORD policy_flags;
1925     } testcases[] = {
1926         /*  0 */ { "http://www.winehq.org", "http://www.winehq.org", 0, S_FALSE, URLPOLICY_ALLOW },
1927         /*  1 */ { "http://www.winehq.org", "http://www.winehq.org", 0, S_OK, URLPOLICY_DISALLOW },
1928         /*  2 */ { "http://www.winehq.org", "http://www.codeweavers.com", 0, S_FALSE, URLPOLICY_ALLOW },
1929         /*  3 */ { "http://www.winehq.org", "http://www.codeweavers.com", 0, S_OK, URLPOLICY_DISALLOW },
1930         /*  4 */ { "http://www.winehq.org", "http://www.winehq.org", GET_FEATURE_FROM_PROCESS, S_FALSE, -1 },
1931         /*  5 */ { "http://www.winehq.org", "http://www.winehq.org/dir", GET_FEATURE_FROM_PROCESS, S_FALSE, -1 },
1932         /*  6 */ { "http://www.winehq.org", "http://www.codeweavers.com", GET_FEATURE_FROM_PROCESS, S_FALSE, -1 },
1933         /*  7 */ { "http://www.winehq.org", "ftp://winehq.org", GET_FEATURE_FROM_PROCESS, S_FALSE, -1 },
1934         /*  8 */ { "http://www.winehq.org", "ftp://winehq.org", GET_FEATURE_FROM_PROCESS|0x100, S_FALSE, URLPOLICY_ALLOW },
1935         /*  9 */ { "http://www.winehq.org", "ftp://winehq.org", GET_FEATURE_FROM_REGISTRY, S_FALSE, URLPOLICY_ALLOW },
1936     };
1937
1938     WCHAR *url_from, *url_to;
1939     int i;
1940     HRESULT hres;
1941
1942     if(!pCoInternetIsFeatureZoneElevationEnabled || !pCoInternetIsFeatureEnabled
1943             || !pCoInternetIsFeatureEnabledForUrl) {
1944         win_skip("Skipping CoInternetIsFeatureZoneElevationEnabled tests\n");
1945         return;
1946     }
1947
1948
1949     hres = pCoInternetIsFeatureEnabled(FEATURE_ZONE_ELEVATION, GET_FEATURE_FROM_PROCESS);
1950     ok(SUCCEEDED(hres), "CoInternetIsFeatureEnabled returned %x\n", hres);
1951
1952     trace("Testing CoInternetIsFeatureZoneElevationEnabled... (%x)\n", hres);
1953
1954     for(i=0; i<sizeof(testcases)/sizeof(testcases[0]); i++) {
1955         if(hres==S_OK && testcases[i].flags == GET_FEATURE_FROM_PROCESS)
1956             testcases[i].policy_flags = URLPOLICY_ALLOW;
1957     }
1958
1959     for(i=0; i<sizeof(testcases)/sizeof(testcases[0]); i++) {
1960         url_from = a2w(testcases[i].url_from);
1961         url_to = a2w(testcases[i].url_to);
1962
1963         if(testcases[i].policy_flags != -1) {
1964             ProcessUrlAction_policy = testcases[i].policy_flags;
1965             SET_EXPECT(ProcessUrlAction);
1966         }
1967         hres = pCoInternetIsFeatureZoneElevationEnabled(url_from, url_to,
1968                 &security_manager, testcases[i].flags);
1969         ok(hres == testcases[i].hres, "%d) CoInternetIsFeatureZoneElevationEnabled returned %x\n", i, hres);
1970         if(testcases[i].policy_flags != -1)
1971             CHECK_CALLED(ProcessUrlAction);
1972
1973         if(testcases[i].policy_flags != -1)
1974             SET_EXPECT(ProcessUrlAction);
1975         hres = pCoInternetIsFeatureEnabledForUrl(FEATURE_ZONE_ELEVATION,
1976                 testcases[i].flags, url_to, &security_manager);
1977         ok(hres == testcases[i].hres, "%d) CoInternetIsFeatureEnabledForUrl returned %x\n", i, hres);
1978         if(testcases[i].policy_flags != -1)
1979             CHECK_CALLED(ProcessUrlAction);
1980
1981         heap_free(url_from);
1982         heap_free(url_to);
1983     }
1984 }
1985
1986 START_TEST(sec_mgr)
1987 {
1988     HMODULE hurlmon;
1989     int argc;
1990     char **argv;
1991
1992     hurlmon = GetModuleHandle("urlmon.dll");
1993     pCoInternetCreateSecurityManager = (void*) GetProcAddress(hurlmon, "CoInternetCreateSecurityManager");
1994     pCoInternetCreateZoneManager = (void*) GetProcAddress(hurlmon, "CoInternetCreateZoneManager");
1995     pCoInternetGetSecurityUrl = (void*) GetProcAddress(hurlmon, "CoInternetGetSecurityUrl");
1996     pCoInternetGetSecurityUrlEx = (void*) GetProcAddress(hurlmon, "CoInternetGetSecurityUrlEx");
1997     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
1998     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
1999     pCoInternetIsFeatureEnabled = (void*) GetProcAddress(hurlmon, "CoInternetIsFeatureEnabled");
2000     pCoInternetIsFeatureEnabledForUrl = (void*) GetProcAddress(hurlmon, "CoInternetIsFeatureEnabledForUrl");
2001     pCoInternetIsFeatureZoneElevationEnabled = (void*) GetProcAddress(hurlmon, "CoInternetIsFeatureZoneElevationEnabled");
2002
2003     if (!pCoInternetCreateSecurityManager || !pCoInternetCreateZoneManager ||
2004         !pCoInternetGetSecurityUrl) {
2005         win_skip("Various CoInternet* functions not present in IE 4.0\n");
2006         return;
2007     }
2008
2009     argc = winetest_get_mainargs(&argv);
2010     if(argc > 2 && !strcmp(argv[2], "domain_tests")) {
2011         test_zone_domain_mappings();
2012         return;
2013     }
2014
2015     OleInitialize(NULL);
2016     register_protocols();
2017
2018     test_InternetGetSecurityUrl();
2019
2020     if(!pCoInternetGetSecurityUrlEx || !pCreateUri)
2021         win_skip("Skipping CoInternetGetSecurityUrlEx tests, IE too old\n");
2022     else {
2023         test_InternetGetSecurityUrlEx();
2024         test_InternetGetSecurityUrlEx_Pluggable();
2025     }
2026
2027     test_SecurityManager();
2028     test_SecurityManagerEx2();
2029     test_polices();
2030     test_zone_domains();
2031     test_CoInternetCreateZoneManager();
2032     test_CreateZoneEnumerator();
2033     test_GetZoneActionPolicy();
2034     test_GetZoneAt();
2035     test_GetZoneAttributes();
2036     test_SetZoneAttributes();
2037     test_InternetSecurityMarshalling();
2038     test_CoInternetIsFeatureZoneElevationEnabled();
2039
2040     unregister_protocols();
2041     OleUninitialize();
2042 }