urlmon: Fixed test on IE7.
[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  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24
25 #define COBJMACROS
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winreg.h"
31 #include "wine/debug.h"
32 #include "ole2.h"
33 #include "wine/unicode.h"
34 #include "urlmon.h"
35 #include "urlmon_main.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
38
39 /***********************************************************************
40  *           InternetSecurityManager implementation
41  *
42  */
43 typedef struct {
44     const IInternetSecurityManagerVtbl* lpInternetSecurityManagerVtbl;
45
46     LONG ref;
47
48     IInternetSecurityMgrSite *mgrsite;
49     IInternetSecurityManager *custom_manager;
50 } SecManagerImpl;
51
52 #define SECMGR_THIS(iface) DEFINE_THIS(SecManagerImpl, InternetSecurityManager, iface)
53
54 static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone)
55 {
56     WCHAR schema[64];
57     DWORD res, size=0;
58     HKEY hkey;
59     HRESULT hres;
60
61     static const WCHAR wszZoneMapProtocolKey[] =
62         {'S','o','f','t','w','a','r','e','\\',
63                     'M','i','c','r','o','s','o','f','t','\\',
64                     'W','i','n','d','o','w','s','\\',
65                     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
66                     'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
67                     'Z','o','n','e','M','a','p','\\',
68                     'P','r','o','t','o','c','o','l','D','e','f','a','u','l','t','s',0};
69     static const WCHAR wszFile[] = {'f','i','l','e',0};
70
71     *zone = -1;
72
73     hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(WCHAR), &size, 0);
74     if(FAILED(hres))
75         return hres;
76     if(!*schema)
77         return 0x80041001;
78
79     /* file protocol is a special case */
80     if(!strcmpW(schema, wszFile)) {
81         WCHAR path[MAX_PATH];
82
83         hres = CoInternetParseUrl(url, PARSE_PATH_FROM_URL, 0, path,
84                 sizeof(path)/sizeof(WCHAR), &size, 0);
85
86         if(SUCCEEDED(hres) && strchrW(path, '\\')) {
87             *zone = 0;
88             return S_OK;
89         }
90     }
91
92     WARN("domains are not yet implemented\n");
93
94     res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapProtocolKey, &hkey);
95     if(res != ERROR_SUCCESS) {
96         ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
97         return E_UNEXPECTED;
98     }
99
100     size = sizeof(DWORD);
101     res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
102     RegCloseKey(hkey);
103     if(res == ERROR_SUCCESS)
104         return S_OK;
105
106     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapProtocolKey, &hkey);
107     if(res != ERROR_SUCCESS) {
108         ERR("Could not open key %s\n", debugstr_w(wszZoneMapProtocolKey));
109         return E_UNEXPECTED;
110     }
111
112     size = sizeof(DWORD);
113     res = RegQueryValueExW(hkey, schema, NULL, NULL, (PBYTE)zone, &size);
114     RegCloseKey(hkey);
115     if(res == ERROR_SUCCESS)
116         return S_OK;
117
118     *zone = 3;
119     return S_OK;
120 }
121
122 static HRESULT WINAPI SecManagerImpl_QueryInterface(IInternetSecurityManager* iface,REFIID riid,void** ppvObject)
123 {
124     SecManagerImpl *This = SECMGR_THIS(iface);
125
126     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
127
128     /* Perform a sanity check on the parameters.*/
129     if ( (This==0) || (ppvObject==0) )
130         return E_INVALIDARG;
131
132     /* Initialize the return parameter */
133     *ppvObject = 0;
134
135     /* Compare the riid with the interface IDs implemented by this object.*/
136     if (IsEqualIID(&IID_IUnknown, riid) ||
137         IsEqualIID(&IID_IInternetSecurityManager, riid))
138         *ppvObject = iface;
139
140     /* Check that we obtained an interface.*/
141     if (!*ppvObject) {
142         WARN("not supported interface %s\n", debugstr_guid(riid));
143         return E_NOINTERFACE;
144     }
145
146     /* Query Interface always increases the reference count by one when it is successful */
147     IInternetSecurityManager_AddRef(iface);
148
149     return S_OK;
150 }
151
152 static ULONG WINAPI SecManagerImpl_AddRef(IInternetSecurityManager* iface)
153 {
154     SecManagerImpl *This = SECMGR_THIS(iface);
155     ULONG refCount = InterlockedIncrement(&This->ref);
156
157     TRACE("(%p) ref=%u\n", This, refCount);
158
159     return refCount;
160 }
161
162 static ULONG WINAPI SecManagerImpl_Release(IInternetSecurityManager* iface)
163 {
164     SecManagerImpl *This = SECMGR_THIS(iface);
165     ULONG refCount = InterlockedDecrement(&This->ref);
166
167     TRACE("(%p) ref=%u\n", This, refCount);
168
169     /* destroy the object if there's no more reference on it */
170     if (!refCount){
171         if(This->mgrsite)
172             IInternetSecurityMgrSite_Release(This->mgrsite);
173         if(This->custom_manager)
174             IInternetSecurityManager_Release(This->custom_manager);
175
176         HeapFree(GetProcessHeap(),0,This);
177
178         URLMON_UnlockModule();
179     }
180
181     return refCount;
182 }
183
184 static HRESULT WINAPI SecManagerImpl_SetSecuritySite(IInternetSecurityManager *iface,
185                                                      IInternetSecurityMgrSite *pSite)
186 {
187     SecManagerImpl *This = SECMGR_THIS(iface);
188
189     TRACE("(%p)->(%p)\n", This, pSite);
190
191     if(This->mgrsite)
192         IInternetSecurityMgrSite_Release(This->mgrsite);
193
194     if(This->custom_manager) {
195         IInternetSecurityManager_Release(This->custom_manager);
196         This->custom_manager = NULL;
197     }
198
199     This->mgrsite = pSite;
200
201     if(pSite) {
202         IServiceProvider *servprov;
203         HRESULT hres;
204
205         IInternetSecurityMgrSite_AddRef(pSite);
206
207         hres = IInternetSecurityMgrSite_QueryInterface(pSite, &IID_IServiceProvider,
208                 (void**)&servprov);
209         if(SUCCEEDED(hres)) {
210             IServiceProvider_QueryService(servprov, &SID_SInternetSecurityManager,
211                     &IID_IInternetSecurityManager, (void**)&This->custom_manager);
212             IServiceProvider_Release(servprov);
213         }
214     }
215
216     return S_OK;
217 }
218
219 static HRESULT WINAPI SecManagerImpl_GetSecuritySite(IInternetSecurityManager *iface,
220                                                      IInternetSecurityMgrSite **ppSite)
221 {
222     SecManagerImpl *This = SECMGR_THIS(iface);
223
224     TRACE("(%p)->(%p)\n", This, ppSite);
225
226     if(!ppSite)
227         return E_INVALIDARG;
228
229     if(This->mgrsite)
230         IInternetSecurityMgrSite_AddRef(This->mgrsite);
231
232     *ppSite = This->mgrsite;
233     return S_OK;
234 }
235
236 static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *iface,
237                                                   LPCWSTR pwszUrl, DWORD *pdwZone,
238                                                   DWORD dwFlags)
239 {
240     SecManagerImpl *This = SECMGR_THIS(iface);
241     LPWSTR url;
242     DWORD size;
243     HRESULT hres;
244
245     TRACE("(%p)->(%s %p %08x)\n", iface, debugstr_w(pwszUrl), pdwZone, dwFlags);
246
247     if(This->custom_manager) {
248         hres = IInternetSecurityManager_MapUrlToZone(This->custom_manager,
249                 pwszUrl, pdwZone, dwFlags);
250         if(hres != INET_E_DEFAULT_ACTION)
251             return hres;
252     }
253
254     if(!pwszUrl) {
255         *pdwZone = -1;
256         return E_INVALIDARG;
257     }
258
259     if(dwFlags)
260         FIXME("not supported flags: %08x\n", dwFlags);
261
262     size = (strlenW(pwszUrl)+16) * sizeof(WCHAR);
263     url = HeapAlloc(GetProcessHeap(), 0, size);
264
265     hres = CoInternetParseUrl(pwszUrl, PARSE_SECURITY_URL, 0, url, size/sizeof(WCHAR), &size, 0);
266     if(FAILED(hres))
267         memcpy(url, pwszUrl, size);
268
269     hres = map_url_to_zone(url, pdwZone);
270
271     HeapFree(GetProcessHeap(), 0, url);
272
273     return hres;
274 }
275
276 static HRESULT WINAPI SecManagerImpl_GetSecurityId(IInternetSecurityManager *iface, 
277         LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
278 {
279     SecManagerImpl *This = SECMGR_THIS(iface);
280     LPWSTR buf, ptr, ptr2;
281     DWORD size, zone, len;
282     HRESULT hres;
283
284     static const WCHAR wszFile[] = {'f','i','l','e',':'};
285
286     TRACE("(%p)->(%s %p %p %08lx)\n", iface, debugstr_w(pwszUrl), pbSecurityId,
287           pcbSecurityId, dwReserved);
288
289     if(This->custom_manager) {
290         hres = IInternetSecurityManager_GetSecurityId(This->custom_manager,
291                 pwszUrl, pbSecurityId, pcbSecurityId, dwReserved);
292         if(hres != INET_E_DEFAULT_ACTION)
293             return hres;
294     }
295
296     if(!pwszUrl || !pbSecurityId || !pcbSecurityId)
297         return E_INVALIDARG;
298
299     if(dwReserved)
300         FIXME("dwReserved is not supported\n");
301
302     len = strlenW(pwszUrl)+1;
303     buf = HeapAlloc(GetProcessHeap(), 0, (len+16)*sizeof(WCHAR));
304
305     hres = CoInternetParseUrl(pwszUrl, PARSE_SECURITY_URL, 0, buf, len, &size, 0);
306     if(FAILED(hres))
307         memcpy(buf, pwszUrl, len*sizeof(WCHAR));
308
309     hres = map_url_to_zone(buf, &zone);
310     if(FAILED(hres)) {
311         HeapFree(GetProcessHeap(), 0, buf);
312         return hres == 0x80041001 ? E_INVALIDARG : hres;
313     }
314
315     /* file protocol is a special case */
316     if(strlenW(pwszUrl) >= sizeof(wszFile)/sizeof(WCHAR)
317             && !memcmp(buf, wszFile, sizeof(wszFile))) {
318
319         static const BYTE secidFile[] = {'f','i','l','e',':'};
320
321         if(*pcbSecurityId < sizeof(secidFile)+sizeof(zone))
322             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
323
324         memcpy(pbSecurityId, secidFile, sizeof(secidFile));
325         *(DWORD*)(pbSecurityId+sizeof(secidFile)) = zone;
326
327         *pcbSecurityId = sizeof(secidFile)+sizeof(zone);
328         return S_OK;
329     }
330
331     ptr = strchrW(buf, ':');
332     ptr2 = ++ptr;
333     while(*ptr2 == '/')
334         ptr2++;
335     if(ptr2 != ptr)
336         memmove(ptr, ptr2, (strlenW(ptr2)+1)*sizeof(WCHAR));
337
338     ptr = strchrW(ptr, '/');
339     if(ptr)
340         *ptr = 0;
341
342     len = WideCharToMultiByte(CP_ACP, 0, buf, -1, NULL, 0, NULL, NULL)-1;
343
344     if(len+sizeof(DWORD) > *pcbSecurityId)
345         return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
346
347     WideCharToMultiByte(CP_ACP, 0, buf, -1, (LPSTR)pbSecurityId, -1, NULL, NULL);
348     HeapFree(GetProcessHeap(), 0, buf);
349
350     *(DWORD*)(pbSecurityId+len) = zone;
351
352     *pcbSecurityId = len+sizeof(DWORD);
353
354     return S_OK;
355 }
356
357
358 static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager *iface,
359                                                       LPCWSTR pwszUrl, DWORD dwAction,
360                                                       BYTE *pPolicy, DWORD cbPolicy,
361                                                       BYTE *pContext, DWORD cbContext,
362                                                       DWORD dwFlags, DWORD dwReserved)
363 {
364     SecManagerImpl *This = SECMGR_THIS(iface);
365     HRESULT hres;
366
367     TRACE("(%p)->(%s %08x %p %08x %p %08x %08x %08x)\n", iface, debugstr_w(pwszUrl), dwAction,
368           pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
369
370     if(This->custom_manager) {
371         hres = IInternetSecurityManager_ProcessUrlAction(This->custom_manager, pwszUrl, dwAction,
372                 pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
373         if(hres != INET_E_DEFAULT_ACTION)
374             return hres;
375     }
376
377     FIXME("Default action is not implemented\n");
378     return E_NOTIMPL;
379 }
380                                                
381
382 static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManager *iface,
383                                                        LPCWSTR pwszUrl, REFGUID guidKey,
384                                                        BYTE **ppPolicy, DWORD *pcbPolicy,
385                                                        BYTE *pContext, DWORD cbContext,
386                                                        DWORD dwReserved)
387 {
388     SecManagerImpl *This = SECMGR_THIS(iface);
389     HRESULT hres;
390
391     TRACE("(%p)->(%s %s %p %p %p %08x %08x )\n", iface, debugstr_w(pwszUrl), debugstr_guid(guidKey),
392           ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
393
394     if(This->custom_manager) {
395         hres = IInternetSecurityManager_QueryCustomPolicy(This->custom_manager, pwszUrl, guidKey,
396                 ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
397         if(hres != INET_E_DEFAULT_ACTION)
398             return hres;
399     }
400
401     FIXME("Default action is not implemented\n");
402     return E_NOTIMPL;
403 }
404
405 static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManager *iface,
406                                                     DWORD dwZone, LPCWSTR pwszPattern, DWORD dwFlags)
407 {
408     SecManagerImpl *This = SECMGR_THIS(iface);
409     HRESULT hres;
410
411     TRACE("(%p)->(%08x %s %08x)\n", iface, dwZone, debugstr_w(pwszPattern),dwFlags);
412
413     if(This->custom_manager) {
414         hres = IInternetSecurityManager_SetZoneMapping(This->custom_manager, dwZone,
415                 pwszPattern, dwFlags);
416         if(hres != INET_E_DEFAULT_ACTION)
417             return hres;
418     }
419
420     FIXME("Default action is not implemented\n");
421     return E_NOTIMPL;
422 }
423
424 static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManager *iface,
425         DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
426 {
427     SecManagerImpl *This = SECMGR_THIS(iface);
428     HRESULT hres;
429
430     TRACE("(%p)->(%08x %p %08x)\n", iface, dwZone, ppenumString,dwFlags);
431
432     if(This->custom_manager) {
433         hres = IInternetSecurityManager_GetZoneMappings(This->custom_manager, dwZone,
434                 ppenumString, dwFlags);
435         if(hres != INET_E_DEFAULT_ACTION)
436             return hres;
437     }
438
439     FIXME("Default action is not implemented\n");
440     return E_NOTIMPL;
441 }
442
443 static const IInternetSecurityManagerVtbl VT_SecManagerImpl =
444 {
445     SecManagerImpl_QueryInterface,
446     SecManagerImpl_AddRef,
447     SecManagerImpl_Release,
448     SecManagerImpl_SetSecuritySite,
449     SecManagerImpl_GetSecuritySite,
450     SecManagerImpl_MapUrlToZone,
451     SecManagerImpl_GetSecurityId,
452     SecManagerImpl_ProcessUrlAction,
453     SecManagerImpl_QueryCustomPolicy,
454     SecManagerImpl_SetZoneMapping,
455     SecManagerImpl_GetZoneMappings
456 };
457
458 HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
459 {
460     SecManagerImpl *This;
461
462     TRACE("(%p,%p)\n",pUnkOuter,ppobj);
463     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
464
465     /* Initialize the virtual function table. */
466     This->lpInternetSecurityManagerVtbl = &VT_SecManagerImpl;
467
468     This->ref = 1;
469     This->mgrsite = NULL;
470     This->custom_manager = NULL;
471
472     *ppobj = This;
473
474     URLMON_LockModule();
475
476     return S_OK;
477 }
478
479 /***********************************************************************
480  *           InternetZoneManager implementation
481  *
482  */
483 typedef struct {
484     const IInternetZoneManagerVtbl* lpVtbl;
485     LONG ref;
486 } ZoneMgrImpl;
487
488 static HRESULT open_zone_key(DWORD zone, HKEY *hkey, URLZONEREG zone_reg)
489 {
490     static const WCHAR wszZonesKey[] =
491         {'S','o','f','t','w','a','r','e','\\',
492             'M','i','c','r','o','s','o','f','t','\\',
493             'W','i','n','d','o','w','s','\\',
494             'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
495             'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
496             'Z','o','n','e','s','\\',0};
497     static const WCHAR wszFormat[] = {'%','s','%','l','d',0};
498
499     WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+8];
500     HKEY parent_key;
501     DWORD res;
502
503     switch(zone_reg) {
504     case URLZONEREG_DEFAULT: /* FIXME: TEST */
505     case URLZONEREG_HKCU:
506         parent_key = HKEY_CURRENT_USER;
507         break;
508     case URLZONEREG_HKLM:
509         parent_key = HKEY_LOCAL_MACHINE;
510         break;
511     default:
512         WARN("Unknown URLZONEREG: %d\n", zone_reg);
513         return E_FAIL;
514     };
515
516     wsprintfW(key_name, wszFormat, wszZonesKey, zone);
517
518     res = RegOpenKeyW(parent_key, key_name, hkey);
519
520     if(res != ERROR_SUCCESS) {
521         WARN("RegOpenKey failed\n");
522         return E_INVALIDARG;
523     }
524
525     return S_OK;
526 }
527
528 /********************************************************************
529  *      IInternetZoneManager_QueryInterface
530  */
531 static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManager* iface, REFIID riid, void** ppvObject)
532 {
533     ZoneMgrImpl* This = (ZoneMgrImpl*)iface;
534
535     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);
536
537     if(!This || !ppvObject)
538         return E_INVALIDARG;
539
540     if(!IsEqualIID(&IID_IUnknown, riid) && !IsEqualIID(&IID_IInternetZoneManager, riid)) {
541         FIXME("Unknown interface: %s\n", debugstr_guid(riid));
542         *ppvObject = NULL;
543         return E_NOINTERFACE;
544     }
545
546     *ppvObject = iface;
547     IInternetZoneManager_AddRef(iface);
548
549     return S_OK;
550 }
551
552 /********************************************************************
553  *      IInternetZoneManager_AddRef
554  */
555 static ULONG WINAPI ZoneMgrImpl_AddRef(IInternetZoneManager* iface)
556 {
557     ZoneMgrImpl* This = (ZoneMgrImpl*)iface;
558     ULONG refCount = InterlockedIncrement(&This->ref);
559
560     TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
561
562     return refCount;
563 }
564
565 /********************************************************************
566  *      IInternetZoneManager_Release
567  */
568 static ULONG WINAPI ZoneMgrImpl_Release(IInternetZoneManager* iface)
569 {
570     ZoneMgrImpl* This = (ZoneMgrImpl*)iface;
571     ULONG refCount = InterlockedDecrement(&This->ref);
572
573     TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
574
575     if(!refCount) {
576         HeapFree(GetProcessHeap(), 0, This);
577         URLMON_UnlockModule();
578     }
579     
580     return refCount;
581 }
582
583 /********************************************************************
584  *      IInternetZoneManager_GetZoneAttributes
585  */
586 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributes(IInternetZoneManager* iface,
587                                                     DWORD dwZone,
588                                                     ZONEATTRIBUTES* pZoneAttributes)
589 {
590     FIXME("(%p)->(%d %p) stub\n", iface, dwZone, pZoneAttributes);
591     return E_NOTIMPL;
592 }
593
594 /********************************************************************
595  *      IInternetZoneManager_SetZoneAttributes
596  */
597 static HRESULT WINAPI ZoneMgrImpl_SetZoneAttributes(IInternetZoneManager* iface,
598                                                     DWORD dwZone,
599                                                     ZONEATTRIBUTES* pZoneAttributes)
600 {
601     FIXME("(%p)->(%08x %p) stub\n", iface, dwZone, pZoneAttributes);
602     return E_NOTIMPL;
603 }
604
605 /********************************************************************
606  *      IInternetZoneManager_GetZoneCustomPolicy
607  */
608 static HRESULT WINAPI ZoneMgrImpl_GetZoneCustomPolicy(IInternetZoneManager* iface,
609                                                       DWORD dwZone,
610                                                       REFGUID guidKey,
611                                                       BYTE** ppPolicy,
612                                                       DWORD* pcbPolicy,
613                                                       URLZONEREG ulrZoneReg)
614 {
615     FIXME("(%p)->(%08x %s %p %p %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
616                                                     ppPolicy, pcbPolicy, ulrZoneReg);
617     return E_NOTIMPL;
618 }
619
620 /********************************************************************
621  *      IInternetZoneManager_SetZoneCustomPolicy
622  */
623 static HRESULT WINAPI ZoneMgrImpl_SetZoneCustomPolicy(IInternetZoneManager* iface,
624                                                       DWORD dwZone,
625                                                       REFGUID guidKey,
626                                                       BYTE* ppPolicy,
627                                                       DWORD cbPolicy,
628                                                       URLZONEREG ulrZoneReg)
629 {
630     FIXME("(%p)->(%08x %s %p %08x %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
631                                                     ppPolicy, cbPolicy, ulrZoneReg);
632     return E_NOTIMPL;
633 }
634
635 /********************************************************************
636  *      IInternetZoneManager_GetZoneActionPolicy
637  */
638 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicy(IInternetZoneManager* iface,
639         DWORD dwZone, DWORD dwAction, BYTE* pPolicy, DWORD cbPolicy, URLZONEREG urlZoneReg)
640 {
641     WCHAR action[16];
642     HKEY hkey;
643     LONG res;
644     DWORD size = cbPolicy;
645     HRESULT hres;
646
647     static const WCHAR wszFormat[] = {'%','l','X',0};
648
649     TRACE("(%p)->(%d %08x %p %d %d)\n", iface, dwZone, dwAction, pPolicy,
650             cbPolicy, urlZoneReg);
651
652     if(!pPolicy)
653         return E_INVALIDARG;
654
655     hres = open_zone_key(dwZone, &hkey, urlZoneReg);
656     if(FAILED(hres))
657         return hres;
658
659     wsprintfW(action, wszFormat, dwAction);
660
661     res = RegQueryValueExW(hkey, action, NULL, NULL, pPolicy, &size);
662     if(res == ERROR_MORE_DATA) {
663         hres = E_INVALIDARG;
664     }else if(res == ERROR_FILE_NOT_FOUND) {
665         hres = E_FAIL;
666     }else if(res != ERROR_SUCCESS) {
667         ERR("RegQueryValue failed: %d\n", res);
668         hres = E_UNEXPECTED;
669     }
670
671     RegCloseKey(hkey);
672
673     return hres;
674 }
675
676 /********************************************************************
677  *      IInternetZoneManager_SetZoneActionPolicy
678  */
679 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicy(IInternetZoneManager* iface,
680                                                       DWORD dwZone,
681                                                       DWORD dwAction,
682                                                       BYTE* pPolicy,
683                                                       DWORD cbPolicy,
684                                                       URLZONEREG urlZoneReg)
685 {
686     FIXME("(%p)->(%08x %08x %p %08x %08x) stub\n", iface, dwZone, dwAction, pPolicy,
687                                                        cbPolicy, urlZoneReg);
688     return E_NOTIMPL;
689 }
690
691 /********************************************************************
692  *      IInternetZoneManager_PromptAction
693  */
694 static HRESULT WINAPI ZoneMgrImpl_PromptAction(IInternetZoneManager* iface,
695                                                DWORD dwAction,
696                                                HWND hwndParent,
697                                                LPCWSTR pwszUrl,
698                                                LPCWSTR pwszText,
699                                                DWORD dwPromptFlags)
700 {
701     FIXME("%p %08x %p %s %s %08x\n", iface, dwAction, hwndParent,
702           debugstr_w(pwszUrl), debugstr_w(pwszText), dwPromptFlags );
703     return E_NOTIMPL;
704 }
705
706 /********************************************************************
707  *      IInternetZoneManager_LogAction
708  */
709 static HRESULT WINAPI ZoneMgrImpl_LogAction(IInternetZoneManager* iface,
710                                             DWORD dwAction,
711                                             LPCWSTR pwszUrl,
712                                             LPCWSTR pwszText,
713                                             DWORD dwLogFlags)
714 {
715     FIXME("(%p)->(%08x %s %s %08x) stub\n", iface, dwAction, debugstr_w(pwszUrl),
716                                               debugstr_w(pwszText), dwLogFlags);
717     return E_NOTIMPL;
718 }
719
720 /********************************************************************
721  *      IInternetZoneManager_CreateZoneEnumerator
722  */
723 static HRESULT WINAPI ZoneMgrImpl_CreateZoneEnumerator(IInternetZoneManager* iface,
724                                                        DWORD* pdwEnum,
725                                                        DWORD* pdwCount,
726                                                        DWORD dwFlags)
727 {
728     FIXME("(%p)->(%p %p %08x) stub\n", iface, pdwEnum, pdwCount, dwFlags);
729     return E_NOTIMPL;
730 }
731
732 /********************************************************************
733  *      IInternetZoneManager_GetZoneAt
734  */
735 static HRESULT WINAPI ZoneMgrImpl_GetZoneAt(IInternetZoneManager* iface,
736                                             DWORD dwEnum,
737                                             DWORD dwIndex,
738                                             DWORD* pdwZone)
739 {
740     FIXME("(%p)->(%08x %08x %p) stub\n", iface, dwEnum, dwIndex, pdwZone);
741     return E_NOTIMPL;
742 }
743
744 /********************************************************************
745  *      IInternetZoneManager_DestroyZoneEnumerator
746  */
747 static HRESULT WINAPI ZoneMgrImpl_DestroyZoneEnumerator(IInternetZoneManager* iface,
748                                                         DWORD dwEnum)
749 {
750     FIXME("(%p)->(%08x) stub\n", iface, dwEnum);
751     return E_NOTIMPL;
752 }
753
754 /********************************************************************
755  *      IInternetZoneManager_CopyTemplatePoliciesToZone
756  */
757 static HRESULT WINAPI ZoneMgrImpl_CopyTemplatePoliciesToZone(IInternetZoneManager* iface,
758                                                              DWORD dwTemplate,
759                                                              DWORD dwZone,
760                                                              DWORD dwReserved)
761 {
762     FIXME("(%p)->(%08x %08x %08x) stub\n", iface, dwTemplate, dwZone, dwReserved);
763     return E_NOTIMPL;
764 }
765
766 /********************************************************************
767  *      IInternetZoneManager_Construct
768  */
769 static const IInternetZoneManagerVtbl ZoneMgrImplVtbl = {
770     ZoneMgrImpl_QueryInterface,
771     ZoneMgrImpl_AddRef,
772     ZoneMgrImpl_Release,
773     ZoneMgrImpl_GetZoneAttributes,
774     ZoneMgrImpl_SetZoneAttributes,
775     ZoneMgrImpl_GetZoneCustomPolicy,
776     ZoneMgrImpl_SetZoneCustomPolicy,
777     ZoneMgrImpl_GetZoneActionPolicy,
778     ZoneMgrImpl_SetZoneActionPolicy,
779     ZoneMgrImpl_PromptAction,
780     ZoneMgrImpl_LogAction,
781     ZoneMgrImpl_CreateZoneEnumerator,
782     ZoneMgrImpl_GetZoneAt,
783     ZoneMgrImpl_DestroyZoneEnumerator,
784     ZoneMgrImpl_CopyTemplatePoliciesToZone,
785 };
786
787 HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
788 {
789     ZoneMgrImpl* ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ZoneMgrImpl));
790
791     TRACE("(%p %p)\n", pUnkOuter, ppobj);
792     ret->lpVtbl = &ZoneMgrImplVtbl;
793     ret->ref = 1;
794     *ppobj = (IInternetZoneManager*)ret;
795
796     URLMON_LockModule();
797
798     return S_OK;
799 }
800
801 /***********************************************************************
802  *           CoInternetCreateSecurityManager (URLMON.@)
803  *
804  */
805 HRESULT WINAPI CoInternetCreateSecurityManager( IServiceProvider *pSP,
806     IInternetSecurityManager **ppSM, DWORD dwReserved )
807 {
808     TRACE("%p %p %d\n", pSP, ppSM, dwReserved );
809
810     if(pSP)
811         FIXME("pSP not supported\n");
812
813     return SecManagerImpl_Construct(NULL, (void**) ppSM);
814 }
815
816 /********************************************************************
817  *      CoInternetCreateZoneManager (URLMON.@)
818  */
819 HRESULT WINAPI CoInternetCreateZoneManager(IServiceProvider* pSP, IInternetZoneManager** ppZM, DWORD dwReserved)
820 {
821     TRACE("(%p %p %x)\n", pSP, ppZM, dwReserved);
822     return ZoneMgrImpl_Construct(NULL, (void**)ppZM);
823 }