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