[URLMON]
[reactos.git] / reactos / dll / win32 / urlmon / sec_mgr.c
1 /*
2 * Internet Security and Zone Manager
3 *
4 * Copyright (c) 2004 Huw D M Davies
5 * Copyright 2004 Jacek Caban
6 * Copyright 2009 Detlef Riekenberg
7 * Copyright 2011 Thomas Mullaly for CodeWeavers
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24 #include "urlmon_main.h"
25
26 static const WCHAR currentlevelW[] = {'C','u','r','r','e','n','t','L','e','v','e','l',0};
27 static const WCHAR descriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
28 static const WCHAR displaynameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
29 static const WCHAR fileW[] = {'f','i','l','e',0};
30 static const WCHAR flagsW[] = {'F','l','a','g','s',0};
31 static const WCHAR iconW[] = {'I','c','o','n',0};
32 static const WCHAR minlevelW[] = {'M','i','n','L','e','v','e','l',0};
33 static const WCHAR recommendedlevelW[] = {'R','e','c','o','m','m','e','n','d','e','d',
34 'L','e','v','e','l',0};
35 static const WCHAR wszZonesKey[] = {'S','o','f','t','w','a','r','e','\\',
36 'M','i','c','r','o','s','o','f','t','\\',
37 'W','i','n','d','o','w','s','\\',
38 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
39 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
40 'Z','o','n','e','s','\\',0};
41 static const WCHAR zone_map_keyW[] = {'S','o','f','t','w','a','r','e','\\',
42 'M','i','c','r','o','s','o','f','t','\\',
43 'W','i','n','d','o','w','s','\\',
44 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
45 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
46 'Z','o','n','e','M','a','p',0};
47 static const WCHAR wszZoneMapDomainsKey[] = {'S','o','f','t','w','a','r','e','\\',
48 'M','i','c','r','o','s','o','f','t','\\',
49 'W','i','n','d','o','w','s','\\',
50 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
51 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
52 'Z','o','n','e','M','a','p','\\',
53 'D','o','m','a','i','n','s',0};
54
55 static inline BOOL is_drive_path(const WCHAR *path)
56 {
57 return isalphaW(*path) && *(path+1) == ':';
58 }
59
60 /* List of schemes types Windows seems to expect to be hierarchical. */
61 static inline BOOL is_hierarchical_scheme(URL_SCHEME type) {
62 return(type == URL_SCHEME_HTTP || type == URL_SCHEME_FTP ||
63 type == URL_SCHEME_GOPHER || type == URL_SCHEME_NNTP ||
64 type == URL_SCHEME_TELNET || type == URL_SCHEME_WAIS ||
65 type == URL_SCHEME_FILE || type == URL_SCHEME_HTTPS ||
66 type == URL_SCHEME_RES);
67 }
68
69 /********************************************************************
70 * get_string_from_reg [internal]
71 *
72 * helper to get a string from the reg.
73 *
74 */
75 static void get_string_from_reg(HKEY hcu, HKEY hklm, LPCWSTR name, LPWSTR out, DWORD maxlen)
76 {
77 DWORD type = REG_SZ;
78 DWORD len = maxlen * sizeof(WCHAR);
79 DWORD res;
80
81 res = RegQueryValueExW(hcu, name, NULL, &type, (LPBYTE) out, &len);
82
83 if (res && hklm) {
84 len = maxlen * sizeof(WCHAR);
85 type = REG_SZ;
86 res = RegQueryValueExW(hklm, name, NULL, &type, (LPBYTE) out, &len);
87 }
88
89 if (res) {
90 TRACE("%s failed: %d\n", debugstr_w(name), res);
91 *out = '\0';
92 }
93 }
94
95 /********************************************************************
96 * get_dword_from_reg [internal]
97 *
98 * helper to get a dword from the reg.
99 *
100 */
101 static void get_dword_from_reg(HKEY hcu, HKEY hklm, LPCWSTR name, LPDWORD out)
102 {
103 DWORD type = REG_DWORD;
104 DWORD len = sizeof(DWORD);
105 DWORD res;
106
107 res = RegQueryValueExW(hcu, name, NULL, &type, (LPBYTE) out, &len);
108
109 if (res && hklm) {
110 len = sizeof(DWORD);
111 type = REG_DWORD;
112 res = RegQueryValueExW(hklm, name, NULL, &type, (LPBYTE) out, &len);
113 }
114
115 if (res) {
116 TRACE("%s failed: %d\n", debugstr_w(name), res);
117 *out = 0;
118 }
119 }
120
121 static HRESULT get_zone_from_reg(LPCWSTR schema, DWORD *zone)
122 {
123 DWORD res, size;
124 HKEY hkey;
125
126 static const WCHAR wszZoneMapProtocolKey[] =
127 {'S','o','f','t','w','a','r','e','\\',
128 'M','i','c','r','o','s','o','f','t','\\',
129 'W','i','n','d','o','w','s','\\',
130 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
131 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
132 'Z','o','n','e','M','a','p','\\',
133 'P','r','o','t','o','c','o','l','D','e','f','a','u','l','t','s',0};
134
135 res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapProtocolKey, &hkey);
136 if(res != ERROR_SUCCESS) {
137 ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
138 return E_UNEXPECTED;
139 }
140
141 size = sizeof(DWORD);
142 res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
143 RegCloseKey(hkey);
144 if(res == ERROR_SUCCESS)
145 return S_OK;
146
147 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapProtocolKey, &hkey);
148 if(res != ERROR_SUCCESS) {
149 ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
150 return E_UNEXPECTED;
151 }
152
153 size = sizeof(DWORD);
154 res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
155 RegCloseKey(hkey);
156 if(res == ERROR_SUCCESS)
157 return S_OK;
158
159 *zone = 3;
160 return S_OK;
161 }
162
163 /********************************************************************
164 * matches_domain_pattern [internal]
165 *
166 * Checks if the given string matches the specified domain pattern.
167 *
168 * This function looks for explicit wildcard domain components iff
169 * they appear at the very beginning of the 'pattern' string
170 *
171 * pattern = "*.google.com"
172 */
173 static BOOL matches_domain_pattern(LPCWSTR pattern, LPCWSTR str, BOOL implicit_wildcard, LPCWSTR *matched)
174 {
175 BOOL matches = FALSE;
176 DWORD pattern_len = strlenW(pattern);
177 DWORD str_len = strlenW(str);
178
179 TRACE("(%d) Checking if %s matches %s\n", implicit_wildcard, debugstr_w(str), debugstr_w(pattern));
180
181 *matched = NULL;
182 if(str_len >= pattern_len) {
183 /* Check if there's an explicit wildcard in the pattern. */
184 if(pattern[0] == '*' && pattern[1] == '.') {
185 /* Make sure that 'str' matches the wildcard pattern.
186 *
187 * Example:
188 * pattern = "*.google.com"
189 *
190 * So in this case 'str' would have to end with ".google.com" in order
191 * to map to this pattern.
192 */
193 if(str_len >= pattern_len+1 && !strcmpiW(str+(str_len-pattern_len+1), pattern+1)) {
194 /* Check if there's another '.' inside of the "unmatched" portion
195 * of 'str'.
196 *
197 * Example:
198 * pattern = "*.google.com"
199 * str = "test.testing.google.com"
200 *
201 * The currently matched portion is ".google.com" in 'str', we need
202 * see if there's a '.' inside of the unmatched portion ("test.testing"), because
203 * if there is and 'implicit_wildcard' isn't set, then this isn't
204 * a match.
205 */
206 const WCHAR *ptr;
207 if(str_len > pattern_len+1 && (ptr = memrchrW(str, '.', str_len-pattern_len-2))) {
208 if(implicit_wildcard) {
209 matches = TRUE;
210 *matched = ptr+1;
211 }
212 } else {
213 matches = TRUE;
214 *matched = str;
215 }
216 }
217 } else if(implicit_wildcard && str_len > pattern_len) {
218 /* When the pattern has an implicit wildcard component, it means
219 * that anything goes in 'str' as long as it ends with the pattern
220 * and that the beginning of the match has a '.' before it.
221 *
222 * Example:
223 * pattern = "google.com"
224 * str = "www.google.com"
225 *
226 * Implicitly matches the pattern, where as:
227 *
228 * pattern = "google.com"
229 * str = "wwwgoogle.com"
230 *
231 * Doesn't match the pattern.
232 */
233 if(str_len > pattern_len) {
234 if(str[str_len-pattern_len-1] == '.' && !strcmpiW(str+(str_len-pattern_len), pattern)) {
235 matches = TRUE;
236 *matched = str+(str_len-pattern_len);
237 }
238 }
239 } else {
240 /* The pattern doesn't have an implicit wildcard, or an explicit wildcard,
241 * so 'str' has to be an exact match to the 'pattern'.
242 */
243 if(!strcmpiW(str, pattern)) {
244 matches = TRUE;
245 *matched = str;
246 }
247 }
248 }
249
250 if(matches)
251 TRACE("Found a match: matched=%s\n", debugstr_w(*matched));
252 else
253 TRACE("No match found\n");
254
255 return matches;
256 }
257
258 static BOOL get_zone_for_scheme(HKEY key, LPCWSTR schema, DWORD *zone)
259 {
260 static const WCHAR wildcardW[] = {'*',0};
261
262 DWORD res;
263 DWORD size = sizeof(DWORD);
264 DWORD type;
265
266 /* See if the key contains a value for the scheme first. */
267 res = RegQueryValueExW(key, schema, NULL, &type, (BYTE*)zone, &size);
268 if(res == ERROR_SUCCESS) {
269 if(type == REG_DWORD)
270 return TRUE;
271 WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(schema));
272 }
273
274 /* Try to get the zone for the wildcard scheme. */
275 size = sizeof(DWORD);
276 res = RegQueryValueExW(key, wildcardW, NULL, &type, (BYTE*)zone, &size);
277 if(res != ERROR_SUCCESS)
278 return FALSE;
279
280 if(type != REG_DWORD) {
281 WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(wildcardW));
282 return FALSE;
283 }
284
285 return TRUE;
286 }
287
288 /********************************************************************
289 * search_domain_for_zone [internal]
290 *
291 * Searches the specified 'domain' registry key to see if 'host' maps into it, or any
292 * of its subdomain registry keys.
293 *
294 * Returns S_OK if a match is found, S_FALSE if no matches were found, or an error code.
295 */
296 static HRESULT search_domain_for_zone(HKEY domains, LPCWSTR domain, DWORD domain_len, LPCWSTR schema,
297 LPCWSTR host, DWORD host_len, DWORD *zone)
298 {
299 BOOL found = FALSE;
300 HKEY domain_key;
301 DWORD res;
302 LPCWSTR matched;
303
304 if(host_len >= domain_len && matches_domain_pattern(domain, host, TRUE, &matched)) {
305 res = RegOpenKeyW(domains, domain, &domain_key);
306 if(res != ERROR_SUCCESS) {
307 ERR("Failed to open domain key %s: %d\n", debugstr_w(domain), res);
308 return E_UNEXPECTED;
309 }
310
311 if(matched == host)
312 found = get_zone_for_scheme(domain_key, schema, zone);
313 else {
314 INT domain_offset;
315 DWORD subdomain_count, subdomain_len;
316 BOOL check_domain = TRUE;
317
318 find_domain_name(domain, domain_len, &domain_offset);
319
320 res = RegQueryInfoKeyW(domain_key, NULL, NULL, NULL, &subdomain_count, &subdomain_len,
321 NULL, NULL, NULL, NULL, NULL, NULL);
322 if(res != ERROR_SUCCESS) {
323 ERR("Unable to query info for key %s: %d\n", debugstr_w(domain), res);
324 RegCloseKey(domain_key);
325 return E_UNEXPECTED;
326 }
327
328 if(subdomain_count) {
329 WCHAR *subdomain;
330 WCHAR *component;
331 DWORD i;
332
333 subdomain = heap_alloc((subdomain_len+1)*sizeof(WCHAR));
334 if(!subdomain) {
335 RegCloseKey(domain_key);
336 return E_OUTOFMEMORY;
337 }
338
339 component = heap_strndupW(host, matched-host-1);
340 if(!component) {
341 heap_free(subdomain);
342 RegCloseKey(domain_key);
343 return E_OUTOFMEMORY;
344 }
345
346 for(i = 0; i < subdomain_count; ++i) {
347 DWORD len = subdomain_len+1;
348 const WCHAR *sub_matched;
349
350 res = RegEnumKeyExW(domain_key, i, subdomain, &len, NULL, NULL, NULL, NULL);
351 if(res != ERROR_SUCCESS) {
352 heap_free(component);
353 heap_free(subdomain);
354 RegCloseKey(domain_key);
355 return E_UNEXPECTED;
356 }
357
358 if(matches_domain_pattern(subdomain, component, FALSE, &sub_matched)) {
359 HKEY subdomain_key;
360
361 res = RegOpenKeyW(domain_key, subdomain, &subdomain_key);
362 if(res != ERROR_SUCCESS) {
363 ERR("Unable to open subdomain key %s of %s: %d\n", debugstr_w(subdomain),
364 debugstr_w(domain), res);
365 heap_free(component);
366 heap_free(subdomain);
367 RegCloseKey(domain_key);
368 return E_UNEXPECTED;
369 }
370
371 found = get_zone_for_scheme(subdomain_key, schema, zone);
372 check_domain = FALSE;
373 RegCloseKey(subdomain_key);
374 break;
375 }
376 }
377 heap_free(subdomain);
378 heap_free(component);
379 }
380
381 /* There's a chance that 'host' implicitly mapped into 'domain', in
382 * which case we check to see if 'domain' contains zone information.
383 *
384 * This can only happen if 'domain' is its own domain name.
385 * Example:
386 * "google.com" (domain name = "google.com")
387 *
388 * So if:
389 * host = "www.google.com"
390 *
391 * Then host would map directly into the "google.com" domain key.
392 *
393 * If 'domain' has more than just its domain name, or it does not
394 * have a domain name, then we don't perform the check. The reason
395 * for this is that these domains don't allow implicit mappings.
396 * Example:
397 * domain = "org" (has no domain name)
398 * host = "www.org"
399 *
400 * The mapping would only happen if the "org" key had an explicit subkey
401 * called "www".
402 */
403 if(check_domain && !domain_offset && !strchrW(host, matched-host-1))
404 found = get_zone_for_scheme(domain_key, schema, zone);
405 }
406 RegCloseKey(domain_key);
407 }
408
409 return found ? S_OK : S_FALSE;
410 }
411
412 static HRESULT search_for_domain_mapping(HKEY domains, LPCWSTR schema, LPCWSTR host, DWORD host_len, DWORD *zone)
413 {
414 WCHAR *domain;
415 DWORD domain_count, domain_len, i;
416 DWORD res;
417 HRESULT hres = S_FALSE;
418
419 res = RegQueryInfoKeyW(domains, NULL, NULL, NULL, &domain_count, &domain_len,
420 NULL, NULL, NULL, NULL, NULL, NULL);
421 if(res != ERROR_SUCCESS) {
422 WARN("Failed to retrieve information about key\n");
423 return E_UNEXPECTED;
424 }
425
426 if(!domain_count)
427 return S_FALSE;
428
429 domain = heap_alloc((domain_len+1)*sizeof(WCHAR));
430 if(!domain)
431 return E_OUTOFMEMORY;
432
433 for(i = 0; i < domain_count; ++i) {
434 DWORD len = domain_len+1;
435
436 res = RegEnumKeyExW(domains, i, domain, &len, NULL, NULL, NULL, NULL);
437 if(res != ERROR_SUCCESS) {
438 heap_free(domain);
439 return E_UNEXPECTED;
440 }
441
442 hres = search_domain_for_zone(domains, domain, len, schema, host, host_len, zone);
443 if(FAILED(hres) || hres == S_OK)
444 break;
445 }
446
447 heap_free(domain);
448 return hres;
449 }
450
451 static HRESULT get_zone_from_domains(IUri *uri, DWORD *zone)
452 {
453 HRESULT hres;
454 BSTR host, scheme;
455 DWORD res;
456 HKEY domains;
457 DWORD scheme_type;
458
459 hres = IUri_GetScheme(uri, &scheme_type);
460 if(FAILED(hres))
461 return hres;
462
463 /* Windows doesn't play nice with unknown scheme types when it tries
464 * to check if a host name maps into any domains.
465 */
466 if(scheme_type == URL_SCHEME_UNKNOWN)
467 return S_FALSE;
468
469 hres = IUri_GetHost(uri, &host);
470 if(FAILED(hres))
471 return hres;
472
473 /* Known hierarchical scheme types must have a host. If they don't Windows
474 * assigns URLZONE_INVALID to the zone.
475 */
476 if((scheme_type != URL_SCHEME_UNKNOWN && scheme_type != URL_SCHEME_FILE)
477 && is_hierarchical_scheme(scheme_type) && !*host) {
478 *zone = URLZONE_INVALID;
479
480 SysFreeString(host);
481
482 /* The MapUrlToZone functions return S_OK when this condition occurs. */
483 return S_OK;
484 }
485
486 hres = IUri_GetSchemeName(uri, &scheme);
487 if(FAILED(hres)) {
488 SysFreeString(host);
489 return hres;
490 }
491
492 /* First try CURRENT_USER. */
493 res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapDomainsKey, &domains);
494 if(res == ERROR_SUCCESS) {
495 hres = search_for_domain_mapping(domains, scheme, host, SysStringLen(host), zone);
496 RegCloseKey(domains);
497 } else
498 WARN("Failed to open HKCU's %s key\n", debugstr_w(wszZoneMapDomainsKey));
499
500 /* If that doesn't work try LOCAL_MACHINE. */
501 if(hres == S_FALSE) {
502 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapDomainsKey, &domains);
503 if(res == ERROR_SUCCESS) {
504 hres = search_for_domain_mapping(domains, scheme, host, SysStringLen(host), zone);
505 RegCloseKey(domains);
506 } else
507 WARN("Failed to open HKLM's %s key\n", debugstr_w(wszZoneMapDomainsKey));
508 }
509
510 SysFreeString(host);
511 SysFreeString(scheme);
512 return hres;
513 }
514
515 static HRESULT map_security_uri_to_zone(IUri *uri, DWORD *zone)
516 {
517 HRESULT hres;
518 BSTR scheme;
519
520 *zone = URLZONE_INVALID;
521
522 hres = IUri_GetSchemeName(uri, &scheme);
523 if(FAILED(hres))
524 return hres;
525
526 if(!strcmpiW(scheme, fileW)) {
527 BSTR path;
528 WCHAR *ptr, *path_start, root[20];
529
530 hres = IUri_GetPath(uri, &path);
531 if(FAILED(hres)) {
532 SysFreeString(scheme);
533 return hres;
534 }
535
536 if(*path == '/' && is_drive_path(path+1))
537 path_start = path+1;
538 else
539 path_start = path;
540
541 if((ptr = strchrW(path_start, ':')) && ptr-path_start+1 < sizeof(root)/sizeof(WCHAR)) {
542 UINT type;
543
544 memcpy(root, path_start, (ptr-path_start+1)*sizeof(WCHAR));
545 root[ptr-path_start+1] = 0;
546
547 type = GetDriveTypeW(root);
548
549 switch(type) {
550 case DRIVE_UNKNOWN:
551 case DRIVE_NO_ROOT_DIR:
552 break;
553 case DRIVE_REMOVABLE:
554 case DRIVE_FIXED:
555 case DRIVE_CDROM:
556 case DRIVE_RAMDISK:
557 *zone = URLZONE_LOCAL_MACHINE;
558 hres = S_OK;
559 break;
560 case DRIVE_REMOTE:
561 *zone = URLZONE_INTERNET;
562 hres = S_OK;
563 break;
564 default:
565 FIXME("unsupported drive type %d\n", type);
566 }
567 }
568 SysFreeString(path);
569 }
570
571 if(*zone == URLZONE_INVALID) {
572 hres = get_zone_from_domains(uri, zone);
573 if(hres == S_FALSE)
574 hres = get_zone_from_reg(scheme, zone);
575 }
576
577 SysFreeString(scheme);
578 return hres;
579 }
580
581 static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
582 {
583 IUri *secur_uri;
584 LPWSTR secur_url;
585 HRESULT hres;
586
587 *zone = URLZONE_INVALID;
588
589 hres = CoInternetGetSecurityUrl(url, &secur_url, PSU_SECURITY_URL_ONLY, 0);
590 if(hres != S_OK) {
591 DWORD size = strlenW(url)*sizeof(WCHAR);
592
593 secur_url = CoTaskMemAlloc(size);
594 if(!secur_url)
595 return E_OUTOFMEMORY;
596
597 memcpy(secur_url, url, size);
598 }
599
600 hres = CreateUri(secur_url, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &secur_uri);
601 if(FAILED(hres)) {
602 CoTaskMemFree(secur_url);
603 return hres;
604 }
605
606 hres = map_security_uri_to_zone(secur_uri, zone);
607 IUri_Release(secur_uri);
608
609 if(FAILED(hres) || !ret_url)
610 CoTaskMemFree(secur_url);
611 else
612 *ret_url = secur_url;
613
614 return hres;
615 }
616
617 static HRESULT map_uri_to_zone(IUri *uri, DWORD *zone, IUri **ret_uri)
618 {
619 HRESULT hres;
620 IUri *secur_uri;
621
622 hres = CoInternetGetSecurityUrlEx(uri, &secur_uri, PSU_SECURITY_URL_ONLY, 0);
623 if(FAILED(hres))
624 return hres;
625
626 hres = map_security_uri_to_zone(secur_uri, zone);
627 if(FAILED(hres) || !ret_uri)
628 IUri_Release(secur_uri);
629 else
630 *ret_uri = secur_uri;
631
632 return hres;
633 }
634
635 static HRESULT open_zone_key(HKEY parent_key, DWORD zone, HKEY *hkey)
636 {
637 static const WCHAR wszFormat[] = {'%','s','%','u',0};
638
639 WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+12];
640 DWORD res;
641
642 wsprintfW(key_name, wszFormat, wszZonesKey, zone);
643
644 res = RegOpenKeyW(parent_key, key_name, hkey);
645
646 if(res != ERROR_SUCCESS) {
647 WARN("RegOpenKey failed\n");
648 return E_INVALIDARG;
649 }
650
651 return S_OK;
652 }
653
654 static HRESULT get_action_policy(DWORD zone, DWORD action, BYTE *policy, DWORD size, URLZONEREG zone_reg)
655 {
656 HKEY parent_key;
657 HKEY hkey;
658 LONG res;
659 HRESULT hres;
660
661 switch(action) {
662 case URLACTION_SCRIPT_OVERRIDE_SAFETY:
663 case URLACTION_ACTIVEX_OVERRIDE_SCRIPT_SAFETY:
664 *(DWORD*)policy = URLPOLICY_DISALLOW;
665 return S_OK;
666 }
667
668 switch(zone_reg) {
669 case URLZONEREG_DEFAULT:
670 case URLZONEREG_HKCU:
671 parent_key = HKEY_CURRENT_USER;
672 break;
673 case URLZONEREG_HKLM:
674 parent_key = HKEY_LOCAL_MACHINE;
675 break;
676 default:
677 WARN("Unknown URLZONEREG: %d\n", zone_reg);
678 return E_FAIL;
679 };
680
681 hres = open_zone_key(parent_key, zone, &hkey);
682 if(SUCCEEDED(hres)) {
683 WCHAR action_str[16];
684 DWORD len = size;
685
686 static const WCHAR formatW[] = {'%','X',0};
687
688 wsprintfW(action_str, formatW, action);
689
690 res = RegQueryValueExW(hkey, action_str, NULL, NULL, policy, &len);
691 if(res == ERROR_MORE_DATA) {
692 hres = E_INVALIDARG;
693 }else if(res == ERROR_FILE_NOT_FOUND) {
694 hres = E_FAIL;
695 }else if(res != ERROR_SUCCESS) {
696 ERR("RegQueryValue failed: %d\n", res);
697 hres = E_UNEXPECTED;
698 }
699
700 RegCloseKey(hkey);
701 }
702
703 if(FAILED(hres) && zone_reg == URLZONEREG_DEFAULT)
704 return get_action_policy(zone, action, policy, size, URLZONEREG_HKLM);
705
706 return hres;
707 }
708
709 static HRESULT generate_security_id(IUri *uri, BYTE *secid, DWORD *secid_len, DWORD zone)
710 {
711 DWORD len;
712 HRESULT hres;
713 DWORD scheme_type;
714
715 if(zone == URLZONE_INVALID)
716 return E_INVALIDARG;
717
718 hres = IUri_GetScheme(uri, &scheme_type);
719 if(FAILED(hres))
720 return hres;
721
722 /* Windows handles opaque URLs differently then hierarchical ones. */
723 if(!is_hierarchical_scheme(scheme_type) && scheme_type != URL_SCHEME_WILDCARD) {
724 BSTR display_uri;
725
726 hres = IUri_GetDisplayUri(uri, &display_uri);
727 if(FAILED(hres))
728 return hres;
729
730 len = WideCharToMultiByte(CP_ACP, 0, display_uri, -1, NULL, 0, NULL, NULL)-1;
731
732 if(len+sizeof(DWORD) > *secid_len) {
733 SysFreeString(display_uri);
734 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
735 }
736
737 WideCharToMultiByte(CP_ACP, 0, display_uri, -1, (LPSTR)secid, len, NULL, NULL);
738 SysFreeString(display_uri);
739
740 *(DWORD*)(secid+len) = zone;
741 } else {
742 BSTR host, scheme;
743 DWORD host_len, scheme_len;
744 BYTE *ptr;
745
746 hres = IUri_GetHost(uri, &host);
747 if(FAILED(hres))
748 return hres;
749
750 /* The host can't be empty for Wildcard URIs. */
751 if(scheme_type == URL_SCHEME_WILDCARD && !*host) {
752 SysFreeString(host);
753 return E_INVALIDARG;
754 }
755
756 hres = IUri_GetSchemeName(uri, &scheme);
757 if(FAILED(hres)) {
758 SysFreeString(host);
759 return hres;
760 }
761
762 host_len = WideCharToMultiByte(CP_ACP, 0, host, -1, NULL, 0, NULL, NULL)-1;
763 scheme_len = WideCharToMultiByte(CP_ACP, 0, scheme, -1, NULL, 0, NULL, NULL)-1;
764
765 len = host_len+scheme_len+sizeof(BYTE);
766
767 if(len+sizeof(DWORD) > *secid_len) {
768 SysFreeString(host);
769 SysFreeString(scheme);
770 return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
771 }
772
773 WideCharToMultiByte(CP_ACP, 0, scheme, -1, (LPSTR)secid, len, NULL, NULL);
774 SysFreeString(scheme);
775
776 ptr = secid+scheme_len;
777 *ptr++ = ':';
778
779 WideCharToMultiByte(CP_ACP, 0, host, -1, (LPSTR)ptr, host_len, NULL, NULL);
780 SysFreeString(host);
781
782 ptr += host_len;
783
784 *(DWORD*)ptr = zone;
785 }
786
787 *secid_len = len+sizeof(DWORD);
788
789 return S_OK;
790 }
791
792 static HRESULT get_security_id_for_url(LPCWSTR url, BYTE *secid, DWORD *secid_len)
793 {
794 HRESULT hres;
795 DWORD zone = URLZONE_INVALID;
796 LPWSTR secur_url = NULL;
797 IUri *uri;
798
799 hres = map_url_to_zone(url, &zone, &secur_url);
800 if(FAILED(hres))
801 return hres == 0x80041001 ? E_INVALIDARG : hres;
802
803 hres = CreateUri(secur_url, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &uri);
804 CoTaskMemFree(secur_url);
805 if(FAILED(hres))
806 return hres;
807
808 hres = generate_security_id(uri, secid, secid_len, zone);
809 IUri_Release(uri);
810
811 return hres;
812 }
813
814 static HRESULT get_security_id_for_uri(IUri *uri, BYTE *secid, DWORD *secid_len)
815 {
816 HRESULT hres;
817 IUri *secur_uri;
818 DWORD zone = URLZONE_INVALID;
819
820 hres = map_uri_to_zone(uri, &zone, &secur_uri);
821 if(FAILED(hres))
822 return hres;
823
824 hres = generate_security_id(secur_uri, secid, secid_len, zone);
825 IUri_Release(secur_uri);
826
827 return hres;
828 }
829
830 /***********************************************************************
831 * InternetSecurityManager implementation
832 *
833 */
834 typedef struct {
835 IInternetSecurityManagerEx2 IInternetSecurityManagerEx2_iface;
836
837 LONG ref;
838
839 IInternetSecurityMgrSite *mgrsite;
840 IInternetSecurityManager *custom_manager;
841 } SecManagerImpl;
842
843 static inline SecManagerImpl *impl_from_IInternetSecurityManagerEx2(IInternetSecurityManagerEx2 *iface)
844 {
845 return CONTAINING_RECORD(iface, SecManagerImpl, IInternetSecurityManagerEx2_iface);
846 }
847
848 static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManagerEx2* iface,REFIID riid,void** ppvObject)
849 {
850 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
851
852 TRACE("(%p)->(%s %p)\n",This,debugstr_guid(riid),ppvObject);
853
854 if(!ppvObject)
855 return E_INVALIDARG;
856
857 if(IsEqualIID(&IID_IUnknown, riid) ||
858 IsEqualIID(&IID_IInternetSecurityManager, riid) ||
859 IsEqualIID(&IID_IInternetSecurityManagerEx, riid) ||
860 IsEqualIID(&IID_IInternetSecurityManagerEx2, riid)) {
861 *ppvObject = iface;
862 } else {
863 WARN("not supported interface %s\n", debugstr_guid(riid));
864 *ppvObject = NULL;
865 return E_NOINTERFACE;
866 }
867
868 IInternetSecurityManagerEx2_AddRef(iface);
869 return S_OK;
870 }
871
872 static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManagerEx2* iface)
873 {
874 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
875 ULONG refCount = InterlockedIncrement(&This->ref);
876
877 TRACE("(%p) ref=%u\n", This, refCount);
878
879 return refCount;
880 }
881
882 static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManagerEx2* iface)
883 {
884 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
885 ULONG refCount = InterlockedDecrement(&This->ref);
886
887 TRACE("(%p) ref=%u\n", This, refCount);
888
889 /* destroy the object if there's no more reference on it */
890 if (!refCount){
891 if(This->mgrsite)
892 IInternetSecurityMgrSite_Release(This->mgrsite);
893 if(This->custom_manager)
894 IInternetSecurityManager_Release(This->custom_manager);
895
896 heap_free(This);
897
898 URLMON_UnlockModule();
899 }
900
901 return refCount;
902 }
903
904 static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManagerEx2 *iface,
905 IInternetSecurityMgrSite *pSite)
906 {
907 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
908
909 TRACE("(%p)->(%p)\n", This, pSite);
910
911 if(This->mgrsite)
912 IInternetSecurityMgrSite_Release(This->mgrsite);
913
914 if(This->custom_manager) {
915 IInternetSecurityManager_Release(This->custom_manager);
916 This->custom_manager = NULL;
917 }
918
919 This->mgrsite = pSite;
920
921 if(pSite) {
922 IServiceProvider *servprov;
923 HRESULT hres;
924
925 IInternetSecurityMgrSite_AddRef(pSite);
926
927 hres = IInternetSecurityMgrSite_QueryInterface(pSite, &IID_IServiceProvider,
928 (void**)&servprov);
929 if(SUCCEEDED(hres)) {
930 IServiceProvider_QueryService(servprov, &SID_SInternetSecurityManager,
931 &IID_IInternetSecurityManager, (void**)&This->custom_manager);
932 IServiceProvider_Release(servprov);
933 }
934 }
935
936 return S_OK;
937 }
938
939 static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManagerEx2 *iface,
940 IInternetSecurityMgrSite **ppSite)
941 {
942 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
943
944 TRACE("(%p)->(%p)\n", This, ppSite);
945
946 if(!ppSite)
947 return E_INVALIDARG;
948
949 if(This->mgrsite)
950 IInternetSecurityMgrSite_AddRef(This->mgrsite);
951
952 *ppSite = This->mgrsite;
953 return S_OK;
954 }
955
956 static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManagerEx2 *iface,
957 LPCWSTR pwszUrl, DWORD *pdwZone,
958 DWORD dwFlags)
959 {
960 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
961 HRESULT hres;
962
963 TRACE("(%p)->(%s %p %08x)\n", iface, debugstr_w(pwszUrl), pdwZone, dwFlags);
964
965 if(This->custom_manager) {
966 hres = IInternetSecurityManager_MapUrlToZone(This->custom_manager,
967 pwszUrl, pdwZone, dwFlags);
968 if(hres != INET_E_DEFAULT_ACTION)
969 return hres;
970 }
971
972 if(!pwszUrl) {
973 *pdwZone = URLZONE_INVALID;
974 return E_INVALIDARG;
975 }
976
977 if(dwFlags)
978 FIXME("not supported flags: %08x\n", dwFlags);
979
980 return map_url_to_zone(pwszUrl, pdwZone, NULL);
981 }
982
983 static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManagerEx2 *iface,
984 LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
985 {
986 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
987
988 TRACE("(%p)->(%s %p %p %08lx)\n", iface, debugstr_w(pwszUrl), pbSecurityId,
989 pcbSecurityId, dwReserved);
990
991 if(This->custom_manager) {
992 HRESULT hres;
993
994 hres = IInternetSecurityManager_GetSecurityId(This->custom_manager,
995 pwszUrl, pbSecurityId, pcbSecurityId, dwReserved);
996 if(hres != INET_E_DEFAULT_ACTION)
997 return hres;
998 }
999
1000 if(!pwszUrl || !pbSecurityId || !pcbSecurityId)
1001 return E_INVALIDARG;
1002
1003 if(dwReserved)
1004 FIXME("dwReserved is not supported\n");
1005
1006 return get_security_id_for_url(pwszUrl, pbSecurityId, pcbSecurityId);
1007 }
1008
1009
1010 static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManagerEx2 *iface,
1011 LPCWSTR pwszUrl, DWORD dwAction,
1012 BYTE *pPolicy, DWORD cbPolicy,
1013 BYTE *pContext, DWORD cbContext,
1014 DWORD dwFlags, DWORD dwReserved)
1015 {
1016 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1017 DWORD zone, policy;
1018 HRESULT hres;
1019
1020 TRACE("(%p)->(%s %08x %p %08x %p %08x %08x %08x)\n", iface, debugstr_w(pwszUrl), dwAction,
1021 pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
1022
1023 if(This->custom_manager) {
1024 hres = IInternetSecurityManager_ProcessUrlAction(This->custom_manager, pwszUrl, dwAction,
1025 pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
1026 if(hres != INET_E_DEFAULT_ACTION)
1027 return hres;
1028 }
1029
1030 if(dwFlags || dwReserved)
1031 FIXME("Unsupported arguments\n");
1032
1033 if(!pwszUrl)
1034 return E_INVALIDARG;
1035
1036 hres = map_url_to_zone(pwszUrl, &zone, NULL);
1037 if(FAILED(hres))
1038 return hres;
1039
1040 hres = get_action_policy(zone, dwAction, (BYTE*)&policy, sizeof(policy), URLZONEREG_DEFAULT);
1041 if(FAILED(hres))
1042 return hres;
1043
1044 TRACE("policy %x\n", policy);
1045 if(cbPolicy >= sizeof(DWORD))
1046 *(DWORD*)pPolicy = policy;
1047
1048 switch(GetUrlPolicyPermissions(policy)) {
1049 case URLPOLICY_ALLOW:
1050 case URLPOLICY_CHANNEL_SOFTDIST_PRECACHE:
1051 return S_OK;
1052 case URLPOLICY_DISALLOW:
1053 return S_FALSE;
1054 case URLPOLICY_QUERY:
1055 FIXME("URLPOLICY_QUERY not implemented\n");
1056 return E_FAIL;
1057 default:
1058 FIXME("Not implemented policy %x\n", policy);
1059 }
1060
1061 return E_FAIL;
1062 }
1063
1064
1065 static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManagerEx2 *iface,
1066 LPCWSTR pwszUrl, REFGUID guidKey,
1067 BYTE **ppPolicy, DWORD *pcbPolicy,
1068 BYTE *pContext, DWORD cbContext,
1069 DWORD dwReserved)
1070 {
1071 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1072 HRESULT hres;
1073
1074 TRACE("(%p)->(%s %s %p %p %p %08x %08x )\n", iface, debugstr_w(pwszUrl), debugstr_guid(guidKey),
1075 ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
1076
1077 if(This->custom_manager) {
1078 hres = IInternetSecurityManager_QueryCustomPolicy(This->custom_manager, pwszUrl, guidKey,
1079 ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
1080 if(hres != INET_E_DEFAULT_ACTION)
1081 return hres;
1082 }
1083
1084 WARN("Unknown guidKey %s\n", debugstr_guid(guidKey));
1085 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1086 }
1087
1088 static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManagerEx2 *iface,
1089 DWORD dwZone, LPCWSTR pwszPattern, DWORD dwFlags)
1090 {
1091 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1092 HRESULT hres;
1093
1094 TRACE("(%p)->(%08x %s %08x)\n", iface, dwZone, debugstr_w(pwszPattern),dwFlags);
1095
1096 if(This->custom_manager) {
1097 hres = IInternetSecurityManager_SetZoneMapping(This->custom_manager, dwZone,
1098 pwszPattern, dwFlags);
1099 if(hres != INET_E_DEFAULT_ACTION)
1100 return hres;
1101 }
1102
1103 FIXME("Default action is not implemented\n");
1104 return E_NOTIMPL;
1105 }
1106
1107 static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManagerEx2 *iface,
1108 DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
1109 {
1110 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1111 HRESULT hres;
1112
1113 TRACE("(%p)->(%08x %p %08x)\n", iface, dwZone, ppenumString,dwFlags);
1114
1115 if(This->custom_manager) {
1116 hres = IInternetSecurityManager_GetZoneMappings(This->custom_manager, dwZone,
1117 ppenumString, dwFlags);
1118 if(hres != INET_E_DEFAULT_ACTION)
1119 return hres;
1120 }
1121
1122 FIXME("Default action is not implemented\n");
1123 return E_NOTIMPL;
1124 }
1125
1126 static HRESULT WINAPI SecManagerImpl_ProcessUrlActionEx(IInternetSecurityManagerEx2 *iface,
1127 LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext,
1128 DWORD dwFlags, DWORD dwReserved, DWORD *pdwOutFlags)
1129 {
1130 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1131 FIXME("(%p)->(%s %08x %p %d %p %d %08x %08x %p) stub\n", This, debugstr_w(pwszUrl), dwAction, pPolicy, cbPolicy,
1132 pContext, cbContext, dwFlags, dwReserved, pdwOutFlags);
1133 return E_NOTIMPL;
1134 }
1135
1136 static HRESULT WINAPI SecManagerImpl_MapUrlToZoneEx2(IInternetSecurityManagerEx2 *iface,
1137 IUri *pUri, DWORD *pdwZone, DWORD dwFlags, LPWSTR *ppwszMappedUrl, DWORD *pdwOutFlags)
1138 {
1139 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1140
1141 TRACE("(%p)->(%p %p %08x %p %p)\n", This, pUri, pdwZone, dwFlags, ppwszMappedUrl, pdwOutFlags);
1142
1143 if(This->custom_manager) {
1144 HRESULT hres;
1145 IInternetSecurityManagerEx2 *sec_mgr2;
1146
1147 hres = IInternetSecurityManager_QueryInterface(This->custom_manager, &IID_IInternetSecurityManagerEx2,
1148 (void**)&sec_mgr2);
1149 if(SUCCEEDED(hres)) {
1150 hres = IInternetSecurityManagerEx2_MapUrlToZoneEx2(sec_mgr2, pUri, pdwZone, dwFlags, ppwszMappedUrl, pdwOutFlags);
1151 IInternetSecurityManagerEx2_Release(sec_mgr2);
1152 } else {
1153 BSTR url;
1154
1155 hres = IUri_GetDisplayUri(pUri, &url);
1156 if(FAILED(hres))
1157 return hres;
1158
1159 hres = IInternetSecurityManager_MapUrlToZone(This->custom_manager, url, pdwZone, dwFlags);
1160 SysFreeString(url);
1161 }
1162
1163 if(hres != INET_E_DEFAULT_ACTION)
1164 return hres;
1165 }
1166
1167 if(!pdwZone)
1168 return E_INVALIDARG;
1169
1170 if(!pUri) {
1171 *pdwZone = URLZONE_INVALID;
1172 return E_INVALIDARG;
1173 }
1174
1175 if(dwFlags)
1176 FIXME("Unsupported flags: %08x\n", dwFlags);
1177
1178 return map_uri_to_zone(pUri, pdwZone, NULL);
1179 }
1180
1181 static HRESULT WINAPI SecManagerImpl_ProcessUrlActionEx2(IInternetSecurityManagerEx2 *iface,
1182 IUri *pUri, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext,
1183 DWORD dwFlags, DWORD_PTR dwReserved, DWORD *pdwOutFlags)
1184 {
1185 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1186 FIXME("(%p)->(%p %08x %p %d %p %d %08x %08x %p) stub\n", This, pUri, dwAction, pPolicy,
1187 cbPolicy, pContext, cbContext, dwFlags, (DWORD)dwReserved, pdwOutFlags);
1188 return E_NOTIMPL;
1189 }
1190
1191 static HRESULT WINAPI SecManagerImpl_GetSecurityIdEx2(IInternetSecurityManagerEx2 *iface,
1192 IUri *pUri, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
1193 {
1194 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1195 TRACE("(%p)->(%p %p %p %08x) stub\n", This, pUri, pbSecurityId, pcbSecurityId, (DWORD)dwReserved);
1196
1197 if(dwReserved)
1198 FIXME("dwReserved is not supported yet\n");
1199
1200 if(!pUri || !pcbSecurityId || !pbSecurityId)
1201 return E_INVALIDARG;
1202
1203 return get_security_id_for_uri(pUri, pbSecurityId, pcbSecurityId);
1204 }
1205
1206 static HRESULT WINAPI SecManagerImpl_QueryCustomPolicyEx2(IInternetSecurityManagerEx2 *iface,
1207 IUri *pUri, REFGUID guidKey, BYTE **ppPolicy, DWORD *pcbPolicy, BYTE *pContext,
1208 DWORD cbContext, DWORD_PTR dwReserved)
1209 {
1210 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1211 FIXME("(%p)->(%p %s %p %p %p %d %08x) stub\n", This, pUri, debugstr_guid(guidKey), ppPolicy, pcbPolicy,
1212 pContext, cbContext, (DWORD)dwReserved);
1213 return E_NOTIMPL;
1214 }
1215
1216 static const IInternetSecurityManagerEx2Vtbl VT_SecManagerImpl =
1217 {
1218 SecManagerImpl_QueryInterface,
1219 SecManagerImpl_AddRef,
1220 SecManagerImpl_Release,
1221 SecManagerImpl_SetSecuritySite,
1222 SecManagerImpl_GetSecuritySite,
1223 SecManagerImpl_MapUrlToZone,
1224 SecManagerImpl_GetSecurityId,
1225 SecManagerImpl_ProcessUrlAction,
1226 SecManagerImpl_QueryCustomPolicy,
1227 SecManagerImpl_SetZoneMapping,
1228 SecManagerImpl_GetZoneMappings,
1229 SecManagerImpl_ProcessUrlActionEx,
1230 SecManagerImpl_MapUrlToZoneEx2,
1231 SecManagerImpl_ProcessUrlActionEx2,
1232 SecManagerImpl_GetSecurityIdEx2,
1233 SecManagerImpl_QueryCustomPolicyEx2
1234 };
1235
1236 HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
1237 {
1238 SecManagerImpl *This;
1239
1240 TRACE("(%p,%p)\n",pUnkOuter,ppobj);
1241 This = heap_alloc(sizeof(*This));
1242
1243 /* Initialize the virtual function table. */
1244 This->IInternetSecurityManagerEx2_iface.lpVtbl = &VT_SecManagerImpl;
1245
1246 This->ref = 1;
1247 This->mgrsite = NULL;
1248 This->custom_manager = NULL;
1249
1250 *ppobj = This;
1251
1252 URLMON_LockModule();
1253
1254 return S_OK;
1255 }
1256
1257 /***********************************************************************
1258 * InternetZoneManager implementation
1259 *
1260 */
1261 typedef struct {
1262 IInternetZoneManagerEx2 IInternetZoneManagerEx2_iface;
1263 LONG ref;
1264 LPDWORD *zonemaps;
1265 DWORD zonemap_count;
1266 } ZoneMgrImpl;
1267
1268 static inline ZoneMgrImpl *impl_from_IInternetZoneManagerEx2(IInternetZoneManagerEx2 *iface)
1269 {
1270 return CONTAINING_RECORD(iface, ZoneMgrImpl, IInternetZoneManagerEx2_iface);
1271 }
1272
1273
1274 /***********************************************************************
1275 * build_zonemap_from_reg [internal]
1276 *
1277 * Enumerate the Zones in the Registry and return the Zones in a DWORD-array
1278 * The number of the Zones is returned in data[0]
1279 */
1280 static LPDWORD build_zonemap_from_reg(void)
1281 {
1282 WCHAR name[32];
1283 HKEY hkey;
1284 LPDWORD data = NULL;
1285 DWORD allocated = 6; /* space for the zonecount and Zone "0" up to Zone "4" */
1286 DWORD used = 0;
1287 DWORD res;
1288 DWORD len;
1289
1290
1291 res = RegOpenKeyW(HKEY_CURRENT_USER, wszZonesKey, &hkey);
1292 if (res)
1293 return NULL;
1294
1295 data = heap_alloc(allocated * sizeof(DWORD));
1296 if (!data)
1297 goto cleanup;
1298
1299 while (!res) {
1300 name[0] = '\0';
1301 len = sizeof(name) / sizeof(name[0]);
1302 res = RegEnumKeyExW(hkey, used, name, &len, NULL, NULL, NULL, NULL);
1303
1304 if (!res) {
1305 used++;
1306 if (used == allocated) {
1307 LPDWORD new_data;
1308
1309 allocated *= 2;
1310 new_data = heap_realloc_zero(data, allocated * sizeof(DWORD));
1311 if (!new_data)
1312 goto cleanup;
1313
1314 data = new_data;
1315 }
1316 data[used] = atoiW(name);
1317 }
1318 }
1319 if (used) {
1320 RegCloseKey(hkey);
1321 data[0] = used;
1322 return data;
1323 }
1324
1325 cleanup:
1326 /* something failed */
1327 RegCloseKey(hkey);
1328 heap_free(data);
1329 return NULL;
1330 }
1331
1332 /********************************************************************
1333 * IInternetZoneManager_QueryInterface
1334 */
1335 static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManagerEx2* iface, REFIID riid, void** ppvObject)
1336 {
1337 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1338
1339 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);
1340
1341 if(!This || !ppvObject)
1342 return E_INVALIDARG;
1343
1344 if(IsEqualIID(&IID_IUnknown, riid)) {
1345 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppvObject);
1346 }else if(IsEqualIID(&IID_IInternetZoneManager, riid)) {
1347 TRACE("(%p)->(IID_InternetZoneManager %p)\n", This, ppvObject);
1348 }else if(IsEqualIID(&IID_IInternetZoneManagerEx, riid)) {
1349 TRACE("(%p)->(IID_InternetZoneManagerEx %p)\n", This, ppvObject);
1350 }else if(IsEqualIID(&IID_IInternetZoneManagerEx2, riid)) {
1351 TRACE("(%p)->(IID_InternetZoneManagerEx2 %p)\n", This, ppvObject);
1352 }
1353 else
1354 {
1355 FIXME("Unknown interface: %s\n", debugstr_guid(riid));
1356 *ppvObject = NULL;
1357 return E_NOINTERFACE;
1358 }
1359
1360 *ppvObject = iface;
1361 IInternetZoneManagerEx2_AddRef(iface);
1362 return S_OK;
1363 }
1364
1365 /********************************************************************
1366 * IInternetZoneManager_AddRef
1367 */
1368 static ULONG WINAPI ZoneMgrImpl_AddRef(IInternetZoneManagerEx2* iface)
1369 {
1370 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1371 ULONG refCount = InterlockedIncrement(&This->ref);
1372
1373 TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
1374
1375 return refCount;
1376 }
1377
1378 /********************************************************************
1379 * IInternetZoneManager_Release
1380 */
1381 static ULONG WINAPI ZoneMgrImpl_Release(IInternetZoneManagerEx2* iface)
1382 {
1383 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1384 ULONG refCount = InterlockedDecrement(&This->ref);
1385
1386 TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
1387
1388 if(!refCount) {
1389 while (This->zonemap_count) heap_free(This->zonemaps[--This->zonemap_count]);
1390 heap_free(This->zonemaps);
1391 heap_free(This);
1392 URLMON_UnlockModule();
1393 }
1394
1395 return refCount;
1396 }
1397
1398 /********************************************************************
1399 * IInternetZoneManager_GetZoneAttributes
1400 */
1401 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributes(IInternetZoneManagerEx2* iface,
1402 DWORD dwZone,
1403 ZONEATTRIBUTES* pZoneAttributes)
1404 {
1405 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1406 HRESULT hr;
1407 HKEY hcu;
1408 HKEY hklm = NULL;
1409
1410 TRACE("(%p)->(%d %p)\n", This, dwZone, pZoneAttributes);
1411
1412 if (!pZoneAttributes)
1413 return E_INVALIDARG;
1414
1415 hr = open_zone_key(HKEY_CURRENT_USER, dwZone, &hcu);
1416 if (FAILED(hr))
1417 return S_OK; /* IE6 and older returned E_FAIL here */
1418
1419 hr = open_zone_key(HKEY_LOCAL_MACHINE, dwZone, &hklm);
1420 if (FAILED(hr))
1421 TRACE("Zone %d not in HKLM\n", dwZone);
1422
1423 get_string_from_reg(hcu, hklm, displaynameW, pZoneAttributes->szDisplayName, MAX_ZONE_PATH);
1424 get_string_from_reg(hcu, hklm, descriptionW, pZoneAttributes->szDescription, MAX_ZONE_DESCRIPTION);
1425 get_string_from_reg(hcu, hklm, iconW, pZoneAttributes->szIconPath, MAX_ZONE_PATH);
1426 get_dword_from_reg(hcu, hklm, minlevelW, &pZoneAttributes->dwTemplateMinLevel);
1427 get_dword_from_reg(hcu, hklm, currentlevelW, &pZoneAttributes->dwTemplateCurrentLevel);
1428 get_dword_from_reg(hcu, hklm, recommendedlevelW, &pZoneAttributes->dwTemplateRecommended);
1429 get_dword_from_reg(hcu, hklm, flagsW, &pZoneAttributes->dwFlags);
1430
1431 RegCloseKey(hklm);
1432 RegCloseKey(hcu);
1433 return S_OK;
1434 }
1435
1436 /********************************************************************
1437 * IInternetZoneManager_SetZoneAttributes
1438 */
1439 static HRESULT WINAPI ZoneMgrImpl_SetZoneAttributes(IInternetZoneManagerEx2* iface,
1440 DWORD dwZone,
1441 ZONEATTRIBUTES* pZoneAttributes)
1442 {
1443 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1444 HRESULT hr;
1445 HKEY hcu;
1446
1447 TRACE("(%p)->(%d %p)\n", This, dwZone, pZoneAttributes);
1448
1449 if (!pZoneAttributes)
1450 return E_INVALIDARG;
1451
1452 hr = open_zone_key(HKEY_CURRENT_USER, dwZone, &hcu);
1453 if (FAILED(hr))
1454 return S_OK; /* IE6 returned E_FAIL here */
1455
1456 /* cbSize is ignored */
1457 RegSetValueExW(hcu, displaynameW, 0, REG_SZ, (LPBYTE) pZoneAttributes->szDisplayName,
1458 (lstrlenW(pZoneAttributes->szDisplayName)+1)* sizeof(WCHAR));
1459
1460 RegSetValueExW(hcu, descriptionW, 0, REG_SZ, (LPBYTE) pZoneAttributes->szDescription,
1461 (lstrlenW(pZoneAttributes->szDescription)+1)* sizeof(WCHAR));
1462
1463 RegSetValueExW(hcu, iconW, 0, REG_SZ, (LPBYTE) pZoneAttributes->szIconPath,
1464 (lstrlenW(pZoneAttributes->szIconPath)+1)* sizeof(WCHAR));
1465
1466 RegSetValueExW(hcu, minlevelW, 0, REG_DWORD,
1467 (const BYTE*) &pZoneAttributes->dwTemplateMinLevel, sizeof(DWORD));
1468
1469 RegSetValueExW(hcu, currentlevelW, 0, REG_DWORD,
1470 (const BYTE*) &pZoneAttributes->dwTemplateCurrentLevel, sizeof(DWORD));
1471
1472 RegSetValueExW(hcu, recommendedlevelW, 0, REG_DWORD,
1473 (const BYTE*) &pZoneAttributes->dwTemplateRecommended, sizeof(DWORD));
1474
1475 RegSetValueExW(hcu, flagsW, 0, REG_DWORD, (const BYTE*) &pZoneAttributes->dwFlags, sizeof(DWORD));
1476 RegCloseKey(hcu);
1477 return S_OK;
1478
1479 }
1480
1481 /********************************************************************
1482 * IInternetZoneManager_GetZoneCustomPolicy
1483 */
1484 static HRESULT WINAPI ZoneMgrImpl_GetZoneCustomPolicy(IInternetZoneManagerEx2* iface,
1485 DWORD dwZone,
1486 REFGUID guidKey,
1487 BYTE** ppPolicy,
1488 DWORD* pcbPolicy,
1489 URLZONEREG ulrZoneReg)
1490 {
1491 FIXME("(%p)->(%08x %s %p %p %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
1492 ppPolicy, pcbPolicy, ulrZoneReg);
1493 return E_NOTIMPL;
1494 }
1495
1496 /********************************************************************
1497 * IInternetZoneManager_SetZoneCustomPolicy
1498 */
1499 static HRESULT WINAPI ZoneMgrImpl_SetZoneCustomPolicy(IInternetZoneManagerEx2* iface,
1500 DWORD dwZone,
1501 REFGUID guidKey,
1502 BYTE* ppPolicy,
1503 DWORD cbPolicy,
1504 URLZONEREG ulrZoneReg)
1505 {
1506 FIXME("(%p)->(%08x %s %p %08x %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
1507 ppPolicy, cbPolicy, ulrZoneReg);
1508 return E_NOTIMPL;
1509 }
1510
1511 /********************************************************************
1512 * IInternetZoneManager_GetZoneActionPolicy
1513 */
1514 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicy(IInternetZoneManagerEx2* iface,
1515 DWORD dwZone, DWORD dwAction, BYTE* pPolicy, DWORD cbPolicy, URLZONEREG urlZoneReg)
1516 {
1517 TRACE("(%p)->(%d %08x %p %d %d)\n", iface, dwZone, dwAction, pPolicy,
1518 cbPolicy, urlZoneReg);
1519
1520 if(!pPolicy)
1521 return E_INVALIDARG;
1522
1523 return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg);
1524 }
1525
1526 /********************************************************************
1527 * IInternetZoneManager_SetZoneActionPolicy
1528 */
1529 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicy(IInternetZoneManagerEx2* iface,
1530 DWORD dwZone,
1531 DWORD dwAction,
1532 BYTE* pPolicy,
1533 DWORD cbPolicy,
1534 URLZONEREG urlZoneReg)
1535 {
1536 FIXME("(%p)->(%08x %08x %p %08x %08x) stub\n", iface, dwZone, dwAction, pPolicy,
1537 cbPolicy, urlZoneReg);
1538 return E_NOTIMPL;
1539 }
1540
1541 /********************************************************************
1542 * IInternetZoneManager_PromptAction
1543 */
1544 static HRESULT WINAPI ZoneMgrImpl_PromptAction(IInternetZoneManagerEx2* iface,
1545 DWORD dwAction,
1546 HWND hwndParent,
1547 LPCWSTR pwszUrl,
1548 LPCWSTR pwszText,
1549 DWORD dwPromptFlags)
1550 {
1551 FIXME("%p %08x %p %s %s %08x\n", iface, dwAction, hwndParent,
1552 debugstr_w(pwszUrl), debugstr_w(pwszText), dwPromptFlags );
1553 return E_NOTIMPL;
1554 }
1555
1556 /********************************************************************
1557 * IInternetZoneManager_LogAction
1558 */
1559 static HRESULT WINAPI ZoneMgrImpl_LogAction(IInternetZoneManagerEx2* iface,
1560 DWORD dwAction,
1561 LPCWSTR pwszUrl,
1562 LPCWSTR pwszText,
1563 DWORD dwLogFlags)
1564 {
1565 FIXME("(%p)->(%08x %s %s %08x) stub\n", iface, dwAction, debugstr_w(pwszUrl),
1566 debugstr_w(pwszText), dwLogFlags);
1567 return E_NOTIMPL;
1568 }
1569
1570 /********************************************************************
1571 * IInternetZoneManager_CreateZoneEnumerator
1572 */
1573 static HRESULT WINAPI ZoneMgrImpl_CreateZoneEnumerator(IInternetZoneManagerEx2* iface,
1574 DWORD* pdwEnum,
1575 DWORD* pdwCount,
1576 DWORD dwFlags)
1577 {
1578 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1579 LPDWORD * new_maps;
1580 LPDWORD data;
1581 DWORD i;
1582
1583 TRACE("(%p)->(%p, %p, 0x%08x)\n", This, pdwEnum, pdwCount, dwFlags);
1584 if (!pdwEnum || !pdwCount || (dwFlags != 0))
1585 return E_INVALIDARG;
1586
1587 data = build_zonemap_from_reg();
1588 TRACE("found %d zones\n", data ? data[0] : -1);
1589
1590 if (!data)
1591 return E_FAIL;
1592
1593 for (i = 0; i < This->zonemap_count; i++) {
1594 if (This->zonemaps && !This->zonemaps[i]) {
1595 This->zonemaps[i] = data;
1596 *pdwEnum = i;
1597 *pdwCount = data[0];
1598 return S_OK;
1599 }
1600 }
1601
1602 if (This->zonemaps) {
1603 /* try to double the nr. of pointers in the array */
1604 new_maps = heap_realloc_zero(This->zonemaps, This->zonemap_count * 2 * sizeof(LPDWORD));
1605 if (new_maps)
1606 This->zonemap_count *= 2;
1607 }
1608 else
1609 {
1610 This->zonemap_count = 2;
1611 new_maps = heap_alloc_zero(This->zonemap_count * sizeof(LPDWORD));
1612 }
1613
1614 if (!new_maps) {
1615 heap_free(data);
1616 return E_FAIL;
1617 }
1618 This->zonemaps = new_maps;
1619 This->zonemaps[i] = data;
1620 *pdwEnum = i;
1621 *pdwCount = data[0];
1622 return S_OK;
1623 }
1624
1625 /********************************************************************
1626 * IInternetZoneManager_GetZoneAt
1627 */
1628 static HRESULT WINAPI ZoneMgrImpl_GetZoneAt(IInternetZoneManagerEx2* iface,
1629 DWORD dwEnum,
1630 DWORD dwIndex,
1631 DWORD* pdwZone)
1632 {
1633 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1634 LPDWORD data;
1635
1636 TRACE("(%p)->(0x%08x, %d, %p)\n", This, dwEnum, dwIndex, pdwZone);
1637
1638 /* make sure, that dwEnum and dwIndex are in the valid range */
1639 if (dwEnum < This->zonemap_count) {
1640 if ((data = This->zonemaps[dwEnum])) {
1641 if (dwIndex < data[0]) {
1642 *pdwZone = data[dwIndex + 1];
1643 return S_OK;
1644 }
1645 }
1646 }
1647 return E_INVALIDARG;
1648 }
1649
1650 /********************************************************************
1651 * IInternetZoneManager_DestroyZoneEnumerator
1652 */
1653 static HRESULT WINAPI ZoneMgrImpl_DestroyZoneEnumerator(IInternetZoneManagerEx2* iface,
1654 DWORD dwEnum)
1655 {
1656 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1657 LPDWORD data;
1658
1659 TRACE("(%p)->(0x%08x)\n", This, dwEnum);
1660 /* make sure, that dwEnum is valid */
1661 if (dwEnum < This->zonemap_count) {
1662 if ((data = This->zonemaps[dwEnum])) {
1663 This->zonemaps[dwEnum] = NULL;
1664 heap_free(data);
1665 return S_OK;
1666 }
1667 }
1668 return E_INVALIDARG;
1669 }
1670
1671 /********************************************************************
1672 * IInternetZoneManager_CopyTemplatePoliciesToZone
1673 */
1674 static HRESULT WINAPI ZoneMgrImpl_CopyTemplatePoliciesToZone(IInternetZoneManagerEx2* iface,
1675 DWORD dwTemplate,
1676 DWORD dwZone,
1677 DWORD dwReserved)
1678 {
1679 FIXME("(%p)->(%08x %08x %08x) stub\n", iface, dwTemplate, dwZone, dwReserved);
1680 return E_NOTIMPL;
1681 }
1682
1683 /********************************************************************
1684 * IInternetZoneManagerEx_GetZoneActionPolicyEx
1685 */
1686 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicyEx(IInternetZoneManagerEx2* iface,
1687 DWORD dwZone,
1688 DWORD dwAction,
1689 BYTE* pPolicy,
1690 DWORD cbPolicy,
1691 URLZONEREG urlZoneReg,
1692 DWORD dwFlags)
1693 {
1694 TRACE("(%p)->(%d, 0x%x, %p, %d, %d, 0x%x)\n", iface, dwZone,
1695 dwAction, pPolicy, cbPolicy, urlZoneReg, dwFlags);
1696
1697 if(!pPolicy)
1698 return E_INVALIDARG;
1699
1700 if (dwFlags)
1701 FIXME("dwFlags 0x%x ignored\n", dwFlags);
1702
1703 return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg);
1704 }
1705
1706 /********************************************************************
1707 * IInternetZoneManagerEx_SetZoneActionPolicyEx
1708 */
1709 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicyEx(IInternetZoneManagerEx2* iface,
1710 DWORD dwZone,
1711 DWORD dwAction,
1712 BYTE* pPolicy,
1713 DWORD cbPolicy,
1714 URLZONEREG urlZoneReg,
1715 DWORD dwFlags)
1716 {
1717 FIXME("(%p)->(%d, 0x%x, %p, %d, %d, 0x%x) stub\n", iface, dwZone, dwAction, pPolicy,
1718 cbPolicy, urlZoneReg, dwFlags);
1719 return E_NOTIMPL;
1720 }
1721
1722 /********************************************************************
1723 * IInternetZoneManagerEx2_GetZoneAttributesEx
1724 */
1725 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributesEx(IInternetZoneManagerEx2* iface,
1726 DWORD dwZone,
1727 ZONEATTRIBUTES* pZoneAttributes,
1728 DWORD dwFlags)
1729 {
1730 TRACE("(%p)->(%d, %p, 0x%x)\n", iface, dwZone, pZoneAttributes, dwFlags);
1731
1732 if (dwFlags)
1733 FIXME("dwFlags 0x%x ignored\n", dwFlags);
1734
1735 return IInternetZoneManagerEx2_GetZoneAttributes(iface, dwZone, pZoneAttributes);
1736 }
1737
1738
1739 /********************************************************************
1740 * IInternetZoneManagerEx2_GetZoneSecurityState
1741 */
1742 static HRESULT WINAPI ZoneMgrImpl_GetZoneSecurityState(IInternetZoneManagerEx2* iface,
1743 DWORD dwZoneIndex,
1744 BOOL fRespectPolicy,
1745 LPDWORD pdwState,
1746 BOOL *pfPolicyEncountered)
1747 {
1748 FIXME("(%p)->(%d, %d, %p, %p) stub\n", iface, dwZoneIndex, fRespectPolicy,
1749 pdwState, pfPolicyEncountered);
1750
1751 *pdwState = SECURITY_IE_STATE_GREEN;
1752
1753 if (pfPolicyEncountered)
1754 *pfPolicyEncountered = FALSE;
1755
1756 return S_OK;
1757 }
1758
1759 /********************************************************************
1760 * IInternetZoneManagerEx2_GetIESecurityState
1761 */
1762 static HRESULT WINAPI ZoneMgrImpl_GetIESecurityState(IInternetZoneManagerEx2* iface,
1763 BOOL fRespectPolicy,
1764 LPDWORD pdwState,
1765 BOOL *pfPolicyEncountered,
1766 BOOL fNoCache)
1767 {
1768 FIXME("(%p)->(%d, %p, %p, %d) stub\n", iface, fRespectPolicy, pdwState,
1769 pfPolicyEncountered, fNoCache);
1770
1771 *pdwState = SECURITY_IE_STATE_GREEN;
1772
1773 if (pfPolicyEncountered)
1774 *pfPolicyEncountered = FALSE;
1775
1776 return S_OK;
1777 }
1778
1779 /********************************************************************
1780 * IInternetZoneManagerEx2_FixInsecureSettings
1781 */
1782 static HRESULT WINAPI ZoneMgrImpl_FixInsecureSettings(IInternetZoneManagerEx2* iface)
1783 {
1784 FIXME("(%p) stub\n", iface);
1785 return S_OK;
1786 }
1787
1788 /********************************************************************
1789 * IInternetZoneManager_Construct
1790 */
1791 static const IInternetZoneManagerEx2Vtbl ZoneMgrImplVtbl = {
1792 ZoneMgrImpl_QueryInterface,
1793 ZoneMgrImpl_AddRef,
1794 ZoneMgrImpl_Release,
1795 /* IInternetZoneManager */
1796 ZoneMgrImpl_GetZoneAttributes,
1797 ZoneMgrImpl_SetZoneAttributes,
1798 ZoneMgrImpl_GetZoneCustomPolicy,
1799 ZoneMgrImpl_SetZoneCustomPolicy,
1800 ZoneMgrImpl_GetZoneActionPolicy,
1801 ZoneMgrImpl_SetZoneActionPolicy,
1802 ZoneMgrImpl_PromptAction,
1803 ZoneMgrImpl_LogAction,
1804 ZoneMgrImpl_CreateZoneEnumerator,
1805 ZoneMgrImpl_GetZoneAt,
1806 ZoneMgrImpl_DestroyZoneEnumerator,
1807 ZoneMgrImpl_CopyTemplatePoliciesToZone,
1808 /* IInternetZoneManagerEx */
1809 ZoneMgrImpl_GetZoneActionPolicyEx,
1810 ZoneMgrImpl_SetZoneActionPolicyEx,
1811 /* IInternetZoneManagerEx2 */
1812 ZoneMgrImpl_GetZoneAttributesEx,
1813 ZoneMgrImpl_GetZoneSecurityState,
1814 ZoneMgrImpl_GetIESecurityState,
1815 ZoneMgrImpl_FixInsecureSettings,
1816 };
1817
1818 HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
1819 {
1820 ZoneMgrImpl* ret = heap_alloc_zero(sizeof(ZoneMgrImpl));
1821
1822 TRACE("(%p %p)\n", pUnkOuter, ppobj);
1823 ret->IInternetZoneManagerEx2_iface.lpVtbl = &ZoneMgrImplVtbl;
1824 ret->ref = 1;
1825 *ppobj = (IInternetZoneManagerEx*)ret;
1826
1827 URLMON_LockModule();
1828
1829 return S_OK;
1830 }
1831
1832 /***********************************************************************
1833 * CoInternetCreateSecurityManager (URLMON.@)
1834 *
1835 */
1836 HRESULT WINAPI CoInternetCreateSecurityManager( IServiceProvider *pSP,
1837 IInternetSecurityManager **ppSM, DWORD dwReserved )
1838 {
1839 TRACE("%p %p %d\n", pSP, ppSM, dwReserved );
1840
1841 if(pSP)
1842 FIXME("pSP not supported\n");
1843
1844 return SecManagerImpl_Construct(NULL, (void**) ppSM);
1845 }
1846
1847 /********************************************************************
1848 * CoInternetCreateZoneManager (URLMON.@)
1849 */
1850 HRESULT WINAPI CoInternetCreateZoneManager(IServiceProvider* pSP, IInternetZoneManager** ppZM, DWORD dwReserved)
1851 {
1852 TRACE("(%p %p %x)\n", pSP, ppZM, dwReserved);
1853 return ZoneMgrImpl_Construct(NULL, (void**)ppZM);
1854 }
1855
1856 static HRESULT parse_security_url(const WCHAR *url, PSUACTION action, WCHAR **result) {
1857 IInternetProtocolInfo *protocol_info;
1858 WCHAR *tmp, *new_url = NULL, *alloc_url = NULL;
1859 DWORD size, new_size;
1860 HRESULT hres = S_OK, parse_hres;
1861
1862 while(1) {
1863 TRACE("parsing %s\n", debugstr_w(url));
1864
1865 protocol_info = get_protocol_info(url);
1866 if(!protocol_info)
1867 break;
1868
1869 size = strlenW(url)+1;
1870 new_url = CoTaskMemAlloc(size*sizeof(WCHAR));
1871 if(!new_url) {
1872 hres = E_OUTOFMEMORY;
1873 break;
1874 }
1875
1876 new_size = 0;
1877 parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_URL, 0, new_url, size, &new_size, 0);
1878 if(parse_hres == S_FALSE) {
1879 if(!new_size) {
1880 hres = E_UNEXPECTED;
1881 break;
1882 }
1883
1884 tmp = CoTaskMemRealloc(new_url, new_size*sizeof(WCHAR));
1885 if(!tmp) {
1886 hres = E_OUTOFMEMORY;
1887 break;
1888 }
1889 new_url = tmp;
1890 parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_URL, 0, new_url,
1891 new_size, &new_size, 0);
1892 if(parse_hres == S_FALSE) {
1893 hres = E_FAIL;
1894 break;
1895 }
1896 }
1897
1898 if(parse_hres != S_OK || !strcmpW(url, new_url))
1899 break;
1900
1901 CoTaskMemFree(alloc_url);
1902 url = alloc_url = new_url;
1903 new_url = NULL;
1904 }
1905
1906 CoTaskMemFree(new_url);
1907
1908 if(hres != S_OK) {
1909 WARN("failed: %08x\n", hres);
1910 CoTaskMemFree(alloc_url);
1911 return hres;
1912 }
1913
1914 if(action == PSU_DEFAULT && (protocol_info = get_protocol_info(url))) {
1915 size = strlenW(url)+1;
1916 new_url = CoTaskMemAlloc(size * sizeof(WCHAR));
1917 if(new_url) {
1918 new_size = 0;
1919 parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_DOMAIN, 0,
1920 new_url, size, &new_size, 0);
1921 if(parse_hres == S_FALSE) {
1922 if(new_size) {
1923 tmp = CoTaskMemRealloc(new_url, new_size*sizeof(WCHAR));
1924 if(tmp) {
1925 new_url = tmp;
1926 parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_DOMAIN, 0, new_url,
1927 new_size, &new_size, 0);
1928 if(parse_hres == S_FALSE)
1929 hres = E_FAIL;
1930 }else {
1931 hres = E_OUTOFMEMORY;
1932 }
1933 }else {
1934 hres = E_UNEXPECTED;
1935 }
1936 }
1937
1938 if(hres == S_OK && parse_hres == S_OK) {
1939 CoTaskMemFree(alloc_url);
1940 url = alloc_url = new_url;
1941 new_url = NULL;
1942 }
1943
1944 CoTaskMemFree(new_url);
1945 }else {
1946 hres = E_OUTOFMEMORY;
1947 }
1948 IInternetProtocolInfo_Release(protocol_info);
1949 }
1950
1951 if(FAILED(hres)) {
1952 WARN("failed %08x\n", hres);
1953 CoTaskMemFree(alloc_url);
1954 return hres;
1955 }
1956
1957 if(!alloc_url) {
1958 size = strlenW(url)+1;
1959 alloc_url = CoTaskMemAlloc(size * sizeof(WCHAR));
1960 if(!alloc_url)
1961 return E_OUTOFMEMORY;
1962 memcpy(alloc_url, url, size * sizeof(WCHAR));
1963 }
1964
1965 *result = alloc_url;
1966 return S_OK;
1967 }
1968
1969 /********************************************************************
1970 * CoInternetGetSecurityUrl (URLMON.@)
1971 */
1972 HRESULT WINAPI CoInternetGetSecurityUrl(LPCWSTR pwzUrl, LPWSTR *ppwzSecUrl, PSUACTION psuAction, DWORD dwReserved)
1973 {
1974 WCHAR *secure_url;
1975 HRESULT hres;
1976
1977 TRACE("(%p,%p,%u,%u)\n", pwzUrl, ppwzSecUrl, psuAction, dwReserved);
1978
1979 hres = parse_security_url(pwzUrl, psuAction, &secure_url);
1980 if(FAILED(hres))
1981 return hres;
1982
1983 if(psuAction != PSU_SECURITY_URL_ONLY) {
1984 PARSEDURLW parsed_url = { sizeof(parsed_url) };
1985 DWORD size;
1986
1987 /* FIXME: Use helpers from uri.c */
1988 if(SUCCEEDED(ParseURLW(secure_url, &parsed_url))) {
1989 WCHAR *new_url;
1990
1991 switch(parsed_url.nScheme) {
1992 case URL_SCHEME_FTP:
1993 case URL_SCHEME_HTTP:
1994 case URL_SCHEME_HTTPS:
1995 size = strlenW(secure_url)+1;
1996 new_url = CoTaskMemAlloc(size * sizeof(WCHAR));
1997 if(new_url)
1998 hres = UrlGetPartW(secure_url, new_url, &size, URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME);
1999 else
2000 hres = E_OUTOFMEMORY;
2001 CoTaskMemFree(secure_url);
2002 if(hres != S_OK) {
2003 WARN("UrlGetPart failed: %08x\n", hres);
2004 CoTaskMemFree(new_url);
2005 return FAILED(hres) ? hres : E_FAIL;
2006 }
2007 secure_url = new_url;
2008 }
2009 }
2010 }
2011
2012 *ppwzSecUrl = secure_url;
2013 return S_OK;
2014 }
2015
2016 /********************************************************************
2017 * CoInternetGetSecurityUrlEx (URLMON.@)
2018 */
2019 HRESULT WINAPI CoInternetGetSecurityUrlEx(IUri *pUri, IUri **ppSecUri, PSUACTION psuAction, DWORD_PTR dwReserved)
2020 {
2021 URL_SCHEME scheme_type;
2022 BSTR secure_uri;
2023 WCHAR *ret_url;
2024 HRESULT hres;
2025
2026 TRACE("(%p,%p,%u,%u)\n", pUri, ppSecUri, psuAction, (DWORD)dwReserved);
2027
2028 if(!pUri || !ppSecUri)
2029 return E_INVALIDARG;
2030
2031 hres = IUri_GetDisplayUri(pUri, &secure_uri);
2032 if(FAILED(hres))
2033 return hres;
2034
2035 hres = parse_security_url(secure_uri, psuAction, &ret_url);
2036 SysFreeString(secure_uri);
2037 if(FAILED(hres))
2038 return hres;
2039
2040 /* File URIs have to hierarchical. */
2041 hres = IUri_GetScheme(pUri, (DWORD*)&scheme_type);
2042 if(SUCCEEDED(hres) && scheme_type == URL_SCHEME_FILE) {
2043 const WCHAR *tmp = ret_url;
2044
2045 /* Check and see if a "//" is after the scheme name. */
2046 tmp += sizeof(fileW)/sizeof(WCHAR);
2047 if(*tmp != '/' || *(tmp+1) != '/')
2048 hres = E_INVALIDARG;
2049 }
2050
2051 if(SUCCEEDED(hres))
2052 hres = CreateUri(ret_url, Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, 0, ppSecUri);
2053 CoTaskMemFree(ret_url);
2054 return hres;
2055 }
2056
2057 /********************************************************************
2058 * CompareSecurityIds (URLMON.@)
2059 */
2060 HRESULT WINAPI CompareSecurityIds(BYTE *secid1, DWORD size1, BYTE *secid2, DWORD size2, DWORD reserved)
2061 {
2062 FIXME("(%p %d %p %d %x)\n", secid1, size1, secid2, size2, reserved);
2063 return E_NOTIMPL;
2064 }
2065
2066 /********************************************************************
2067 * IsInternetESCEnabledLocal (URLMON.108)
2068 *
2069 * Undocumented, returns if IE is running in Enhanced Security Configuration.
2070 */
2071 BOOL WINAPI IsInternetESCEnabledLocal(void)
2072 {
2073 static BOOL esc_initialized, esc_enabled;
2074
2075 TRACE("()\n");
2076
2077 if(!esc_initialized) {
2078 DWORD type, size, val;
2079 HKEY zone_map;
2080
2081 static const WCHAR iehardenW[] = {'I','E','H','a','r','d','e','n',0};
2082
2083 if(RegOpenKeyExW(HKEY_CURRENT_USER, zone_map_keyW, 0, KEY_QUERY_VALUE, &zone_map) == ERROR_SUCCESS) {
2084 size = sizeof(DWORD);
2085 if(RegQueryValueExW(zone_map, iehardenW, NULL, &type, (BYTE*)&val, &size) == ERROR_SUCCESS)
2086 esc_enabled = type == REG_DWORD && val != 0;
2087 RegCloseKey(zone_map);
2088 }
2089 esc_initialized = TRUE;
2090 }
2091
2092 return esc_enabled;
2093 }