push eb25bf65c4616aa55a810ed5c29198b1a080b208
[wine/hacks.git] / dlls / urlmon / umon.c
blob770e46e3624560b7e622fe3c3d03df65f1616737
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 <stdio.h>
25 #include "urlmon_main.h"
27 #include "winreg.h"
28 #include "winternl.h"
29 #include "wininet.h"
30 #include "shlwapi.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
36 typedef struct {
38 const IMonikerVtbl* lpvtbl; /* VTable relative to the IMoniker interface.*/
40 LONG ref; /* reference counter for this object */
42 LPOLESTR URLName; /* URL string identified by this URLmoniker */
43 } URLMonikerImpl;
45 /*******************************************************************************
46 * URLMoniker_QueryInterface
47 *******************************************************************************/
48 static HRESULT WINAPI URLMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
50 URLMonikerImpl *This = (URLMonikerImpl *)iface;
52 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppvObject);
54 /* Perform a sanity check on the parameters.*/
55 if ( (This==0) || (ppvObject==0) )
56 return E_INVALIDARG;
58 /* Initialize the return parameter */
59 *ppvObject = 0;
61 /* Compare the riid with the interface IDs implemented by this object.*/
62 if (IsEqualIID(&IID_IUnknown, riid) ||
63 IsEqualIID(&IID_IPersist, riid) ||
64 IsEqualIID(&IID_IPersistStream,riid) ||
65 IsEqualIID(&IID_IMoniker, riid)
67 *ppvObject = iface;
69 /* Check that we obtained an interface.*/
70 if ((*ppvObject)==0)
71 return E_NOINTERFACE;
73 /* Query Interface always increases the reference count by one when it is successful */
74 IMoniker_AddRef(iface);
76 return S_OK;
79 /******************************************************************************
80 * URLMoniker_AddRef
81 ******************************************************************************/
82 static ULONG WINAPI URLMonikerImpl_AddRef(IMoniker* iface)
84 URLMonikerImpl *This = (URLMonikerImpl *)iface;
85 ULONG refCount = InterlockedIncrement(&This->ref);
87 TRACE("(%p) ref=%u\n",This, refCount);
89 return refCount;
92 /******************************************************************************
93 * URLMoniker_Release
94 ******************************************************************************/
95 static ULONG WINAPI URLMonikerImpl_Release(IMoniker* iface)
97 URLMonikerImpl *This = (URLMonikerImpl *)iface;
98 ULONG refCount = InterlockedDecrement(&This->ref);
100 TRACE("(%p) ref=%u\n",This, refCount);
102 /* destroy the object if there's no more reference on it */
103 if (!refCount) {
104 heap_free(This->URLName);
105 heap_free(This);
107 URLMON_UnlockModule();
110 return refCount;
114 /******************************************************************************
115 * URLMoniker_GetClassID
116 ******************************************************************************/
117 static HRESULT WINAPI URLMonikerImpl_GetClassID(IMoniker* iface,
118 CLSID *pClassID)/* Pointer to CLSID of object */
120 URLMonikerImpl *This = (URLMonikerImpl *)iface;
122 TRACE("(%p,%p)\n",This,pClassID);
124 if (pClassID==NULL)
125 return E_POINTER;
126 /* Windows always returns CLSID_StdURLMoniker */
127 *pClassID = CLSID_StdURLMoniker;
128 return S_OK;
131 /******************************************************************************
132 * URLMoniker_IsDirty
133 ******************************************************************************/
134 static HRESULT WINAPI URLMonikerImpl_IsDirty(IMoniker* iface)
136 URLMonikerImpl *This = (URLMonikerImpl *)iface;
137 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
138 method in the OLE-provided moniker interfaces always return S_FALSE because
139 their internal state never changes. */
141 TRACE("(%p)\n",This);
143 return S_FALSE;
146 /******************************************************************************
147 * URLMoniker_Load
149 * NOTE
150 * Writes a ULONG containing length of unicode string, followed
151 * by that many unicode characters
152 ******************************************************************************/
153 static HRESULT WINAPI URLMonikerImpl_Load(IMoniker* iface,IStream* pStm)
155 URLMonikerImpl *This = (URLMonikerImpl *)iface;
157 HRESULT res;
158 ULONG size;
159 ULONG got;
160 TRACE("(%p,%p)\n",This,pStm);
162 if(!pStm)
163 return E_INVALIDARG;
165 res = IStream_Read(pStm, &size, sizeof(ULONG), &got);
166 if(SUCCEEDED(res)) {
167 if(got == sizeof(ULONG)) {
168 heap_free(This->URLName);
169 This->URLName = heap_alloc(size);
170 if(!This->URLName)
171 res = E_OUTOFMEMORY;
172 else {
173 res = IStream_Read(pStm, This->URLName, size, NULL);
174 This->URLName[size/sizeof(WCHAR) - 1] = 0;
177 else
178 res = E_FAIL;
180 return res;
183 /******************************************************************************
184 * URLMoniker_Save
185 ******************************************************************************/
186 static HRESULT WINAPI URLMonikerImpl_Save(IMoniker* iface,
187 IStream* pStm,/* pointer to the stream where the object is to be saved */
188 BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
190 URLMonikerImpl *This = (URLMonikerImpl *)iface;
192 HRESULT res;
193 ULONG size;
194 TRACE("(%p,%p,%d)\n",This,pStm,fClearDirty);
196 if(!pStm)
197 return E_INVALIDARG;
199 size = (strlenW(This->URLName) + 1)*sizeof(WCHAR);
200 res=IStream_Write(pStm,&size,sizeof(ULONG),NULL);
201 if(SUCCEEDED(res))
202 res=IStream_Write(pStm,This->URLName,size,NULL);
203 return res;
207 /******************************************************************************
208 * URLMoniker_GetSizeMax
209 ******************************************************************************/
210 static HRESULT WINAPI URLMonikerImpl_GetSizeMax(IMoniker* iface,
211 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
213 URLMonikerImpl *This = (URLMonikerImpl *)iface;
215 TRACE("(%p,%p)\n",This,pcbSize);
217 if(!pcbSize)
218 return E_INVALIDARG;
220 pcbSize->QuadPart = sizeof(ULONG) + ((strlenW(This->URLName)+1) * sizeof(WCHAR));
221 return S_OK;
224 /******************************************************************************
225 * URLMoniker_BindToObject
226 ******************************************************************************/
227 static HRESULT WINAPI URLMonikerImpl_BindToObject(IMoniker* iface,
228 IBindCtx* pbc,
229 IMoniker* pmkToLeft,
230 REFIID riid,
231 VOID** ppv)
233 URLMonikerImpl *This = (URLMonikerImpl *)iface;
234 IRunningObjectTable *obj_tbl;
235 HRESULT hres;
237 TRACE("(%p)->(%p,%p,%s,%p): stub\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppv);
239 hres = IBindCtx_GetRunningObjectTable(pbc, &obj_tbl);
240 if(SUCCEEDED(hres)) {
241 FIXME("use running object table\n");
242 IRunningObjectTable_Release(obj_tbl);
245 return bind_to_object(iface, This->URLName, pbc, riid, ppv);
248 /******************************************************************************
249 * URLMoniker_BindToStorage
250 ******************************************************************************/
251 static HRESULT WINAPI URLMonikerImpl_BindToStorage(IMoniker* iface,
252 IBindCtx* pbc,
253 IMoniker* pmkToLeft,
254 REFIID riid,
255 VOID** ppvObject)
257 URLMonikerImpl *This = (URLMonikerImpl*)iface;
259 TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObject);
261 if(pmkToLeft)
262 FIXME("Unsupported pmkToLeft\n");
264 return bind_to_storage(This->URLName, pbc, riid, ppvObject);
267 /******************************************************************************
268 * URLMoniker_Reduce
269 ******************************************************************************/
270 static HRESULT WINAPI URLMonikerImpl_Reduce(IMoniker* iface,
271 IBindCtx* pbc,
272 DWORD dwReduceHowFar,
273 IMoniker** ppmkToLeft,
274 IMoniker** ppmkReduced)
276 URLMonikerImpl *This = (URLMonikerImpl *)iface;
278 TRACE("(%p,%p,%d,%p,%p)\n",This,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
280 if(!ppmkReduced)
281 return E_INVALIDARG;
283 URLMonikerImpl_AddRef(iface);
284 *ppmkReduced = iface;
285 return MK_S_REDUCED_TO_SELF;
288 /******************************************************************************
289 * URLMoniker_ComposeWith
290 ******************************************************************************/
291 static HRESULT WINAPI URLMonikerImpl_ComposeWith(IMoniker* iface,
292 IMoniker* pmkRight,
293 BOOL fOnlyIfNotGeneric,
294 IMoniker** ppmkComposite)
296 URLMonikerImpl *This = (URLMonikerImpl *)iface;
297 FIXME("(%p)->(%p,%d,%p): stub\n",This,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
299 return E_NOTIMPL;
302 /******************************************************************************
303 * URLMoniker_Enum
304 ******************************************************************************/
305 static HRESULT WINAPI URLMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
307 URLMonikerImpl *This = (URLMonikerImpl *)iface;
308 TRACE("(%p,%d,%p)\n",This,fForward,ppenumMoniker);
310 if(!ppenumMoniker)
311 return E_INVALIDARG;
313 /* Does not support sub-monikers */
314 *ppenumMoniker = NULL;
315 return S_OK;
318 /******************************************************************************
319 * URLMoniker_IsEqual
320 ******************************************************************************/
321 static HRESULT WINAPI URLMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
323 URLMonikerImpl *This = (URLMonikerImpl *)iface;
324 CLSID clsid;
325 LPOLESTR urlPath;
326 IBindCtx* bind;
327 HRESULT res;
329 TRACE("(%p,%p)\n",This,pmkOtherMoniker);
331 if(pmkOtherMoniker==NULL)
332 return E_INVALIDARG;
334 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
336 if(!IsEqualCLSID(&clsid,&CLSID_StdURLMoniker))
337 return S_FALSE;
339 res = CreateBindCtx(0,&bind);
340 if(FAILED(res))
341 return res;
343 res = S_FALSE;
344 if(SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&urlPath))) {
345 int result = lstrcmpiW(urlPath, This->URLName);
346 CoTaskMemFree(urlPath);
347 if(result == 0)
348 res = S_OK;
350 IUnknown_Release(bind);
351 return res;
355 /******************************************************************************
356 * URLMoniker_Hash
357 ******************************************************************************/
358 static HRESULT WINAPI URLMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
360 URLMonikerImpl *This = (URLMonikerImpl *)iface;
362 int h = 0,i,skip,len;
363 int off = 0;
364 LPOLESTR val;
366 TRACE("(%p,%p)\n",This,pdwHash);
368 if(!pdwHash)
369 return E_INVALIDARG;
371 val = This->URLName;
372 len = lstrlenW(val);
374 if(len < 16) {
375 for(i = len ; i > 0; i--) {
376 h = (h * 37) + val[off++];
379 else {
380 /* only sample some characters */
381 skip = len / 8;
382 for(i = len; i > 0; i -= skip, off += skip) {
383 h = (h * 39) + val[off];
386 *pdwHash = h;
387 return S_OK;
390 /******************************************************************************
391 * URLMoniker_IsRunning
392 ******************************************************************************/
393 static HRESULT WINAPI URLMonikerImpl_IsRunning(IMoniker* iface,
394 IBindCtx* pbc,
395 IMoniker* pmkToLeft,
396 IMoniker* pmkNewlyRunning)
398 URLMonikerImpl *This = (URLMonikerImpl *)iface;
399 FIXME("(%p)->(%p,%p,%p): stub\n",This,pbc,pmkToLeft,pmkNewlyRunning);
401 return E_NOTIMPL;
404 /******************************************************************************
405 * URLMoniker_GetTimeOfLastChange
406 ******************************************************************************/
407 static HRESULT WINAPI URLMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
408 IBindCtx* pbc,
409 IMoniker* pmkToLeft,
410 FILETIME* pFileTime)
412 URLMonikerImpl *This = (URLMonikerImpl *)iface;
413 FIXME("(%p)->(%p,%p,%p): stub\n",This,pbc,pmkToLeft,pFileTime);
415 return E_NOTIMPL;
418 /******************************************************************************
419 * URLMoniker_Inverse
420 ******************************************************************************/
421 static HRESULT WINAPI URLMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
423 URLMonikerImpl *This = (URLMonikerImpl *)iface;
424 TRACE("(%p,%p)\n",This,ppmk);
426 return MK_E_NOINVERSE;
429 /******************************************************************************
430 * URLMoniker_CommonPrefixWith
431 ******************************************************************************/
432 static HRESULT WINAPI URLMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
434 URLMonikerImpl *This = (URLMonikerImpl *)iface;
435 FIXME("(%p)->(%p,%p): stub\n",This,pmkOther,ppmkPrefix);
437 return E_NOTIMPL;
440 /******************************************************************************
441 * URLMoniker_RelativePathTo
442 ******************************************************************************/
443 static HRESULT WINAPI URLMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
445 URLMonikerImpl *This = (URLMonikerImpl *)iface;
446 FIXME("(%p)->(%p,%p): stub\n",This,pmOther,ppmkRelPath);
448 return E_NOTIMPL;
451 /******************************************************************************
452 * URLMoniker_GetDisplayName
453 ******************************************************************************/
454 static HRESULT WINAPI URLMonikerImpl_GetDisplayName(IMoniker* iface,
455 IBindCtx* pbc,
456 IMoniker* pmkToLeft,
457 LPOLESTR *ppszDisplayName)
459 URLMonikerImpl *This = (URLMonikerImpl *)iface;
461 int len;
463 TRACE("(%p,%p,%p,%p)\n",This,pbc,pmkToLeft,ppszDisplayName);
465 if(!ppszDisplayName)
466 return E_INVALIDARG;
468 /* FIXME: If this is a partial URL, try and get a URL moniker from SZ_URLCONTEXT in the bind context,
469 then look at pmkToLeft to try and complete the URL
471 len = lstrlenW(This->URLName)+1;
472 *ppszDisplayName = CoTaskMemAlloc(len*sizeof(WCHAR));
473 if(!*ppszDisplayName)
474 return E_OUTOFMEMORY;
475 lstrcpyW(*ppszDisplayName, This->URLName);
476 return S_OK;
479 /******************************************************************************
480 * URLMoniker_ParseDisplayName
481 ******************************************************************************/
482 static HRESULT WINAPI URLMonikerImpl_ParseDisplayName(IMoniker* iface,
483 IBindCtx* pbc,
484 IMoniker* pmkToLeft,
485 LPOLESTR pszDisplayName,
486 ULONG* pchEaten,
487 IMoniker** ppmkOut)
489 URLMonikerImpl *This = (URLMonikerImpl *)iface;
490 FIXME("(%p)->(%p,%p,%p,%p,%p): stub\n",This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
492 return E_NOTIMPL;
495 /******************************************************************************
496 * URLMoniker_IsSystemMoniker
497 ******************************************************************************/
498 static HRESULT WINAPI URLMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
500 URLMonikerImpl *This = (URLMonikerImpl *)iface;
501 TRACE("(%p,%p)\n",This,pwdMksys);
503 if(!pwdMksys)
504 return E_INVALIDARG;
506 *pwdMksys = MKSYS_URLMONIKER;
507 return S_OK;
510 /********************************************************************************/
511 /* Virtual function table for the URLMonikerImpl class which include IPersist,*/
512 /* IPersistStream and IMoniker functions. */
513 static const IMonikerVtbl VT_URLMonikerImpl =
515 URLMonikerImpl_QueryInterface,
516 URLMonikerImpl_AddRef,
517 URLMonikerImpl_Release,
518 URLMonikerImpl_GetClassID,
519 URLMonikerImpl_IsDirty,
520 URLMonikerImpl_Load,
521 URLMonikerImpl_Save,
522 URLMonikerImpl_GetSizeMax,
523 URLMonikerImpl_BindToObject,
524 URLMonikerImpl_BindToStorage,
525 URLMonikerImpl_Reduce,
526 URLMonikerImpl_ComposeWith,
527 URLMonikerImpl_Enum,
528 URLMonikerImpl_IsEqual,
529 URLMonikerImpl_Hash,
530 URLMonikerImpl_IsRunning,
531 URLMonikerImpl_GetTimeOfLastChange,
532 URLMonikerImpl_Inverse,
533 URLMonikerImpl_CommonPrefixWith,
534 URLMonikerImpl_RelativePathTo,
535 URLMonikerImpl_GetDisplayName,
536 URLMonikerImpl_ParseDisplayName,
537 URLMonikerImpl_IsSystemMoniker
540 /******************************************************************************
541 * URLMoniker_Construct (local function)
542 *******************************************************************************/
543 static HRESULT URLMonikerImpl_Construct(URLMonikerImpl* This, LPCOLESTR lpszLeftURLName, LPCOLESTR lpszURLName)
545 HRESULT hres;
546 DWORD sizeStr = 0;
548 TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszLeftURLName),debugstr_w(lpszURLName));
550 This->lpvtbl = &VT_URLMonikerImpl;
551 This->ref = 0;
553 This->URLName = heap_alloc(INTERNET_MAX_URL_LENGTH*sizeof(WCHAR));
555 if(lpszLeftURLName)
556 hres = CoInternetCombineUrl(lpszLeftURLName, lpszURLName, URL_FILE_USE_PATHURL,
557 This->URLName, INTERNET_MAX_URL_LENGTH, &sizeStr, 0);
558 else
559 hres = CoInternetParseUrl(lpszURLName, PARSE_CANONICALIZE, URL_FILE_USE_PATHURL,
560 This->URLName, INTERNET_MAX_URL_LENGTH, &sizeStr, 0);
562 if(FAILED(hres)) {
563 heap_free(This->URLName);
564 return hres;
567 URLMON_LockModule();
569 if(sizeStr != INTERNET_MAX_URL_LENGTH)
570 This->URLName = heap_realloc(This->URLName, (sizeStr+1)*sizeof(WCHAR));
572 TRACE("URLName = %s\n", debugstr_w(This->URLName));
574 return S_OK;
577 /***********************************************************************
578 * CreateURLMonikerEx (URLMON.@)
580 * Create a url moniker.
582 * PARAMS
583 * pmkContext [I] Context
584 * szURL [I] Url to create the moniker for
585 * ppmk [O] Destination for created moniker.
586 * dwFlags [I] Flags.
588 * RETURNS
589 * Success: S_OK. ppmk contains the created IMoniker object.
590 * Failure: MK_E_SYNTAX if szURL is not a valid url, or
591 * E_OUTOFMEMORY if memory allocation fails.
593 HRESULT WINAPI CreateURLMonikerEx(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk, DWORD dwFlags)
595 URLMonikerImpl *obj;
596 HRESULT hres;
597 LPOLESTR lefturl = NULL;
599 TRACE("(%p, %s, %p, %08x)\n", pmkContext, debugstr_w(szURL), ppmk, dwFlags);
601 if (dwFlags & URL_MK_UNIFORM) FIXME("ignoring flag URL_MK_UNIFORM\n");
603 if(!(obj = heap_alloc(sizeof(*obj))))
604 return E_OUTOFMEMORY;
606 if(pmkContext) {
607 IBindCtx* bind;
608 DWORD dwMksys = 0;
609 IMoniker_IsSystemMoniker(pmkContext, &dwMksys);
610 if(dwMksys == MKSYS_URLMONIKER && SUCCEEDED(CreateBindCtx(0, &bind))) {
611 IMoniker_GetDisplayName(pmkContext, bind, NULL, &lefturl);
612 TRACE("lefturl = %s\n", debugstr_w(lefturl));
613 IBindCtx_Release(bind);
617 hres = URLMonikerImpl_Construct(obj, lefturl, szURL);
618 CoTaskMemFree(lefturl);
619 if(SUCCEEDED(hres))
620 hres = URLMonikerImpl_QueryInterface((IMoniker*)obj, &IID_IMoniker, (void**)ppmk);
621 else
622 heap_free(obj);
623 return hres;
626 /**********************************************************************
627 * CreateURLMoniker (URLMON.@)
629 * Create a url moniker.
631 * PARAMS
632 * pmkContext [I] Context
633 * szURL [I] Url to create the moniker for
634 * ppmk [O] Destination for created moniker.
636 * RETURNS
637 * Success: S_OK. ppmk contains the created IMoniker object.
638 * Failure: MK_E_SYNTAX if szURL is not a valid url, or
639 * E_OUTOFMEMORY if memory allocation fails.
641 HRESULT WINAPI CreateURLMoniker(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk)
643 return CreateURLMonikerEx(pmkContext, szURL, ppmk, URL_MK_LEGACY);
646 /***********************************************************************
647 * IsAsyncMoniker (URLMON.@)
649 HRESULT WINAPI IsAsyncMoniker(IMoniker *pmk)
651 IUnknown *am;
653 TRACE("(%p)\n", pmk);
654 if(!pmk)
655 return E_INVALIDARG;
656 if(SUCCEEDED(IMoniker_QueryInterface(pmk, &IID_IAsyncMoniker, (void**)&am))) {
657 IUnknown_Release(am);
658 return S_OK;
660 return S_FALSE;
663 /***********************************************************************
664 * BindAsyncMoniker (URLMON.@)
666 * Bind a bind status callback to an asynchronous URL Moniker.
668 * PARAMS
669 * pmk [I] Moniker object to bind status callback to
670 * grfOpt [I] Options, seems not used
671 * pbsc [I] Status callback to bind
672 * iidResult [I] Interface to return
673 * ppvResult [O] Resulting asynchronous moniker object
675 * RETURNS
676 * Success: S_OK.
677 * Failure: E_INVALIDARG, if any argument is invalid, or
678 * E_OUTOFMEMORY if memory allocation fails.
680 HRESULT WINAPI BindAsyncMoniker(IMoniker *pmk, DWORD grfOpt, IBindStatusCallback *pbsc, REFIID iidResult, LPVOID *ppvResult)
682 LPBC pbc = NULL;
683 HRESULT hr = E_INVALIDARG;
685 TRACE("(%p %08x %p %s %p)\n", pmk, grfOpt, pbsc, debugstr_guid(iidResult), ppvResult);
687 if (pmk && ppvResult)
689 *ppvResult = NULL;
691 hr = CreateAsyncBindCtx(0, pbsc, NULL, &pbc);
692 if (hr == NOERROR)
694 hr = IMoniker_BindToObject(pmk, pbc, NULL, iidResult, ppvResult);
695 IBindCtx_Release(pbc);
698 return hr;
701 /***********************************************************************
702 * MkParseDisplayNameEx (URLMON.@)
704 HRESULT WINAPI MkParseDisplayNameEx(IBindCtx *pbc, LPCWSTR szDisplayName, ULONG *pchEaten, LPMONIKER *ppmk)
706 TRACE("(%p %s %p %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
708 if(is_registered_protocol(szDisplayName)) {
709 HRESULT hres;
711 hres = CreateURLMoniker(NULL, szDisplayName, ppmk);
712 if(SUCCEEDED(hres)) {
713 *pchEaten = strlenW(szDisplayName);
714 return hres;
718 return MkParseDisplayName(pbc, szDisplayName, pchEaten, ppmk);
722 /***********************************************************************
723 * URLDownloadToCacheFileA (URLMON.@)
725 HRESULT WINAPI URLDownloadToCacheFileA(LPUNKNOWN lpUnkCaller, LPCSTR szURL, LPSTR szFileName,
726 DWORD dwBufLength, DWORD dwReserved, LPBINDSTATUSCALLBACK pBSC)
728 LPWSTR url = NULL, file_name = NULL;
729 int len;
730 HRESULT hres;
732 TRACE("(%p %s %p %d %d %p)\n", lpUnkCaller, debugstr_a(szURL), szFileName,
733 dwBufLength, dwReserved, pBSC);
735 if(szURL) {
736 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0);
737 url = heap_alloc(len*sizeof(WCHAR));
738 MultiByteToWideChar(CP_ACP, 0, szURL, -1, url, len);
741 if(szFileName)
742 file_name = heap_alloc(dwBufLength*sizeof(WCHAR));
744 hres = URLDownloadToCacheFileW(lpUnkCaller, url, file_name, dwBufLength*sizeof(WCHAR),
745 dwReserved, pBSC);
747 if(SUCCEEDED(hres) && file_name)
748 WideCharToMultiByte(CP_ACP, 0, file_name, -1, szFileName, dwBufLength, NULL, NULL);
750 heap_free(url);
751 heap_free(file_name);
753 return hres;
756 /***********************************************************************
757 * URLDownloadToCacheFileW (URLMON.@)
759 HRESULT WINAPI URLDownloadToCacheFileW(LPUNKNOWN lpUnkCaller, LPCWSTR szURL, LPWSTR szFileName,
760 DWORD dwBufLength, DWORD dwReserved, LPBINDSTATUSCALLBACK pBSC)
762 WCHAR cache_path[MAX_PATH + 1];
763 FILETIME expire, modified;
764 HRESULT hr;
765 LPWSTR ext;
767 static WCHAR header[] = {
768 'H','T','T','P','/','1','.','0',' ','2','0','0',' ',
769 'O','K','\\','r','\\','n','\\','r','\\','n',0
772 TRACE("(%p, %s, %p, %d, %d, %p)\n", lpUnkCaller, debugstr_w(szURL),
773 szFileName, dwBufLength, dwReserved, pBSC);
775 if (!szURL || !szFileName)
776 return E_INVALIDARG;
778 ext = PathFindExtensionW(szURL);
780 if (!CreateUrlCacheEntryW(szURL, 0, ext, cache_path, 0))
781 return E_FAIL;
783 hr = URLDownloadToFileW(lpUnkCaller, szURL, cache_path, 0, pBSC);
784 if (FAILED(hr))
785 return hr;
787 expire.dwHighDateTime = 0;
788 expire.dwLowDateTime = 0;
789 modified.dwHighDateTime = 0;
790 modified.dwLowDateTime = 0;
792 if (!CommitUrlCacheEntryW(szURL, cache_path, expire, modified, NORMAL_CACHE_ENTRY,
793 header, sizeof(header), NULL, NULL))
794 return E_FAIL;
796 if (strlenW(cache_path) > dwBufLength)
797 return E_OUTOFMEMORY;
799 lstrcpyW(szFileName, cache_path);
801 return S_OK;
804 /***********************************************************************
805 * HlinkSimpleNavigateToMoniker (URLMON.@)
807 HRESULT WINAPI HlinkSimpleNavigateToMoniker(IMoniker *pmkTarget,
808 LPCWSTR szLocation, LPCWSTR szTargetFrameName, IUnknown *pUnk,
809 IBindCtx *pbc, IBindStatusCallback *pbsc, DWORD grfHLNF, DWORD dwReserved)
811 FIXME("stub\n");
812 return E_NOTIMPL;
815 /***********************************************************************
816 * HlinkSimpleNavigateToString (URLMON.@)
818 HRESULT WINAPI HlinkSimpleNavigateToString( LPCWSTR szTarget,
819 LPCWSTR szLocation, LPCWSTR szTargetFrameName, IUnknown *pUnk,
820 IBindCtx *pbc, IBindStatusCallback *pbsc, DWORD grfHLNF, DWORD dwReserved)
822 FIXME("%s\n", debugstr_w( szTarget ) );
823 return E_NOTIMPL;
826 /***********************************************************************
827 * HlinkNavigateString (URLMON.@)
829 HRESULT WINAPI HlinkNavigateString( IUnknown *pUnk, LPCWSTR szTarget )
831 TRACE("%p %s\n", pUnk, debugstr_w( szTarget ) );
832 return HlinkSimpleNavigateToString(
833 szTarget, NULL, NULL, pUnk, NULL, NULL, 0, 0 );
836 /***********************************************************************
837 * GetSoftwareUpdateInfo (URLMON.@)
839 HRESULT WINAPI GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi )
841 FIXME("%s %p\n", debugstr_w(szDistUnit), psdi );
842 return E_FAIL;