ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

sec_mgr.c
Go to the documentation of this file.
00001 /*
00002  * Internet Security and Zone Manager
00003  *
00004  * Copyright (c) 2004 Huw D M Davies
00005  * Copyright 2004 Jacek Caban
00006  * Copyright 2009 Detlef Riekenberg
00007  * Copyright 2011 Thomas Mullaly for CodeWeavers
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 #include <stdio.h>
00025 
00026 #include "urlmon_main.h"
00027 #include "winreg.h"
00028 #include "wininet.h"
00029 
00030 #define NO_SHLWAPI_REG
00031 #include "shlwapi.h"
00032 
00033 #include "wine/debug.h"
00034 
00035 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
00036 
00037 static const WCHAR currentlevelW[] = {'C','u','r','r','e','n','t','L','e','v','e','l',0};
00038 static const WCHAR descriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
00039 static const WCHAR displaynameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
00040 static const WCHAR fileW[] = {'f','i','l','e',0};
00041 static const WCHAR flagsW[] = {'F','l','a','g','s',0};
00042 static const WCHAR iconW[] = {'I','c','o','n',0};
00043 static const WCHAR minlevelW[] = {'M','i','n','L','e','v','e','l',0};
00044 static const WCHAR recommendedlevelW[] = {'R','e','c','o','m','m','e','n','d','e','d',
00045                                           'L','e','v','e','l',0};
00046 static const WCHAR wszZonesKey[] = {'S','o','f','t','w','a','r','e','\\',
00047                                     'M','i','c','r','o','s','o','f','t','\\',
00048                                     'W','i','n','d','o','w','s','\\',
00049                                     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00050                                     'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
00051                                     'Z','o','n','e','s','\\',0};
00052 static const WCHAR wszZoneMapDomainsKey[] = {'S','o','f','t','w','a','r','e','\\',
00053                                              'M','i','c','r','o','s','o','f','t','\\',
00054                                              'W','i','n','d','o','w','s','\\',
00055                                              'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00056                                              'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
00057                                              'Z','o','n','e','M','a','p','\\',
00058                                              'D','o','m','a','i','n','s',0};
00059 
00060 /********************************************************************
00061  * get_string_from_reg [internal]
00062  *
00063  * helper to get a string from the reg.
00064  *
00065  */
00066 static void get_string_from_reg(HKEY hcu, HKEY hklm, LPCWSTR name, LPWSTR out, DWORD maxlen)
00067 {
00068     DWORD type = REG_SZ;
00069     DWORD len = maxlen * sizeof(WCHAR);
00070     DWORD res;
00071 
00072     res = RegQueryValueExW(hcu, name, NULL, &type, (LPBYTE) out, &len);
00073 
00074     if (res && hklm) {
00075         len = maxlen * sizeof(WCHAR);
00076         type = REG_SZ;
00077         res = RegQueryValueExW(hklm, name, NULL, &type, (LPBYTE) out, &len);
00078     }
00079 
00080     if (res) {
00081         TRACE("%s failed: %d\n", debugstr_w(name), res);
00082         *out = '\0';
00083     }
00084 }
00085 
00086 /********************************************************************
00087  * get_dword_from_reg [internal]
00088  *
00089  * helper to get a dword from the reg.
00090  *
00091  */
00092 static void get_dword_from_reg(HKEY hcu, HKEY hklm, LPCWSTR name, LPDWORD out)
00093 {
00094     DWORD type = REG_DWORD;
00095     DWORD len = sizeof(DWORD);
00096     DWORD res;
00097 
00098     res = RegQueryValueExW(hcu, name, NULL, &type, (LPBYTE) out, &len);
00099 
00100     if (res && hklm) {
00101         len = sizeof(DWORD);
00102         type = REG_DWORD;
00103         res = RegQueryValueExW(hklm, name, NULL, &type, (LPBYTE) out, &len);
00104     }
00105 
00106     if (res) {
00107         TRACE("%s failed: %d\n", debugstr_w(name), res);
00108         *out = 0;
00109     }
00110 }
00111 
00112 static HRESULT get_zone_from_reg(LPCWSTR schema, DWORD *zone)
00113 {
00114     DWORD res, size;
00115     HKEY hkey;
00116 
00117     static const WCHAR wszZoneMapProtocolKey[] =
00118         {'S','o','f','t','w','a','r','e','\\',
00119          'M','i','c','r','o','s','o','f','t','\\',
00120          'W','i','n','d','o','w','s','\\',
00121          'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00122          'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
00123          'Z','o','n','e','M','a','p','\\',
00124          'P','r','o','t','o','c','o','l','D','e','f','a','u','l','t','s',0};
00125 
00126     res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapProtocolKey, &hkey);
00127     if(res != ERROR_SUCCESS) {
00128         ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
00129         return E_UNEXPECTED;
00130     }
00131 
00132     size = sizeof(DWORD);
00133     res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
00134     RegCloseKey(hkey);
00135     if(res == ERROR_SUCCESS)
00136         return S_OK;
00137 
00138     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapProtocolKey, &hkey);
00139     if(res != ERROR_SUCCESS) {
00140         ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
00141         return E_UNEXPECTED;
00142     }
00143 
00144     size = sizeof(DWORD);
00145     res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
00146     RegCloseKey(hkey);
00147     if(res == ERROR_SUCCESS)
00148         return S_OK;
00149 
00150     *zone = 3;
00151     return S_OK;
00152 }
00153 
00154 /********************************************************************
00155  * matches_domain_pattern [internal]
00156  *
00157  * Checks if the given string matches the specified domain pattern.
00158  *
00159  * This function looks for explicit wildcard domain components iff
00160  * they appear at the very beginning of the 'pattern' string
00161  *
00162  *  pattern = "*.google.com"
00163  */
00164 static BOOL matches_domain_pattern(LPCWSTR pattern, LPCWSTR str, BOOL implicit_wildcard, LPCWSTR *matched)
00165 {
00166     BOOL matches = FALSE;
00167     DWORD pattern_len = strlenW(pattern);
00168     DWORD str_len = strlenW(str);
00169 
00170     TRACE("(%d) Checking if %s matches %s\n", implicit_wildcard, debugstr_w(str), debugstr_w(pattern));
00171 
00172     *matched = NULL;
00173     if(str_len >= pattern_len) {
00174         /* Check if there's an explicit wildcard in the pattern. */
00175         if(pattern[0] == '*' && pattern[1] == '.') {
00176             /* Make sure that 'str' matches the wildcard pattern.
00177              *
00178              * Example:
00179              *  pattern = "*.google.com"
00180              *
00181              * So in this case 'str' would have to end with ".google.com" in order
00182              * to map to this pattern.
00183              */
00184             if(str_len >= pattern_len+1 && !strcmpiW(str+(str_len-pattern_len+1), pattern+1)) {
00185                 /* Check if there's another '.' inside of the "unmatched" portion
00186                  * of 'str'.
00187                  *
00188                  * Example:
00189                  *  pattern = "*.google.com"
00190                  *  str     = "test.testing.google.com"
00191                  *
00192                  * The currently matched portion is ".google.com" in 'str', we need
00193                  * see if there's a '.' inside of the unmatched portion ("test.testing"), because
00194                  * if there is and 'implicit_wildcard' isn't set, then this isn't
00195                  * a match.
00196                  */
00197                 const WCHAR *ptr;
00198                 if(str_len > pattern_len+1 && (ptr = memrchrW(str, '.', str_len-pattern_len-2))) {
00199                     if(implicit_wildcard) {
00200                         matches = TRUE;
00201                         *matched = ptr+1;
00202                     }
00203                 } else {
00204                     matches = TRUE;
00205                     *matched = str;
00206                 }
00207             }
00208         } else if(implicit_wildcard && str_len > pattern_len) {
00209             /* When the pattern has an implicit wildcard component, it means
00210              * that anything goes in 'str' as long as it ends with the pattern
00211              * and that the beginning of the match has a '.' before it.
00212              *
00213              * Example:
00214              *  pattern = "google.com"
00215              *  str     = "www.google.com"
00216              *
00217              * Implicitly matches the pattern, where as:
00218              *
00219              *  pattern = "google.com"
00220              *  str     = "wwwgoogle.com"
00221              *
00222              * Doesn't match the pattern.
00223              */
00224             if(str_len > pattern_len) {
00225                 if(str[str_len-pattern_len-1] == '.' && !strcmpiW(str+(str_len-pattern_len), pattern)) {
00226                     matches = TRUE;
00227                     *matched = str+(str_len-pattern_len);
00228                 }
00229             }
00230         } else {
00231             /* The pattern doesn't have an implicit wildcard, or an explicit wildcard,
00232              * so 'str' has to be an exact match to the 'pattern'.
00233              */
00234             if(!strcmpiW(str, pattern)) {
00235                 matches = TRUE;
00236                 *matched = str;
00237             }
00238         }
00239     }
00240 
00241     if(matches)
00242         TRACE("Found a match: matched=%s\n", debugstr_w(*matched));
00243     else
00244         TRACE("No match found\n");
00245 
00246     return matches;
00247 }
00248 
00249 static BOOL get_zone_for_scheme(HKEY key, LPCWSTR schema, DWORD *zone)
00250 {
00251     static const WCHAR wildcardW[] = {'*',0};
00252 
00253     DWORD res;
00254     DWORD size = sizeof(DWORD);
00255     DWORD type;
00256 
00257     /* See if the key contains a value for the scheme first. */
00258     res = RegQueryValueExW(key, schema, NULL, &type, (BYTE*)zone, &size);
00259     if(type != REG_DWORD)
00260         WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(schema));
00261 
00262     if(res != ERROR_SUCCESS || type != REG_DWORD) {
00263         /* Try to get the zone for the wildcard scheme. */
00264         size = sizeof(DWORD);
00265         res = RegQueryValueExW(key, wildcardW, NULL, &type, (BYTE*)zone, &size);
00266         if(type != REG_DWORD)
00267             WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(wildcardW));
00268     }
00269 
00270     return res == ERROR_SUCCESS && type == REG_DWORD;
00271 }
00272 
00273 /********************************************************************
00274  * search_domain_for_zone [internal]
00275  *
00276  * Searches the specified 'domain' registry key to see if 'host' maps into it, or any
00277  * of it's subdomain registry keys.
00278  *
00279  * Returns S_OK if a match is found, S_FALSE if no matches were found, or an error code.
00280  */
00281 static HRESULT search_domain_for_zone(HKEY domains, LPCWSTR domain, DWORD domain_len, LPCWSTR schema,
00282                                       LPCWSTR host, DWORD host_len, DWORD *zone)
00283 {
00284     BOOL found = FALSE;
00285     HKEY domain_key;
00286     DWORD res;
00287     LPCWSTR matched;
00288 
00289     if(host_len >= domain_len && matches_domain_pattern(domain, host, TRUE, &matched)) {
00290         res = RegOpenKeyW(domains, domain, &domain_key);
00291         if(res != ERROR_SUCCESS) {
00292             ERR("Failed to open domain key %s: %d\n", debugstr_w(domain), res);
00293             return E_UNEXPECTED;
00294         }
00295 
00296         if(matched == host)
00297             found = get_zone_for_scheme(domain_key, schema, zone);
00298         else {
00299             INT domain_offset;
00300             DWORD subdomain_count, subdomain_len;
00301             BOOL check_domain = TRUE;
00302 
00303             find_domain_name(domain, domain_len, &domain_offset);
00304 
00305             res = RegQueryInfoKeyW(domain_key, NULL, NULL, NULL, &subdomain_count, &subdomain_len,
00306                                    NULL, NULL, NULL, NULL, NULL, NULL);
00307             if(res != ERROR_SUCCESS) {
00308                 ERR("Unable to query info for key %s: %d\n", debugstr_w(domain), res);
00309                 RegCloseKey(domain_key);
00310                 return E_UNEXPECTED;
00311             }
00312 
00313             if(subdomain_count) {
00314                 WCHAR *subdomain;
00315                 WCHAR *component;
00316                 DWORD i;
00317 
00318                 subdomain = heap_alloc((subdomain_len+1)*sizeof(WCHAR));
00319                 if(!subdomain) {
00320                     RegCloseKey(domain_key);
00321                     return E_OUTOFMEMORY;
00322                 }
00323 
00324                 component = heap_strndupW(host, matched-host-1);
00325                 if(!component) {
00326                     heap_free(subdomain);
00327                     RegCloseKey(domain_key);
00328                     return E_OUTOFMEMORY;
00329                 }
00330 
00331                 for(i = 0; i < subdomain_count; ++i) {
00332                     DWORD len = subdomain_len+1;
00333                     const WCHAR *sub_matched;
00334 
00335                     res = RegEnumKeyExW(domain_key, i, subdomain, &len, NULL, NULL, NULL, NULL);
00336                     if(res != ERROR_SUCCESS) {
00337                         heap_free(component);
00338                         heap_free(subdomain);
00339                         RegCloseKey(domain_key);
00340                         return E_UNEXPECTED;
00341                     }
00342 
00343                     if(matches_domain_pattern(subdomain, component, FALSE, &sub_matched)) {
00344                         HKEY subdomain_key;
00345 
00346                         res = RegOpenKeyW(domain_key, subdomain, &subdomain_key);
00347                         if(res != ERROR_SUCCESS) {
00348                             ERR("Unable to open subdomain key %s of %s: %d\n", debugstr_w(subdomain),
00349                                 debugstr_w(domain), res);
00350                             heap_free(component);
00351                             heap_free(subdomain);
00352                             RegCloseKey(domain_key);
00353                             return E_UNEXPECTED;
00354                         }
00355 
00356                         found = get_zone_for_scheme(subdomain_key, schema, zone);
00357                         check_domain = FALSE;
00358                         RegCloseKey(subdomain_key);
00359                         break;
00360                     }
00361                 }
00362                 heap_free(subdomain);
00363                 heap_free(component);
00364             }
00365 
00366             /* There's a chance that 'host' implicitly mapped into 'domain', in
00367              * which case we check to see if 'domain' contains zone information.
00368              *
00369              * This can only happen if 'domain' is it's own domain name.
00370              *  Example:
00371              *      "google.com" (domain name = "google.com")
00372              *
00373              *  So if:
00374              *      host = "www.google.com"
00375              *
00376              *  Then host would map directly into the "google.com" domain key.
00377              *
00378              * If 'domain' has more than just it's domain name, or it does not
00379              * have a domain name, then we don't perform the check. The reason
00380              * for this is that these domains don't allow implicit mappings.
00381              *  Example:
00382              *      domain = "org" (has no domain name)
00383              *      host   = "www.org"
00384              *
00385              *  The mapping would only happen if the "org" key had an explicit subkey
00386              *  called "www".
00387              */
00388             if(check_domain && !domain_offset && !strchrW(host, matched-host-1))
00389                 found = get_zone_for_scheme(domain_key, schema, zone);
00390         }
00391         RegCloseKey(domain_key);
00392     }
00393 
00394     return found ? S_OK : S_FALSE;
00395 }
00396 
00397 static HRESULT search_for_domain_mapping(HKEY domains, LPCWSTR schema, LPCWSTR host, DWORD host_len, DWORD *zone)
00398 {
00399     WCHAR *domain;
00400     DWORD domain_count, domain_len, i;
00401     DWORD res;
00402     HRESULT hres = S_FALSE;
00403 
00404     res = RegQueryInfoKeyW(domains, NULL, NULL, NULL, &domain_count, &domain_len,
00405                            NULL, NULL, NULL, NULL, NULL, NULL);
00406     if(res != ERROR_SUCCESS) {
00407         WARN("Failed to retrieve information about key\n");
00408         return E_UNEXPECTED;
00409     }
00410 
00411     if(!domain_count)
00412         return S_FALSE;
00413 
00414     domain = heap_alloc((domain_len+1)*sizeof(WCHAR));
00415     if(!domain)
00416         return E_OUTOFMEMORY;
00417 
00418     for(i = 0; i < domain_count; ++i) {
00419         DWORD len = domain_len+1;
00420 
00421         res = RegEnumKeyExW(domains, i, domain, &len, NULL, NULL, NULL, NULL);
00422         if(res != ERROR_SUCCESS) {
00423             heap_free(domain);
00424             return E_UNEXPECTED;
00425         }
00426 
00427         hres = search_domain_for_zone(domains, domain, len, schema, host, host_len, zone);
00428         if(FAILED(hres) || hres == S_OK)
00429             break;
00430     }
00431 
00432     heap_free(domain);
00433     return hres;
00434 }
00435 
00436 static HRESULT get_zone_from_domains(LPCWSTR url, LPCWSTR schema, DWORD *zone)
00437 {
00438     HRESULT hres;
00439     WCHAR *host_name;
00440     DWORD host_len = lstrlenW(url)+1;
00441     DWORD res;
00442     HKEY domains;
00443 
00444     host_name = heap_alloc(host_len*sizeof(WCHAR));
00445     if(!host_name)
00446         return E_OUTOFMEMORY;
00447 
00448     hres = CoInternetParseUrl(url, PARSE_DOMAIN, 0, host_name, host_len, &host_len, 0);
00449     if(hres == S_FALSE) {
00450         WCHAR *tmp = heap_realloc(host_name, (host_len+1)*sizeof(WCHAR));
00451         if(!tmp) {
00452             heap_free(host_name);
00453             return E_OUTOFMEMORY;
00454         }
00455 
00456         host_name = tmp;
00457         hres = CoInternetParseUrl(url, PARSE_DOMAIN, 0, host_name, host_len+1, &host_len, 0);
00458     }
00459 
00460     /* Windows doesn't play nice with unknown scheme types when it tries
00461      * to check if a host name maps into any domains.
00462      *
00463      * The reason is with how CoInternetParseUrl handles unknown scheme types
00464      * when it's parsing the domain of a URL (IE it always returns E_FAIL).
00465      *
00466      * Windows doesn't compenstate for this and simply doesn't check if
00467      * the URL maps into any domains.
00468      */
00469     if(hres != S_OK) {
00470         heap_free(host_name);
00471         if(hres == E_FAIL)
00472             return S_FALSE;
00473         return hres;
00474     }
00475 
00476     /* First try CURRENT_USER. */
00477     res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapDomainsKey, &domains);
00478     if(res == ERROR_SUCCESS) {
00479         hres = search_for_domain_mapping(domains, schema, host_name, host_len, zone);
00480         RegCloseKey(domains);
00481     } else
00482         WARN("Failed to open HKCU's %s key\n", debugstr_w(wszZoneMapDomainsKey));
00483 
00484     /* If that doesn't work try LOCAL_MACHINE. */
00485     if(hres == S_FALSE) {
00486         res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapDomainsKey, &domains);
00487         if(res == ERROR_SUCCESS) {
00488             hres = search_for_domain_mapping(domains, schema, host_name, host_len, zone);
00489             RegCloseKey(domains);
00490         } else
00491             WARN("Failed to open HKLM's %s key\n", debugstr_w(wszZoneMapDomainsKey));
00492     }
00493 
00494     heap_free(host_name);
00495     return hres;
00496 }
00497 
00498 static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
00499 {
00500     LPWSTR secur_url;
00501     WCHAR schema[64];
00502     DWORD size=0;
00503     HRESULT hres;
00504 
00505     *zone = URLZONE_INVALID;
00506 
00507     hres = CoInternetGetSecurityUrl(url, &secur_url, PSU_SECURITY_URL_ONLY, 0);
00508     if(hres != S_OK) {
00509         size = strlenW(url)*sizeof(WCHAR);
00510 
00511         secur_url = heap_alloc(size);
00512         if(!secur_url)
00513             return E_OUTOFMEMORY;
00514 
00515         memcpy(secur_url, url, size);
00516     }
00517 
00518     hres = CoInternetParseUrl(secur_url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(WCHAR), &size, 0);
00519     if(FAILED(hres) || !*schema) {
00520         heap_free(secur_url);
00521         return E_INVALIDARG;
00522     }
00523 
00524     /* file protocol is a special case */
00525     if(!strcmpW(schema, fileW)) {
00526         WCHAR path[MAX_PATH], root[20];
00527         WCHAR *ptr;
00528 
00529         hres = CoInternetParseUrl(secur_url, PARSE_PATH_FROM_URL, 0, path,
00530                 sizeof(path)/sizeof(WCHAR), &size, 0);
00531 
00532         if(SUCCEEDED(hres) && (ptr = strchrW(path, '\\')) && ptr-path < sizeof(root)/sizeof(WCHAR)) {
00533             UINT type;
00534 
00535             memcpy(root, path, (ptr-path)*sizeof(WCHAR));
00536             root[ptr-path] = 0;
00537 
00538             type = GetDriveTypeW(root);
00539 
00540             switch(type) {
00541             case DRIVE_UNKNOWN:
00542             case DRIVE_NO_ROOT_DIR:
00543                 break;
00544             case DRIVE_REMOVABLE:
00545             case DRIVE_FIXED:
00546             case DRIVE_CDROM:
00547             case DRIVE_RAMDISK:
00548                 *zone = URLZONE_LOCAL_MACHINE;
00549                 hres = S_OK;
00550                 break;
00551             case DRIVE_REMOTE:
00552                 *zone = URLZONE_INTERNET;
00553                 hres = S_OK;
00554                 break;
00555             default:
00556                 FIXME("unsupported drive type %d\n", type);
00557             }
00558         }
00559     }
00560 
00561     if(*zone == URLZONE_INVALID) {
00562         hres = get_zone_from_domains(secur_url, schema, zone);
00563         if(hres == S_FALSE)
00564             hres = get_zone_from_reg(schema, zone);
00565     }
00566 
00567     if(FAILED(hres) || !ret_url)
00568         heap_free(secur_url);
00569     else
00570         *ret_url = secur_url;
00571 
00572     return hres;
00573 }
00574 
00575 static HRESULT open_zone_key(HKEY parent_key, DWORD zone, HKEY *hkey)
00576 {
00577     static const WCHAR wszFormat[] = {'%','s','%','u',0};
00578 
00579     WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+12];
00580     DWORD res;
00581 
00582     wsprintfW(key_name, wszFormat, wszZonesKey, zone);
00583 
00584     res = RegOpenKeyW(parent_key, key_name, hkey);
00585 
00586     if(res != ERROR_SUCCESS) {
00587         WARN("RegOpenKey failed\n");
00588         return E_INVALIDARG;
00589     }
00590 
00591     return S_OK;
00592 }
00593 
00594 static HRESULT get_action_policy(DWORD zone, DWORD action, BYTE *policy, DWORD size, URLZONEREG zone_reg)
00595 {
00596     HKEY parent_key;
00597     HKEY hkey;
00598     LONG res;
00599     HRESULT hres;
00600 
00601     switch(action) {
00602     case URLACTION_SCRIPT_OVERRIDE_SAFETY:
00603     case URLACTION_ACTIVEX_OVERRIDE_SCRIPT_SAFETY:
00604         *(DWORD*)policy = URLPOLICY_DISALLOW;
00605         return S_OK;
00606     }
00607 
00608     switch(zone_reg) {
00609     case URLZONEREG_DEFAULT:
00610     case URLZONEREG_HKCU:
00611         parent_key = HKEY_CURRENT_USER;
00612         break;
00613     case URLZONEREG_HKLM:
00614         parent_key = HKEY_LOCAL_MACHINE;
00615         break;
00616     default:
00617         WARN("Unknown URLZONEREG: %d\n", zone_reg);
00618         return E_FAIL;
00619     };
00620 
00621     hres = open_zone_key(parent_key, zone, &hkey);
00622     if(SUCCEEDED(hres)) {
00623         WCHAR action_str[16];
00624         DWORD len = size;
00625 
00626         static const WCHAR formatW[] = {'%','X',0};
00627 
00628         wsprintfW(action_str, formatW, action);
00629 
00630         res = RegQueryValueExW(hkey, action_str, NULL, NULL, policy, &len);
00631         if(res == ERROR_MORE_DATA) {
00632             hres = E_INVALIDARG;
00633         }else if(res == ERROR_FILE_NOT_FOUND) {
00634             hres = E_FAIL;
00635         }else if(res != ERROR_SUCCESS) {
00636             ERR("RegQueryValue failed: %d\n", res);
00637             hres = E_UNEXPECTED;
00638         }
00639 
00640         RegCloseKey(hkey);
00641     }
00642 
00643     if(FAILED(hres) && zone_reg == URLZONEREG_DEFAULT)
00644         return get_action_policy(zone, action, policy, size, URLZONEREG_HKLM);
00645 
00646     return hres;
00647 }
00648 
00649 /***********************************************************************
00650  *           InternetSecurityManager implementation
00651  *
00652  */
00653 typedef struct {
00654     IInternetSecurityManager IInternetSecurityManager_iface;
00655 
00656     LONG ref;
00657 
00658     IInternetSecurityMgrSite *mgrsite;
00659     IInternetSecurityManager *custom_manager;
00660 } SecManagerImpl;
00661 
00662 static inline SecManagerImpl *impl_from_IInternetSecurityManager(IInternetSecurityManager *iface)
00663 {
00664     return CONTAINING_RECORD(iface, SecManagerImpl, IInternetSecurityManager_iface);
00665 }
00666 
00667 static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManager* iface,REFIID riid,void** ppvObject)
00668 {
00669     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00670 
00671     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
00672 
00673     /* Perform a sanity check on the parameters.*/
00674     if ( (This==0) || (ppvObject==0) )
00675     return E_INVALIDARG;
00676 
00677     /* Initialize the return parameter */
00678     *ppvObject = 0;
00679 
00680     /* Compare the riid with the interface IDs implemented by this object.*/
00681     if (IsEqualIID(&IID_IUnknown, riid) ||
00682         IsEqualIID(&IID_IInternetSecurityManager, riid))
00683         *ppvObject = iface;
00684 
00685     /* Check that we obtained an interface.*/
00686     if (!*ppvObject) {
00687         WARN("not supported interface %s\n", debugstr_guid(riid));
00688         return E_NOINTERFACE;
00689     }
00690 
00691     /* Query Interface always increases the reference count by one when it is successful */
00692     IInternetSecurityManager_AddRef(iface);
00693 
00694     return S_OK;
00695 }
00696 
00697 static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManager* iface)
00698 {
00699     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00700     ULONG refCount = InterlockedIncrement(&This->ref);
00701 
00702     TRACE("(%p) ref=%u\n", This, refCount);
00703 
00704     return refCount;
00705 }
00706 
00707 static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManager* iface)
00708 {
00709     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00710     ULONG refCount = InterlockedDecrement(&This->ref);
00711 
00712     TRACE("(%p) ref=%u\n", This, refCount);
00713 
00714     /* destroy the object if there's no more reference on it */
00715     if (!refCount){
00716         if(This->mgrsite)
00717             IInternetSecurityMgrSite_Release(This->mgrsite);
00718         if(This->custom_manager)
00719             IInternetSecurityManager_Release(This->custom_manager);
00720 
00721         heap_free(This);
00722 
00723         URLMON_UnlockModule();
00724     }
00725 
00726     return refCount;
00727 }
00728 
00729 static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManager *iface,
00730                                                      IInternetSecurityMgrSite *pSite)
00731 {
00732     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00733 
00734     TRACE("(%p)->(%p)\n", This, pSite);
00735 
00736     if(This->mgrsite)
00737         IInternetSecurityMgrSite_Release(This->mgrsite);
00738 
00739     if(This->custom_manager) {
00740         IInternetSecurityManager_Release(This->custom_manager);
00741         This->custom_manager = NULL;
00742     }
00743 
00744     This->mgrsite = pSite;
00745 
00746     if(pSite) {
00747         IServiceProvider *servprov;
00748         HRESULT hres;
00749 
00750         IInternetSecurityMgrSite_AddRef(pSite);
00751 
00752         hres = IInternetSecurityMgrSite_QueryInterface(pSite, &IID_IServiceProvider,
00753                 (void**)&servprov);
00754         if(SUCCEEDED(hres)) {
00755             IServiceProvider_QueryService(servprov, &SID_SInternetSecurityManager,
00756                     &IID_IInternetSecurityManager, (void**)&This->custom_manager);
00757             IServiceProvider_Release(servprov);
00758         }
00759     }
00760 
00761     return S_OK;
00762 }
00763 
00764 static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManager *iface,
00765                                                      IInternetSecurityMgrSite **ppSite)
00766 {
00767     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00768 
00769     TRACE("(%p)->(%p)\n", This, ppSite);
00770 
00771     if(!ppSite)
00772         return E_INVALIDARG;
00773 
00774     if(This->mgrsite)
00775         IInternetSecurityMgrSite_AddRef(This->mgrsite);
00776 
00777     *ppSite = This->mgrsite;
00778     return S_OK;
00779 }
00780 
00781 static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *iface,
00782                                                   LPCWSTR pwszUrl, DWORD *pdwZone,
00783                                                   DWORD dwFlags)
00784 {
00785     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00786     HRESULT hres;
00787 
00788     TRACE("(%p)->(%s %p %08x)\n", iface, debugstr_w(pwszUrl), pdwZone, dwFlags);
00789 
00790     if(This->custom_manager) {
00791         hres = IInternetSecurityManager_MapUrlToZone(This->custom_manager,
00792                 pwszUrl, pdwZone, dwFlags);
00793         if(hres != INET_E_DEFAULT_ACTION)
00794             return hres;
00795     }
00796 
00797     if(!pwszUrl) {
00798         *pdwZone = URLZONE_INVALID;
00799         return E_INVALIDARG;
00800     }
00801 
00802     if(dwFlags)
00803         FIXME("not supported flags: %08x\n", dwFlags);
00804 
00805     return map_url_to_zone(pwszUrl, pdwZone, NULL);
00806 }
00807 
00808 static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *iface, 
00809         LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
00810 {
00811     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00812     LPWSTR url, ptr, ptr2;
00813     DWORD zone, len;
00814     HRESULT hres;
00815 
00816     static const WCHAR wszFile[] = {'f','i','l','e',':'};
00817 
00818     TRACE("(%p)->(%s %p %p %08lx)\n", iface, debugstr_w(pwszUrl), pbSecurityId,
00819           pcbSecurityId, dwReserved);
00820 
00821     if(This->custom_manager) {
00822         hres = IInternetSecurityManager_GetSecurityId(This->custom_manager,
00823                 pwszUrl, pbSecurityId, pcbSecurityId, dwReserved);
00824         if(hres != INET_E_DEFAULT_ACTION)
00825             return hres;
00826     }
00827 
00828     if(!pwszUrl || !pbSecurityId || !pcbSecurityId)
00829         return E_INVALIDARG;
00830 
00831     if(dwReserved)
00832         FIXME("dwReserved is not supported\n");
00833 
00834     hres = map_url_to_zone(pwszUrl, &zone, &url);
00835     if(FAILED(hres))
00836         return hres == 0x80041001 ? E_INVALIDARG : hres;
00837 
00838     /* file protocol is a special case */
00839     if(strlenW(url) >= sizeof(wszFile)/sizeof(WCHAR)
00840             && !memcmp(url, wszFile, sizeof(wszFile)) && strchrW(url, '\\')) {
00841 
00842         static const BYTE secidFile[] = {'f','i','l','e',':'};
00843 
00844         heap_free(url);
00845 
00846         if(*pcbSecurityId < sizeof(secidFile)+sizeof(zone))
00847             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
00848 
00849         memcpy(pbSecurityId, secidFile, sizeof(secidFile));
00850         *(DWORD*)(pbSecurityId+sizeof(secidFile)) = zone;
00851 
00852         *pcbSecurityId = sizeof(secidFile)+sizeof(zone);
00853         return S_OK;
00854     }
00855 
00856     ptr = strchrW(url, ':');
00857     ptr2 = ++ptr;
00858     while(*ptr2 == '/')
00859         ptr2++;
00860     if(ptr2 != ptr)
00861         memmove(ptr, ptr2, (strlenW(ptr2)+1)*sizeof(WCHAR));
00862 
00863     ptr = strchrW(ptr, '/');
00864     if(ptr)
00865         *ptr = 0;
00866 
00867     len = WideCharToMultiByte(CP_ACP, 0, url, -1, NULL, 0, NULL, NULL)-1;
00868 
00869     if(len+sizeof(DWORD) > *pcbSecurityId) {
00870         heap_free(url);
00871         return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
00872     }
00873 
00874     WideCharToMultiByte(CP_ACP, 0, url, -1, (LPSTR)pbSecurityId, len, NULL, NULL);
00875     heap_free(url);
00876 
00877     *(DWORD*)(pbSecurityId+len) = zone;
00878 
00879     *pcbSecurityId = len+sizeof(DWORD);
00880 
00881     return S_OK;
00882 }
00883 
00884 
00885 static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager *iface,
00886                                                       LPCWSTR pwszUrl, DWORD dwAction,
00887                                                       BYTE *pPolicy, DWORD cbPolicy,
00888                                                       BYTE *pContext, DWORD cbContext,
00889                                                       DWORD dwFlags, DWORD dwReserved)
00890 {
00891     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00892     DWORD zone, policy;
00893     HRESULT hres;
00894 
00895     TRACE("(%p)->(%s %08x %p %08x %p %08x %08x %08x)\n", iface, debugstr_w(pwszUrl), dwAction,
00896           pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
00897 
00898     if(This->custom_manager) {
00899         hres = IInternetSecurityManager_ProcessUrlAction(This->custom_manager, pwszUrl, dwAction,
00900                 pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
00901         if(hres != INET_E_DEFAULT_ACTION)
00902             return hres;
00903     }
00904 
00905     if(dwFlags || dwReserved)
00906         FIXME("Unsupported arguments\n");
00907 
00908     if(!pwszUrl)
00909         return E_INVALIDARG;
00910 
00911     hres = map_url_to_zone(pwszUrl, &zone, NULL);
00912     if(FAILED(hres))
00913         return hres;
00914 
00915     hres = get_action_policy(zone, dwAction, (BYTE*)&policy, sizeof(policy), URLZONEREG_DEFAULT);
00916     if(FAILED(hres))
00917         return hres;
00918 
00919     TRACE("policy %x\n", policy);
00920     if(cbPolicy >= sizeof(DWORD))
00921         *(DWORD*)pPolicy = policy;
00922 
00923     switch(GetUrlPolicyPermissions(policy)) {
00924     case URLPOLICY_ALLOW:
00925     case URLPOLICY_CHANNEL_SOFTDIST_PRECACHE:
00926         return S_OK;
00927     case URLPOLICY_DISALLOW:
00928         return S_FALSE;
00929     case URLPOLICY_QUERY:
00930         FIXME("URLPOLICY_QUERY not implemented\n");
00931         return E_FAIL;
00932     default:
00933         FIXME("Not implemented policy %x\n", policy);
00934     }
00935 
00936     return E_FAIL;
00937 }
00938                                                
00939 
00940 static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManager *iface,
00941                                                        LPCWSTR pwszUrl, REFGUID guidKey,
00942                                                        BYTE **ppPolicy, DWORD *pcbPolicy,
00943                                                        BYTE *pContext, DWORD cbContext,
00944                                                        DWORD dwReserved)
00945 {
00946     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00947     HRESULT hres;
00948 
00949     TRACE("(%p)->(%s %s %p %p %p %08x %08x )\n", iface, debugstr_w(pwszUrl), debugstr_guid(guidKey),
00950           ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
00951 
00952     if(This->custom_manager) {
00953         hres = IInternetSecurityManager_QueryCustomPolicy(This->custom_manager, pwszUrl, guidKey,
00954                 ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
00955         if(hres != INET_E_DEFAULT_ACTION)
00956             return hres;
00957     }
00958 
00959     WARN("Unknown guidKey %s\n", debugstr_guid(guidKey));
00960     return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
00961 }
00962 
00963 static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManager *iface,
00964                                                     DWORD dwZone, LPCWSTR pwszPattern, DWORD dwFlags)
00965 {
00966     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00967     HRESULT hres;
00968 
00969     TRACE("(%p)->(%08x %s %08x)\n", iface, dwZone, debugstr_w(pwszPattern),dwFlags);
00970 
00971     if(This->custom_manager) {
00972         hres = IInternetSecurityManager_SetZoneMapping(This->custom_manager, dwZone,
00973                 pwszPattern, dwFlags);
00974         if(hres != INET_E_DEFAULT_ACTION)
00975             return hres;
00976     }
00977 
00978     FIXME("Default action is not implemented\n");
00979     return E_NOTIMPL;
00980 }
00981 
00982 static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManager *iface,
00983         DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
00984 {
00985     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
00986     HRESULT hres;
00987 
00988     TRACE("(%p)->(%08x %p %08x)\n", iface, dwZone, ppenumString,dwFlags);
00989 
00990     if(This->custom_manager) {
00991         hres = IInternetSecurityManager_GetZoneMappings(This->custom_manager, dwZone,
00992                 ppenumString, dwFlags);
00993         if(hres != INET_E_DEFAULT_ACTION)
00994             return hres;
00995     }
00996 
00997     FIXME("Default action is not implemented\n");
00998     return E_NOTIMPL;
00999 }
01000 
01001 static const IInternetSecurityManagerVtbl VT_SecManagerImpl =
01002 {
01003     SecManagerImpl_QueryInterface,
01004     SecManagerImpl_AddRef,
01005     SecManagerImpl_Release,
01006     SecManagerImpl_SetSecuritySite,
01007     SecManagerImpl_GetSecuritySite,
01008     SecManagerImpl_MapUrlToZone,
01009     SecManagerImpl_GetSecurityId,
01010     SecManagerImpl_ProcessUrlAction,
01011     SecManagerImpl_QueryCustomPolicy,
01012     SecManagerImpl_SetZoneMapping,
01013     SecManagerImpl_GetZoneMappings
01014 };
01015 
01016 HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
01017 {
01018     SecManagerImpl *This;
01019 
01020     TRACE("(%p,%p)\n",pUnkOuter,ppobj);
01021     This = heap_alloc(sizeof(*This));
01022 
01023     /* Initialize the virtual function table. */
01024     This->IInternetSecurityManager_iface.lpVtbl = &VT_SecManagerImpl;
01025 
01026     This->ref = 1;
01027     This->mgrsite = NULL;
01028     This->custom_manager = NULL;
01029 
01030     *ppobj = This;
01031 
01032     URLMON_LockModule();
01033 
01034     return S_OK;
01035 }
01036 
01037 /***********************************************************************
01038  *           InternetZoneManager implementation
01039  *
01040  */
01041 typedef struct {
01042     IInternetZoneManagerEx2 IInternetZoneManagerEx2_iface;
01043     LONG ref;
01044     LPDWORD *zonemaps;
01045     DWORD zonemap_count;
01046 } ZoneMgrImpl;
01047 
01048 static inline ZoneMgrImpl *impl_from_IInternetZoneManagerEx2(IInternetZoneManagerEx2 *iface)
01049 {
01050     return CONTAINING_RECORD(iface, ZoneMgrImpl, IInternetZoneManagerEx2_iface);
01051 }
01052 
01053 
01054 /***********************************************************************
01055  * build_zonemap_from_reg [internal]
01056  *
01057  * Enumerate the Zones in the Registry and return the Zones in a DWORD-array
01058  * The number of the Zones is returned in data[0]
01059  */
01060 static LPDWORD build_zonemap_from_reg(void)
01061 {
01062     WCHAR name[32];
01063     HKEY hkey;
01064     LPDWORD data = NULL;
01065     DWORD allocated = 6; /* space for the zonecount and Zone "0" up to Zone "4" */
01066     DWORD used = 0;
01067     DWORD res;
01068     DWORD len;
01069 
01070 
01071     res = RegOpenKeyW(HKEY_CURRENT_USER, wszZonesKey, &hkey);
01072     if (res)
01073         return NULL;
01074 
01075     data = heap_alloc(allocated * sizeof(DWORD));
01076     if (!data)
01077         goto cleanup;
01078 
01079     while (!res) {
01080         name[0] = '\0';
01081         len = sizeof(name) / sizeof(name[0]);
01082         res = RegEnumKeyExW(hkey, used, name, &len, NULL, NULL, NULL, NULL);
01083 
01084         if (!res) {
01085             used++;
01086             if (used == allocated) {
01087                 LPDWORD new_data;
01088 
01089                 allocated *= 2;
01090                 new_data = heap_realloc_zero(data, allocated * sizeof(DWORD));
01091                 if (!new_data)
01092                     goto cleanup;
01093 
01094                 data = new_data;
01095             }
01096             data[used] = atoiW(name);
01097         }
01098     }
01099     if (used) {
01100         RegCloseKey(hkey);
01101         data[0] = used;
01102         return data;
01103     }
01104 
01105 cleanup:
01106     /* something failed */
01107     RegCloseKey(hkey);
01108     heap_free(data);
01109     return NULL;
01110 }
01111 
01112 /********************************************************************
01113  *      IInternetZoneManager_QueryInterface
01114  */
01115 static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManagerEx2* iface, REFIID riid, void** ppvObject)
01116 {
01117     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
01118 
01119     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);
01120 
01121     if(!This || !ppvObject)
01122         return E_INVALIDARG;
01123 
01124     if(IsEqualIID(&IID_IUnknown, riid)) {
01125         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppvObject);
01126     }else if(IsEqualIID(&IID_IInternetZoneManager, riid)) {
01127         TRACE("(%p)->(IID_InternetZoneManager %p)\n", This, ppvObject);
01128     }else if(IsEqualIID(&IID_IInternetZoneManagerEx, riid)) {
01129         TRACE("(%p)->(IID_InternetZoneManagerEx %p)\n", This, ppvObject);
01130     }else if(IsEqualIID(&IID_IInternetZoneManagerEx2, riid)) {
01131         TRACE("(%p)->(IID_InternetZoneManagerEx2 %p)\n", This, ppvObject);
01132     }
01133     else
01134     {
01135         FIXME("Unknown interface: %s\n", debugstr_guid(riid));
01136         *ppvObject = NULL;
01137         return E_NOINTERFACE;
01138     }
01139 
01140     *ppvObject = iface;
01141     IInternetZoneManager_AddRef(iface);
01142     return S_OK;
01143 }
01144 
01145 /********************************************************************
01146  *      IInternetZoneManager_AddRef
01147  */
01148 static ULONG WINAPI ZoneMgrImpl_AddRef(IInternetZoneManagerEx2* iface)
01149 {
01150     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
01151     ULONG refCount = InterlockedIncrement(&This->ref);
01152 
01153     TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
01154 
01155     return refCount;
01156 }
01157 
01158 /********************************************************************
01159  *      IInternetZoneManager_Release
01160  */
01161 static ULONG WINAPI ZoneMgrImpl_Release(IInternetZoneManagerEx2* iface)
01162 {
01163     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
01164     ULONG refCount = InterlockedDecrement(&This->ref);
01165 
01166     TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
01167 
01168     if(!refCount) {
01169         while (This->zonemap_count) heap_free(This->zonemaps[--This->zonemap_count]);
01170         heap_free(This->zonemaps);
01171         heap_free(This);
01172         URLMON_UnlockModule();
01173     }
01174     
01175     return refCount;
01176 }
01177 
01178 /********************************************************************
01179  *      IInternetZoneManager_GetZoneAttributes
01180  */
01181 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributes(IInternetZoneManagerEx2* iface,
01182                                                     DWORD dwZone,
01183                                                     ZONEATTRIBUTES* pZoneAttributes)
01184 {
01185     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
01186     HRESULT hr;
01187     HKEY hcu;
01188     HKEY hklm = NULL;
01189 
01190     TRACE("(%p)->(%d %p)\n", This, dwZone, pZoneAttributes);
01191 
01192     if (!pZoneAttributes)
01193         return E_INVALIDARG;
01194 
01195     hr = open_zone_key(HKEY_CURRENT_USER, dwZone, &hcu);
01196     if (FAILED(hr))
01197         return S_OK;  /* IE6 and older returned E_FAIL here */
01198 
01199     hr = open_zone_key(HKEY_LOCAL_MACHINE, dwZone, &hklm);
01200     if (FAILED(hr))
01201         TRACE("Zone %d not in HKLM\n", dwZone);
01202 
01203     get_string_from_reg(hcu, hklm, displaynameW, pZoneAttributes->szDisplayName, MAX_ZONE_PATH);
01204     get_string_from_reg(hcu, hklm, descriptionW, pZoneAttributes->szDescription, MAX_ZONE_DESCRIPTION);
01205     get_string_from_reg(hcu, hklm, iconW, pZoneAttributes->szIconPath, MAX_ZONE_PATH);
01206     get_dword_from_reg(hcu, hklm, minlevelW, &pZoneAttributes->dwTemplateMinLevel);
01207     get_dword_from_reg(hcu, hklm, currentlevelW, &pZoneAttributes->dwTemplateCurrentLevel);
01208     get_dword_from_reg(hcu, hklm, recommendedlevelW, &pZoneAttributes->dwTemplateRecommended);
01209     get_dword_from_reg(hcu, hklm, flagsW, &pZoneAttributes->dwFlags);
01210 
01211     RegCloseKey(hklm);
01212     RegCloseKey(hcu);
01213     return S_OK;
01214 }
01215 
01216 /********************************************************************
01217  *      IInternetZoneManager_SetZoneAttributes
01218  */
01219 static HRESULT WINAPI ZoneMgrImpl_SetZoneAttributes(IInternetZoneManagerEx2* iface,
01220                                                     DWORD dwZone,
01221                                                     ZONEATTRIBUTES* pZoneAttributes)
01222 {
01223     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
01224     HRESULT hr;
01225     HKEY hcu;
01226 
01227     TRACE("(%p)->(%d %p)\n", This, dwZone, pZoneAttributes);
01228 
01229     if (!pZoneAttributes)
01230         return E_INVALIDARG;
01231 
01232     hr = open_zone_key(HKEY_CURRENT_USER, dwZone, &hcu);
01233     if (FAILED(hr))
01234         return S_OK;  /* IE6 returned E_FAIL here */
01235 
01236     /* cbSize is ignored */
01237     RegSetValueExW(hcu, displaynameW, 0, REG_SZ, (LPBYTE) pZoneAttributes->szDisplayName,
01238                     (lstrlenW(pZoneAttributes->szDisplayName)+1)* sizeof(WCHAR));
01239 
01240     RegSetValueExW(hcu, descriptionW, 0, REG_SZ, (LPBYTE) pZoneAttributes->szDescription,
01241                     (lstrlenW(pZoneAttributes->szDescription)+1)* sizeof(WCHAR));
01242 
01243     RegSetValueExW(hcu, iconW, 0, REG_SZ, (LPBYTE) pZoneAttributes->szIconPath,
01244                     (lstrlenW(pZoneAttributes->szIconPath)+1)* sizeof(WCHAR));
01245 
01246     RegSetValueExW(hcu, minlevelW, 0, REG_DWORD,
01247                     (const BYTE*) &pZoneAttributes->dwTemplateMinLevel, sizeof(DWORD));
01248 
01249     RegSetValueExW(hcu, currentlevelW, 0, REG_DWORD,
01250                     (const BYTE*) &pZoneAttributes->dwTemplateCurrentLevel, sizeof(DWORD));
01251 
01252     RegSetValueExW(hcu, recommendedlevelW, 0, REG_DWORD,
01253                     (const BYTE*) &pZoneAttributes->dwTemplateRecommended, sizeof(DWORD));
01254 
01255     RegSetValueExW(hcu, flagsW, 0, REG_DWORD, (const BYTE*) &pZoneAttributes->dwFlags, sizeof(DWORD));
01256     RegCloseKey(hcu);
01257     return S_OK;
01258 
01259 }
01260 
01261 /********************************************************************
01262  *      IInternetZoneManager_GetZoneCustomPolicy
01263  */
01264 static HRESULT WINAPI ZoneMgrImpl_GetZoneCustomPolicy(IInternetZoneManagerEx2* iface,
01265                                                       DWORD dwZone,
01266                                                       REFGUID guidKey,
01267                                                       BYTE** ppPolicy,
01268                                                       DWORD* pcbPolicy,
01269                                                       URLZONEREG ulrZoneReg)
01270 {
01271     FIXME("(%p)->(%08x %s %p %p %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
01272                                                     ppPolicy, pcbPolicy, ulrZoneReg);
01273     return E_NOTIMPL;
01274 }
01275 
01276 /********************************************************************
01277  *      IInternetZoneManager_SetZoneCustomPolicy
01278  */
01279 static HRESULT WINAPI ZoneMgrImpl_SetZoneCustomPolicy(IInternetZoneManagerEx2* iface,
01280                                                       DWORD dwZone,
01281                                                       REFGUID guidKey,
01282                                                       BYTE* ppPolicy,
01283                                                       DWORD cbPolicy,
01284                                                       URLZONEREG ulrZoneReg)
01285 {
01286     FIXME("(%p)->(%08x %s %p %08x %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
01287                                                     ppPolicy, cbPolicy, ulrZoneReg);
01288     return E_NOTIMPL;
01289 }
01290 
01291 /********************************************************************
01292  *      IInternetZoneManager_GetZoneActionPolicy
01293  */
01294 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicy(IInternetZoneManagerEx2* iface,
01295         DWORD dwZone, DWORD dwAction, BYTE* pPolicy, DWORD cbPolicy, URLZONEREG urlZoneReg)
01296 {
01297     TRACE("(%p)->(%d %08x %p %d %d)\n", iface, dwZone, dwAction, pPolicy,
01298             cbPolicy, urlZoneReg);
01299 
01300     if(!pPolicy)
01301         return E_INVALIDARG;
01302 
01303     return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg);
01304 }
01305 
01306 /********************************************************************
01307  *      IInternetZoneManager_SetZoneActionPolicy
01308  */
01309 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicy(IInternetZoneManagerEx2* iface,
01310                                                       DWORD dwZone,
01311                                                       DWORD dwAction,
01312                                                       BYTE* pPolicy,
01313                                                       DWORD cbPolicy,
01314                                                       URLZONEREG urlZoneReg)
01315 {
01316     FIXME("(%p)->(%08x %08x %p %08x %08x) stub\n", iface, dwZone, dwAction, pPolicy,
01317                                                        cbPolicy, urlZoneReg);
01318     return E_NOTIMPL;
01319 }
01320 
01321 /********************************************************************
01322  *      IInternetZoneManager_PromptAction
01323  */
01324 static HRESULT WINAPI ZoneMgrImpl_PromptAction(IInternetZoneManagerEx2* iface,
01325                                                DWORD dwAction,
01326                                                HWND hwndParent,
01327                                                LPCWSTR pwszUrl,
01328                                                LPCWSTR pwszText,
01329                                                DWORD dwPromptFlags)
01330 {
01331     FIXME("%p %08x %p %s %s %08x\n", iface, dwAction, hwndParent,
01332           debugstr_w(pwszUrl), debugstr_w(pwszText), dwPromptFlags );
01333     return E_NOTIMPL;
01334 }
01335 
01336 /********************************************************************
01337  *      IInternetZoneManager_LogAction
01338  */
01339 static HRESULT WINAPI ZoneMgrImpl_LogAction(IInternetZoneManagerEx2* iface,
01340                                             DWORD dwAction,
01341                                             LPCWSTR pwszUrl,
01342                                             LPCWSTR pwszText,
01343                                             DWORD dwLogFlags)
01344 {
01345     FIXME("(%p)->(%08x %s %s %08x) stub\n", iface, dwAction, debugstr_w(pwszUrl),
01346                                               debugstr_w(pwszText), dwLogFlags);
01347     return E_NOTIMPL;
01348 }
01349 
01350 /********************************************************************
01351  *      IInternetZoneManager_CreateZoneEnumerator
01352  */
01353 static HRESULT WINAPI ZoneMgrImpl_CreateZoneEnumerator(IInternetZoneManagerEx2* iface,
01354                                                        DWORD* pdwEnum,
01355                                                        DWORD* pdwCount,
01356                                                        DWORD dwFlags)
01357 {
01358     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
01359     LPDWORD * new_maps;
01360     LPDWORD data;
01361     DWORD i;
01362 
01363     TRACE("(%p)->(%p, %p, 0x%08x)\n", This, pdwEnum, pdwCount, dwFlags);
01364     if (!pdwEnum || !pdwCount || (dwFlags != 0))
01365         return E_INVALIDARG;
01366 
01367     data = build_zonemap_from_reg();
01368     TRACE("found %d zones\n", data ? data[0] : -1);
01369 
01370     if (!data)
01371         return E_FAIL;
01372 
01373     for (i = 0; i < This->zonemap_count; i++) {
01374         if (This->zonemaps && !This->zonemaps[i]) {
01375             This->zonemaps[i] = data;
01376             *pdwEnum = i;
01377             *pdwCount = data[0];
01378             return S_OK;
01379         }
01380     }
01381 
01382     if (This->zonemaps) {
01383         /* try to double the nr. of pointers in the array */
01384         new_maps = heap_realloc_zero(This->zonemaps, This->zonemap_count * 2 * sizeof(LPDWORD));
01385         if (new_maps)
01386             This->zonemap_count *= 2;
01387     }
01388     else
01389     {
01390         This->zonemap_count = 2;
01391         new_maps = heap_alloc_zero(This->zonemap_count * sizeof(LPDWORD));
01392     }
01393 
01394     if (!new_maps) {
01395         heap_free(data);
01396         return E_FAIL;
01397     }
01398     This->zonemaps = new_maps;
01399     This->zonemaps[i] = data;
01400     *pdwEnum = i;
01401     *pdwCount = data[0];
01402     return S_OK;
01403 }
01404 
01405 /********************************************************************
01406  *      IInternetZoneManager_GetZoneAt
01407  */
01408 static HRESULT WINAPI ZoneMgrImpl_GetZoneAt(IInternetZoneManagerEx2* iface,
01409                                             DWORD dwEnum,
01410                                             DWORD dwIndex,
01411                                             DWORD* pdwZone)
01412 {
01413     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
01414     LPDWORD data;
01415 
01416     TRACE("(%p)->(0x%08x, %d, %p)\n", This, dwEnum, dwIndex, pdwZone);
01417 
01418     /* make sure, that dwEnum and dwIndex are in the valid range */
01419     if (dwEnum < This->zonemap_count) {
01420         if ((data = This->zonemaps[dwEnum])) {
01421             if (dwIndex < data[0]) {
01422                 *pdwZone = data[dwIndex + 1];
01423                 return S_OK;
01424             }
01425         }
01426     }
01427     return E_INVALIDARG;
01428 }
01429 
01430 /********************************************************************
01431  *      IInternetZoneManager_DestroyZoneEnumerator
01432  */
01433 static HRESULT WINAPI ZoneMgrImpl_DestroyZoneEnumerator(IInternetZoneManagerEx2* iface,
01434                                                         DWORD dwEnum)
01435 {
01436     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
01437     LPDWORD data;
01438 
01439     TRACE("(%p)->(0x%08x)\n", This, dwEnum);
01440     /* make sure, that dwEnum is valid */
01441     if (dwEnum < This->zonemap_count) {
01442         if ((data = This->zonemaps[dwEnum])) {
01443             This->zonemaps[dwEnum] = NULL;
01444             heap_free(data);
01445             return S_OK;
01446         }
01447     }
01448     return E_INVALIDARG;
01449 }
01450 
01451 /********************************************************************
01452  *      IInternetZoneManager_CopyTemplatePoliciesToZone
01453  */
01454 static HRESULT WINAPI ZoneMgrImpl_CopyTemplatePoliciesToZone(IInternetZoneManagerEx2* iface,
01455                                                              DWORD dwTemplate,
01456                                                              DWORD dwZone,
01457                                                              DWORD dwReserved)
01458 {
01459     FIXME("(%p)->(%08x %08x %08x) stub\n", iface, dwTemplate, dwZone, dwReserved);
01460     return E_NOTIMPL;
01461 }
01462 
01463 /********************************************************************
01464  *      IInternetZoneManagerEx_GetZoneActionPolicyEx
01465  */
01466 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicyEx(IInternetZoneManagerEx2* iface,
01467                                                         DWORD dwZone,
01468                                                         DWORD dwAction,
01469                                                         BYTE* pPolicy,
01470                                                         DWORD cbPolicy,
01471                                                         URLZONEREG urlZoneReg,
01472                                                         DWORD dwFlags)
01473 {
01474     TRACE("(%p)->(%d, 0x%x, %p, %d, %d, 0x%x)\n", iface, dwZone,
01475             dwAction, pPolicy, cbPolicy, urlZoneReg, dwFlags);
01476 
01477     if(!pPolicy)
01478         return E_INVALIDARG;
01479 
01480     if (dwFlags)
01481         FIXME("dwFlags 0x%x ignored\n", dwFlags);
01482 
01483     return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg);
01484 }
01485 
01486 /********************************************************************
01487  *      IInternetZoneManagerEx_SetZoneActionPolicyEx
01488  */
01489 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicyEx(IInternetZoneManagerEx2* iface,
01490                                                         DWORD dwZone,
01491                                                         DWORD dwAction,
01492                                                         BYTE* pPolicy,
01493                                                         DWORD cbPolicy,
01494                                                         URLZONEREG urlZoneReg,
01495                                                         DWORD dwFlags)
01496 {
01497     FIXME("(%p)->(%d, 0x%x, %p, %d, %d, 0x%x) stub\n", iface, dwZone, dwAction, pPolicy,
01498                                                        cbPolicy, urlZoneReg, dwFlags);
01499     return E_NOTIMPL;
01500 }
01501 
01502 /********************************************************************
01503  *      IInternetZoneManagerEx2_GetZoneAttributesEx
01504  */
01505 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributesEx(IInternetZoneManagerEx2* iface,
01506                                                       DWORD dwZone,
01507                                                       ZONEATTRIBUTES* pZoneAttributes,
01508                                                       DWORD dwFlags)
01509 {
01510     TRACE("(%p)->(%d, %p, 0x%x)\n", iface, dwZone, pZoneAttributes, dwFlags);
01511 
01512     if (dwFlags)
01513         FIXME("dwFlags 0x%x ignored\n", dwFlags);
01514 
01515     return IInternetZoneManager_GetZoneAttributes(iface, dwZone, pZoneAttributes);
01516 }
01517 
01518 
01519 /********************************************************************
01520  *      IInternetZoneManagerEx2_GetZoneSecurityState
01521  */
01522 static HRESULT WINAPI ZoneMgrImpl_GetZoneSecurityState(IInternetZoneManagerEx2* iface,
01523                                                        DWORD dwZoneIndex,
01524                                                        BOOL fRespectPolicy,
01525                                                        LPDWORD pdwState,
01526                                                        BOOL *pfPolicyEncountered)
01527 {
01528     FIXME("(%p)->(%d, %d, %p, %p) stub\n", iface, dwZoneIndex, fRespectPolicy,
01529                                            pdwState, pfPolicyEncountered);
01530 
01531     *pdwState = SECURITY_IE_STATE_GREEN;
01532 
01533     if (pfPolicyEncountered)
01534         *pfPolicyEncountered = FALSE;
01535 
01536     return S_OK;
01537 }
01538 
01539 /********************************************************************
01540  *      IInternetZoneManagerEx2_GetIESecurityState
01541  */
01542 static HRESULT WINAPI ZoneMgrImpl_GetIESecurityState(IInternetZoneManagerEx2* iface,
01543                                                      BOOL fRespectPolicy,
01544                                                      LPDWORD pdwState,
01545                                                      BOOL *pfPolicyEncountered,
01546                                                      BOOL fNoCache)
01547 {
01548     FIXME("(%p)->(%d, %p, %p, %d) stub\n", iface, fRespectPolicy, pdwState,
01549                                            pfPolicyEncountered, fNoCache);
01550 
01551     *pdwState = SECURITY_IE_STATE_GREEN;
01552 
01553     if (pfPolicyEncountered)
01554         *pfPolicyEncountered = FALSE;
01555 
01556     return S_OK;
01557 }
01558 
01559 /********************************************************************
01560  *      IInternetZoneManagerEx2_FixInsecureSettings
01561  */
01562 static HRESULT WINAPI ZoneMgrImpl_FixInsecureSettings(IInternetZoneManagerEx2* iface)
01563 {
01564     FIXME("(%p) stub\n", iface);
01565     return S_OK;
01566 }
01567 
01568 /********************************************************************
01569  *      IInternetZoneManager_Construct
01570  */
01571 static const IInternetZoneManagerEx2Vtbl ZoneMgrImplVtbl = {
01572     ZoneMgrImpl_QueryInterface,
01573     ZoneMgrImpl_AddRef,
01574     ZoneMgrImpl_Release,
01575     /* IInternetZoneManager */
01576     ZoneMgrImpl_GetZoneAttributes,
01577     ZoneMgrImpl_SetZoneAttributes,
01578     ZoneMgrImpl_GetZoneCustomPolicy,
01579     ZoneMgrImpl_SetZoneCustomPolicy,
01580     ZoneMgrImpl_GetZoneActionPolicy,
01581     ZoneMgrImpl_SetZoneActionPolicy,
01582     ZoneMgrImpl_PromptAction,
01583     ZoneMgrImpl_LogAction,
01584     ZoneMgrImpl_CreateZoneEnumerator,
01585     ZoneMgrImpl_GetZoneAt,
01586     ZoneMgrImpl_DestroyZoneEnumerator,
01587     ZoneMgrImpl_CopyTemplatePoliciesToZone,
01588     /* IInternetZoneManagerEx */
01589     ZoneMgrImpl_GetZoneActionPolicyEx,
01590     ZoneMgrImpl_SetZoneActionPolicyEx,
01591     /* IInternetZoneManagerEx2 */
01592     ZoneMgrImpl_GetZoneAttributesEx,
01593     ZoneMgrImpl_GetZoneSecurityState,
01594     ZoneMgrImpl_GetIESecurityState,
01595     ZoneMgrImpl_FixInsecureSettings,
01596 };
01597 
01598 HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
01599 {
01600     ZoneMgrImpl* ret = heap_alloc_zero(sizeof(ZoneMgrImpl));
01601 
01602     TRACE("(%p %p)\n", pUnkOuter, ppobj);
01603     ret->IInternetZoneManagerEx2_iface.lpVtbl = &ZoneMgrImplVtbl;
01604     ret->ref = 1;
01605     *ppobj = (IInternetZoneManagerEx*)ret;
01606 
01607     URLMON_LockModule();
01608 
01609     return S_OK;
01610 }
01611 
01612 /***********************************************************************
01613  *           CoInternetCreateSecurityManager (URLMON.@)
01614  *
01615  */
01616 HRESULT WINAPI CoInternetCreateSecurityManager( IServiceProvider *pSP,
01617     IInternetSecurityManager **ppSM, DWORD dwReserved )
01618 {
01619     TRACE("%p %p %d\n", pSP, ppSM, dwReserved );
01620 
01621     if(pSP)
01622         FIXME("pSP not supported\n");
01623 
01624     return SecManagerImpl_Construct(NULL, (void**) ppSM);
01625 }
01626 
01627 /********************************************************************
01628  *      CoInternetCreateZoneManager (URLMON.@)
01629  */
01630 HRESULT WINAPI CoInternetCreateZoneManager(IServiceProvider* pSP, IInternetZoneManager** ppZM, DWORD dwReserved)
01631 {
01632     TRACE("(%p %p %x)\n", pSP, ppZM, dwReserved);
01633     return ZoneMgrImpl_Construct(NULL, (void**)ppZM);
01634 }
01635 
01636 static HRESULT parse_security_url(const WCHAR *url, PSUACTION action, WCHAR **result) {
01637     IInternetProtocolInfo *protocol_info;
01638     WCHAR *tmp, *new_url = NULL, *alloc_url = NULL;
01639     DWORD size, new_size;
01640     HRESULT hres = S_OK, parse_hres;
01641 
01642     while(1) {
01643         TRACE("parsing %s\n", debugstr_w(url));
01644 
01645         protocol_info = get_protocol_info(url);
01646         if(!protocol_info)
01647             break;
01648 
01649         size = strlenW(url)+1;
01650         new_url = CoTaskMemAlloc(size*sizeof(WCHAR));
01651         if(!new_url) {
01652             hres = E_OUTOFMEMORY;
01653             break;
01654         }
01655 
01656         new_size = 0;
01657         parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_URL, 0, new_url, size, &new_size, 0);
01658         if(parse_hres == S_FALSE) {
01659             if(!new_size) {
01660                 hres = E_UNEXPECTED;
01661                 break;
01662             }
01663 
01664             tmp = CoTaskMemRealloc(new_url, new_size*sizeof(WCHAR));
01665             if(!tmp) {
01666                 hres = E_OUTOFMEMORY;
01667                 break;
01668             }
01669             new_url = tmp;
01670             parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_URL, 0, new_url,
01671                     new_size, &new_size, 0);
01672             if(parse_hres == S_FALSE) {
01673                 hres = E_FAIL;
01674                 break;
01675             }
01676         }
01677 
01678         if(parse_hres != S_OK || !strcmpW(url, new_url))
01679             break;
01680 
01681         CoTaskMemFree(alloc_url);
01682         url = alloc_url = new_url;
01683         new_url = NULL;
01684     }
01685 
01686     CoTaskMemFree(new_url);
01687 
01688     if(hres != S_OK) {
01689         WARN("failed: %08x\n", hres);
01690         CoTaskMemFree(alloc_url);
01691         return hres;
01692     }
01693 
01694     if(action == PSU_DEFAULT && (protocol_info = get_protocol_info(url))) {
01695         size = strlenW(url)+1;
01696         new_url = CoTaskMemAlloc(size * sizeof(WCHAR));
01697         if(new_url) {
01698             new_size = 0;
01699             parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_DOMAIN, 0,
01700                     new_url, size, &new_size, 0);
01701             if(parse_hres == S_FALSE) {
01702                 if(new_size) {
01703                     tmp = CoTaskMemRealloc(new_url, new_size*sizeof(WCHAR));
01704                     if(tmp) {
01705                         new_url = tmp;
01706                         parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_DOMAIN, 0, new_url,
01707                                 new_size, &new_size, 0);
01708                         if(parse_hres == S_FALSE)
01709                             hres = E_FAIL;
01710                     }else {
01711                         hres = E_OUTOFMEMORY;
01712                     }
01713                 }else {
01714                     hres = E_UNEXPECTED;
01715                 }
01716             }
01717 
01718             if(hres == S_OK && parse_hres == S_OK) {
01719                 CoTaskMemFree(alloc_url);
01720                 url = alloc_url = new_url;
01721                 new_url = NULL;
01722             }
01723 
01724             CoTaskMemFree(new_url);
01725         }else {
01726             hres = E_OUTOFMEMORY;
01727         }
01728         IInternetProtocolInfo_Release(protocol_info);
01729     }
01730 
01731     if(FAILED(hres)) {
01732         WARN("failed %08x\n", hres);
01733         CoTaskMemFree(alloc_url);
01734         return hres;
01735     }
01736 
01737     if(!alloc_url) {
01738         size = strlenW(url)+1;
01739         alloc_url = CoTaskMemAlloc(size * sizeof(WCHAR));
01740         if(!alloc_url)
01741             return E_OUTOFMEMORY;
01742         memcpy(alloc_url, url, size * sizeof(WCHAR));
01743     }
01744 
01745     *result = alloc_url;
01746     return S_OK;
01747 }
01748 
01749 /********************************************************************
01750  *      CoInternetGetSecurityUrl (URLMON.@)
01751  */
01752 HRESULT WINAPI CoInternetGetSecurityUrl(LPCWSTR pwzUrl, LPWSTR *ppwzSecUrl, PSUACTION psuAction, DWORD dwReserved)
01753 {
01754     WCHAR *secure_url;
01755     HRESULT hres;
01756 
01757     TRACE("(%p,%p,%u,%u)\n", pwzUrl, ppwzSecUrl, psuAction, dwReserved);
01758 
01759     hres = parse_security_url(pwzUrl, psuAction, &secure_url);
01760     if(FAILED(hres))
01761         return hres;
01762 
01763     if(psuAction != PSU_SECURITY_URL_ONLY) {
01764         PARSEDURLW parsed_url = { sizeof(parsed_url) };
01765         DWORD size;
01766 
01767         /* FIXME: Use helpers from uri.c */
01768         if(SUCCEEDED(ParseURLW(secure_url, &parsed_url))) {
01769             WCHAR *new_url;
01770 
01771             switch(parsed_url.nScheme) {
01772             case URL_SCHEME_FTP:
01773             case URL_SCHEME_HTTP:
01774             case URL_SCHEME_HTTPS:
01775                 size = strlenW(secure_url)+1;
01776                 new_url = CoTaskMemAlloc(size * sizeof(WCHAR));
01777                 if(new_url)
01778                     hres = UrlGetPartW(secure_url, new_url, &size, URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME);
01779                 else
01780                     hres = E_OUTOFMEMORY;
01781                 CoTaskMemFree(secure_url);
01782                 if(hres != S_OK) {
01783                     WARN("UrlGetPart failed: %08x\n", hres);
01784                     CoTaskMemFree(new_url);
01785                     return FAILED(hres) ? hres : E_FAIL;
01786                 }
01787                 secure_url = new_url;
01788             }
01789         }
01790     }
01791 
01792     *ppwzSecUrl = secure_url;
01793     return S_OK;
01794 }
01795 
01796 /********************************************************************
01797  *      CoInternetGetSecurityUrlEx (URLMON.@)
01798  */
01799 HRESULT WINAPI CoInternetGetSecurityUrlEx(IUri *pUri, IUri **ppSecUri, PSUACTION psuAction, DWORD_PTR dwReserved)
01800 {
01801     URL_SCHEME scheme_type;
01802     BSTR secure_uri;
01803     WCHAR *ret_url;
01804     HRESULT hres;
01805 
01806     TRACE("(%p,%p,%u,%u)\n", pUri, ppSecUri, psuAction, (DWORD)dwReserved);
01807 
01808     if(!pUri || !ppSecUri)
01809         return E_INVALIDARG;
01810 
01811     hres = IUri_GetDisplayUri(pUri, &secure_uri);
01812     if(FAILED(hres))
01813         return hres;
01814 
01815     hres = parse_security_url(secure_uri, psuAction, &ret_url);
01816     SysFreeString(secure_uri);
01817     if(FAILED(hres))
01818         return hres;
01819 
01820     hres = CreateUri(ret_url, Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, 0, ppSecUri);
01821     if(FAILED(hres)) {
01822         CoTaskMemFree(ret_url);
01823         return hres;
01824     }
01825 
01826     /* File URIs have to hierarchical. */
01827     hres = IUri_GetScheme(pUri, (DWORD*)&scheme_type);
01828     if(SUCCEEDED(hres) && scheme_type == URL_SCHEME_FILE) {
01829         const WCHAR *tmp = ret_url;
01830 
01831         /* Check and see if a "//" is after the scheme name. */
01832         tmp += sizeof(fileW)/sizeof(WCHAR);
01833         if(*tmp != '/' || *(tmp+1) != '/')
01834             hres = E_INVALIDARG;
01835     }
01836 
01837     if(SUCCEEDED(hres))
01838         hres = CreateUri(ret_url, Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, 0, ppSecUri);
01839     CoTaskMemFree(ret_url);
01840     return hres;
01841 }

Generated on Sun May 27 2012 04:26:40 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.