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