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