hlink: Added HlinkGetSpecialReference implementation.
[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         HeapFree(GetProcessHeap(), 0, buf);
322
323         if(*pcbSecurityId < sizeof(secidFile)+sizeof(zone))
324             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
325
326         memcpy(pbSecurityId, secidFile, sizeof(secidFile));
327         *(DWORD*)(pbSecurityId+sizeof(secidFile)) = zone;
328
329         *pcbSecurityId = sizeof(secidFile)+sizeof(zone);
330         return S_OK;
331     }
332
333     ptr = strchrW(buf, ':');
334     ptr2 = ++ptr;
335     while(*ptr2 == '/')
336         ptr2++;
337     if(ptr2 != ptr)
338         memmove(ptr, ptr2, (strlenW(ptr2)+1)*sizeof(WCHAR));
339
340     ptr = strchrW(ptr, '/');
341     if(ptr)
342         *ptr = 0;
343
344     len = WideCharToMultiByte(CP_ACP, 0, buf, -1, NULL, 0, NULL, NULL)-1;
345
346     if(len+sizeof(DWORD) > *pcbSecurityId) {
347         HeapFree(GetProcessHeap(), 0, buf);
348         return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
349     }
350
351     WideCharToMultiByte(CP_ACP, 0, buf, -1, (LPSTR)pbSecurityId, -1, NULL, NULL);
352     HeapFree(GetProcessHeap(), 0, buf);
353
354     *(DWORD*)(pbSecurityId+len) = zone;
355
356     *pcbSecurityId = len+sizeof(DWORD);
357
358     return S_OK;
359 }
360
361
362 static HRESULT WINAPI SecManagerImpl_ProcessUrlAction(IInternetSecurityManager *iface,
363                                                       LPCWSTR pwszUrl, DWORD dwAction,
364                                                       BYTE *pPolicy, DWORD cbPolicy,
365                                                       BYTE *pContext, DWORD cbContext,
366                                                       DWORD dwFlags, DWORD dwReserved)
367 {
368     SecManagerImpl *This = SECMGR_THIS(iface);
369     HRESULT hres;
370
371     TRACE("(%p)->(%s %08x %p %08x %p %08x %08x %08x)\n", iface, debugstr_w(pwszUrl), dwAction,
372           pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
373
374     if(This->custom_manager) {
375         hres = IInternetSecurityManager_ProcessUrlAction(This->custom_manager, pwszUrl, dwAction,
376                 pPolicy, cbPolicy, pContext, cbContext, dwFlags, dwReserved);
377         if(hres != INET_E_DEFAULT_ACTION)
378             return hres;
379     }
380
381     FIXME("Default action is not implemented\n");
382     return E_NOTIMPL;
383 }
384                                                
385
386 static HRESULT WINAPI SecManagerImpl_QueryCustomPolicy(IInternetSecurityManager *iface,
387                                                        LPCWSTR pwszUrl, REFGUID guidKey,
388                                                        BYTE **ppPolicy, DWORD *pcbPolicy,
389                                                        BYTE *pContext, DWORD cbContext,
390                                                        DWORD dwReserved)
391 {
392     SecManagerImpl *This = SECMGR_THIS(iface);
393     HRESULT hres;
394
395     TRACE("(%p)->(%s %s %p %p %p %08x %08x )\n", iface, debugstr_w(pwszUrl), debugstr_guid(guidKey),
396           ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
397
398     if(This->custom_manager) {
399         hres = IInternetSecurityManager_QueryCustomPolicy(This->custom_manager, pwszUrl, guidKey,
400                 ppPolicy, pcbPolicy, pContext, cbContext, dwReserved);
401         if(hres != INET_E_DEFAULT_ACTION)
402             return hres;
403     }
404
405     FIXME("Default action is not implemented\n");
406     return E_NOTIMPL;
407 }
408
409 static HRESULT WINAPI SecManagerImpl_SetZoneMapping(IInternetSecurityManager *iface,
410                                                     DWORD dwZone, LPCWSTR pwszPattern, DWORD dwFlags)
411 {
412     SecManagerImpl *This = SECMGR_THIS(iface);
413     HRESULT hres;
414
415     TRACE("(%p)->(%08x %s %08x)\n", iface, dwZone, debugstr_w(pwszPattern),dwFlags);
416
417     if(This->custom_manager) {
418         hres = IInternetSecurityManager_SetZoneMapping(This->custom_manager, dwZone,
419                 pwszPattern, dwFlags);
420         if(hres != INET_E_DEFAULT_ACTION)
421             return hres;
422     }
423
424     FIXME("Default action is not implemented\n");
425     return E_NOTIMPL;
426 }
427
428 static HRESULT WINAPI SecManagerImpl_GetZoneMappings(IInternetSecurityManager *iface,
429         DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
430 {
431     SecManagerImpl *This = SECMGR_THIS(iface);
432     HRESULT hres;
433
434     TRACE("(%p)->(%08x %p %08x)\n", iface, dwZone, ppenumString,dwFlags);
435
436     if(This->custom_manager) {
437         hres = IInternetSecurityManager_GetZoneMappings(This->custom_manager, dwZone,
438                 ppenumString, dwFlags);
439         if(hres != INET_E_DEFAULT_ACTION)
440             return hres;
441     }
442
443     FIXME("Default action is not implemented\n");
444     return E_NOTIMPL;
445 }
446
447 static const IInternetSecurityManagerVtbl VT_SecManagerImpl =
448 {
449     SecManagerImpl_QueryInterface,
450     SecManagerImpl_AddRef,
451     SecManagerImpl_Release,
452     SecManagerImpl_SetSecuritySite,
453     SecManagerImpl_GetSecuritySite,
454     SecManagerImpl_MapUrlToZone,
455     SecManagerImpl_GetSecurityId,
456     SecManagerImpl_ProcessUrlAction,
457     SecManagerImpl_QueryCustomPolicy,
458     SecManagerImpl_SetZoneMapping,
459     SecManagerImpl_GetZoneMappings
460 };
461
462 HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
463 {
464     SecManagerImpl *This;
465
466     TRACE("(%p,%p)\n",pUnkOuter,ppobj);
467     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
468
469     /* Initialize the virtual function table. */
470     This->lpInternetSecurityManagerVtbl = &VT_SecManagerImpl;
471
472     This->ref = 1;
473     This->mgrsite = NULL;
474     This->custom_manager = NULL;
475
476     *ppobj = This;
477
478     URLMON_LockModule();
479
480     return S_OK;
481 }
482
483 /***********************************************************************
484  *           InternetZoneManager implementation
485  *
486  */
487 typedef struct {
488     const IInternetZoneManagerVtbl* lpVtbl;
489     LONG ref;
490 } ZoneMgrImpl;
491
492 static HRESULT open_zone_key(DWORD zone, HKEY *hkey, URLZONEREG zone_reg)
493 {
494     static const WCHAR wszZonesKey[] =
495         {'S','o','f','t','w','a','r','e','\\',
496             'M','i','c','r','o','s','o','f','t','\\',
497             'W','i','n','d','o','w','s','\\',
498             'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
499             'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
500             'Z','o','n','e','s','\\',0};
501     static const WCHAR wszFormat[] = {'%','s','%','l','d',0};
502
503     WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+8];
504     HKEY parent_key;
505     DWORD res;
506
507     switch(zone_reg) {
508     case URLZONEREG_DEFAULT: /* FIXME: TEST */
509     case URLZONEREG_HKCU:
510         parent_key = HKEY_CURRENT_USER;
511         break;
512     case URLZONEREG_HKLM:
513         parent_key = HKEY_LOCAL_MACHINE;
514         break;
515     default:
516         WARN("Unknown URLZONEREG: %d\n", zone_reg);
517         return E_FAIL;
518     };
519
520     wsprintfW(key_name, wszFormat, wszZonesKey, zone);
521
522     res = RegOpenKeyW(parent_key, key_name, hkey);
523
524     if(res != ERROR_SUCCESS) {
525         WARN("RegOpenKey failed\n");
526         return E_INVALIDARG;
527     }
528
529     return S_OK;
530 }
531
532 /********************************************************************
533  *      IInternetZoneManager_QueryInterface
534  */
535 static HRESULT WINAPI ZoneMgrImpl_QueryInterface(IInternetZoneManager* iface, REFIID riid, void** ppvObject)
536 {
537     ZoneMgrImpl* This = (ZoneMgrImpl*)iface;
538
539     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppvObject);
540
541     if(!This || !ppvObject)
542         return E_INVALIDARG;
543
544     if(!IsEqualIID(&IID_IUnknown, riid) && !IsEqualIID(&IID_IInternetZoneManager, riid)) {
545         FIXME("Unknown interface: %s\n", debugstr_guid(riid));
546         *ppvObject = NULL;
547         return E_NOINTERFACE;
548     }
549
550     *ppvObject = iface;
551     IInternetZoneManager_AddRef(iface);
552
553     return S_OK;
554 }
555
556 /********************************************************************
557  *      IInternetZoneManager_AddRef
558  */
559 static ULONG WINAPI ZoneMgrImpl_AddRef(IInternetZoneManager* iface)
560 {
561     ZoneMgrImpl* This = (ZoneMgrImpl*)iface;
562     ULONG refCount = InterlockedIncrement(&This->ref);
563
564     TRACE("(%p)->(ref before=%u)\n",This, refCount - 1);
565
566     return refCount;
567 }
568
569 /********************************************************************
570  *      IInternetZoneManager_Release
571  */
572 static ULONG WINAPI ZoneMgrImpl_Release(IInternetZoneManager* iface)
573 {
574     ZoneMgrImpl* This = (ZoneMgrImpl*)iface;
575     ULONG refCount = InterlockedDecrement(&This->ref);
576
577     TRACE("(%p)->(ref before=%u)\n",This, refCount + 1);
578
579     if(!refCount) {
580         HeapFree(GetProcessHeap(), 0, This);
581         URLMON_UnlockModule();
582     }
583     
584     return refCount;
585 }
586
587 /********************************************************************
588  *      IInternetZoneManager_GetZoneAttributes
589  */
590 static HRESULT WINAPI ZoneMgrImpl_GetZoneAttributes(IInternetZoneManager* iface,
591                                                     DWORD dwZone,
592                                                     ZONEATTRIBUTES* pZoneAttributes)
593 {
594     FIXME("(%p)->(%d %p) stub\n", iface, dwZone, pZoneAttributes);
595     return E_NOTIMPL;
596 }
597
598 /********************************************************************
599  *      IInternetZoneManager_SetZoneAttributes
600  */
601 static HRESULT WINAPI ZoneMgrImpl_SetZoneAttributes(IInternetZoneManager* iface,
602                                                     DWORD dwZone,
603                                                     ZONEATTRIBUTES* pZoneAttributes)
604 {
605     FIXME("(%p)->(%08x %p) stub\n", iface, dwZone, pZoneAttributes);
606     return E_NOTIMPL;
607 }
608
609 /********************************************************************
610  *      IInternetZoneManager_GetZoneCustomPolicy
611  */
612 static HRESULT WINAPI ZoneMgrImpl_GetZoneCustomPolicy(IInternetZoneManager* iface,
613                                                       DWORD dwZone,
614                                                       REFGUID guidKey,
615                                                       BYTE** ppPolicy,
616                                                       DWORD* pcbPolicy,
617                                                       URLZONEREG ulrZoneReg)
618 {
619     FIXME("(%p)->(%08x %s %p %p %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
620                                                     ppPolicy, pcbPolicy, ulrZoneReg);
621     return E_NOTIMPL;
622 }
623
624 /********************************************************************
625  *      IInternetZoneManager_SetZoneCustomPolicy
626  */
627 static HRESULT WINAPI ZoneMgrImpl_SetZoneCustomPolicy(IInternetZoneManager* iface,
628                                                       DWORD dwZone,
629                                                       REFGUID guidKey,
630                                                       BYTE* ppPolicy,
631                                                       DWORD cbPolicy,
632                                                       URLZONEREG ulrZoneReg)
633 {
634     FIXME("(%p)->(%08x %s %p %08x %08x) stub\n", iface, dwZone, debugstr_guid(guidKey),
635                                                     ppPolicy, cbPolicy, ulrZoneReg);
636     return E_NOTIMPL;
637 }
638
639 /********************************************************************
640  *      IInternetZoneManager_GetZoneActionPolicy
641  */
642 static HRESULT WINAPI ZoneMgrImpl_GetZoneActionPolicy(IInternetZoneManager* iface,
643         DWORD dwZone, DWORD dwAction, BYTE* pPolicy, DWORD cbPolicy, URLZONEREG urlZoneReg)
644 {
645     WCHAR action[16];
646     HKEY hkey;
647     LONG res;
648     DWORD size = cbPolicy;
649     HRESULT hres;
650
651     static const WCHAR wszFormat[] = {'%','l','X',0};
652
653     TRACE("(%p)->(%d %08x %p %d %d)\n", iface, dwZone, dwAction, pPolicy,
654             cbPolicy, urlZoneReg);
655
656     if(!pPolicy)
657         return E_INVALIDARG;
658
659     hres = open_zone_key(dwZone, &hkey, urlZoneReg);
660     if(FAILED(hres))
661         return hres;
662
663     wsprintfW(action, wszFormat, dwAction);
664
665     res = RegQueryValueExW(hkey, action, NULL, NULL, pPolicy, &size);
666     if(res == ERROR_MORE_DATA) {
667         hres = E_INVALIDARG;
668     }else if(res == ERROR_FILE_NOT_FOUND) {
669         hres = E_FAIL;
670     }else if(res != ERROR_SUCCESS) {
671         ERR("RegQueryValue failed: %d\n", res);
672         hres = E_UNEXPECTED;
673     }
674
675     RegCloseKey(hkey);
676
677     return hres;
678 }
679
680 /********************************************************************
681  *      IInternetZoneManager_SetZoneActionPolicy
682  */
683 static HRESULT WINAPI ZoneMgrImpl_SetZoneActionPolicy(IInternetZoneManager* iface,
684                                                       DWORD dwZone,
685                                                       DWORD dwAction,
686                                                       BYTE* pPolicy,
687                                                       DWORD cbPolicy,
688                                                       URLZONEREG urlZoneReg)
689 {
690     FIXME("(%p)->(%08x %08x %p %08x %08x) stub\n", iface, dwZone, dwAction, pPolicy,
691                                                        cbPolicy, urlZoneReg);
692     return E_NOTIMPL;
693 }
694
695 /********************************************************************
696  *      IInternetZoneManager_PromptAction
697  */
698 static HRESULT WINAPI ZoneMgrImpl_PromptAction(IInternetZoneManager* iface,
699                                                DWORD dwAction,
700                                                HWND hwndParent,
701                                                LPCWSTR pwszUrl,
702                                                LPCWSTR pwszText,
703                                                DWORD dwPromptFlags)
704 {
705     FIXME("%p %08x %p %s %s %08x\n", iface, dwAction, hwndParent,
706           debugstr_w(pwszUrl), debugstr_w(pwszText), dwPromptFlags );
707     return E_NOTIMPL;
708 }
709
710 /********************************************************************
711  *      IInternetZoneManager_LogAction
712  */
713 static HRESULT WINAPI ZoneMgrImpl_LogAction(IInternetZoneManager* iface,
714                                             DWORD dwAction,
715                                             LPCWSTR pwszUrl,
716                                             LPCWSTR pwszText,
717                                             DWORD dwLogFlags)
718 {
719     FIXME("(%p)->(%08x %s %s %08x) stub\n", iface, dwAction, debugstr_w(pwszUrl),
720                                               debugstr_w(pwszText), dwLogFlags);
721     return E_NOTIMPL;
722 }
723
724 /********************************************************************
725  *      IInternetZoneManager_CreateZoneEnumerator
726  */
727 static HRESULT WINAPI ZoneMgrImpl_CreateZoneEnumerator(IInternetZoneManager* iface,
728                                                        DWORD* pdwEnum,
729                                                        DWORD* pdwCount,
730                                                        DWORD dwFlags)
731 {
732     FIXME("(%p)->(%p %p %08x) stub\n", iface, pdwEnum, pdwCount, dwFlags);
733     return E_NOTIMPL;
734 }
735
736 /********************************************************************
737  *      IInternetZoneManager_GetZoneAt
738  */
739 static HRESULT WINAPI ZoneMgrImpl_GetZoneAt(IInternetZoneManager* iface,
740                                             DWORD dwEnum,
741                                             DWORD dwIndex,
742                                             DWORD* pdwZone)
743 {
744     FIXME("(%p)->(%08x %08x %p) stub\n", iface, dwEnum, dwIndex, pdwZone);
745     return E_NOTIMPL;
746 }
747
748 /********************************************************************
749  *      IInternetZoneManager_DestroyZoneEnumerator
750  */
751 static HRESULT WINAPI ZoneMgrImpl_DestroyZoneEnumerator(IInternetZoneManager* iface,
752                                                         DWORD dwEnum)
753 {
754     FIXME("(%p)->(%08x) stub\n", iface, dwEnum);
755     return E_NOTIMPL;
756 }
757
758 /********************************************************************
759  *      IInternetZoneManager_CopyTemplatePoliciesToZone
760  */
761 static HRESULT WINAPI ZoneMgrImpl_CopyTemplatePoliciesToZone(IInternetZoneManager* iface,
762                                                              DWORD dwTemplate,
763                                                              DWORD dwZone,
764                                                              DWORD dwReserved)
765 {
766     FIXME("(%p)->(%08x %08x %08x) stub\n", iface, dwTemplate, dwZone, dwReserved);
767     return E_NOTIMPL;
768 }
769
770 /********************************************************************
771  *      IInternetZoneManager_Construct
772  */
773 static const IInternetZoneManagerVtbl ZoneMgrImplVtbl = {
774     ZoneMgrImpl_QueryInterface,
775     ZoneMgrImpl_AddRef,
776     ZoneMgrImpl_Release,
777     ZoneMgrImpl_GetZoneAttributes,
778     ZoneMgrImpl_SetZoneAttributes,
779     ZoneMgrImpl_GetZoneCustomPolicy,
780     ZoneMgrImpl_SetZoneCustomPolicy,
781     ZoneMgrImpl_GetZoneActionPolicy,
782     ZoneMgrImpl_SetZoneActionPolicy,
783     ZoneMgrImpl_PromptAction,
784     ZoneMgrImpl_LogAction,
785     ZoneMgrImpl_CreateZoneEnumerator,
786     ZoneMgrImpl_GetZoneAt,
787     ZoneMgrImpl_DestroyZoneEnumerator,
788     ZoneMgrImpl_CopyTemplatePoliciesToZone,
789 };
790
791 HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
792 {
793     ZoneMgrImpl* ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ZoneMgrImpl));
794
795     TRACE("(%p %p)\n", pUnkOuter, ppobj);
796     ret->lpVtbl = &ZoneMgrImplVtbl;
797     ret->ref = 1;
798     *ppobj = (IInternetZoneManager*)ret;
799
800     URLMON_LockModule();
801
802     return S_OK;
803 }
804
805 /***********************************************************************
806  *           CoInternetCreateSecurityManager (URLMON.@)
807  *
808  */
809 HRESULT WINAPI CoInternetCreateSecurityManager( IServiceProvider *pSP,
810     IInternetSecurityManager **ppSM, DWORD dwReserved )
811 {
812     TRACE("%p %p %d\n", pSP, ppSM, dwReserved );
813
814     if(pSP)
815         FIXME("pSP not supported\n");
816
817     return SecManagerImpl_Construct(NULL, (void**) ppSM);
818 }
819
820 /********************************************************************
821  *      CoInternetCreateZoneManager (URLMON.@)
822  */
823 HRESULT WINAPI CoInternetCreateZoneManager(IServiceProvider* pSP, IInternetZoneManager** ppZM, DWORD dwReserved)
824 {
825     TRACE("(%p %p %x)\n", pSP, ppZM, dwReserved);
826     return ZoneMgrImpl_Construct(NULL, (void**)ppZM);
827 }