urlmon: Standardize the COM usage in sec_mgr.c.
[wine] / dlls / 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  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <stdio.h>
24
25 #include "urlmon_main.h"
26 #include "winreg.h"
27 #include "wininet.h"
28
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
32
33 static const WCHAR currentlevelW[] = {'C','u','r','r','e','n','t','L','e','v','e','l',0};
34 static const WCHAR descriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
35 static const WCHAR displaynameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
36 static const WCHAR fileW[] = {'f','i','l','e',0};
37 static const WCHAR flagsW[] = {'F','l','a','g','s',0};
38 static const WCHAR iconW[] = {'I','c','o','n',0};
39 static const WCHAR minlevelW[] = {'M','i','n','L','e','v','e','l',0};
40 static const WCHAR recommendedlevelW[] = {'R','e','c','o','m','m','e','n','d','e','d',
41                                           'L','e','v','e','l',0};
42 static const WCHAR wszZonesKey[] = {'S','o','f','t','w','a','r','e','\\',
43                                     'M','i','c','r','o','s','o','f','t','\\',
44                                     'W','i','n','d','o','w','s','\\',
45                                     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
46                                     'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
47                                     'Z','o','n','e','s','\\',0};
48
49 /********************************************************************
50  * get_string_from_reg [internal]
51  *
52  * helper to get a string from the reg.
53  *
54  */
55 static void get_string_from_reg(HKEY hcu, HKEY hklm, LPCWSTR name, LPWSTR out, DWORD maxlen)
56 {
57     DWORD type = REG_SZ;
58     DWORD len = maxlen * sizeof(WCHAR);
59     DWORD res;
60
61     res = RegQueryValueExW(hcu, name, NULL, &type, (LPBYTE) out, &len);
62
63     if (res && hklm) {
64         len = maxlen * sizeof(WCHAR);
65         type = REG_SZ;
66         res = RegQueryValueExW(hklm, name, NULL, &type, (LPBYTE) out, &len);
67     }
68
69     if (res) {
70         TRACE("%s failed: %d\n", debugstr_w(name), res);
71         *out = '\0';
72     }
73 }
74
75 /********************************************************************
76  * get_dword_from_reg [internal]
77  *
78  * helper to get a dword from the reg.
79  *
80  */
81 static void get_dword_from_reg(HKEY hcu, HKEY hklm, LPCWSTR name, LPDWORD out)
82 {
83     DWORD type = REG_DWORD;
84     DWORD len = sizeof(DWORD);
85     DWORD res;
86
87     res = RegQueryValueExW(hcu, name, NULL, &type, (LPBYTE) out, &len);
88
89     if (res && hklm) {
90         len = sizeof(DWORD);
91         type = REG_DWORD;
92         res = RegQueryValueExW(hklm, name, NULL, &type, (LPBYTE) out, &len);
93     }
94
95     if (res) {
96         TRACE("%s failed: %d\n", debugstr_w(name), res);
97         *out = 0;
98     }
99 }
100
101 static HRESULT get_zone_from_reg(LPCWSTR schema, DWORD *zone)
102 {
103     DWORD res, size;
104     HKEY hkey;
105
106     static const WCHAR wszZoneMapProtocolKey[] =
107         {'S','o','f','t','w','a','r','e','\\',
108          'M','i','c','r','o','s','o','f','t','\\',
109          'W','i','n','d','o','w','s','\\',
110          'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
111          'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
112          'Z','o','n','e','M','a','p','\\',
113          'P','r','o','t','o','c','o','l','D','e','f','a','u','l','t','s',0};
114
115     res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapProtocolKey, &hkey);
116     if(res != ERROR_SUCCESS) {
117         ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
118         return E_UNEXPECTED;
119     }
120
121     size = sizeof(DWORD);
122     res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
123     RegCloseKey(hkey);
124     if(res == ERROR_SUCCESS)
125         return S_OK;
126
127     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapProtocolKey, &hkey);
128     if(res != ERROR_SUCCESS) {
129         ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
130         return E_UNEXPECTED;
131     }
132
133     size = sizeof(DWORD);
134     res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
135     RegCloseKey(hkey);
136     if(res == ERROR_SUCCESS)
137         return S_OK;
138
139     *zone = 3;
140     return S_OK;
141 }
142
143 static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
144 {
145     LPWSTR secur_url;
146     WCHAR schema[64];
147     DWORD size=0;
148     HRESULT hres;
149
150     *zone = -1;
151
152     hres = CoInternetGetSecurityUrl(url, &secur_url, PSU_SECURITY_URL_ONLY, 0);
153     if(hres != S_OK) {
154         size = strlenW(url)*sizeof(WCHAR);
155
156         secur_url = heap_alloc(size);
157         if(!secur_url)
158             return E_OUTOFMEMORY;
159
160         memcpy(secur_url, url, size);
161     }
162
163     hres = CoInternetParseUrl(secur_url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(WCHAR), &size, 0);
164     if(FAILED(hres) || !*schema) {
165         heap_free(secur_url);
166         return E_INVALIDARG;
167     }
168
169     /* file protocol is a special case */
170     if(!strcmpW(schema, fileW)) {
171         WCHAR path[MAX_PATH], root[20];
172         WCHAR *ptr;
173
174         hres = CoInternetParseUrl(secur_url, PARSE_PATH_FROM_URL, 0, path,
175                 sizeof(path)/sizeof(WCHAR), &size, 0);
176
177         if(SUCCEEDED(hres) && (ptr = strchrW(path, '\\')) && ptr-path < sizeof(root)/sizeof(WCHAR)) {
178             UINT type;
179
180             memcpy(root, path, (ptr-path)*sizeof(WCHAR));
181             root[ptr-path] = 0;
182
183             type = GetDriveTypeW(root);
184
185             switch(type) {
186             case DRIVE_UNKNOWN:
187             case DRIVE_NO_ROOT_DIR:
188                 break;
189             case DRIVE_REMOVABLE:
190             case DRIVE_FIXED:
191             case DRIVE_CDROM:
192             case DRIVE_RAMDISK:
193                 *zone = 0;
194                 hres = S_OK;
195                 break;
196             case DRIVE_REMOTE:
197                 *zone = 3;
198                 hres = S_OK;
199                 break;
200             default:
201                 FIXME("unsupported drive type %d\n", type);
202             }
203         }
204     }
205
206     if(*zone == -1) {
207         WARN("domains are not yet implemented\n");
208         hres = get_zone_from_reg(schema, zone);
209     }
210
211     if(FAILED(hres) || !ret_url)
212         heap_free(secur_url);
213     else
214         *ret_url = secur_url;
215
216     return hres;
217 }
218
219 static HRESULT open_zone_key(HKEY parent_key, DWORD zone, HKEY *hkey)
220 {
221     static const WCHAR wszFormat[] = {'%','s','%','l','d',0};
222
223     WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+8];
224     DWORD res;
225
226     wsprintfW(key_name, wszFormat, wszZonesKey, zone);
227
228     res = RegOpenKeyW(parent_key, key_name, hkey);
229
230     if(res != ERROR_SUCCESS) {
231         WARN("RegOpenKey failed\n");
232         return E_INVALIDARG;
233     }
234
235     return S_OK;
236 }
237
238 static HRESULT get_action_policy(DWORD zone, DWORD action, BYTE *policy, DWORD size, URLZONEREG zone_reg)
239 {
240     HKEY parent_key;
241     HKEY hkey;
242     LONG res;
243     HRESULT hres;
244
245     switch(action) {
246     case URLACTION_SCRIPT_OVERRIDE_SAFETY:
247     case URLACTION_ACTIVEX_OVERRIDE_SCRIPT_SAFETY:
248         *(DWORD*)policy = URLPOLICY_DISALLOW;
249         return S_OK;
250     }
251
252     switch(zone_reg) {
253     case URLZONEREG_DEFAULT:
254     case URLZONEREG_HKCU:
255         parent_key = HKEY_CURRENT_USER;
256         break;
257     case URLZONEREG_HKLM:
258         parent_key = HKEY_LOCAL_MACHINE;
259         break;
260     default:
261         WARN("Unknown URLZONEREG: %d\n", zone_reg);
262         return E_FAIL;
263     };
264
265     hres = open_zone_key(parent_key, zone, &hkey);
266     if(SUCCEEDED(hres)) {
267         WCHAR action_str[16];
268         DWORD len = size;
269
270         static const WCHAR formatW[] = {'%','X',0};
271
272         wsprintfW(action_str, formatW, action);
273
274         res = RegQueryValueExW(hkey, action_str, NULL, NULL, policy, &len);
275         if(res == ERROR_MORE_DATA) {
276             hres = E_INVALIDARG;
277         }else if(res == ERROR_FILE_NOT_FOUND) {
278             hres = E_FAIL;
279         }else if(res != ERROR_SUCCESS) {
280             ERR("RegQueryValue failed: %d\n", res);
281             hres = E_UNEXPECTED;
282         }
283
284         RegCloseKey(hkey);
285     }
286
287     if(FAILED(hres) && zone_reg == URLZONEREG_DEFAULT)
288         return get_action_policy(zone, action, policy, size, URLZONEREG_HKLM);
289
290     return hres;
291 }
292
293 /***********************************************************************
294  *           InternetSecurityManager implementation
295  *
296  */
297 typedef struct {
298     IInternetSecurityManager IInternetSecurityManager_iface;
299
300     LONG ref;
301
302     IInternetSecurityMgrSite *mgrsite;
303     IInternetSecurityManager *custom_manager;
304 } SecManagerImpl;
305
306 static inline SecManagerImpl *impl_from_IInternetSecurityManager(IInternetSecurityManager *iface)
307 {
308     return CONTAINING_RECORD(iface, SecManagerImpl, IInternetSecurityManager_iface);
309 }
310
311 static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManager* iface,REFIID riid,void** ppvObject)
312 {
313     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
314
315     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
316
317     /* Perform a sanity check on the parameters.*/
318     if ( (This==0) || (ppvObject==0) )
319         return E_INVALIDARG;
320
321     /* Initialize the return parameter */
322     *ppvObject = 0;
323
324     /* Compare the riid with the interface IDs implemented by this object.*/
325     if (IsEqualIID(&IID_IUnknown, riid) ||
326         IsEqualIID(&IID_IInternetSecurityManager, riid))
327         *ppvObject = iface;
328
329     /* Check that we obtained an interface.*/
330     if (!*ppvObject) {
331         WARN("not supported interface %s\n", debugstr_guid(riid));
332         return E_NOINTERFACE;
333     }
334
335     /* Query Interface always increases the reference count by one when it is successful */
336     IInternetSecurityManager_AddRef(iface);
337
338     return S_OK;
339 }
340
341 static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManager* iface)
342 {
343     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
344     ULONG refCount = InterlockedIncrement(&This->ref);
345
346     TRACE("(%p) ref=%u\n", This, refCount);
347
348     return refCount;
349 }
350
351 static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManager* iface)
352 {
353     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
354     ULONG refCount = InterlockedDecrement(&This->ref);
355
356     TRACE("(%p) ref=%u\n", This, refCount);
357
358     /* destroy the object if there's no more reference on it */
359     if (!refCount){
360         if(This->mgrsite)
361             IInternetSecurityMgrSite_Release(This->mgrsite);
362         if(This->custom_manager)
363             IInternetSecurityManager_Release(This->custom_manager);
364
365         heap_free(This);
366
367         URLMON_UnlockModule();
368     }
369
370     return refCount;
371 }
372
373 static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManager *iface,
374                                                      IInternetSecurityMgrSite *pSite)
375 {
376     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
377
378     TRACE("(%p)->(%p)\n", This, pSite);
379
380     if(This->mgrsite)
381         IInternetSecurityMgrSite_Release(This->mgrsite);
382
383     if(This->custom_manager) {
384         IInternetSecurityManager_Release(This->custom_manager);
385         This->custom_manager = NULL;
386     }
387
388     This->mgrsite = pSite;
389
390     if(pSite) {
391         IServiceProvider *servprov;
392         HRESULT hres;
393
394         IInternetSecurityMgrSite_AddRef(pSite);
395
396         hres = IInternetSecurityMgrSite_QueryInterface(pSite, &IID_IServiceProvider,
397                 (void**)&servprov);
398         if(SUCCEEDED(hres)) {
399             IServiceProvider_QueryService(servprov, &SID_SInternetSecurityManager,
400                     &IID_IInternetSecurityManager, (void**)&This->custom_manager);
401             IServiceProvider_Release(servprov);
402         }
403     }
404
405     return S_OK;
406 }
407
408 static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManager *iface,
409                                                      IInternetSecurityMgrSite **ppSite)
410 {
411     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
412
413     TRACE("(%p)->(%p)\n", This, ppSite);
414
415     if(!ppSite)
416         return E_INVALIDARG;
417
418     if(This->mgrsite)
419         IInternetSecurityMgrSite_AddRef(This->mgrsite);
420
421     *ppSite = This->mgrsite;
422     return S_OK;
423 }
424
425 static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *iface,
426                                                   LPCWSTR pwszUrl, DWORD *pdwZone,
427                                                   DWORD dwFlags)
428 {
429     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
430     HRESULT hres;
431
432     TRACE("(%p)->(%s %p %08x)\n", iface, debugstr_w(pwszUrl), pdwZone, dwFlags);
433
434     if(This->custom_manager) {
435         hres = IInternetSecurityManager_MapUrlToZone(This->custom_manager,
436                 pwszUrl, pdwZone, dwFlags);
437         if(hres != INET_E_DEFAULT_ACTION)
438             return hres;
439     }
440
441     if(!pwszUrl) {
442         *pdwZone = -1;
443         return E_INVALIDARG;
444     }
445
446     if(dwFlags)
447         FIXME("not supported flags: %08x\n", dwFlags);
448
449     return map_url_to_zone(pwszUrl, pdwZone, NULL);
450 }
451
452 static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *iface, 
453         LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
454 {
455     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
456     LPWSTR url, ptr, ptr2;
457     DWORD zone, len;
458     HRESULT hres;
459
460     static const WCHAR wszFile[] = {'f','i','l','e',':'};
461
462     TRACE("(%p)->(%s %p %p %08lx)\n", iface, debugstr_w(pwszUrl), pbSecurityId,
463           pcbSecurityId, dwReserved);
464
465     if(This->custom_manager) {
466         hres = IInternetSecurityManager_GetSecurityId(This->custom_manager,
467                 pwszUrl, pbSecurityId, pcbSecurityId, dwReserved);
468         if(hres != INET_E_DEFAULT_ACTION)
469             return hres;
470     }
471
472     if(!pwszUrl || !pbSecurityId || !pcbSecurityId)
473         return E_INVALIDARG;
474
475     if(dwReserved)
476         FIXME("dwReserved is not supported\n");
477
478     hres = map_url_to_zone(pwszUrl, &zone, &url);
479     if(FAILED(hres))
480         return hres == 0x80041001 ? E_INVALIDARG : hres;
481
482     /* file protocol is a special case */
483     if(strlenW(url) >= sizeof(wszFile)/sizeof(WCHAR)
484             && !memcmp(url, wszFile, sizeof(wszFile)) && strchrW(url, '\\')) {
485
486         static const BYTE secidFile[] = {'f','i','l','e',':'};
487
488         heap_free(url);
489
490         if(*pcbSecurityId < sizeof(secidFile)+sizeof(zone))
491             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
492
493         memcpy(pbSecurityId, secidFile, sizeof(secidFile));
494         *(DWORD*)(pbSecurityId+sizeof(secidFile)) = zone;
495
496         *pcbSecurityId = sizeof(secidFile)+sizeof(zone);
497         return S_OK;
498     }
499
500     ptr = strchrW(url, ':');
501     ptr2 = ++ptr;
502     while(*ptr2 == '/')
503         ptr2++;
504     if(ptr2 != ptr)
505         memmove(ptr, ptr2, (strlenW(ptr2)+1)*sizeof(WCHAR));
506
507     ptr = strchrW(ptr, '/');
508     if(ptr)
509         *ptr = 0;
510
511     len = WideCharToMultiByte(CP_ACP, 0, url, -1, NULL, 0, NULL, NULL)-1;
512
513     if(len+sizeof(DWORD) > *pcbSecurityId) {
514         heap_free(url);
515         return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
516     }
517
518     WideCharToMultiByte(CP_ACP, 0, url, -1, (LPSTR)pbSecurityId, len, NULL, NULL);
519     heap_free(url);
520
521     *(DWORD*)(pbSecurityId+len) = zone;
522
523     *pcbSecurityId = len+sizeof(DWORD);
524
525     return S_OK;
526 }
527
528
529 static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager *iface,
530                                                       LPCWSTR pwszUrl, DWORD dwAction,
531                                                       BYTE *pPolicy, DWORD cbPolicy,
532                                                       BYTE *pContext, DWORD cbContext,
533                                                       DWORD dwFlags, DWORD dwReserved)
534 {
535     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
536     DWORD zone, policy;
537     HRESULT hres;
538
539     TRACE("(%p)->(%s %08x %p %08x %p %08x %08x %08x)\n", iface, debugstr_w(pwszUrl), dwAction,
540           pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
541
542     if(This->custom_manager) {
543         hres = IInternetSecurityManager_ProcessUrlAction(This->custom_manager, pwszUrl, dwAction,
544                 pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
545         if(hres != INET_E_DEFAULT_ACTION)
546             return hres;
547     }
548
549     if(dwFlags || dwReserved)
550         FIXME("Unsupported arguments\n");
551
552     if(!pwszUrl)
553         return E_INVALIDARG;
554
555     hres = map_url_to_zone(pwszUrl, &zone, NULL);
556     if(FAILED(hres))
557         return hres;
558
559     hres = get_action_policy(zone, dwAction, (BYTE*)&policy, sizeof(policy), URLZONEREG_DEFAULT);
560     if(FAILED(hres))
561         return hres;
562
563     TRACE("policy %x\n", policy);
564     if(cbPolicy >= sizeof(DWORD))
565         *(DWORD*)pPolicy = policy;
566
567     switch(GetUrlPolicyPermissions(policy)) {
568     case URLPOLICY_ALLOW:
569     case URLPOLICY_CHANNEL_SOFTDIST_PRECACHE:
570         return S_OK;
571     case URLPOLICY_DISALLOW:
572         return S_FALSE;
573     case URLPOLICY_QUERY:
574         FIXME("URLPOLICY_QUERY not implemented\n");
575         return E_FAIL;
576     default:
577         FIXME("Not implemented policy %x\n", policy);
578     }
579
580     return E_FAIL;
581 }
582                                                
583
584 static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManager *iface,
585                                                        LPCWSTR pwszUrl, REFGUID guidKey,
586                                                        BYTE **ppPolicy, DWORD *pcbPolicy,
587                                                        BYTE *pContext, DWORD cbContext,
588                                                        DWORD dwReserved)
589 {
590     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
591     HRESULT hres;
592
593     TRACE("(%p)->(%s %s %p %p %p %08x %08x )\n", iface, debugstr_w(pwszUrl), debugstr_guid(guidKey),
594           ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
595
596     if(This->custom_manager) {
597         hres = IInternetSecurityManager_QueryCustomPolicy(This->custom_manager, pwszUrl, guidKey,
598                 ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
599         if(hres != INET_E_DEFAULT_ACTION)
600             return hres;
601     }
602
603     WARN("Unknown guidKey %s\n", debugstr_guid(guidKey));
604     return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
605 }
606
607 static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManager *iface,
608                                                     DWORD dwZone, LPCWSTR pwszPattern, DWORD dwFlags)
609 {
610     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
611     HRESULT hres;
612
613     TRACE("(%p)->(%08x %s %08x)\n", iface, dwZone, debugstr_w(pwszPattern),dwFlags);
614
615     if(This->custom_manager) {
616         hres = IInternetSecurityManager_SetZoneMapping(This->custom_manager, dwZone,
617                 pwszPattern, dwFlags);
618         if(hres != INET_E_DEFAULT_ACTION)
619             return hres;
620     }
621
622     FIXME("Default action is not implemented\n");
623     return E_NOTIMPL;
624 }
625
626 static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManager *iface,
627         DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
628 {
629     SecManagerImpl *This = impl_from_IInternetSecurityManager(iface);
630     HRESULT hres;
631
632     TRACE("(%p)->(%08x %p %08x)\n", iface, dwZone, ppenumString,dwFlags);
633
634     if(This->custom_manager) {
635         hres = IInternetSecurityManager_GetZoneMappings(This->custom_manager, dwZone,
636                 ppenumString, dwFlags);
637         if(hres != INET_E_DEFAULT_ACTION)
638             return hres;
639     }
640
641     FIXME("Default action is not implemented\n");
642     return E_NOTIMPL;
643 }
644
645 static const IInternetSecurityManagerVtbl VT_SecManagerImpl =
646 {
647     SecManagerImpl_QueryInterface,
648     SecManagerImpl_AddRef,
649     SecManagerImpl_Release,
650     SecManagerImpl_SetSecuritySite,
651     SecManagerImpl_GetSecuritySite,
652     SecManagerImpl_MapUrlToZone,
653     SecManagerImpl_GetSecurityId,
654     SecManagerImpl_ProcessUrlAction,
655     SecManagerImpl_QueryCustomPolicy,
656     SecManagerImpl_SetZoneMapping,
657     SecManagerImpl_GetZoneMappings
658 };
659
660 HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
661 {
662     SecManagerImpl *This;
663
664     TRACE("(%p,%p)\n",pUnkOuter,ppobj);
665     This = heap_alloc(sizeof(*This));
666
667     /* Initialize the virtual function table. */
668     This->IInternetSecurityManager_iface.lpVtbl = &VT_SecManagerImpl;
669
670     This->ref = 1;
671     This->mgrsite = NULL;
672     This->custom_manager = NULL;
673
674     *ppobj = This;
675
676     URLMON_LockModule();
677
678     return S_OK;
679 }
680
681 /***********************************************************************
682  *           InternetZoneManager implementation
683  *
684  */
685 typedef struct {
686     IInternetZoneManagerEx2 IInternetZoneManagerEx2_iface;
687     LONG ref;
688     LPDWORD *zonemaps;
689     DWORD zonemap_count;
690 } ZoneMgrImpl;
691
692 static inline ZoneMgrImpl *impl_from_IInternetZoneManagerEx2(IInternetZoneManagerEx2 *iface)
693 {
694     return CONTAINING_RECORD(iface, ZoneMgrImpl, IInternetZoneManagerEx2_iface);
695 }
696
697
698 /***********************************************************************
699  * build_zonemap_from_reg [internal]
700  *
701  * Enumerate the Zones in the Registry and return the Zones in a DWORD-array
702  * The number of the Zones is returned in data[0]
703  */
704 static LPDWORD build_zonemap_from_reg(void)
705 {
706     WCHAR name[32];
707     HKEY hkey;
708     LPDWORD data = NULL;
709     DWORD allocated = 6; /* space for the zonecount and Zone "0" up to Zone "4" */
710     DWORD used = 0;
711     DWORD res;
712     DWORD len;
713
714
715     res = RegOpenKeyW(HKEY_CURRENT_USER, wszZonesKey, &hkey);
716     if (res)
717         return NULL;
718
719     data = heap_alloc(allocated * sizeof(DWORD));
720     if (!data)
721         goto cleanup;
722
723     while (!res) {
724         name[0] = '\0';
725         len = sizeof(name) / sizeof(name[0]);
726         res = RegEnumKeyExW(hkey, used, name, &len, NULL, NULL, NULL, NULL);
727
728         if (!res) {
729             used++;
730             if (used == allocated) {
731                 LPDWORD new_data;
732
733                 allocated *= 2;
734                 new_data = heap_realloc_zero(data, allocated * sizeof(DWORD));
735                 if (!new_data)
736                     goto cleanup;
737
738                 data = new_data;
739             }
740             data[used] = atoiW(name);
741         }
742     }
743     if (used) {
744         RegCloseKey(hkey);
745         data[0] = used;
746         return data;
747     }
748
749 cleanup:
750     /* something failed */
751     RegCloseKey(hkey);
752     heap_free(data);
753     return NULL;
754 }
755
756 /********************************************************************
757  *      IInternetZoneManager_QueryInterface
758  */
759 static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManagerEx2* iface, REFIID riid, void** ppvObject)
760 {
761     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
762
763     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);
764
765     if(!This || !ppvObject)
766         return E_INVALIDARG;
767
768     if(IsEqualIID(&IID_IUnknown, riid)) {
769         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppvObject);
770     }else if(IsEqualIID(&IID_IInternetZoneManager, riid)) {
771         TRACE("(%p)->(IID_InternetZoneManager %p)\n", This, ppvObject);
772     }else if(IsEqualIID(&IID_IInternetZoneManagerEx, riid)) {
773         TRACE("(%p)->(IID_InternetZoneManagerEx %p)\n", This, ppvObject);
774     }else if(IsEqualIID(&IID_IInternetZoneManagerEx2, riid)) {
775         TRACE("(%p)->(IID_InternetZoneManagerEx2 %p)\n", This, ppvObject);
776     }
777     else
778     {
779         FIXME("Unknown interface: %s\n", debugstr_guid(riid));
780         *ppvObject = NULL;
781         return E_NOINTERFACE;
782     }
783
784     *ppvObject = iface;
785     IInternetZoneManager_AddRef(iface);
786     return S_OK;
787 }
788
789 /********************************************************************
790  *      IInternetZoneManager_AddRef
791  */
792 static ULONG WINAPI ZoneMgrImpl_AddRef(IInternetZoneManagerEx2* iface)
793 {
794     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
795     ULONG refCount = InterlockedIncrement(&This->ref);
796
797     TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
798
799     return refCount;
800 }
801
802 /********************************************************************
803  *      IInternetZoneManager_Release
804  */
805 static ULONG WINAPI ZoneMgrImpl_Release(IInternetZoneManagerEx2* iface)
806 {
807     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
808     ULONG refCount = InterlockedDecrement(&This->ref);
809
810     TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
811
812     if(!refCount) {
813         while (This->zonemap_count) heap_free(This->zonemaps[--This->zonemap_count]);
814         heap_free(This->zonemaps);
815         heap_free(This);
816         URLMON_UnlockModule();
817     }
818     
819     return refCount;
820 }
821
822 /********************************************************************
823  *      IInternetZoneManager_GetZoneAttributes
824  */
825 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributes(IInternetZoneManagerEx2* iface,
826                                                     DWORD dwZone,
827                                                     ZONEATTRIBUTES* pZoneAttributes)
828 {
829     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
830     HRESULT hr;
831     HKEY hcu;
832     HKEY hklm = NULL;
833
834     TRACE("(%p)->(%d %p)\n", This, dwZone, pZoneAttributes);
835
836     if (!pZoneAttributes)
837         return E_INVALIDARG;
838
839     hr = open_zone_key(HKEY_CURRENT_USER, dwZone, &hcu);
840     if (FAILED(hr))
841         return S_OK;  /* IE6 and older returned E_FAIL here */
842
843     hr = open_zone_key(HKEY_LOCAL_MACHINE, dwZone, &hklm);
844     if (FAILED(hr))
845         TRACE("Zone %d not in HKLM\n", dwZone);
846
847     get_string_from_reg(hcu, hklm, displaynameW, pZoneAttributes->szDisplayName, MAX_ZONE_PATH);
848     get_string_from_reg(hcu, hklm, descriptionW, pZoneAttributes->szDescription, MAX_ZONE_DESCRIPTION);
849     get_string_from_reg(hcu, hklm, iconW, pZoneAttributes->szIconPath, MAX_ZONE_PATH);
850     get_dword_from_reg(hcu, hklm, minlevelW, &pZoneAttributes->dwTemplateMinLevel);
851     get_dword_from_reg(hcu, hklm, currentlevelW, &pZoneAttributes->dwTemplateCurrentLevel);
852     get_dword_from_reg(hcu, hklm, recommendedlevelW, &pZoneAttributes->dwTemplateRecommended);
853     get_dword_from_reg(hcu, hklm, flagsW, &pZoneAttributes->dwFlags);
854
855     RegCloseKey(hklm);
856     RegCloseKey(hcu);
857     return S_OK;
858 }
859
860 /********************************************************************
861  *      IInternetZoneManager_SetZoneAttributes
862  */
863 static HRESULT WINAPI ZoneMgrImpl_SetZoneAttributes(IInternetZoneManagerEx2* iface,
864                                                     DWORD dwZone,
865                                                     ZONEATTRIBUTES* pZoneAttributes)
866 {
867     FIXME("(%p)->(%08x %p) stub\n", iface, dwZone, pZoneAttributes);
868     return E_NOTIMPL;
869 }
870
871 /********************************************************************
872  *      IInternetZoneManager_GetZoneCustomPolicy
873  */
874 static HRESULT WINAPI ZoneMgrImpl_GetZoneCustomPolicy(IInternetZoneManagerEx2* iface,
875                                                       DWORD dwZone,
876                                                       REFGUID guidKey,
877                                                       BYTE** ppPolicy,
878                                                       DWORD* pcbPolicy,
879                                                       URLZONEREG ulrZoneReg)
880 {
881     FIXME("(%p)->(%08x %s %p %p %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
882                                                     ppPolicy, pcbPolicy, ulrZoneReg);
883     return E_NOTIMPL;
884 }
885
886 /********************************************************************
887  *      IInternetZoneManager_SetZoneCustomPolicy
888  */
889 static HRESULT WINAPI ZoneMgrImpl_SetZoneCustomPolicy(IInternetZoneManagerEx2* iface,
890                                                       DWORD dwZone,
891                                                       REFGUID guidKey,
892                                                       BYTE* ppPolicy,
893                                                       DWORD cbPolicy,
894                                                       URLZONEREG ulrZoneReg)
895 {
896     FIXME("(%p)->(%08x %s %p %08x %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
897                                                     ppPolicy, cbPolicy, ulrZoneReg);
898     return E_NOTIMPL;
899 }
900
901 /********************************************************************
902  *      IInternetZoneManager_GetZoneActionPolicy
903  */
904 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicy(IInternetZoneManagerEx2* iface,
905         DWORD dwZone, DWORD dwAction, BYTE* pPolicy, DWORD cbPolicy, URLZONEREG urlZoneReg)
906 {
907     TRACE("(%p)->(%d %08x %p %d %d)\n", iface, dwZone, dwAction, pPolicy,
908             cbPolicy, urlZoneReg);
909
910     if(!pPolicy)
911         return E_INVALIDARG;
912
913     return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg);
914 }
915
916 /********************************************************************
917  *      IInternetZoneManager_SetZoneActionPolicy
918  */
919 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicy(IInternetZoneManagerEx2* iface,
920                                                       DWORD dwZone,
921                                                       DWORD dwAction,
922                                                       BYTE* pPolicy,
923                                                       DWORD cbPolicy,
924                                                       URLZONEREG urlZoneReg)
925 {
926     FIXME("(%p)->(%08x %08x %p %08x %08x) stub\n", iface, dwZone, dwAction, pPolicy,
927                                                        cbPolicy, urlZoneReg);
928     return E_NOTIMPL;
929 }
930
931 /********************************************************************
932  *      IInternetZoneManager_PromptAction
933  */
934 static HRESULT WINAPI ZoneMgrImpl_PromptAction(IInternetZoneManagerEx2* iface,
935                                                DWORD dwAction,
936                                                HWND hwndParent,
937                                                LPCWSTR pwszUrl,
938                                                LPCWSTR pwszText,
939                                                DWORD dwPromptFlags)
940 {
941     FIXME("%p %08x %p %s %s %08x\n", iface, dwAction, hwndParent,
942           debugstr_w(pwszUrl), debugstr_w(pwszText), dwPromptFlags );
943     return E_NOTIMPL;
944 }
945
946 /********************************************************************
947  *      IInternetZoneManager_LogAction
948  */
949 static HRESULT WINAPI ZoneMgrImpl_LogAction(IInternetZoneManagerEx2* iface,
950                                             DWORD dwAction,
951                                             LPCWSTR pwszUrl,
952                                             LPCWSTR pwszText,
953                                             DWORD dwLogFlags)
954 {
955     FIXME("(%p)->(%08x %s %s %08x) stub\n", iface, dwAction, debugstr_w(pwszUrl),
956                                               debugstr_w(pwszText), dwLogFlags);
957     return E_NOTIMPL;
958 }
959
960 /********************************************************************
961  *      IInternetZoneManager_CreateZoneEnumerator
962  */
963 static HRESULT WINAPI ZoneMgrImpl_CreateZoneEnumerator(IInternetZoneManagerEx2* iface,
964                                                        DWORD* pdwEnum,
965                                                        DWORD* pdwCount,
966                                                        DWORD dwFlags)
967 {
968     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
969     LPDWORD * new_maps;
970     LPDWORD data;
971     DWORD i;
972
973     TRACE("(%p)->(%p, %p, 0x%08x)\n", This, pdwEnum, pdwCount, dwFlags);
974     if (!pdwEnum || !pdwCount || (dwFlags != 0))
975         return E_INVALIDARG;
976
977     data = build_zonemap_from_reg();
978     TRACE("found %d zones\n", data ? data[0] : -1);
979
980     if (!data)
981         return E_FAIL;
982
983     for (i = 0; i < This->zonemap_count; i++) {
984         if (This->zonemaps && !This->zonemaps[i]) {
985             This->zonemaps[i] = data;
986             *pdwEnum = i;
987             *pdwCount = data[0];
988             return S_OK;
989         }
990     }
991
992     if (This->zonemaps) {
993         /* try to double the nr. of pointers in the array */
994         new_maps = heap_realloc_zero(This->zonemaps, This->zonemap_count * 2 * sizeof(LPDWORD));
995         if (new_maps)
996             This->zonemap_count *= 2;
997     }
998     else
999     {
1000         This->zonemap_count = 2;
1001         new_maps = heap_alloc_zero(This->zonemap_count * sizeof(LPDWORD));
1002     }
1003
1004     if (!new_maps) {
1005         heap_free(data);
1006         return E_FAIL;
1007     }
1008     This->zonemaps = new_maps;
1009     This->zonemaps[i] = data;
1010     *pdwEnum = i;
1011     *pdwCount = data[0];
1012     return S_OK;
1013 }
1014
1015 /********************************************************************
1016  *      IInternetZoneManager_GetZoneAt
1017  */
1018 static HRESULT WINAPI ZoneMgrImpl_GetZoneAt(IInternetZoneManagerEx2* iface,
1019                                             DWORD dwEnum,
1020                                             DWORD dwIndex,
1021                                             DWORD* pdwZone)
1022 {
1023     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1024     LPDWORD data;
1025
1026     TRACE("(%p)->(0x%08x, %d, %p)\n", This, dwEnum, dwIndex, pdwZone);
1027
1028     /* make sure, that dwEnum and dwIndex are in the valid range */
1029     if (dwEnum < This->zonemap_count) {
1030         if ((data = This->zonemaps[dwEnum])) {
1031             if (dwIndex < data[0]) {
1032                 *pdwZone = data[dwIndex + 1];
1033                 return S_OK;
1034             }
1035         }
1036     }
1037     return E_INVALIDARG;
1038 }
1039
1040 /********************************************************************
1041  *      IInternetZoneManager_DestroyZoneEnumerator
1042  */
1043 static HRESULT WINAPI ZoneMgrImpl_DestroyZoneEnumerator(IInternetZoneManagerEx2* iface,
1044                                                         DWORD dwEnum)
1045 {
1046     ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
1047     LPDWORD data;
1048
1049     TRACE("(%p)->(0x%08x)\n", This, dwEnum);
1050     /* make sure, that dwEnum is valid */
1051     if (dwEnum < This->zonemap_count) {
1052         if ((data = This->zonemaps[dwEnum])) {
1053             This->zonemaps[dwEnum] = NULL;
1054             heap_free(data);
1055             return S_OK;
1056         }
1057     }
1058     return E_INVALIDARG;
1059 }
1060
1061 /********************************************************************
1062  *      IInternetZoneManager_CopyTemplatePoliciesToZone
1063  */
1064 static HRESULT WINAPI ZoneMgrImpl_CopyTemplatePoliciesToZone(IInternetZoneManagerEx2* iface,
1065                                                              DWORD dwTemplate,
1066                                                              DWORD dwZone,
1067                                                              DWORD dwReserved)
1068 {
1069     FIXME("(%p)->(%08x %08x %08x) stub\n", iface, dwTemplate, dwZone, dwReserved);
1070     return E_NOTIMPL;
1071 }
1072
1073 /********************************************************************
1074  *      IInternetZoneManagerEx_GetZoneActionPolicyEx
1075  */
1076 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicyEx(IInternetZoneManagerEx2* iface,
1077                                                         DWORD dwZone,
1078                                                         DWORD dwAction,
1079                                                         BYTE* pPolicy,
1080                                                         DWORD cbPolicy,
1081                                                         URLZONEREG urlZoneReg,
1082                                                         DWORD dwFlags)
1083 {
1084     TRACE("(%p)->(%d, 0x%x, %p, %d, %d, 0x%x)\n", iface, dwZone,
1085             dwAction, pPolicy, cbPolicy, urlZoneReg, dwFlags);
1086
1087     if(!pPolicy)
1088         return E_INVALIDARG;
1089
1090     if (dwFlags)
1091         FIXME("dwFlags 0x%x ignored\n", dwFlags);
1092
1093     return get_action_policy(dwZone, dwAction, pPolicy, cbPolicy, urlZoneReg);
1094 }
1095
1096 /********************************************************************
1097  *      IInternetZoneManagerEx_SetZoneActionPolicyEx
1098  */
1099 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicyEx(IInternetZoneManagerEx2* iface,
1100                                                         DWORD dwZone,
1101                                                         DWORD dwAction,
1102                                                         BYTE* pPolicy,
1103                                                         DWORD cbPolicy,
1104                                                         URLZONEREG urlZoneReg,
1105                                                         DWORD dwFlags)
1106 {
1107     FIXME("(%p)->(%d, 0x%x, %p, %d, %d, 0x%x) stub\n", iface, dwZone, dwAction, pPolicy,
1108                                                        cbPolicy, urlZoneReg, dwFlags);
1109     return E_NOTIMPL;
1110 }
1111
1112 /********************************************************************
1113  *      IInternetZoneManagerEx2_GetZoneAttributesEx
1114  */
1115 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributesEx(IInternetZoneManagerEx2* iface,
1116                                                       DWORD dwZone,
1117                                                       ZONEATTRIBUTES* pZoneAttributes,
1118                                                       DWORD dwFlags)
1119 {
1120     TRACE("(%p)->(%d, %p, 0x%x)\n", iface, dwZone, pZoneAttributes, dwFlags);
1121
1122     if (dwFlags)
1123         FIXME("dwFlags 0x%x ignored\n", dwFlags);
1124
1125     return IInternetZoneManager_GetZoneAttributes(iface, dwZone, pZoneAttributes);
1126 }
1127
1128
1129 /********************************************************************
1130  *      IInternetZoneManagerEx2_GetZoneSecurityState
1131  */
1132 static HRESULT WINAPI ZoneMgrImpl_GetZoneSecurityState(IInternetZoneManagerEx2* iface,
1133                                                        DWORD dwZoneIndex,
1134                                                        BOOL fRespectPolicy,
1135                                                        LPDWORD pdwState,
1136                                                        BOOL *pfPolicyEncountered)
1137 {
1138     FIXME("(%p)->(%d, %d, %p, %p) stub\n", iface, dwZoneIndex, fRespectPolicy,
1139                                            pdwState, pfPolicyEncountered);
1140
1141     *pdwState = SECURITY_IE_STATE_GREEN;
1142
1143     if (pfPolicyEncountered)
1144         *pfPolicyEncountered = FALSE;
1145
1146     return S_OK;
1147 }
1148
1149 /********************************************************************
1150  *      IInternetZoneManagerEx2_GetIESecurityState
1151  */
1152 static HRESULT WINAPI ZoneMgrImpl_GetIESecurityState(IInternetZoneManagerEx2* iface,
1153                                                      BOOL fRespectPolicy,
1154                                                      LPDWORD pdwState,
1155                                                      BOOL *pfPolicyEncountered,
1156                                                      BOOL fNoCache)
1157 {
1158     FIXME("(%p)->(%d, %p, %p, %d) stub\n", iface, fRespectPolicy, pdwState,
1159                                            pfPolicyEncountered, fNoCache);
1160
1161     *pdwState = SECURITY_IE_STATE_GREEN;
1162
1163     if (pfPolicyEncountered)
1164         *pfPolicyEncountered = FALSE;
1165
1166     return S_OK;
1167 }
1168
1169 /********************************************************************
1170  *      IInternetZoneManagerEx2_FixInsecureSettings
1171  */
1172 static HRESULT WINAPI ZoneMgrImpl_FixInsecureSettings(IInternetZoneManagerEx2* iface)
1173 {
1174     FIXME("(%p) stub\n", iface);
1175     return S_OK;
1176 }
1177
1178 /********************************************************************
1179  *      IInternetZoneManager_Construct
1180  */
1181 static const IInternetZoneManagerEx2Vtbl ZoneMgrImplVtbl = {
1182     ZoneMgrImpl_QueryInterface,
1183     ZoneMgrImpl_AddRef,
1184     ZoneMgrImpl_Release,
1185     /* IInternetZoneManager */
1186     ZoneMgrImpl_GetZoneAttributes,
1187     ZoneMgrImpl_SetZoneAttributes,
1188     ZoneMgrImpl_GetZoneCustomPolicy,
1189     ZoneMgrImpl_SetZoneCustomPolicy,
1190     ZoneMgrImpl_GetZoneActionPolicy,
1191     ZoneMgrImpl_SetZoneActionPolicy,
1192     ZoneMgrImpl_PromptAction,
1193     ZoneMgrImpl_LogAction,
1194     ZoneMgrImpl_CreateZoneEnumerator,
1195     ZoneMgrImpl_GetZoneAt,
1196     ZoneMgrImpl_DestroyZoneEnumerator,
1197     ZoneMgrImpl_CopyTemplatePoliciesToZone,
1198     /* IInternetZoneManagerEx */
1199     ZoneMgrImpl_GetZoneActionPolicyEx,
1200     ZoneMgrImpl_SetZoneActionPolicyEx,
1201     /* IInternetZoneManagerEx2 */
1202     ZoneMgrImpl_GetZoneAttributesEx,
1203     ZoneMgrImpl_GetZoneSecurityState,
1204     ZoneMgrImpl_GetIESecurityState,
1205     ZoneMgrImpl_FixInsecureSettings,
1206 };
1207
1208 HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
1209 {
1210     ZoneMgrImpl* ret = heap_alloc_zero(sizeof(ZoneMgrImpl));
1211
1212     TRACE("(%p %p)\n", pUnkOuter, ppobj);
1213     ret->IInternetZoneManagerEx2_iface.lpVtbl = &ZoneMgrImplVtbl;
1214     ret->ref = 1;
1215     *ppobj = (IInternetZoneManagerEx*)ret;
1216
1217     URLMON_LockModule();
1218
1219     return S_OK;
1220 }
1221
1222 /***********************************************************************
1223  *           CoInternetCreateSecurityManager (URLMON.@)
1224  *
1225  */
1226 HRESULT WINAPI CoInternetCreateSecurityManager( IServiceProvider *pSP,
1227     IInternetSecurityManager **ppSM, DWORD dwReserved )
1228 {
1229     TRACE("%p %p %d\n", pSP, ppSM, dwReserved );
1230
1231     if(pSP)
1232         FIXME("pSP not supported\n");
1233
1234     return SecManagerImpl_Construct(NULL, (void**) ppSM);
1235 }
1236
1237 /********************************************************************
1238  *      CoInternetCreateZoneManager (URLMON.@)
1239  */
1240 HRESULT WINAPI CoInternetCreateZoneManager(IServiceProvider* pSP, IInternetZoneManager** ppZM, DWORD dwReserved)
1241 {
1242     TRACE("(%p %p %x)\n", pSP, ppZM, dwReserved);
1243     return ZoneMgrImpl_Construct(NULL, (void**)ppZM);
1244 }
1245
1246 /********************************************************************
1247  *      CoInternetGetSecurityUrl (URLMON.@)
1248  */
1249 HRESULT WINAPI CoInternetGetSecurityUrl(LPCWSTR pwzUrl, LPWSTR *ppwzSecUrl, PSUACTION psuAction, DWORD dwReserved)
1250 {
1251     WCHAR buf1[INTERNET_MAX_URL_LENGTH], buf2[INTERNET_MAX_URL_LENGTH];
1252     LPWSTR url, domain;
1253     DWORD len;
1254     HRESULT hres;
1255
1256     TRACE("(%p,%p,%u,%u)\n", pwzUrl, ppwzSecUrl, psuAction, dwReserved);
1257
1258     url = buf1;
1259     domain = buf2;
1260     strcpyW(url, pwzUrl);
1261
1262     while(1) {
1263         hres = CoInternetParseUrl(url, PARSE_SECURITY_URL, 0, domain, INTERNET_MAX_URL_LENGTH, &len, 0);
1264         if(hres!=S_OK || !strcmpW(url, domain))
1265             break;
1266
1267         if(url == buf1) {
1268             url = buf2;
1269             domain = buf1;
1270         } else {
1271             url = buf1;
1272             domain = buf2;
1273         }
1274     }
1275
1276     if(psuAction==PSU_SECURITY_URL_ONLY) {
1277         len = lstrlenW(url)+1;
1278         *ppwzSecUrl = CoTaskMemAlloc(len*sizeof(WCHAR));
1279         if(!*ppwzSecUrl)
1280             return E_OUTOFMEMORY;
1281
1282         memcpy(*ppwzSecUrl, url, len*sizeof(WCHAR));
1283         return S_OK;
1284     }
1285
1286     hres = CoInternetParseUrl(url, PARSE_SECURITY_DOMAIN, 0, domain,
1287             INTERNET_MAX_URL_LENGTH, &len, 0);
1288     if(SUCCEEDED(hres)) {
1289         len++;
1290         *ppwzSecUrl = CoTaskMemAlloc(len*sizeof(WCHAR));
1291         if(!*ppwzSecUrl)
1292             return E_OUTOFMEMORY;
1293
1294         memcpy(*ppwzSecUrl, domain, len*sizeof(WCHAR));
1295         return S_OK;
1296     }
1297
1298     hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, domain,
1299             INTERNET_MAX_URL_LENGTH, &len, 0);
1300     if(hres == S_OK){
1301         const WCHAR fileW[] = {'f','i','l','e',0};
1302         if(!strcmpW(domain, fileW)){
1303             hres = CoInternetParseUrl(url, PARSE_ROOTDOCUMENT, 0, domain, INTERNET_MAX_URL_LENGTH, &len, 0);
1304         }else{
1305             domain[len] = ':';
1306             hres = CoInternetParseUrl(url, PARSE_DOMAIN, 0, domain+len+1,
1307                     INTERNET_MAX_URL_LENGTH-len-1, &len, 0);
1308             if(hres == S_OK) {
1309                 len = lstrlenW(domain)+1;
1310                 *ppwzSecUrl = CoTaskMemAlloc(len*sizeof(WCHAR));
1311                 if(!*ppwzSecUrl)
1312                     return E_OUTOFMEMORY;
1313
1314                 memcpy(*ppwzSecUrl, domain, len*sizeof(WCHAR));
1315                 return S_OK;
1316             }
1317         }
1318     }else
1319         return hres;
1320
1321     len = lstrlenW(url)+1;
1322     *ppwzSecUrl = CoTaskMemAlloc(len*sizeof(WCHAR));
1323     if(!*ppwzSecUrl)
1324         return E_OUTOFMEMORY;
1325
1326     memcpy(*ppwzSecUrl, url, len*sizeof(WCHAR));
1327     return S_OK;
1328 }