include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / urlmon / umon.c
blob0ee8502d070492a19ac875735cae5fc707a94730
1 /*
2 * UrlMon
4 * Copyright 1999 Ulrich Czekalla for Corel Corporation
5 * Copyright 2002 Huw D M Davies for CodeWeavers
6 * Copyright 2005 Jacek Caban for CodeWeavers
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.
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.
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
23 #include "urlmon_main.h"
25 #include "winreg.h"
26 #include "shlwapi.h"
27 #include "hlink.h"
28 #include "shellapi.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
34 typedef struct {
35 IMoniker IMoniker_iface;
36 IUriContainer IUriContainer_iface;
38 LONG ref;
40 IUri *uri;
41 BSTR URLName;
42 } URLMoniker;
44 static inline URLMoniker *impl_from_IMoniker(IMoniker *iface)
46 return CONTAINING_RECORD(iface, URLMoniker, IMoniker_iface);
49 static HRESULT WINAPI URLMoniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
51 URLMoniker *This = impl_from_IMoniker(iface);
53 if(!ppv)
54 return E_INVALIDARG;
56 if(IsEqualIID(&IID_IUnknown, riid)) {
57 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
58 *ppv = iface;
59 }else if(IsEqualIID(&IID_IPersist, riid)) {
60 TRACE("(%p)->(IID_IPersist %p)\n", This, ppv);
61 *ppv = iface;
62 }else if(IsEqualIID(&IID_IPersistStream,riid)) {
63 TRACE("(%p)->(IID_IPersistStream %p)\n", This, ppv);
64 *ppv = iface;
65 }else if(IsEqualIID(&IID_IMoniker, riid)) {
66 TRACE("(%p)->(IID_IMoniker %p)\n", This, ppv);
67 *ppv = iface;
68 }else if(IsEqualIID(&IID_IAsyncMoniker, riid)) {
69 TRACE("(%p)->(IID_IAsyncMoniker %p)\n", This, ppv);
70 *ppv = iface;
71 }else if(IsEqualIID(&IID_IUriContainer, riid)) {
72 TRACE("(%p)->(IID_IUriContainer %p)\n", This, ppv);
73 *ppv = &This->IUriContainer_iface;
74 }else {
75 WARN("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
76 *ppv = NULL;
77 return E_NOINTERFACE;
80 IUnknown_AddRef((IUnknown*)*ppv);
81 return S_OK;
84 static ULONG WINAPI URLMoniker_AddRef(IMoniker *iface)
86 URLMoniker *This = impl_from_IMoniker(iface);
87 ULONG refCount = InterlockedIncrement(&This->ref);
89 TRACE("(%p) ref=%lu\n",This, refCount);
91 return refCount;
94 static ULONG WINAPI URLMoniker_Release(IMoniker *iface)
96 URLMoniker *This = impl_from_IMoniker(iface);
97 ULONG refCount = InterlockedDecrement(&This->ref);
99 TRACE("(%p) ref=%lu\n",This, refCount);
101 if (!refCount) {
102 if(This->uri)
103 IUri_Release(This->uri);
104 SysFreeString(This->URLName);
105 free(This);
107 URLMON_UnlockModule();
110 return refCount;
113 static HRESULT WINAPI URLMoniker_GetClassID(IMoniker *iface, CLSID *pClassID)
115 URLMoniker *This = impl_from_IMoniker(iface);
117 TRACE("(%p,%p)\n", This, pClassID);
119 if(!pClassID)
120 return E_POINTER;
122 /* Windows always returns CLSID_StdURLMoniker */
123 *pClassID = CLSID_StdURLMoniker;
124 return S_OK;
127 static HRESULT WINAPI URLMoniker_IsDirty(IMoniker *iface)
129 URLMoniker *This = impl_from_IMoniker(iface);
131 TRACE("(%p)\n",This);
133 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
134 method in the OLE-provided moniker interfaces always return S_FALSE because
135 their internal state never changes. */
136 return S_FALSE;
139 static HRESULT WINAPI URLMoniker_Load(IMoniker* iface,IStream* pStm)
141 URLMoniker *This = impl_from_IMoniker(iface);
142 WCHAR *new_uri_str;
143 IUri *new_uri;
144 BSTR new_url;
145 ULONG size;
146 ULONG got;
147 HRESULT hres;
149 TRACE("(%p,%p)\n",This,pStm);
151 if(!pStm)
152 return E_INVALIDARG;
155 * NOTE
156 * Writes a ULONG containing length of unicode string, followed
157 * by that many unicode characters
159 hres = IStream_Read(pStm, &size, sizeof(ULONG), &got);
160 if(FAILED(hres))
161 return hres;
162 if(got != sizeof(ULONG))
163 return E_FAIL;
165 new_uri_str = malloc(size + sizeof(WCHAR));
166 if(!new_uri_str)
167 return E_OUTOFMEMORY;
169 hres = IStream_Read(pStm, new_uri_str, size, NULL);
170 new_uri_str[size/sizeof(WCHAR)] = 0;
171 if(SUCCEEDED(hres))
172 hres = CreateUri(new_uri_str, 0, 0, &new_uri);
173 free(new_uri_str);
174 if(FAILED(hres))
175 return hres;
177 hres = IUri_GetDisplayUri(new_uri, &new_url);
178 if(FAILED(hres)) {
179 IUri_Release(new_uri);
180 return hres;
183 SysFreeString(This->URLName);
184 if(This->uri)
185 IUri_Release(This->uri);
187 This->uri = new_uri;
188 This->URLName = new_url;
189 return S_OK;
192 static HRESULT WINAPI URLMoniker_Save(IMoniker *iface, IStream* pStm, BOOL fClearDirty)
194 URLMoniker *This = impl_from_IMoniker(iface);
195 HRESULT res;
196 ULONG size;
198 TRACE("(%p,%p,%d)\n", This, pStm, fClearDirty);
200 if(!pStm)
201 return E_INVALIDARG;
203 size = (SysStringLen(This->URLName) + 1)*sizeof(WCHAR);
204 res=IStream_Write(pStm,&size,sizeof(ULONG),NULL);
205 if(SUCCEEDED(res))
206 res=IStream_Write(pStm,This->URLName,size,NULL);
208 return res;
212 static HRESULT WINAPI URLMoniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER *pcbSize)
214 URLMoniker *This = impl_from_IMoniker(iface);
216 TRACE("(%p,%p)\n",This,pcbSize);
218 if(!pcbSize)
219 return E_INVALIDARG;
221 pcbSize->QuadPart = sizeof(ULONG) + ((SysStringLen(This->URLName)+1) * sizeof(WCHAR));
222 return S_OK;
225 static HRESULT WINAPI URLMoniker_BindToObject(IMoniker *iface, IBindCtx* pbc, IMoniker *pmkToLeft,
226 REFIID riid, void **ppv)
228 URLMoniker *This = impl_from_IMoniker(iface);
229 IRunningObjectTable *obj_tbl;
230 HRESULT hres;
232 TRACE("(%p)->(%p,%p,%s,%p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppv);
234 hres = IBindCtx_GetRunningObjectTable(pbc, &obj_tbl);
235 if(SUCCEEDED(hres)) {
236 hres = IRunningObjectTable_IsRunning(obj_tbl, &This->IMoniker_iface);
237 if(hres == S_OK) {
238 IUnknown *unk = NULL;
240 TRACE("Found in running object table\n");
242 hres = IRunningObjectTable_GetObject(obj_tbl, &This->IMoniker_iface, &unk);
243 if(SUCCEEDED(hres)) {
244 hres = IUnknown_QueryInterface(unk, riid, ppv);
245 IUnknown_Release(unk);
248 IRunningObjectTable_Release(obj_tbl);
249 return hres;
252 IRunningObjectTable_Release(obj_tbl);
255 if(!This->uri) {
256 *ppv = NULL;
257 return MK_E_SYNTAX;
260 return bind_to_object(&This->IMoniker_iface, This->uri, pbc, riid, ppv);
263 static HRESULT WINAPI URLMoniker_BindToStorage(IMoniker* iface, IBindCtx* pbc,
264 IMoniker* pmkToLeft, REFIID riid, void **ppvObject)
266 URLMoniker *This = impl_from_IMoniker(iface);
268 TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObject);
270 if(ppvObject) *ppvObject = NULL;
272 if(!pbc || !ppvObject) return E_INVALIDARG;
274 if(pmkToLeft)
275 FIXME("Unsupported pmkToLeft\n");
277 if(!This->uri)
278 return MK_E_SYNTAX;
280 return bind_to_storage(This->uri, pbc, riid, ppvObject);
283 static HRESULT WINAPI URLMoniker_Reduce(IMoniker *iface, IBindCtx *pbc,
284 DWORD dwReduceHowFar, IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
286 URLMoniker *This = impl_from_IMoniker(iface);
288 TRACE("(%p,%p,%ld,%p,%p)\n", This, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
290 if(!ppmkReduced)
291 return E_INVALIDARG;
293 IMoniker_AddRef(iface);
294 *ppmkReduced = iface;
295 return MK_S_REDUCED_TO_SELF;
298 static HRESULT WINAPI URLMoniker_ComposeWith(IMoniker *iface, IMoniker *right,
299 BOOL only_if_not_generic, IMoniker **composite)
301 HRESULT res;
302 IUri *right_uri;
303 IUriContainer *uri_container;
305 TRACE("(%p)->(%p,%d,%p)\n", iface, right, only_if_not_generic, composite);
307 if (!right || !composite) return E_INVALIDARG;
309 res = IMoniker_QueryInterface(right, &IID_IUriContainer, (void**)&uri_container);
310 if (SUCCEEDED(res)){
311 res = IUriContainer_GetIUri(uri_container, &right_uri);
312 if (SUCCEEDED(res)) res = CreateURLMonikerEx2(iface, right_uri, composite, 0);
313 IUriContainer_Release(uri_container);
314 return res;
317 if(only_if_not_generic) return MK_E_NEEDGENERIC;
318 return CreateGenericComposite(iface, right, composite);
321 static HRESULT WINAPI URLMoniker_Enum(IMoniker *iface, BOOL fForward, IEnumMoniker **ppenumMoniker)
323 URLMoniker *This = impl_from_IMoniker(iface);
325 TRACE("(%p,%d,%p)\n", This, fForward, ppenumMoniker);
327 if(!ppenumMoniker)
328 return E_INVALIDARG;
330 /* Does not support sub-monikers */
331 *ppenumMoniker = NULL;
332 return S_OK;
335 static HRESULT WINAPI URLMoniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
337 URLMoniker *This = impl_from_IMoniker(iface);
338 CLSID clsid;
339 LPOLESTR urlPath;
340 IBindCtx* bind;
341 HRESULT res;
343 TRACE("(%p,%p)\n",This, pmkOtherMoniker);
345 if(pmkOtherMoniker==NULL)
346 return E_INVALIDARG;
348 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
350 if(!IsEqualCLSID(&clsid,&CLSID_StdURLMoniker))
351 return S_FALSE;
353 res = CreateBindCtx(0,&bind);
354 if(FAILED(res))
355 return res;
357 res = S_FALSE;
358 if(SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&urlPath))) {
359 int result = lstrcmpiW(urlPath, This->URLName);
360 CoTaskMemFree(urlPath);
361 if(result == 0)
362 res = S_OK;
364 IBindCtx_Release(bind);
365 return res;
369 static HRESULT WINAPI URLMoniker_Hash(IMoniker *iface, DWORD *pdwHash)
371 URLMoniker *This = impl_from_IMoniker(iface);
372 int h = 0,i,skip,len;
373 int off = 0;
374 LPOLESTR val;
376 TRACE("(%p,%p)\n",This,pdwHash);
378 if(!pdwHash)
379 return E_INVALIDARG;
381 val = This->URLName;
382 len = lstrlenW(val);
384 if(len < 16) {
385 for(i = len ; i > 0; i--) {
386 h = (h * 37) + val[off++];
388 }else {
389 /* only sample some characters */
390 skip = len / 8;
391 for(i = len; i > 0; i -= skip, off += skip) {
392 h = (h * 39) + val[off];
395 *pdwHash = h;
396 return S_OK;
399 static HRESULT WINAPI URLMoniker_IsRunning(IMoniker* iface, IBindCtx* pbc,
400 IMoniker *pmkToLeft, IMoniker *pmkNewlyRunning)
402 URLMoniker *This = impl_from_IMoniker(iface);
403 FIXME("(%p)->(%p,%p,%p): stub\n",This,pbc,pmkToLeft,pmkNewlyRunning);
404 return E_NOTIMPL;
407 static HRESULT WINAPI URLMoniker_GetTimeOfLastChange(IMoniker *iface,
408 IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pFileTime)
410 URLMoniker *This = impl_from_IMoniker(iface);
411 FIXME("(%p)->(%p,%p,%p): stub\n", This, pbc, pmkToLeft, pFileTime);
412 return E_NOTIMPL;
415 static HRESULT WINAPI URLMoniker_Inverse(IMoniker *iface, IMoniker **ppmk)
417 URLMoniker *This = impl_from_IMoniker(iface);
418 TRACE("(%p,%p)\n",This,ppmk);
419 return MK_E_NOINVERSE;
422 static HRESULT WINAPI URLMoniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther, IMoniker **ppmkPrefix)
424 URLMoniker *This = impl_from_IMoniker(iface);
425 FIXME("(%p)->(%p,%p): stub\n",This,pmkOther,ppmkPrefix);
426 return E_NOTIMPL;
429 static HRESULT WINAPI URLMoniker_RelativePathTo(IMoniker *iface, IMoniker *pmOther, IMoniker **ppmkRelPath)
431 URLMoniker *This = impl_from_IMoniker(iface);
432 FIXME("(%p)->(%p,%p): stub\n",This,pmOther,ppmkRelPath);
433 return E_NOTIMPL;
436 static HRESULT WINAPI URLMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
437 LPOLESTR *ppszDisplayName)
439 URLMoniker *This = impl_from_IMoniker(iface);
440 int len;
442 TRACE("(%p,%p,%p,%p)\n", This, pbc, pmkToLeft, ppszDisplayName);
444 if(!ppszDisplayName)
445 return E_INVALIDARG;
447 if(!This->URLName)
448 return E_OUTOFMEMORY;
450 /* FIXME: If this is a partial URL, try and get a URL moniker from SZ_URLCONTEXT in the bind context,
451 then look at pmkToLeft to try and complete the URL
453 len = SysStringLen(This->URLName)+1;
454 *ppszDisplayName = CoTaskMemAlloc(len*sizeof(WCHAR));
455 if(!*ppszDisplayName)
456 return E_OUTOFMEMORY;
457 lstrcpyW(*ppszDisplayName, This->URLName);
458 return S_OK;
461 static HRESULT WINAPI URLMoniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
462 LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
464 URLMoniker *This = impl_from_IMoniker(iface);
465 FIXME("(%p)->(%p,%p,%p,%p,%p): stub\n",This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
466 return E_NOTIMPL;
469 static HRESULT WINAPI URLMoniker_IsSystemMoniker(IMoniker *iface, DWORD *pwdMksys)
471 URLMoniker *This = impl_from_IMoniker(iface);
473 TRACE("(%p,%p)\n",This,pwdMksys);
475 if(!pwdMksys)
476 return E_INVALIDARG;
478 *pwdMksys = MKSYS_URLMONIKER;
479 return S_OK;
482 static const IMonikerVtbl URLMonikerVtbl =
484 URLMoniker_QueryInterface,
485 URLMoniker_AddRef,
486 URLMoniker_Release,
487 URLMoniker_GetClassID,
488 URLMoniker_IsDirty,
489 URLMoniker_Load,
490 URLMoniker_Save,
491 URLMoniker_GetSizeMax,
492 URLMoniker_BindToObject,
493 URLMoniker_BindToStorage,
494 URLMoniker_Reduce,
495 URLMoniker_ComposeWith,
496 URLMoniker_Enum,
497 URLMoniker_IsEqual,
498 URLMoniker_Hash,
499 URLMoniker_IsRunning,
500 URLMoniker_GetTimeOfLastChange,
501 URLMoniker_Inverse,
502 URLMoniker_CommonPrefixWith,
503 URLMoniker_RelativePathTo,
504 URLMoniker_GetDisplayName,
505 URLMoniker_ParseDisplayName,
506 URLMoniker_IsSystemMoniker
509 static inline URLMoniker *impl_from_IUriContainer(IUriContainer *iface)
511 return CONTAINING_RECORD(iface, URLMoniker, IUriContainer_iface);
514 static HRESULT WINAPI UriContainer_QueryInterface(IUriContainer *iface, REFIID riid, void **ppv)
516 URLMoniker *This = impl_from_IUriContainer(iface);
517 return IMoniker_QueryInterface(&This->IMoniker_iface, riid, ppv);
520 static ULONG WINAPI UriContainer_AddRef(IUriContainer *iface)
522 URLMoniker *This = impl_from_IUriContainer(iface);
523 return IMoniker_AddRef(&This->IMoniker_iface);
526 static ULONG WINAPI UriContainer_Release(IUriContainer *iface)
528 URLMoniker *This = impl_from_IUriContainer(iface);
529 return IMoniker_Release(&This->IMoniker_iface);
532 static HRESULT WINAPI UriContainer_GetIUri(IUriContainer *iface, IUri **ppIUri)
534 URLMoniker *This = impl_from_IUriContainer(iface);
536 TRACE("(%p)->(%p)\n", This, ppIUri);
538 if(!This->uri) {
539 *ppIUri = NULL;
540 return S_FALSE;
543 IUri_AddRef(This->uri);
544 *ppIUri = This->uri;
545 return S_OK;
548 static const IUriContainerVtbl UriContainerVtbl = {
549 UriContainer_QueryInterface,
550 UriContainer_AddRef,
551 UriContainer_Release,
552 UriContainer_GetIUri
555 static HRESULT create_moniker(IUri *uri, URLMoniker **ret)
557 URLMoniker *mon;
558 HRESULT hres;
560 mon = malloc(sizeof(*mon));
561 if(!mon)
562 return E_OUTOFMEMORY;
564 mon->IMoniker_iface.lpVtbl = &URLMonikerVtbl;
565 mon->IUriContainer_iface.lpVtbl = &UriContainerVtbl;
566 mon->ref = 1;
568 if(uri) {
569 /* FIXME: try to avoid it */
570 hres = IUri_GetDisplayUri(uri, &mon->URLName);
571 if(FAILED(hres)) {
572 free(mon);
573 return hres;
576 IUri_AddRef(uri);
577 mon->uri = uri;
578 }else {
579 mon->URLName = NULL;
580 mon->uri = NULL;
583 URLMON_LockModule();
584 *ret = mon;
585 return S_OK;
588 HRESULT StdURLMoniker_Construct(IUnknown *outer, void **ppv)
590 URLMoniker *mon;
591 HRESULT hres;
593 TRACE("(%p %p)\n", outer, ppv);
595 hres = create_moniker(NULL, &mon);
596 if(FAILED(hres))
597 return hres;
599 *ppv = &mon->IMoniker_iface;
600 return S_OK;
603 static const DWORD create_flags_map[3] = {
604 Uri_CREATE_FILE_USE_DOS_PATH, /* URL_MK_LEGACY */
605 0, /* URL_MK_UNIFORM */
606 Uri_CREATE_NO_CANONICALIZE /* URL_MK_NO_CANONICALIZE */
609 static const DWORD combine_flags_map[3] = {
610 URL_FILE_USE_PATHURL, /* URL_MK_LEGACY */
611 0, /* URL_MK_UNIFORM */
612 URL_DONT_SIMPLIFY /* URL_MK_NO_CANONICALIZE */
615 /***********************************************************************
616 * CreateURLMonikerEx (URLMON.@)
618 * Create a url moniker.
620 * PARAMS
621 * pmkContext [I] Context
622 * szURL [I] Url to create the moniker for
623 * ppmk [O] Destination for created moniker.
624 * dwFlags [I] Flags.
626 * RETURNS
627 * Success: S_OK. ppmk contains the created IMoniker object.
628 * Failure: MK_E_SYNTAX if szURL is not a valid url, or
629 * E_OUTOFMEMORY if memory allocation fails.
631 HRESULT WINAPI CreateURLMonikerEx(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk, DWORD dwFlags)
633 IUri *uri, *base_uri = NULL;
634 URLMoniker *obj;
635 HRESULT hres;
637 TRACE("(%p, %s, %p, %08lx)\n", pmkContext, debugstr_w(szURL), ppmk, dwFlags);
639 if (ppmk)
640 *ppmk = NULL;
642 if (!szURL || !ppmk)
643 return E_INVALIDARG;
645 if(dwFlags >= ARRAY_SIZE(create_flags_map)) {
646 FIXME("Unsupported flags %lx\n", dwFlags);
647 return E_INVALIDARG;
650 if(pmkContext) {
651 IUriContainer *uri_container;
653 hres = IMoniker_QueryInterface(pmkContext, &IID_IUriContainer, (void**)&uri_container);
654 if(SUCCEEDED(hres)) {
655 hres = IUriContainer_GetIUri(uri_container, &base_uri);
656 IUriContainer_Release(uri_container);
657 if(FAILED(hres))
658 return hres;
662 if(base_uri) {
663 hres = CoInternetCombineUrlEx(base_uri, szURL, combine_flags_map[dwFlags], &uri, 0);
664 IUri_Release(base_uri);
665 }else {
666 hres = CreateUri(szURL, Uri_CREATE_ALLOW_RELATIVE|Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME|create_flags_map[dwFlags], 0, &uri);
668 if(FAILED(hres))
669 return hres;
671 hres = create_moniker(uri, &obj);
672 IUri_Release(uri);
673 if(FAILED(hres))
674 return hres;
676 *ppmk = &obj->IMoniker_iface;
677 return S_OK;
680 /***********************************************************************
681 * CreateURLMonikerEx2 (URLMON.@)
683 HRESULT WINAPI CreateURLMonikerEx2(IMoniker *pmkContext, IUri *pUri, IMoniker **ppmk, DWORD dwFlags)
685 IUri *context_uri = NULL, *uri;
686 IUriContainer *uri_container;
687 URLMoniker *ret;
688 HRESULT hres;
690 TRACE("(%p %p %p %lx)\n", pmkContext, pUri, ppmk, dwFlags);
692 if (ppmk)
693 *ppmk = NULL;
695 if (!pUri || !ppmk)
696 return E_INVALIDARG;
698 if(dwFlags >= ARRAY_SIZE(create_flags_map)) {
699 FIXME("Unsupported flags %lx\n", dwFlags);
700 return E_INVALIDARG;
703 if(pmkContext) {
704 hres = IMoniker_QueryInterface(pmkContext, &IID_IUriContainer, (void**)&uri_container);
705 if(SUCCEEDED(hres)) {
706 hres = IUriContainer_GetIUri(uri_container, &context_uri);
707 if(FAILED(hres))
708 context_uri = NULL;
709 IUriContainer_Release(uri_container);
713 if(context_uri) {
714 hres = CoInternetCombineIUri(context_uri, pUri, combine_flags_map[dwFlags], &uri, 0);
715 IUri_Release(context_uri);
716 if(FAILED(hres))
717 return hres;
718 }else {
719 uri = pUri;
720 IUri_AddRef(uri);
723 hres = create_moniker(uri, &ret);
724 IUri_Release(uri);
725 if(FAILED(hres))
726 return hres;
728 *ppmk = &ret->IMoniker_iface;
729 return S_OK;
732 /**********************************************************************
733 * CreateURLMoniker (URLMON.@)
735 * Create a url moniker.
737 * PARAMS
738 * pmkContext [I] Context
739 * szURL [I] Url to create the moniker for
740 * ppmk [O] Destination for created moniker.
742 * RETURNS
743 * Success: S_OK. ppmk contains the created IMoniker object.
744 * Failure: MK_E_SYNTAX if szURL is not a valid url, or
745 * E_OUTOFMEMORY if memory allocation fails.
747 HRESULT WINAPI CreateURLMoniker(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk)
749 return CreateURLMonikerEx(pmkContext, szURL, ppmk, URL_MK_LEGACY);
752 /***********************************************************************
753 * IsAsyncMoniker (URLMON.@)
755 HRESULT WINAPI IsAsyncMoniker(IMoniker *pmk)
757 IUnknown *am;
759 TRACE("(%p)\n", pmk);
760 if(!pmk)
761 return E_INVALIDARG;
762 if(SUCCEEDED(IMoniker_QueryInterface(pmk, &IID_IAsyncMoniker, (void**)&am))) {
763 IUnknown_Release(am);
764 return S_OK;
766 return S_FALSE;
769 /***********************************************************************
770 * BindAsyncMoniker (URLMON.@)
772 * Bind a bind status callback to an asynchronous URL Moniker.
774 * PARAMS
775 * pmk [I] Moniker object to bind status callback to
776 * grfOpt [I] Options, seems not used
777 * pbsc [I] Status callback to bind
778 * iidResult [I] Interface to return
779 * ppvResult [O] Resulting asynchronous moniker object
781 * RETURNS
782 * Success: S_OK.
783 * Failure: E_INVALIDARG, if any argument is invalid, or
784 * E_OUTOFMEMORY if memory allocation fails.
786 HRESULT WINAPI BindAsyncMoniker(IMoniker *pmk, DWORD grfOpt, IBindStatusCallback *pbsc, REFIID iidResult, LPVOID *ppvResult)
788 LPBC pbc = NULL;
789 HRESULT hr = E_INVALIDARG;
791 TRACE("(%p %08lx %p %s %p)\n", pmk, grfOpt, pbsc, debugstr_guid(iidResult), ppvResult);
793 if (pmk && ppvResult)
795 *ppvResult = NULL;
797 hr = CreateAsyncBindCtx(0, pbsc, NULL, &pbc);
798 if (hr == NOERROR)
800 hr = IMoniker_BindToObject(pmk, pbc, NULL, iidResult, ppvResult);
801 IBindCtx_Release(pbc);
804 return hr;
807 /***********************************************************************
808 * MkParseDisplayNameEx (URLMON.@)
810 HRESULT WINAPI MkParseDisplayNameEx(IBindCtx *pbc, LPCWSTR szDisplayName, ULONG *pchEaten, LPMONIKER *ppmk)
812 TRACE("(%p %s %p %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
814 if (!pbc || !szDisplayName || !*szDisplayName || !pchEaten || !ppmk)
815 return E_INVALIDARG;
817 if(is_registered_protocol(szDisplayName)) {
818 HRESULT hres;
820 hres = CreateURLMoniker(NULL, szDisplayName, ppmk);
821 if(SUCCEEDED(hres)) {
822 *pchEaten = lstrlenW(szDisplayName);
823 return hres;
827 return MkParseDisplayName(pbc, szDisplayName, pchEaten, ppmk);
831 /***********************************************************************
832 * URLDownloadToCacheFileA (URLMON.@)
834 HRESULT WINAPI URLDownloadToCacheFileA(LPUNKNOWN lpUnkCaller, LPCSTR szURL, LPSTR szFileName,
835 DWORD dwBufLength, DWORD dwReserved, LPBINDSTATUSCALLBACK pBSC)
837 LPWSTR url = NULL, file_name = NULL;
838 int len;
839 HRESULT hres;
841 TRACE("(%p %s %p %ld %ld %p)\n", lpUnkCaller, debugstr_a(szURL), szFileName,
842 dwBufLength, dwReserved, pBSC);
844 if(szURL) {
845 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0);
846 url = malloc(len * sizeof(WCHAR));
847 MultiByteToWideChar(CP_ACP, 0, szURL, -1, url, len);
850 if(szFileName)
851 file_name = malloc(dwBufLength * sizeof(WCHAR));
853 hres = URLDownloadToCacheFileW(lpUnkCaller, url, file_name, dwBufLength*sizeof(WCHAR),
854 dwReserved, pBSC);
856 if(SUCCEEDED(hres) && file_name)
857 WideCharToMultiByte(CP_ACP, 0, file_name, -1, szFileName, dwBufLength, NULL, NULL);
859 free(url);
860 free(file_name);
862 return hres;
865 /***********************************************************************
866 * URLDownloadToCacheFileW (URLMON.@)
868 HRESULT WINAPI URLDownloadToCacheFileW(LPUNKNOWN lpUnkCaller, LPCWSTR szURL, LPWSTR szFileName,
869 DWORD dwBufLength, DWORD dwReserved, LPBINDSTATUSCALLBACK pBSC)
871 WCHAR cache_path[MAX_PATH + 1];
872 FILETIME expire, modified;
873 HRESULT hr;
874 LPWSTR ext;
876 static WCHAR header[] = L"HTTP/1.0 200 OK\\r\\n\\r\\n";
878 TRACE("(%p, %s, %p, %ld, %ld, %p)\n", lpUnkCaller, debugstr_w(szURL),
879 szFileName, dwBufLength, dwReserved, pBSC);
881 if (!szURL || !szFileName)
882 return E_INVALIDARG;
884 ext = PathFindExtensionW(szURL);
886 if (!CreateUrlCacheEntryW(szURL, 0, ext, cache_path, 0))
887 return E_FAIL;
889 hr = URLDownloadToFileW(lpUnkCaller, szURL, cache_path, 0, pBSC);
890 if (FAILED(hr))
891 return hr;
893 expire.dwHighDateTime = 0;
894 expire.dwLowDateTime = 0;
895 modified.dwHighDateTime = 0;
896 modified.dwLowDateTime = 0;
898 if (!CommitUrlCacheEntryW(szURL, cache_path, expire, modified, NORMAL_CACHE_ENTRY,
899 header, sizeof(header), NULL, NULL))
900 return E_FAIL;
902 if (lstrlenW(cache_path) > dwBufLength)
903 return E_OUTOFMEMORY;
905 lstrcpyW(szFileName, cache_path);
907 return S_OK;
910 /***********************************************************************
911 * HlinkSimpleNavigateToMoniker (URLMON.@)
913 HRESULT WINAPI HlinkSimpleNavigateToMoniker(IMoniker *pmkTarget,
914 LPCWSTR szLocation, LPCWSTR szTargetFrameName, IUnknown *pUnk,
915 IBindCtx *pbc, IBindStatusCallback *pbsc, DWORD grfHLNF, DWORD dwReserved)
917 LPWSTR target;
918 HRESULT hres;
920 TRACE("\n");
922 hres = IMoniker_GetDisplayName(pmkTarget, pbc, 0, &target);
923 if(hres == S_OK)
924 hres = HlinkSimpleNavigateToString( target, szLocation, szTargetFrameName,
925 pUnk, pbc, pbsc, grfHLNF, dwReserved );
926 CoTaskMemFree(target);
928 return hres;
931 /***********************************************************************
932 * HlinkSimpleNavigateToString (URLMON.@)
934 HRESULT WINAPI HlinkSimpleNavigateToString( LPCWSTR szTarget,
935 LPCWSTR szLocation, LPCWSTR szTargetFrameName, IUnknown *pUnk,
936 IBindCtx *pbc, IBindStatusCallback *pbsc, DWORD grfHLNF, DWORD dwReserved)
938 FIXME("%s %s %s %p %p %p %lu %lu partial stub\n", debugstr_w( szTarget ), debugstr_w( szLocation ),
939 debugstr_w( szTargetFrameName ), pUnk, pbc, pbsc, grfHLNF, dwReserved);
941 /* undocumented: 0 means HLNF_OPENINNEWWINDOW*/
942 if (!grfHLNF) grfHLNF = HLNF_OPENINNEWWINDOW;
944 if (grfHLNF == HLNF_OPENINNEWWINDOW)
946 SHELLEXECUTEINFOW sei;
948 memset(&sei, 0, sizeof(sei));
949 sei.cbSize = sizeof(sei);
950 sei.lpVerb = L"open";
951 sei.nShow = SW_SHOWNORMAL;
952 sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NO_CONSOLE;
953 sei.lpFile = szTarget;
955 if (ShellExecuteExW(&sei)) return S_OK;
958 return E_NOTIMPL;
961 /***********************************************************************
962 * HlinkNavigateString (URLMON.@)
964 HRESULT WINAPI HlinkNavigateString( IUnknown *pUnk, LPCWSTR szTarget )
966 TRACE("%p %s\n", pUnk, debugstr_w( szTarget ) );
967 return HlinkSimpleNavigateToString(
968 szTarget, NULL, NULL, pUnk, NULL, NULL, 0, 0 );
971 /***********************************************************************
972 * GetSoftwareUpdateInfo (URLMON.@)
974 HRESULT WINAPI GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi )
976 FIXME("%s %p\n", debugstr_w(szDistUnit), psdi );
977 return E_FAIL;