widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / urlmon / sec_mgr.c
blob60672930ebce68cd2b78373321b3db60f5472f48
1 /*
2 * Internet Security and Zone Manager
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
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.
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.
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
24 #include <stdio.h>
26 #include "urlmon_main.h"
27 #include "winreg.h"
28 #include "wininet.h"
30 #define NO_SHLWAPI_REG
31 #include "shlwapi.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
36 static const WCHAR wszZonesKey[] =
37 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\";
38 static const WCHAR zone_map_keyW[] =
39 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap";
40 static const WCHAR wszZoneMapDomainsKey[] =
41 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\Domains";
43 static inline BOOL is_drive_path(const WCHAR *path)
45 return iswalpha(*path) && *(path+1) == ':';
48 /* List of schemes types Windows seems to expect to be hierarchical. */
49 static inline BOOL is_hierarchical_scheme(URL_SCHEME type) {
50 return(type == URL_SCHEME_HTTP || type == URL_SCHEME_FTP ||
51 type == URL_SCHEME_GOPHER || type == URL_SCHEME_NNTP ||
52 type == URL_SCHEME_TELNET || type == URL_SCHEME_WAIS ||
53 type == URL_SCHEME_FILE || type == URL_SCHEME_HTTPS ||
54 type == URL_SCHEME_RES);
57 /********************************************************************
58 * get_string_from_reg [internal]
60 * helper to get a string from the reg.
63 static void get_string_from_reg(HKEY hcu, HKEY hklm, LPCWSTR name, LPWSTR out, DWORD maxlen)
65 DWORD type = REG_SZ;
66 DWORD len = maxlen * sizeof(WCHAR);
67 DWORD res;
69 res = RegQueryValueExW(hcu, name, NULL, &type, (LPBYTE) out, &len);
71 if (res && hklm) {
72 len = maxlen * sizeof(WCHAR);
73 type = REG_SZ;
74 res = RegQueryValueExW(hklm, name, NULL, &type, (LPBYTE) out, &len);
77 if (res) {
78 TRACE("%s failed: %d\n", debugstr_w(name), res);
79 *out = '\0';
83 /********************************************************************
84 * get_dword_from_reg [internal]
86 * helper to get a dword from the reg.
89 static void get_dword_from_reg(HKEY hcu, HKEY hklm, LPCWSTR name, LPDWORD out)
91 DWORD type = REG_DWORD;
92 DWORD len = sizeof(DWORD);
93 DWORD res;
95 res = RegQueryValueExW(hcu, name, NULL, &type, (LPBYTE) out, &len);
97 if (res && hklm) {
98 len = sizeof(DWORD);
99 type = REG_DWORD;
100 res = RegQueryValueExW(hklm, name, NULL, &type, (LPBYTE) out, &len);
103 if (res) {
104 TRACE("%s failed: %d\n", debugstr_w(name), res);
105 *out = 0;
109 static HRESULT get_zone_from_reg(LPCWSTR schema, DWORD *zone)
111 DWORD res, size;
112 HKEY hkey;
114 static const WCHAR wszZoneMapProtocolKey[] =
115 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap\\ProtocolDefaults";
117 res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapProtocolKey, &hkey);
118 if(res != ERROR_SUCCESS) {
119 ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
120 return E_UNEXPECTED;
123 size = sizeof(DWORD);
124 res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
125 RegCloseKey(hkey);
126 if(res == ERROR_SUCCESS)
127 return S_OK;
129 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapProtocolKey, &hkey);
130 if(res != ERROR_SUCCESS) {
131 ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
132 return E_UNEXPECTED;
135 size = sizeof(DWORD);
136 res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
137 RegCloseKey(hkey);
138 if(res == ERROR_SUCCESS)
139 return S_OK;
141 *zone = 3;
142 return S_OK;
145 /********************************************************************
146 * matches_domain_pattern [internal]
148 * Checks if the given string matches the specified domain pattern.
150 * This function looks for explicit wildcard domain components iff
151 * they appear at the very beginning of the 'pattern' string
153 * pattern = "*.google.com"
155 static BOOL matches_domain_pattern(LPCWSTR pattern, LPCWSTR str, BOOL implicit_wildcard, LPCWSTR *matched)
157 BOOL matches = FALSE;
158 DWORD pattern_len = lstrlenW(pattern);
159 DWORD str_len = lstrlenW(str);
161 TRACE("(%d) Checking if %s matches %s\n", implicit_wildcard, debugstr_w(str), debugstr_w(pattern));
163 *matched = NULL;
164 if(str_len >= pattern_len) {
165 /* Check if there's an explicit wildcard in the pattern. */
166 if(pattern[0] == '*' && pattern[1] == '.') {
167 /* Make sure that 'str' matches the wildcard pattern.
169 * Example:
170 * pattern = "*.google.com"
172 * So in this case 'str' would have to end with ".google.com" in order
173 * to map to this pattern.
175 if(str_len >= pattern_len+1 && !wcsicmp(str+(str_len-pattern_len+1), pattern+1)) {
176 /* Check if there's another '.' inside of the "unmatched" portion
177 * of 'str'.
179 * Example:
180 * pattern = "*.google.com"
181 * str = "test.testing.google.com"
183 * The currently matched portion is ".google.com" in 'str', we need
184 * see if there's a '.' inside of the unmatched portion ("test.testing"), because
185 * if there is and 'implicit_wildcard' isn't set, then this isn't
186 * a match.
188 const WCHAR *ptr;
189 for (ptr = str + str_len - pattern_len; ptr > str; ptr--) if (ptr[-1] == '.') break;
190 if (ptr == str || implicit_wildcard) {
191 matches = TRUE;
192 *matched = ptr;
195 } else if(implicit_wildcard && str_len > pattern_len) {
196 /* When the pattern has an implicit wildcard component, it means
197 * that anything goes in 'str' as long as it ends with the pattern
198 * and that the beginning of the match has a '.' before it.
200 * Example:
201 * pattern = "google.com"
202 * str = "www.google.com"
204 * Implicitly matches the pattern, where as:
206 * pattern = "google.com"
207 * str = "wwwgoogle.com"
209 * Doesn't match the pattern.
211 if(str[str_len-pattern_len-1] == '.' && !wcsicmp(str+(str_len-pattern_len), pattern)) {
212 matches = TRUE;
213 *matched = str+(str_len-pattern_len);
215 } else {
216 /* The pattern doesn't have an implicit wildcard, or an explicit wildcard,
217 * so 'str' has to be an exact match to the 'pattern'.
219 if(!wcsicmp(str, pattern)) {
220 matches = TRUE;
221 *matched = str;
226 if(matches)
227 TRACE("Found a match: matched=%s\n", debugstr_w(*matched));
228 else
229 TRACE("No match found\n");
231 return matches;
234 static BOOL get_zone_for_scheme(HKEY key, LPCWSTR schema, DWORD *zone)
236 DWORD res;
237 DWORD size = sizeof(DWORD);
238 DWORD type;
240 /* See if the key contains a value for the scheme first. */
241 res = RegQueryValueExW(key, schema, NULL, &type, (BYTE*)zone, &size);
242 if(res == ERROR_SUCCESS) {
243 if(type == REG_DWORD)
244 return TRUE;
245 WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(schema));
248 /* Try to get the zone for the wildcard scheme. */
249 size = sizeof(DWORD);
250 res = RegQueryValueExW(key, L"*", NULL, &type, (BYTE*)zone, &size);
251 if(res != ERROR_SUCCESS)
252 return FALSE;
254 if(type != REG_DWORD) {
255 WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(L"*"));
256 return FALSE;
259 return TRUE;
262 /********************************************************************
263 * search_domain_for_zone [internal]
265 * Searches the specified 'domain' registry key to see if 'host' maps into it, or any
266 * of its subdomain registry keys.
268 * Returns S_OK if a match is found, S_FALSE if no matches were found, or an error code.
270 static HRESULT search_domain_for_zone(HKEY domains, LPCWSTR domain, DWORD domain_len, LPCWSTR schema,
271 LPCWSTR host, DWORD host_len, DWORD *zone)
273 BOOL found = FALSE;
274 HKEY domain_key;
275 DWORD res;
276 LPCWSTR matched;
278 if(host_len >= domain_len && matches_domain_pattern(domain, host, TRUE, &matched)) {
279 res = RegOpenKeyW(domains, domain, &domain_key);
280 if(res != ERROR_SUCCESS) {
281 ERR("Failed to open domain key %s: %d\n", debugstr_w(domain), res);
282 return E_UNEXPECTED;
285 if(matched == host)
286 found = get_zone_for_scheme(domain_key, schema, zone);
287 else {
288 INT domain_offset;
289 DWORD subdomain_count, subdomain_len;
290 BOOL check_domain = TRUE;
292 find_domain_name(domain, domain_len, &domain_offset);
294 res = RegQueryInfoKeyW(domain_key, NULL, NULL, NULL, &subdomain_count, &subdomain_len,
295 NULL, NULL, NULL, NULL, NULL, NULL);
296 if(res != ERROR_SUCCESS) {
297 ERR("Unable to query info for key %s: %d\n", debugstr_w(domain), res);
298 RegCloseKey(domain_key);
299 return E_UNEXPECTED;
302 if(subdomain_count) {
303 WCHAR *subdomain;
304 WCHAR *component;
305 DWORD i;
307 subdomain = heap_alloc((subdomain_len+1)*sizeof(WCHAR));
308 if(!subdomain) {
309 RegCloseKey(domain_key);
310 return E_OUTOFMEMORY;
313 component = heap_strndupW(host, matched-host-1);
314 if(!component) {
315 heap_free(subdomain);
316 RegCloseKey(domain_key);
317 return E_OUTOFMEMORY;
320 for(i = 0; i < subdomain_count; ++i) {
321 DWORD len = subdomain_len+1;
322 const WCHAR *sub_matched;
324 res = RegEnumKeyExW(domain_key, i, subdomain, &len, NULL, NULL, NULL, NULL);
325 if(res != ERROR_SUCCESS) {
326 heap_free(component);
327 heap_free(subdomain);
328 RegCloseKey(domain_key);
329 return E_UNEXPECTED;
332 if(matches_domain_pattern(subdomain, component, FALSE, &sub_matched)) {
333 HKEY subdomain_key;
335 res = RegOpenKeyW(domain_key, subdomain, &subdomain_key);
336 if(res != ERROR_SUCCESS) {
337 ERR("Unable to open subdomain key %s of %s: %d\n", debugstr_w(subdomain),
338 debugstr_w(domain), res);
339 heap_free(component);
340 heap_free(subdomain);
341 RegCloseKey(domain_key);
342 return E_UNEXPECTED;
345 found = get_zone_for_scheme(subdomain_key, schema, zone);
346 check_domain = FALSE;
347 RegCloseKey(subdomain_key);
348 break;
351 heap_free(subdomain);
352 heap_free(component);
355 /* There's a chance that 'host' implicitly mapped into 'domain', in
356 * which case we check to see if 'domain' contains zone information.
358 * This can only happen if 'domain' is its own domain name.
359 * Example:
360 * "google.com" (domain name = "google.com")
362 * So if:
363 * host = "www.google.com"
365 * Then host would map directly into the "google.com" domain key.
367 * If 'domain' has more than just its domain name, or it does not
368 * have a domain name, then we don't perform the check. The reason
369 * for this is that these domains don't allow implicit mappings.
370 * Example:
371 * domain = "org" (has no domain name)
372 * host = "www.org"
374 * The mapping would only happen if the "org" key had an explicit subkey
375 * called "www".
377 if(check_domain && !domain_offset && !wcschr(host, matched-host-1))
378 found = get_zone_for_scheme(domain_key, schema, zone);
380 RegCloseKey(domain_key);
383 return found ? S_OK : S_FALSE;
386 static HRESULT search_for_domain_mapping(HKEY domains, LPCWSTR schema, LPCWSTR host, DWORD host_len, DWORD *zone)
388 WCHAR *domain;
389 DWORD domain_count, domain_len, i;
390 DWORD res;
391 HRESULT hres = S_FALSE;
393 res = RegQueryInfoKeyW(domains, NULL, NULL, NULL, &domain_count, &domain_len,
394 NULL, NULL, NULL, NULL, NULL, NULL);
395 if(res != ERROR_SUCCESS) {
396 WARN("Failed to retrieve information about key\n");
397 return E_UNEXPECTED;
400 if(!domain_count)
401 return S_FALSE;
403 domain = heap_alloc((domain_len+1)*sizeof(WCHAR));
404 if(!domain)
405 return E_OUTOFMEMORY;
407 for(i = 0; i < domain_count; ++i) {
408 DWORD len = domain_len+1;
410 res = RegEnumKeyExW(domains, i, domain, &len, NULL, NULL, NULL, NULL);
411 if(res != ERROR_SUCCESS) {
412 heap_free(domain);
413 return E_UNEXPECTED;
416 hres = search_domain_for_zone(domains, domain, len, schema, host, host_len, zone);
417 if(FAILED(hres) || hres == S_OK)
418 break;
421 heap_free(domain);
422 return hres;
425 static HRESULT get_zone_from_domains(IUri *uri, DWORD *zone)
427 HRESULT hres;
428 BSTR host, scheme;
429 DWORD res;
430 HKEY domains;
431 DWORD scheme_type;
433 hres = IUri_GetScheme(uri, &scheme_type);
434 if(FAILED(hres))
435 return hres;
437 /* Windows doesn't play nice with unknown scheme types when it tries
438 * to check if a host name maps into any domains.
440 if(scheme_type == URL_SCHEME_UNKNOWN)
441 return S_FALSE;
443 hres = IUri_GetHost(uri, &host);
444 if(FAILED(hres))
445 return hres;
447 /* Known hierarchical scheme types must have a host. If they don't Windows
448 * assigns URLZONE_INVALID to the zone.
450 if((scheme_type != URL_SCHEME_UNKNOWN && scheme_type != URL_SCHEME_FILE)
451 && is_hierarchical_scheme(scheme_type) && !*host) {
452 *zone = URLZONE_INVALID;
454 SysFreeString(host);
456 /* The MapUrlToZone functions return S_OK when this condition occurs. */
457 return S_OK;
460 hres = IUri_GetSchemeName(uri, &scheme);
461 if(FAILED(hres)) {
462 SysFreeString(host);
463 return hres;
466 /* First try CURRENT_USER. */
467 res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapDomainsKey, &domains);
468 if(res == ERROR_SUCCESS) {
469 hres = search_for_domain_mapping(domains, scheme, host, SysStringLen(host), zone);
470 RegCloseKey(domains);
471 } else
472 WARN("Failed to open HKCU's %s key\n", debugstr_w(wszZoneMapDomainsKey));
474 /* If that doesn't work try LOCAL_MACHINE. */
475 if(hres == S_FALSE) {
476 res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapDomainsKey, &domains);
477 if(res == ERROR_SUCCESS) {
478 hres = search_for_domain_mapping(domains, scheme, host, SysStringLen(host), zone);
479 RegCloseKey(domains);
480 } else
481 WARN("Failed to open HKLM's %s key\n", debugstr_w(wszZoneMapDomainsKey));
484 SysFreeString(host);
485 SysFreeString(scheme);
486 return hres;
489 static HRESULT map_security_uri_to_zone(IUri *uri, DWORD *zone)
491 HRESULT hres;
492 BSTR scheme;
494 *zone = URLZONE_INVALID;
496 hres = IUri_GetSchemeName(uri, &scheme);
497 if(FAILED(hres))
498 return hres;
500 if(!wcsicmp(scheme, L"file")) {
501 BSTR path;
502 WCHAR *ptr, *path_start, root[20];
504 hres = IUri_GetPath(uri, &path);
505 if(FAILED(hres)) {
506 SysFreeString(scheme);
507 return hres;
510 if(*path == '/' && is_drive_path(path+1))
511 path_start = path+1;
512 else
513 path_start = path;
515 if((ptr = wcschr(path_start, ':')) && ptr-path_start+1 < ARRAY_SIZE(root)) {
516 UINT type;
518 memcpy(root, path_start, (ptr-path_start+1)*sizeof(WCHAR));
519 root[ptr-path_start+1] = 0;
521 type = GetDriveTypeW(root);
523 switch(type) {
524 case DRIVE_UNKNOWN:
525 case DRIVE_NO_ROOT_DIR:
526 break;
527 case DRIVE_REMOVABLE:
528 case DRIVE_FIXED:
529 case DRIVE_CDROM:
530 case DRIVE_RAMDISK:
531 *zone = URLZONE_LOCAL_MACHINE;
532 hres = S_OK;
533 break;
534 case DRIVE_REMOTE:
535 *zone = URLZONE_INTERNET;
536 hres = S_OK;
537 break;
538 default:
539 FIXME("unsupported drive type %d\n", type);
542 SysFreeString(path);
545 if(*zone == URLZONE_INVALID) {
546 hres = get_zone_from_domains(uri, zone);
547 if(hres == S_FALSE)
548 hres = get_zone_from_reg(scheme, zone);
551 SysFreeString(scheme);
552 return hres;
555 static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
557 IUri *secur_uri;
558 LPWSTR secur_url;
559 HRESULT hres;
561 *zone = URLZONE_INVALID;
563 hres = CoInternetGetSecurityUrl(url, &secur_url, PSU_SECURITY_URL_ONLY, 0);
564 if(hres != S_OK) {
565 DWORD size = lstrlenW(url)*sizeof(WCHAR);
567 secur_url = CoTaskMemAlloc(size);
568 if(!secur_url)
569 return E_OUTOFMEMORY;
571 memcpy(secur_url, url, size);
574 hres = CreateUri(secur_url, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &secur_uri);
575 if(FAILED(hres)) {
576 CoTaskMemFree(secur_url);
577 return hres;
580 hres = map_security_uri_to_zone(secur_uri, zone);
581 IUri_Release(secur_uri);
583 if(FAILED(hres) || !ret_url)
584 CoTaskMemFree(secur_url);
585 else
586 *ret_url = secur_url;
588 return hres;
591 static HRESULT map_uri_to_zone(IUri *uri, DWORD *zone, IUri **ret_uri)
593 HRESULT hres;
594 IUri *secur_uri;
596 hres = CoInternetGetSecurityUrlEx(uri, &secur_uri, PSU_SECURITY_URL_ONLY, 0);
597 if(FAILED(hres))
598 return hres;
600 hres = map_security_uri_to_zone(secur_uri, zone);
601 if(FAILED(hres) || !ret_uri)
602 IUri_Release(secur_uri);
603 else
604 *ret_uri = secur_uri;
606 return hres;
609 static HRESULT open_zone_key(HKEY parent_key, DWORD zone, HKEY *hkey)
611 WCHAR key_name[ARRAY_SIZE(wszZonesKey) + 12];
612 DWORD res;
614 wsprintfW(key_name, L"%s%u", wszZonesKey, zone);
616 res = RegOpenKeyW(parent_key, key_name, hkey);
618 if(res != ERROR_SUCCESS) {
619 WARN("RegOpenKey failed\n");
620 return E_INVALIDARG;
623 return S_OK;
626 static HRESULT get_action_policy(DWORD zone, DWORD action, BYTE *policy, DWORD size, URLZONEREG zone_reg)
628 HKEY parent_key;
629 HKEY hkey;
630 LONG res;
631 HRESULT hres;
633 switch(action) {
634 case URLACTION_SCRIPT_OVERRIDE_SAFETY:
635 case URLACTION_ACTIVEX_OVERRIDE_SCRIPT_SAFETY:
636 *(DWORD*)policy = URLPOLICY_DISALLOW;
637 return S_OK;
640 switch(zone_reg) {
641 case URLZONEREG_DEFAULT:
642 case URLZONEREG_HKCU:
643 parent_key = HKEY_CURRENT_USER;
644 break;
645 case URLZONEREG_HKLM:
646 parent_key = HKEY_LOCAL_MACHINE;
647 break;
648 default:
649 WARN("Unknown URLZONEREG: %d\n", zone_reg);
650 return E_FAIL;
653 hres = open_zone_key(parent_key, zone, &hkey);
654 if(SUCCEEDED(hres)) {
655 WCHAR action_str[16];
656 DWORD len = size;
658 wsprintfW(action_str, L"%X", action);
660 res = RegQueryValueExW(hkey, action_str, NULL, NULL, policy, &len);
661 if(res == ERROR_MORE_DATA) {
662 hres = E_INVALIDARG;
663 }else if(res == ERROR_FILE_NOT_FOUND) {
664 hres = E_FAIL;
665 }else if(res != ERROR_SUCCESS) {
666 ERR("RegQueryValue failed: %d\n", res);
667 hres = E_UNEXPECTED;
670 RegCloseKey(hkey);
673 if(FAILED(hres) && zone_reg == URLZONEREG_DEFAULT)
674 return get_action_policy(zone, action, policy, size, URLZONEREG_HKLM);
676 return hres;
679 static HRESULT generate_security_id(IUri *uri, BYTE *secid, DWORD *secid_len, DWORD zone)
681 DWORD len;
682 HRESULT hres;
683 DWORD scheme_type;
685 if(zone == URLZONE_INVALID)
686 return E_INVALIDARG;
688 hres = IUri_GetScheme(uri, &scheme_type);
689 if(FAILED(hres))
690 return hres;
692 /* Windows handles opaque URLs differently then hierarchical ones. */
693 if(!is_hierarchical_scheme(scheme_type) && scheme_type != URL_SCHEME_WILDCARD) {
694 BSTR display_uri;
696 hres = IUri_GetDisplayUri(uri, &display_uri);
697 if(FAILED(hres))
698 return hres;
700 len = WideCharToMultiByte(CP_ACP, 0, display_uri, -1, NULL, 0, NULL, NULL)-1;
702 if(len+sizeof(DWORD) > *secid_len) {
703 SysFreeString(display_uri);
704 return E_NOT_SUFFICIENT_BUFFER;
707 WideCharToMultiByte(CP_ACP, 0, display_uri, -1, (LPSTR)secid, len, NULL, NULL);
708 SysFreeString(display_uri);
710 *(DWORD*)(secid+len) = zone;
711 } else {
712 BSTR host, scheme;
713 DWORD host_len, scheme_len;
714 BYTE *ptr;
716 hres = IUri_GetHost(uri, &host);
717 if(FAILED(hres))
718 return hres;
720 /* The host can't be empty for Wildcard URIs. */
721 if(scheme_type == URL_SCHEME_WILDCARD && !*host) {
722 SysFreeString(host);
723 return E_INVALIDARG;
726 hres = IUri_GetSchemeName(uri, &scheme);
727 if(FAILED(hres)) {
728 SysFreeString(host);
729 return hres;
732 host_len = WideCharToMultiByte(CP_ACP, 0, host, -1, NULL, 0, NULL, NULL)-1;
733 scheme_len = WideCharToMultiByte(CP_ACP, 0, scheme, -1, NULL, 0, NULL, NULL)-1;
735 len = host_len+scheme_len+sizeof(BYTE);
737 if(len+sizeof(DWORD) > *secid_len) {
738 SysFreeString(host);
739 SysFreeString(scheme);
740 return E_NOT_SUFFICIENT_BUFFER;
743 WideCharToMultiByte(CP_ACP, 0, scheme, -1, (LPSTR)secid, len, NULL, NULL);
744 SysFreeString(scheme);
746 ptr = secid+scheme_len;
747 *ptr++ = ':';
749 WideCharToMultiByte(CP_ACP, 0, host, -1, (LPSTR)ptr, host_len, NULL, NULL);
750 SysFreeString(host);
752 ptr += host_len;
754 *(DWORD*)ptr = zone;
757 *secid_len = len+sizeof(DWORD);
759 return S_OK;
762 static HRESULT get_security_id_for_url(LPCWSTR url, BYTE *secid, DWORD *secid_len)
764 HRESULT hres;
765 DWORD zone = URLZONE_INVALID;
766 LPWSTR secur_url = NULL;
767 IUri *uri;
769 hres = map_url_to_zone(url, &zone, &secur_url);
770 if(FAILED(hres))
771 return hres == 0x80041001 ? E_INVALIDARG : hres;
773 hres = CreateUri(secur_url, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &uri);
774 CoTaskMemFree(secur_url);
775 if(FAILED(hres))
776 return hres;
778 hres = generate_security_id(uri, secid, secid_len, zone);
779 IUri_Release(uri);
781 return hres;
784 static HRESULT get_security_id_for_uri(IUri *uri, BYTE *secid, DWORD *secid_len)
786 HRESULT hres;
787 IUri *secur_uri;
788 DWORD zone = URLZONE_INVALID;
790 hres = map_uri_to_zone(uri, &zone, &secur_uri);
791 if(FAILED(hres))
792 return hres;
794 hres = generate_security_id(secur_uri, secid, secid_len, zone);
795 IUri_Release(secur_uri);
797 return hres;
800 /***********************************************************************
801 * InternetSecurityManager implementation
804 typedef struct {
805 IInternetSecurityManagerEx2 IInternetSecurityManagerEx2_iface;
807 LONG ref;
809 IInternetSecurityMgrSite *mgrsite;
810 IInternetSecurityManager *custom_manager;
811 } SecManagerImpl;
813 static inline SecManagerImpl *impl_from_IInternetSecurityManagerEx2(IInternetSecurityManagerEx2 *iface)
815 return CONTAINING_RECORD(iface, SecManagerImpl, IInternetSecurityManagerEx2_iface);
818 static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManagerEx2* iface,REFIID riid,void** ppvObject)
820 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
822 TRACE("(%p)->(%s %p)\n",This,debugstr_guid(riid),ppvObject);
824 if(!ppvObject)
825 return E_INVALIDARG;
827 if(IsEqualIID(&IID_IUnknown, riid) ||
828 IsEqualIID(&IID_IInternetSecurityManager, riid) ||
829 IsEqualIID(&IID_IInternetSecurityManagerEx, riid) ||
830 IsEqualIID(&IID_IInternetSecurityManagerEx2, riid)) {
831 *ppvObject = iface;
832 } else {
833 WARN("not supported interface %s\n", debugstr_guid(riid));
834 *ppvObject = NULL;
835 return E_NOINTERFACE;
838 IInternetSecurityManagerEx2_AddRef(iface);
839 return S_OK;
842 static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManagerEx2* iface)
844 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
845 ULONG refCount = InterlockedIncrement(&This->ref);
847 TRACE("(%p) ref=%u\n", This, refCount);
849 return refCount;
852 static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManagerEx2* iface)
854 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
855 ULONG refCount = InterlockedDecrement(&This->ref);
857 TRACE("(%p) ref=%u\n", This, refCount);
859 /* destroy the object if there are no more references on it */
860 if (!refCount){
861 if(This->mgrsite)
862 IInternetSecurityMgrSite_Release(This->mgrsite);
863 if(This->custom_manager)
864 IInternetSecurityManager_Release(This->custom_manager);
866 heap_free(This);
868 URLMON_UnlockModule();
871 return refCount;
874 static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManagerEx2 *iface,
875 IInternetSecurityMgrSite *pSite)
877 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
879 TRACE("(%p)->(%p)\n", This, pSite);
881 if(This->mgrsite)
882 IInternetSecurityMgrSite_Release(This->mgrsite);
884 if(This->custom_manager) {
885 IInternetSecurityManager_Release(This->custom_manager);
886 This->custom_manager = NULL;
889 This->mgrsite = pSite;
891 if(pSite) {
892 IServiceProvider *servprov;
893 HRESULT hres;
895 IInternetSecurityMgrSite_AddRef(pSite);
897 hres = IInternetSecurityMgrSite_QueryInterface(pSite, &IID_IServiceProvider,
898 (void**)&servprov);
899 if(SUCCEEDED(hres)) {
900 IServiceProvider_QueryService(servprov, &SID_SInternetSecurityManager,
901 &IID_IInternetSecurityManager, (void**)&This->custom_manager);
902 IServiceProvider_Release(servprov);
906 return S_OK;
909 static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManagerEx2 *iface,
910 IInternetSecurityMgrSite **ppSite)
912 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
914 TRACE("(%p)->(%p)\n", This, ppSite);
916 if(!ppSite)
917 return E_INVALIDARG;
919 if(This->mgrsite)
920 IInternetSecurityMgrSite_AddRef(This->mgrsite);
922 *ppSite = This->mgrsite;
923 return S_OK;
926 static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManagerEx2 *iface,
927 LPCWSTR pwszUrl, DWORD *pdwZone,
928 DWORD dwFlags)
930 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
931 HRESULT hres;
933 TRACE("(%p)->(%s %p %08x)\n", iface, debugstr_w(pwszUrl), pdwZone, dwFlags);
935 if(This->custom_manager) {
936 hres = IInternetSecurityManager_MapUrlToZone(This->custom_manager,
937 pwszUrl, pdwZone, dwFlags);
938 if(hres != INET_E_DEFAULT_ACTION)
939 return hres;
942 if(!pwszUrl) {
943 *pdwZone = URLZONE_INVALID;
944 return E_INVALIDARG;
947 if(dwFlags)
948 FIXME("not supported flags: %08x\n", dwFlags);
950 return map_url_to_zone(pwszUrl, pdwZone, NULL);
953 static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManagerEx2 *iface,
954 LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
956 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
958 TRACE("(%p)->(%s %p %p %08lx)\n", iface, debugstr_w(pwszUrl), pbSecurityId,
959 pcbSecurityId, dwReserved);
961 if(This->custom_manager) {
962 HRESULT hres;
964 hres = IInternetSecurityManager_GetSecurityId(This->custom_manager,
965 pwszUrl, pbSecurityId, pcbSecurityId, dwReserved);
966 if(hres != INET_E_DEFAULT_ACTION)
967 return hres;
970 if(!pwszUrl || !pbSecurityId || !pcbSecurityId)
971 return E_INVALIDARG;
973 if(dwReserved)
974 FIXME("dwReserved is not supported\n");
976 return get_security_id_for_url(pwszUrl, pbSecurityId, pcbSecurityId);
980 static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManagerEx2 *iface,
981 LPCWSTR pwszUrl, DWORD dwAction,
982 BYTE *pPolicy, DWORD cbPolicy,
983 BYTE *pContext, DWORD cbContext,
984 DWORD dwFlags, DWORD dwReserved)
986 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
987 DWORD zone, policy;
988 HRESULT hres;
990 TRACE("(%p)->(%s %08x %p %08x %p %08x %08x %08x)\n", iface, debugstr_w(pwszUrl), dwAction,
991 pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
993 if(This->custom_manager) {
994 hres = IInternetSecurityManager_ProcessUrlAction(This->custom_manager, pwszUrl, dwAction,
995 pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
996 if(hres != INET_E_DEFAULT_ACTION)
997 return hres;
1000 if(dwFlags || dwReserved)
1001 FIXME("Unsupported arguments\n");
1003 if(!pwszUrl)
1004 return E_INVALIDARG;
1006 hres = map_url_to_zone(pwszUrl, &zone, NULL);
1007 if(FAILED(hres))
1008 return hres;
1010 hres = get_action_policy(zone, dwAction, (BYTE*)&policy, sizeof(policy), URLZONEREG_DEFAULT);
1011 if(FAILED(hres))
1012 return hres;
1014 TRACE("policy %x\n", policy);
1015 if(cbPolicy >= sizeof(DWORD))
1016 *(DWORD*)pPolicy = policy;
1018 switch(GetUrlPolicyPermissions(policy)) {
1019 case URLPOLICY_ALLOW:
1020 case URLPOLICY_CHANNEL_SOFTDIST_PRECACHE:
1021 return S_OK;
1022 case URLPOLICY_DISALLOW:
1023 return S_FALSE;
1024 case URLPOLICY_QUERY:
1025 FIXME("URLPOLICY_QUERY not implemented\n");
1026 return E_FAIL;
1027 default:
1028 FIXME("Not implemented policy %x\n", policy);
1031 return E_FAIL;
1035 static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManagerEx2 *iface,
1036 LPCWSTR pwszUrl, REFGUID guidKey,
1037 BYTE **ppPolicy, DWORD *pcbPolicy,
1038 BYTE *pContext, DWORD cbContext,
1039 DWORD dwReserved)
1041 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1042 HRESULT hres;
1044 TRACE("(%p)->(%s %s %p %p %p %08x %08x )\n", iface, debugstr_w(pwszUrl), debugstr_guid(guidKey),
1045 ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
1047 if(This->custom_manager) {
1048 hres = IInternetSecurityManager_QueryCustomPolicy(This->custom_manager, pwszUrl, guidKey,
1049 ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
1050 if(hres != INET_E_DEFAULT_ACTION)
1051 return hres;
1054 WARN("Unknown guidKey %s\n", debugstr_guid(guidKey));
1055 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1058 static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManagerEx2 *iface,
1059 DWORD dwZone, LPCWSTR pwszPattern, DWORD dwFlags)
1061 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1062 HRESULT hres;
1064 TRACE("(%p)->(%08x %s %08x)\n", iface, dwZone, debugstr_w(pwszPattern),dwFlags);
1066 if(This->custom_manager) {
1067 hres = IInternetSecurityManager_SetZoneMapping(This->custom_manager, dwZone,
1068 pwszPattern, dwFlags);
1069 if(hres != INET_E_DEFAULT_ACTION)
1070 return hres;
1073 FIXME("Default action is not implemented\n");
1074 return E_NOTIMPL;
1077 static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManagerEx2 *iface,
1078 DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
1080 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1081 HRESULT hres;
1083 TRACE("(%p)->(%08x %p %08x)\n", iface, dwZone, ppenumString,dwFlags);
1085 if(This->custom_manager) {
1086 hres = IInternetSecurityManager_GetZoneMappings(This->custom_manager, dwZone,
1087 ppenumString, dwFlags);
1088 if(hres != INET_E_DEFAULT_ACTION)
1089 return hres;
1092 FIXME("Default action is not implemented\n");
1093 return E_NOTIMPL;
1096 static HRESULT WINAPI SecManagerImpl_ProcessUrlActionEx(IInternetSecurityManagerEx2 *iface,
1097 LPCWSTR pwszUrl, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext,
1098 DWORD dwFlags, DWORD dwReserved, DWORD *pdwOutFlags)
1100 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1101 FIXME("(%p)->(%s %08x %p %d %p %d %08x %08x %p) stub\n", This, debugstr_w(pwszUrl), dwAction, pPolicy, cbPolicy,
1102 pContext, cbContext, dwFlags, dwReserved, pdwOutFlags);
1103 return E_NOTIMPL;
1106 static HRESULT WINAPI SecManagerImpl_MapUrlToZoneEx2(IInternetSecurityManagerEx2 *iface,
1107 IUri *pUri, DWORD *pdwZone, DWORD dwFlags, LPWSTR *ppwszMappedUrl, DWORD *pdwOutFlags)
1109 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1111 TRACE("(%p)->(%p %p %08x %p %p)\n", This, pUri, pdwZone, dwFlags, ppwszMappedUrl, pdwOutFlags);
1113 if(This->custom_manager) {
1114 HRESULT hres;
1115 IInternetSecurityManagerEx2 *sec_mgr2;
1117 hres = IInternetSecurityManager_QueryInterface(This->custom_manager, &IID_IInternetSecurityManagerEx2,
1118 (void**)&sec_mgr2);
1119 if(SUCCEEDED(hres)) {
1120 hres = IInternetSecurityManagerEx2_MapUrlToZoneEx2(sec_mgr2, pUri, pdwZone, dwFlags, ppwszMappedUrl, pdwOutFlags);
1121 IInternetSecurityManagerEx2_Release(sec_mgr2);
1122 } else {
1123 BSTR url;
1125 hres = IUri_GetDisplayUri(pUri, &url);
1126 if(FAILED(hres))
1127 return hres;
1129 hres = IInternetSecurityManager_MapUrlToZone(This->custom_manager, url, pdwZone, dwFlags);
1130 SysFreeString(url);
1133 if(hres != INET_E_DEFAULT_ACTION)
1134 return hres;
1137 if(!pdwZone)
1138 return E_INVALIDARG;
1140 if(!pUri) {
1141 *pdwZone = URLZONE_INVALID;
1142 return E_INVALIDARG;
1145 if(dwFlags)
1146 FIXME("Unsupported flags: %08x\n", dwFlags);
1148 return map_uri_to_zone(pUri, pdwZone, NULL);
1151 static HRESULT WINAPI SecManagerImpl_ProcessUrlActionEx2(IInternetSecurityManagerEx2 *iface,
1152 IUri *pUri, DWORD dwAction, BYTE *pPolicy, DWORD cbPolicy, BYTE *pContext, DWORD cbContext,
1153 DWORD dwFlags, DWORD_PTR dwReserved, DWORD *pdwOutFlags)
1155 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1156 FIXME("(%p)->(%p %08x %p %d %p %d %08x %08x %p) stub\n", This, pUri, dwAction, pPolicy,
1157 cbPolicy, pContext, cbContext, dwFlags, (DWORD)dwReserved, pdwOutFlags);
1158 return E_NOTIMPL;
1161 static HRESULT WINAPI SecManagerImpl_GetSecurityIdEx2(IInternetSecurityManagerEx2 *iface,
1162 IUri *pUri, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
1164 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1165 TRACE("(%p)->(%p %p %p %08x) stub\n", This, pUri, pbSecurityId, pcbSecurityId, (DWORD)dwReserved);
1167 if(dwReserved)
1168 FIXME("dwReserved is not supported yet\n");
1170 if(!pUri || !pcbSecurityId || !pbSecurityId)
1171 return E_INVALIDARG;
1173 return get_security_id_for_uri(pUri, pbSecurityId, pcbSecurityId);
1176 static HRESULT WINAPI SecManagerImpl_QueryCustomPolicyEx2(IInternetSecurityManagerEx2 *iface,
1177 IUri *pUri, REFGUID guidKey, BYTE **ppPolicy, DWORD *pcbPolicy, BYTE *pContext,
1178 DWORD cbContext, DWORD_PTR dwReserved)
1180 SecManagerImpl *This = impl_from_IInternetSecurityManagerEx2(iface);
1181 FIXME("(%p)->(%p %s %p %p %p %d %08x) stub\n", This, pUri, debugstr_guid(guidKey), ppPolicy, pcbPolicy,
1182 pContext, cbContext, (DWORD)dwReserved);
1183 return E_NOTIMPL;
1186 static const IInternetSecurityManagerEx2Vtbl VT_SecManagerImpl =
1188 SecManagerImpl_QueryInterface,
1189 SecManagerImpl_AddRef,
1190 SecManagerImpl_Release,
1191 SecManagerImpl_SetSecuritySite,
1192 SecManagerImpl_GetSecuritySite,
1193 SecManagerImpl_MapUrlToZone,
1194 SecManagerImpl_GetSecurityId,
1195 SecManagerImpl_ProcessUrlAction,
1196 SecManagerImpl_QueryCustomPolicy,
1197 SecManagerImpl_SetZoneMapping,
1198 SecManagerImpl_GetZoneMappings,
1199 SecManagerImpl_ProcessUrlActionEx,
1200 SecManagerImpl_MapUrlToZoneEx2,
1201 SecManagerImpl_ProcessUrlActionEx2,
1202 SecManagerImpl_GetSecurityIdEx2,
1203 SecManagerImpl_QueryCustomPolicyEx2
1206 HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
1208 SecManagerImpl *This;
1210 TRACE("(%p,%p)\n",pUnkOuter,ppobj);
1211 This = heap_alloc(sizeof(*This));
1213 /* Initialize the virtual function table. */
1214 This->IInternetSecurityManagerEx2_iface.lpVtbl = &VT_SecManagerImpl;
1216 This->ref = 1;
1217 This->mgrsite = NULL;
1218 This->custom_manager = NULL;
1220 *ppobj = This;
1222 URLMON_LockModule();
1224 return S_OK;
1227 /***********************************************************************
1228 * InternetZoneManager implementation
1231 typedef struct {
1232 IInternetZoneManagerEx2 IInternetZoneManagerEx2_iface;
1233 LONG ref;
1234 LPDWORD *zonemaps;
1235 DWORD zonemap_count;
1236 } ZoneMgrImpl;
1238 static inline ZoneMgrImpl *impl_from_IInternetZoneManagerEx2(IInternetZoneManagerEx2 *iface)
1240 return CONTAINING_RECORD(iface, ZoneMgrImpl, IInternetZoneManagerEx2_iface);
1244 /***********************************************************************
1245 * build_zonemap_from_reg [internal]
1247 * Enumerate the Zones in the Registry and return the Zones in a DWORD-array
1248 * The number of the Zones is returned in data[0]
1250 static LPDWORD build_zonemap_from_reg(void)
1252 WCHAR name[32];
1253 HKEY hkey;
1254 LPDWORD data = NULL;
1255 DWORD allocated = 6; /* space for the zonecount and Zone "0" up to Zone "4" */
1256 DWORD used = 0;
1257 DWORD res;
1258 DWORD len;
1261 res = RegOpenKeyW(HKEY_CURRENT_USER, wszZonesKey, &hkey);
1262 if (res)
1263 return NULL;
1265 data = heap_alloc(allocated * sizeof(DWORD));
1266 if (!data)
1267 goto cleanup;
1269 while (!res) {
1270 name[0] = '\0';
1271 len = ARRAY_SIZE(name);
1272 res = RegEnumKeyExW(hkey, used, name, &len, NULL, NULL, NULL, NULL);
1274 if (!res) {
1275 used++;
1276 if (used == allocated) {
1277 LPDWORD new_data;
1279 allocated *= 2;
1280 new_data = heap_realloc_zero(data, allocated * sizeof(DWORD));
1281 if (!new_data)
1282 goto cleanup;
1284 data = new_data;
1286 data[used] = wcstol(name, NULL, 10);
1289 if (used) {
1290 RegCloseKey(hkey);
1291 data[0] = used;
1292 return data;
1295 cleanup:
1296 /* something failed */
1297 RegCloseKey(hkey);
1298 heap_free(data);
1299 return NULL;
1302 /********************************************************************
1303 * IInternetZoneManager_QueryInterface
1305 static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManagerEx2* iface, REFIID riid, void** ppvObject)
1307 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1309 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);
1311 if(!This || !ppvObject)
1312 return E_INVALIDARG;
1314 if(IsEqualIID(&IID_IUnknown, riid)) {
1315 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppvObject);
1316 }else if(IsEqualIID(&IID_IInternetZoneManager, riid)) {
1317 TRACE("(%p)->(IID_InternetZoneManager %p)\n", This, ppvObject);
1318 }else if(IsEqualIID(&IID_IInternetZoneManagerEx, riid)) {
1319 TRACE("(%p)->(IID_InternetZoneManagerEx %p)\n", This, ppvObject);
1320 }else if(IsEqualIID(&IID_IInternetZoneManagerEx2, riid)) {
1321 TRACE("(%p)->(IID_InternetZoneManagerEx2 %p)\n", This, ppvObject);
1323 else
1325 FIXME("Unknown interface: %s\n", debugstr_guid(riid));
1326 *ppvObject = NULL;
1327 return E_NOINTERFACE;
1330 *ppvObject = iface;
1331 IInternetZoneManagerEx2_AddRef(iface);
1332 return S_OK;
1335 /********************************************************************
1336 * IInternetZoneManager_AddRef
1338 static ULONG WINAPI ZoneMgrImpl_AddRef(IInternetZoneManagerEx2* iface)
1340 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1341 ULONG refCount = InterlockedIncrement(&This->ref);
1343 TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
1345 return refCount;
1348 /********************************************************************
1349 * IInternetZoneManager_Release
1351 static ULONG WINAPI ZoneMgrImpl_Release(IInternetZoneManagerEx2* iface)
1353 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1354 ULONG refCount = InterlockedDecrement(&This->ref);
1356 TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
1358 if(!refCount) {
1359 while (This->zonemap_count) heap_free(This->zonemaps[--This->zonemap_count]);
1360 heap_free(This->zonemaps);
1361 heap_free(This);
1362 URLMON_UnlockModule();
1365 return refCount;
1368 /********************************************************************
1369 * IInternetZoneManager_GetZoneAttributes
1371 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributes(IInternetZoneManagerEx2* iface,
1372 DWORD dwZone,
1373 ZONEATTRIBUTES* pZoneAttributes)
1375 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1376 HRESULT hr;
1377 HKEY hcu;
1378 HKEY hklm = NULL;
1380 TRACE("(%p)->(%d %p)\n", This, dwZone, pZoneAttributes);
1382 if (!pZoneAttributes)
1383 return E_INVALIDARG;
1385 hr = open_zone_key(HKEY_CURRENT_USER, dwZone, &hcu);
1386 if (FAILED(hr))
1387 return S_OK; /* IE6 and older returned E_FAIL here */
1389 hr = open_zone_key(HKEY_LOCAL_MACHINE, dwZone, &hklm);
1390 if (FAILED(hr))
1391 TRACE("Zone %d not in HKLM\n", dwZone);
1393 get_string_from_reg(hcu, hklm, L"DisplayName", pZoneAttributes->szDisplayName, MAX_ZONE_PATH);
1394 get_string_from_reg(hcu, hklm, L"Description", pZoneAttributes->szDescription, MAX_ZONE_DESCRIPTION);
1395 get_string_from_reg(hcu, hklm, L"Icon", pZoneAttributes->szIconPath, MAX_ZONE_PATH);
1396 get_dword_from_reg(hcu, hklm, L"MinLevel", &pZoneAttributes->dwTemplateMinLevel);
1397 get_dword_from_reg(hcu, hklm, L"CurrentLevel", &pZoneAttributes->dwTemplateCurrentLevel);
1398 get_dword_from_reg(hcu, hklm, L"RecommendedLevel", &pZoneAttributes->dwTemplateRecommended);
1399 get_dword_from_reg(hcu, hklm, L"Flags", &pZoneAttributes->dwFlags);
1401 RegCloseKey(hklm);
1402 RegCloseKey(hcu);
1403 return S_OK;
1406 /********************************************************************
1407 * IInternetZoneManager_SetZoneAttributes
1409 static HRESULT WINAPI ZoneMgrImpl_SetZoneAttributes(IInternetZoneManagerEx2* iface,
1410 DWORD dwZone,
1411 ZONEATTRIBUTES* pZoneAttributes)
1413 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1414 HRESULT hr;
1415 HKEY hcu;
1417 TRACE("(%p)->(%d %p)\n", This, dwZone, pZoneAttributes);
1419 if (!pZoneAttributes)
1420 return E_INVALIDARG;
1422 hr = open_zone_key(HKEY_CURRENT_USER, dwZone, &hcu);
1423 if (FAILED(hr))
1424 return S_OK; /* IE6 returned E_FAIL here */
1426 /* cbSize is ignored */
1427 RegSetValueExW(hcu, L"DisplayName", 0, REG_SZ, (BYTE*)pZoneAttributes->szDisplayName,
1428 (lstrlenW(pZoneAttributes->szDisplayName)+1)* sizeof(WCHAR));
1430 RegSetValueExW(hcu, L"Description", 0, REG_SZ, (BYTE*)pZoneAttributes->szDescription,
1431 (lstrlenW(pZoneAttributes->szDescription)+1)* sizeof(WCHAR));
1433 RegSetValueExW(hcu, L"Icon", 0, REG_SZ, (BYTE*)pZoneAttributes->szIconPath,
1434 (lstrlenW(pZoneAttributes->szIconPath)+1)* sizeof(WCHAR));
1436 RegSetValueExW(hcu, L"MinLevel", 0, REG_DWORD,
1437 (const BYTE*) &pZoneAttributes->dwTemplateMinLevel, sizeof(DWORD));
1439 RegSetValueExW(hcu, L"CurrentLevel", 0, REG_DWORD,
1440 (const BYTE*) &pZoneAttributes->dwTemplateCurrentLevel, sizeof(DWORD));
1442 RegSetValueExW(hcu, L"RecommendedLevel", 0, REG_DWORD,
1443 (const BYTE*) &pZoneAttributes->dwTemplateRecommended, sizeof(DWORD));
1445 RegSetValueExW(hcu, L"Flags", 0, REG_DWORD, (const BYTE*) &pZoneAttributes->dwFlags, sizeof(DWORD));
1446 RegCloseKey(hcu);
1447 return S_OK;
1451 /********************************************************************
1452 * IInternetZoneManager_GetZoneCustomPolicy
1454 static HRESULT WINAPI ZoneMgrImpl_GetZoneCustomPolicy(IInternetZoneManagerEx2* iface,
1455 DWORD dwZone,
1456 REFGUID guidKey,
1457 BYTE** ppPolicy,
1458 DWORD* pcbPolicy,
1459 URLZONEREG ulrZoneReg)
1461 FIXME("(%p)->(%08x %s %p %p %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
1462 ppPolicy, pcbPolicy, ulrZoneReg);
1463 return E_NOTIMPL;
1466 /********************************************************************
1467 * IInternetZoneManager_SetZoneCustomPolicy
1469 static HRESULT WINAPI ZoneMgrImpl_SetZoneCustomPolicy(IInternetZoneManagerEx2* iface,
1470 DWORD dwZone,
1471 REFGUID guidKey,
1472 BYTE* ppPolicy,
1473 DWORD cbPolicy,
1474 URLZONEREG ulrZoneReg)
1476 FIXME("(%p)->(%08x %s %p %08x %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
1477 ppPolicy, cbPolicy, ulrZoneReg);
1478 return E_NOTIMPL;
1481 /********************************************************************
1482 * IInternetZoneManager_GetZoneActionPolicy
1484 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicy(IInternetZoneManagerEx2* iface,
1485 DWORD dwZone, DWORD dwAction, BYTE* pPolicy, DWORD cbPolicy, URLZONEREG urlZoneReg)
1487 TRACE("(%p)->(%d %08x %p %d %d)\n", iface, dwZone, dwAction, pPolicy,
1488 cbPolicy, urlZoneReg);
1490 if(!pPolicy)
1491 return E_INVALIDARG;
1493 return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg);
1496 /********************************************************************
1497 * IInternetZoneManager_SetZoneActionPolicy
1499 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicy(IInternetZoneManagerEx2* iface,
1500 DWORD dwZone,
1501 DWORD dwAction,
1502 BYTE* pPolicy,
1503 DWORD cbPolicy,
1504 URLZONEREG urlZoneReg)
1506 FIXME("(%p)->(%08x %08x %p %08x %08x) stub\n", iface, dwZone, dwAction, pPolicy,
1507 cbPolicy, urlZoneReg);
1508 return E_NOTIMPL;
1511 /********************************************************************
1512 * IInternetZoneManager_PromptAction
1514 static HRESULT WINAPI ZoneMgrImpl_PromptAction(IInternetZoneManagerEx2* iface,
1515 DWORD dwAction,
1516 HWND hwndParent,
1517 LPCWSTR pwszUrl,
1518 LPCWSTR pwszText,
1519 DWORD dwPromptFlags)
1521 FIXME("%p %08x %p %s %s %08x\n", iface, dwAction, hwndParent,
1522 debugstr_w(pwszUrl), debugstr_w(pwszText), dwPromptFlags );
1523 return E_NOTIMPL;
1526 /********************************************************************
1527 * IInternetZoneManager_LogAction
1529 static HRESULT WINAPI ZoneMgrImpl_LogAction(IInternetZoneManagerEx2* iface,
1530 DWORD dwAction,
1531 LPCWSTR pwszUrl,
1532 LPCWSTR pwszText,
1533 DWORD dwLogFlags)
1535 FIXME("(%p)->(%08x %s %s %08x) stub\n", iface, dwAction, debugstr_w(pwszUrl),
1536 debugstr_w(pwszText), dwLogFlags);
1537 return E_NOTIMPL;
1540 /********************************************************************
1541 * IInternetZoneManager_CreateZoneEnumerator
1543 static HRESULT WINAPI ZoneMgrImpl_CreateZoneEnumerator(IInternetZoneManagerEx2* iface,
1544 DWORD* pdwEnum,
1545 DWORD* pdwCount,
1546 DWORD dwFlags)
1548 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1549 LPDWORD * new_maps;
1550 LPDWORD data;
1551 DWORD i;
1553 TRACE("(%p)->(%p, %p, 0x%08x)\n", This, pdwEnum, pdwCount, dwFlags);
1554 if (!pdwEnum || !pdwCount || (dwFlags != 0))
1555 return E_INVALIDARG;
1557 data = build_zonemap_from_reg();
1558 TRACE("found %d zones\n", data ? data[0] : -1);
1560 if (!data)
1561 return E_FAIL;
1563 for (i = 0; i < This->zonemap_count; i++) {
1564 if (This->zonemaps && !This->zonemaps[i]) {
1565 This->zonemaps[i] = data;
1566 *pdwEnum = i;
1567 *pdwCount = data[0];
1568 return S_OK;
1572 if (This->zonemaps) {
1573 /* try to double the nr. of pointers in the array */
1574 new_maps = heap_realloc_zero(This->zonemaps, This->zonemap_count * 2 * sizeof(LPDWORD));
1575 if (new_maps)
1576 This->zonemap_count *= 2;
1578 else
1580 This->zonemap_count = 2;
1581 new_maps = heap_alloc_zero(This->zonemap_count * sizeof(LPDWORD));
1584 if (!new_maps) {
1585 heap_free(data);
1586 return E_FAIL;
1588 This->zonemaps = new_maps;
1589 This->zonemaps[i] = data;
1590 *pdwEnum = i;
1591 *pdwCount = data[0];
1592 return S_OK;
1595 /********************************************************************
1596 * IInternetZoneManager_GetZoneAt
1598 static HRESULT WINAPI ZoneMgrImpl_GetZoneAt(IInternetZoneManagerEx2* iface,
1599 DWORD dwEnum,
1600 DWORD dwIndex,
1601 DWORD* pdwZone)
1603 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1604 LPDWORD data;
1606 TRACE("(%p)->(0x%08x, %d, %p)\n", This, dwEnum, dwIndex, pdwZone);
1608 /* make sure, that dwEnum and dwIndex are in the valid range */
1609 if (dwEnum < This->zonemap_count) {
1610 if ((data = This->zonemaps[dwEnum])) {
1611 if (dwIndex < data[0]) {
1612 *pdwZone = data[dwIndex + 1];
1613 return S_OK;
1617 return E_INVALIDARG;
1620 /********************************************************************
1621 * IInternetZoneManager_DestroyZoneEnumerator
1623 static HRESULT WINAPI ZoneMgrImpl_DestroyZoneEnumerator(IInternetZoneManagerEx2* iface,
1624 DWORD dwEnum)
1626 ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1627 LPDWORD data;
1629 TRACE("(%p)->(0x%08x)\n", This, dwEnum);
1630 /* make sure, that dwEnum is valid */
1631 if (dwEnum < This->zonemap_count) {
1632 if ((data = This->zonemaps[dwEnum])) {
1633 This->zonemaps[dwEnum] = NULL;
1634 heap_free(data);
1635 return S_OK;
1638 return E_INVALIDARG;
1641 /********************************************************************
1642 * IInternetZoneManager_CopyTemplatePoliciesToZone
1644 static HRESULT WINAPI ZoneMgrImpl_CopyTemplatePoliciesToZone(IInternetZoneManagerEx2* iface,
1645 DWORD dwTemplate,
1646 DWORD dwZone,
1647 DWORD dwReserved)
1649 FIXME("(%p)->(%08x %08x %08x) stub\n", iface, dwTemplate, dwZone, dwReserved);
1650 return E_NOTIMPL;
1653 /********************************************************************
1654 * IInternetZoneManagerEx_GetZoneActionPolicyEx
1656 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicyEx(IInternetZoneManagerEx2* iface,
1657 DWORD dwZone,
1658 DWORD dwAction,
1659 BYTE* pPolicy,
1660 DWORD cbPolicy,
1661 URLZONEREG urlZoneReg,
1662 DWORD dwFlags)
1664 TRACE("(%p)->(%d, 0x%x, %p, %d, %d, 0x%x)\n", iface, dwZone,
1665 dwAction, pPolicy, cbPolicy, urlZoneReg, dwFlags);
1667 if(!pPolicy)
1668 return E_INVALIDARG;
1670 if (dwFlags)
1671 FIXME("dwFlags 0x%x ignored\n", dwFlags);
1673 return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg);
1676 /********************************************************************
1677 * IInternetZoneManagerEx_SetZoneActionPolicyEx
1679 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicyEx(IInternetZoneManagerEx2* iface,
1680 DWORD dwZone,
1681 DWORD dwAction,
1682 BYTE* pPolicy,
1683 DWORD cbPolicy,
1684 URLZONEREG urlZoneReg,
1685 DWORD dwFlags)
1687 FIXME("(%p)->(%d, 0x%x, %p, %d, %d, 0x%x) stub\n", iface, dwZone, dwAction, pPolicy,
1688 cbPolicy, urlZoneReg, dwFlags);
1689 return E_NOTIMPL;
1692 /********************************************************************
1693 * IInternetZoneManagerEx2_GetZoneAttributesEx
1695 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributesEx(IInternetZoneManagerEx2* iface,
1696 DWORD dwZone,
1697 ZONEATTRIBUTES* pZoneAttributes,
1698 DWORD dwFlags)
1700 TRACE("(%p)->(%d, %p, 0x%x)\n", iface, dwZone, pZoneAttributes, dwFlags);
1702 if (dwFlags)
1703 FIXME("dwFlags 0x%x ignored\n", dwFlags);
1705 return IInternetZoneManagerEx2_GetZoneAttributes(iface, dwZone, pZoneAttributes);
1709 /********************************************************************
1710 * IInternetZoneManagerEx2_GetZoneSecurityState
1712 static HRESULT WINAPI ZoneMgrImpl_GetZoneSecurityState(IInternetZoneManagerEx2* iface,
1713 DWORD dwZoneIndex,
1714 BOOL fRespectPolicy,
1715 LPDWORD pdwState,
1716 BOOL *pfPolicyEncountered)
1718 FIXME("(%p)->(%d, %d, %p, %p) stub\n", iface, dwZoneIndex, fRespectPolicy,
1719 pdwState, pfPolicyEncountered);
1721 *pdwState = SECURITY_IE_STATE_GREEN;
1723 if (pfPolicyEncountered)
1724 *pfPolicyEncountered = FALSE;
1726 return S_OK;
1729 /********************************************************************
1730 * IInternetZoneManagerEx2_GetIESecurityState
1732 static HRESULT WINAPI ZoneMgrImpl_GetIESecurityState(IInternetZoneManagerEx2* iface,
1733 BOOL fRespectPolicy,
1734 LPDWORD pdwState,
1735 BOOL *pfPolicyEncountered,
1736 BOOL fNoCache)
1738 FIXME("(%p)->(%d, %p, %p, %d) stub\n", iface, fRespectPolicy, pdwState,
1739 pfPolicyEncountered, fNoCache);
1741 *pdwState = SECURITY_IE_STATE_GREEN;
1743 if (pfPolicyEncountered)
1744 *pfPolicyEncountered = FALSE;
1746 return S_OK;
1749 /********************************************************************
1750 * IInternetZoneManagerEx2_FixInsecureSettings
1752 static HRESULT WINAPI ZoneMgrImpl_FixInsecureSettings(IInternetZoneManagerEx2* iface)
1754 FIXME("(%p) stub\n", iface);
1755 return S_OK;
1758 /********************************************************************
1759 * IInternetZoneManager_Construct
1761 static const IInternetZoneManagerEx2Vtbl ZoneMgrImplVtbl = {
1762 ZoneMgrImpl_QueryInterface,
1763 ZoneMgrImpl_AddRef,
1764 ZoneMgrImpl_Release,
1765 /* IInternetZoneManager */
1766 ZoneMgrImpl_GetZoneAttributes,
1767 ZoneMgrImpl_SetZoneAttributes,
1768 ZoneMgrImpl_GetZoneCustomPolicy,
1769 ZoneMgrImpl_SetZoneCustomPolicy,
1770 ZoneMgrImpl_GetZoneActionPolicy,
1771 ZoneMgrImpl_SetZoneActionPolicy,
1772 ZoneMgrImpl_PromptAction,
1773 ZoneMgrImpl_LogAction,
1774 ZoneMgrImpl_CreateZoneEnumerator,
1775 ZoneMgrImpl_GetZoneAt,
1776 ZoneMgrImpl_DestroyZoneEnumerator,
1777 ZoneMgrImpl_CopyTemplatePoliciesToZone,
1778 /* IInternetZoneManagerEx */
1779 ZoneMgrImpl_GetZoneActionPolicyEx,
1780 ZoneMgrImpl_SetZoneActionPolicyEx,
1781 /* IInternetZoneManagerEx2 */
1782 ZoneMgrImpl_GetZoneAttributesEx,
1783 ZoneMgrImpl_GetZoneSecurityState,
1784 ZoneMgrImpl_GetIESecurityState,
1785 ZoneMgrImpl_FixInsecureSettings,
1788 HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
1790 ZoneMgrImpl* ret = heap_alloc_zero(sizeof(ZoneMgrImpl));
1792 TRACE("(%p %p)\n", pUnkOuter, ppobj);
1793 ret->IInternetZoneManagerEx2_iface.lpVtbl = &ZoneMgrImplVtbl;
1794 ret->ref = 1;
1795 *ppobj = &ret->IInternetZoneManagerEx2_iface;
1797 URLMON_LockModule();
1799 return S_OK;
1802 /***********************************************************************
1803 * CoInternetCreateSecurityManager (URLMON.@)
1806 HRESULT WINAPI CoInternetCreateSecurityManager( IServiceProvider *pSP,
1807 IInternetSecurityManager **ppSM, DWORD dwReserved )
1809 TRACE("%p %p %d\n", pSP, ppSM, dwReserved );
1811 if(pSP)
1812 FIXME("pSP not supported\n");
1814 return SecManagerImpl_Construct(NULL, (void**) ppSM);
1817 /********************************************************************
1818 * CoInternetCreateZoneManager (URLMON.@)
1820 HRESULT WINAPI CoInternetCreateZoneManager(IServiceProvider* pSP, IInternetZoneManager** ppZM, DWORD dwReserved)
1822 TRACE("(%p %p %x)\n", pSP, ppZM, dwReserved);
1823 return ZoneMgrImpl_Construct(NULL, (void**)ppZM);
1826 static HRESULT parse_security_url(const WCHAR *url, PSUACTION action, WCHAR **result) {
1827 IInternetProtocolInfo *protocol_info;
1828 WCHAR *tmp, *new_url = NULL, *alloc_url = NULL;
1829 DWORD size, new_size;
1830 HRESULT hres = S_OK, parse_hres;
1832 while(1) {
1833 TRACE("parsing %s\n", debugstr_w(url));
1835 protocol_info = get_protocol_info(url);
1836 if(!protocol_info)
1837 break;
1839 size = lstrlenW(url)+1;
1840 new_url = CoTaskMemAlloc(size*sizeof(WCHAR));
1841 if(!new_url) {
1842 hres = E_OUTOFMEMORY;
1843 break;
1846 new_size = 0;
1847 parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_URL, 0, new_url, size, &new_size, 0);
1848 if(parse_hres == S_FALSE) {
1849 if(!new_size) {
1850 hres = E_UNEXPECTED;
1851 break;
1854 tmp = CoTaskMemRealloc(new_url, new_size*sizeof(WCHAR));
1855 if(!tmp) {
1856 hres = E_OUTOFMEMORY;
1857 break;
1859 new_url = tmp;
1860 parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_URL, 0, new_url,
1861 new_size, &new_size, 0);
1862 if(parse_hres == S_FALSE) {
1863 hres = E_FAIL;
1864 break;
1868 if(parse_hres != S_OK || !wcscmp(url, new_url))
1869 break;
1871 CoTaskMemFree(alloc_url);
1872 url = alloc_url = new_url;
1873 new_url = NULL;
1876 CoTaskMemFree(new_url);
1878 if(hres != S_OK) {
1879 WARN("failed: %08x\n", hres);
1880 CoTaskMemFree(alloc_url);
1881 return hres;
1884 if(action == PSU_DEFAULT && (protocol_info = get_protocol_info(url))) {
1885 size = lstrlenW(url)+1;
1886 new_url = CoTaskMemAlloc(size * sizeof(WCHAR));
1887 if(new_url) {
1888 new_size = 0;
1889 parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_DOMAIN, 0,
1890 new_url, size, &new_size, 0);
1891 if(parse_hres == S_FALSE) {
1892 if(new_size) {
1893 tmp = CoTaskMemRealloc(new_url, new_size*sizeof(WCHAR));
1894 if(tmp) {
1895 new_url = tmp;
1896 parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_DOMAIN, 0, new_url,
1897 new_size, &new_size, 0);
1898 if(parse_hres == S_FALSE)
1899 hres = E_FAIL;
1900 }else {
1901 hres = E_OUTOFMEMORY;
1903 }else {
1904 hres = E_UNEXPECTED;
1908 if(hres == S_OK && parse_hres == S_OK) {
1909 CoTaskMemFree(alloc_url);
1910 url = alloc_url = new_url;
1911 new_url = NULL;
1914 CoTaskMemFree(new_url);
1915 }else {
1916 hres = E_OUTOFMEMORY;
1918 IInternetProtocolInfo_Release(protocol_info);
1921 if(FAILED(hres)) {
1922 WARN("failed %08x\n", hres);
1923 CoTaskMemFree(alloc_url);
1924 return hres;
1927 if(!alloc_url) {
1928 size = lstrlenW(url)+1;
1929 alloc_url = CoTaskMemAlloc(size * sizeof(WCHAR));
1930 if(!alloc_url)
1931 return E_OUTOFMEMORY;
1932 memcpy(alloc_url, url, size * sizeof(WCHAR));
1935 *result = alloc_url;
1936 return S_OK;
1939 /********************************************************************
1940 * CoInternetGetSecurityUrl (URLMON.@)
1942 HRESULT WINAPI CoInternetGetSecurityUrl(LPCWSTR pwzUrl, LPWSTR *ppwzSecUrl, PSUACTION psuAction, DWORD dwReserved)
1944 WCHAR *secure_url;
1945 HRESULT hres;
1947 TRACE("(%p,%p,%u,%u)\n", pwzUrl, ppwzSecUrl, psuAction, dwReserved);
1949 hres = parse_security_url(pwzUrl, psuAction, &secure_url);
1950 if(FAILED(hres))
1951 return hres;
1953 if(psuAction != PSU_SECURITY_URL_ONLY) {
1954 PARSEDURLW parsed_url = { sizeof(parsed_url) };
1955 DWORD size;
1957 /* FIXME: Use helpers from uri.c */
1958 if(SUCCEEDED(ParseURLW(secure_url, &parsed_url))) {
1959 WCHAR *new_url;
1961 switch(parsed_url.nScheme) {
1962 case URL_SCHEME_FTP:
1963 case URL_SCHEME_HTTP:
1964 case URL_SCHEME_HTTPS:
1965 size = lstrlenW(secure_url)+1;
1966 new_url = CoTaskMemAlloc(size * sizeof(WCHAR));
1967 if(new_url)
1968 hres = UrlGetPartW(secure_url, new_url, &size, URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME);
1969 else
1970 hres = E_OUTOFMEMORY;
1971 CoTaskMemFree(secure_url);
1972 if(hres != S_OK) {
1973 WARN("UrlGetPart failed: %08x\n", hres);
1974 CoTaskMemFree(new_url);
1975 return FAILED(hres) ? hres : E_FAIL;
1977 secure_url = new_url;
1982 *ppwzSecUrl = secure_url;
1983 return S_OK;
1986 /********************************************************************
1987 * CoInternetGetSecurityUrlEx (URLMON.@)
1989 HRESULT WINAPI CoInternetGetSecurityUrlEx(IUri *pUri, IUri **ppSecUri, PSUACTION psuAction, DWORD_PTR dwReserved)
1991 URL_SCHEME scheme_type;
1992 BSTR secure_uri;
1993 WCHAR *ret_url;
1994 HRESULT hres;
1996 TRACE("(%p,%p,%u,%u)\n", pUri, ppSecUri, psuAction, (DWORD)dwReserved);
1998 if(!pUri || !ppSecUri)
1999 return E_INVALIDARG;
2001 hres = IUri_GetDisplayUri(pUri, &secure_uri);
2002 if(FAILED(hres))
2003 return hres;
2005 hres = parse_security_url(secure_uri, psuAction, &ret_url);
2006 SysFreeString(secure_uri);
2007 if(FAILED(hres))
2008 return hres;
2010 /* File URIs have to hierarchical. */
2011 hres = IUri_GetScheme(pUri, (DWORD*)&scheme_type);
2012 if(SUCCEEDED(hres) && scheme_type == URL_SCHEME_FILE) {
2013 const WCHAR *tmp = ret_url;
2015 /* Check and see if a "//" is after the scheme name. */
2016 tmp += ARRAY_SIZE(L"file");
2017 if(*tmp != '/' || *(tmp+1) != '/')
2018 hres = E_INVALIDARG;
2021 if(SUCCEEDED(hres))
2022 hres = CreateUri(ret_url, Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, 0, ppSecUri);
2023 CoTaskMemFree(ret_url);
2024 return hres;
2027 /********************************************************************
2028 * CompareSecurityIds (URLMON.@)
2030 HRESULT WINAPI CompareSecurityIds(BYTE *secid1, DWORD size1, BYTE *secid2, DWORD size2, DWORD reserved)
2032 FIXME("(%p %d %p %d %x)\n", secid1, size1, secid2, size2, reserved);
2033 return E_NOTIMPL;
2036 /********************************************************************
2037 * IsInternetESCEnabledLocal (URLMON.108)
2039 * Undocumented, returns TRUE if IE is running in Enhanced Security Configuration.
2041 BOOL WINAPI IsInternetESCEnabledLocal(void)
2043 static BOOL esc_initialized, esc_enabled;
2045 TRACE("()\n");
2047 if(!esc_initialized) {
2048 DWORD type, size, val;
2049 HKEY zone_map;
2051 if(RegOpenKeyExW(HKEY_CURRENT_USER, zone_map_keyW, 0, KEY_QUERY_VALUE, &zone_map) == ERROR_SUCCESS) {
2052 size = sizeof(DWORD);
2053 if(RegQueryValueExW(zone_map, L"IEHarden", NULL, &type, (BYTE*)&val, &size) == ERROR_SUCCESS)
2054 esc_enabled = type == REG_DWORD && val != 0;
2055 RegCloseKey(zone_map);
2057 esc_initialized = TRUE;
2060 return esc_enabled;