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