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