[TCPIP DRIVER]
[reactos.git] / dll / win32 / urlmon / umon.c
1 /*
2 * UrlMon
3 *
4 * Copyright 1999 Ulrich Czekalla for Corel Corporation
5 * Copyright 2002 Huw D M Davies for CodeWeavers
6 * Copyright 2005 Jacek Caban for CodeWeavers
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 "urlmon_main.h"
24
25 #include "winreg.h"
26 #include "shlwapi.h"
27 #include "hlink.h"
28 #include "shellapi.h"
29
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
33
34 typedef struct {
35 const IMonikerVtbl *lpIMonikerVtbl;
36
37 LONG ref;
38
39 LPOLESTR URLName; /* URL string identified by this URLmoniker */
40 } URLMoniker;
41
42 #define MONIKER_THIS(iface) DEFINE_THIS(URLMoniker, IMoniker, iface)
43
44 static HRESULT WINAPI URLMoniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
45 {
46 URLMoniker *This = MONIKER_THIS(iface);
47
48 if(!ppv)
49 return E_INVALIDARG;
50
51 if(IsEqualIID(&IID_IUnknown, riid)) {
52 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
53 *ppv = iface;
54 }else if(IsEqualIID(&IID_IPersist, riid)) {
55 TRACE("(%p)->(IID_IPersist %p)\n", This, ppv);
56 *ppv = iface;
57 }else if(IsEqualIID(&IID_IPersistStream,riid)) {
58 TRACE("(%p)->(IID_IPersistStream %p)\n", This, ppv);
59 *ppv = iface;
60 }else if(IsEqualIID(&IID_IMoniker, riid)) {
61 TRACE("(%p)->(IID_IMoniker %p)\n", This, ppv);
62 *ppv = iface;
63 }else if(IsEqualIID(&IID_IAsyncMoniker, riid)) {
64 TRACE("(%p)->(IID_IAsyncMoniker %p)\n", This, ppv);
65 *ppv = iface;
66 }else {
67 WARN("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
68 *ppv = NULL;
69 return E_NOINTERFACE;
70 }
71
72 IMoniker_AddRef((IUnknown*)*ppv);
73 return S_OK;
74 }
75
76 static ULONG WINAPI URLMoniker_AddRef(IMoniker *iface)
77 {
78 URLMoniker *This = MONIKER_THIS(iface);
79 ULONG refCount = InterlockedIncrement(&This->ref);
80
81 TRACE("(%p) ref=%u\n",This, refCount);
82
83 return refCount;
84 }
85
86 static ULONG WINAPI URLMoniker_Release(IMoniker *iface)
87 {
88 URLMoniker *This = MONIKER_THIS(iface);
89 ULONG refCount = InterlockedDecrement(&This->ref);
90
91 TRACE("(%p) ref=%u\n",This, refCount);
92
93 if (!refCount) {
94 heap_free(This->URLName);
95 heap_free(This);
96
97 URLMON_UnlockModule();
98 }
99
100 return refCount;
101 }
102
103 static HRESULT WINAPI URLMoniker_GetClassID(IMoniker *iface, CLSID *pClassID)
104 {
105 URLMoniker *This = MONIKER_THIS(iface);
106
107 TRACE("(%p,%p)\n", This, pClassID);
108
109 if(!pClassID)
110 return E_POINTER;
111
112 /* Windows always returns CLSID_StdURLMoniker */
113 *pClassID = CLSID_StdURLMoniker;
114 return S_OK;
115 }
116
117 static HRESULT WINAPI URLMoniker_IsDirty(IMoniker *iface)
118 {
119 URLMoniker *This = MONIKER_THIS(iface);
120
121 TRACE("(%p)\n",This);
122
123 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
124 method in the OLE-provided moniker interfaces always return S_FALSE because
125 their internal state never changes. */
126 return S_FALSE;
127 }
128
129 static HRESULT WINAPI URLMoniker_Load(IMoniker* iface,IStream* pStm)
130 {
131 URLMoniker *This = MONIKER_THIS(iface);
132 HRESULT res;
133 ULONG size;
134 ULONG got;
135
136 TRACE("(%p,%p)\n",This,pStm);
137
138 if(!pStm)
139 return E_INVALIDARG;
140
141 /*
142 * NOTE
143 * Writes a ULONG containing length of unicode string, followed
144 * by that many unicode characters
145 */
146 res = IStream_Read(pStm, &size, sizeof(ULONG), &got);
147 if(SUCCEEDED(res)) {
148 if(got == sizeof(ULONG)) {
149 heap_free(This->URLName);
150 This->URLName = heap_alloc(size);
151 if(!This->URLName)
152 res = E_OUTOFMEMORY;
153 else {
154 res = IStream_Read(pStm, This->URLName, size, NULL);
155 This->URLName[size/sizeof(WCHAR) - 1] = 0;
156 }
157 }
158 else
159 res = E_FAIL;
160 }
161
162 return res;
163 }
164
165 static HRESULT WINAPI URLMoniker_Save(IMoniker *iface, IStream* pStm, BOOL fClearDirty)
166 {
167 URLMoniker *This = MONIKER_THIS(iface);
168 HRESULT res;
169 ULONG size;
170
171 TRACE("(%p,%p,%d)\n", This, pStm, fClearDirty);
172
173 if(!pStm)
174 return E_INVALIDARG;
175
176 size = (strlenW(This->URLName) + 1)*sizeof(WCHAR);
177 res=IStream_Write(pStm,&size,sizeof(ULONG),NULL);
178 if(SUCCEEDED(res))
179 res=IStream_Write(pStm,This->URLName,size,NULL);
180
181 return res;
182
183 }
184
185 static HRESULT WINAPI URLMoniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER *pcbSize)
186 {
187 URLMoniker *This = MONIKER_THIS(iface);
188
189 TRACE("(%p,%p)\n",This,pcbSize);
190
191 if(!pcbSize)
192 return E_INVALIDARG;
193
194 pcbSize->QuadPart = sizeof(ULONG) + ((strlenW(This->URLName)+1) * sizeof(WCHAR));
195 return S_OK;
196 }
197
198 static HRESULT WINAPI URLMoniker_BindToObject(IMoniker *iface, IBindCtx* pbc, IMoniker *pmkToLeft,
199 REFIID riid, void **ppv)
200 {
201 URLMoniker *This = MONIKER_THIS(iface);
202 IRunningObjectTable *obj_tbl;
203 IUri *uri;
204 HRESULT hres;
205
206 TRACE("(%p)->(%p,%p,%s,%p): stub\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppv);
207
208 hres = IBindCtx_GetRunningObjectTable(pbc, &obj_tbl);
209 if(SUCCEEDED(hres)) {
210 FIXME("use running object table\n");
211 IRunningObjectTable_Release(obj_tbl);
212 }
213
214 hres = CreateUri(This->URLName, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
215 if(FAILED(hres))
216 return hres;
217
218 hres = bind_to_object(iface, uri, pbc, riid, ppv);
219
220 IUri_Release(uri);
221 return hres;
222 }
223
224 static HRESULT WINAPI URLMoniker_BindToStorage(IMoniker* iface, IBindCtx* pbc,
225 IMoniker* pmkToLeft, REFIID riid, void **ppvObject)
226 {
227 URLMoniker *This = MONIKER_THIS(iface);
228 IUri *uri;
229 HRESULT hres;
230
231 TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObject);
232
233 if(pmkToLeft)
234 FIXME("Unsupported pmkToLeft\n");
235
236 hres = CreateUri(This->URLName, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
237 if(FAILED(hres))
238 return hres;
239
240 hres = bind_to_storage(uri, pbc, riid, ppvObject);
241
242 IUri_Release(uri);
243 return hres;
244 }
245
246 static HRESULT WINAPI URLMoniker_Reduce(IMoniker *iface, IBindCtx *pbc,
247 DWORD dwReduceHowFar, IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
248 {
249 URLMoniker *This = MONIKER_THIS(iface);
250
251 TRACE("(%p,%p,%d,%p,%p)\n", This, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
252
253 if(!ppmkReduced)
254 return E_INVALIDARG;
255
256 IMoniker_AddRef(iface);
257 *ppmkReduced = iface;
258 return MK_S_REDUCED_TO_SELF;
259 }
260
261 static HRESULT WINAPI URLMoniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
262 BOOL fOnlyIfNotGeneric, IMoniker **ppmkComposite)
263 {
264 URLMoniker *This = MONIKER_THIS(iface);
265 FIXME("(%p)->(%p,%d,%p): stub\n",This,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
266 return E_NOTIMPL;
267 }
268
269 static HRESULT WINAPI URLMoniker_Enum(IMoniker *iface, BOOL fForward, IEnumMoniker **ppenumMoniker)
270 {
271 URLMoniker *This = MONIKER_THIS(iface);
272
273 TRACE("(%p,%d,%p)\n", This, fForward, ppenumMoniker);
274
275 if(!ppenumMoniker)
276 return E_INVALIDARG;
277
278 /* Does not support sub-monikers */
279 *ppenumMoniker = NULL;
280 return S_OK;
281 }
282
283 static HRESULT WINAPI URLMoniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
284 {
285 URLMoniker *This = MONIKER_THIS(iface);
286 CLSID clsid;
287 LPOLESTR urlPath;
288 IBindCtx* bind;
289 HRESULT res;
290
291 TRACE("(%p,%p)\n",This, pmkOtherMoniker);
292
293 if(pmkOtherMoniker==NULL)
294 return E_INVALIDARG;
295
296 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
297
298 if(!IsEqualCLSID(&clsid,&CLSID_StdURLMoniker))
299 return S_FALSE;
300
301 res = CreateBindCtx(0,&bind);
302 if(FAILED(res))
303 return res;
304
305 res = S_FALSE;
306 if(SUCCEEDED(IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&urlPath))) {
307 int result = lstrcmpiW(urlPath, This->URLName);
308 CoTaskMemFree(urlPath);
309 if(result == 0)
310 res = S_OK;
311 }
312 IUnknown_Release(bind);
313 return res;
314 }
315
316
317 static HRESULT WINAPI URLMoniker_Hash(IMoniker *iface, DWORD *pdwHash)
318 {
319 URLMoniker *This = MONIKER_THIS(iface);
320 int h = 0,i,skip,len;
321 int off = 0;
322 LPOLESTR val;
323
324 TRACE("(%p,%p)\n",This,pdwHash);
325
326 if(!pdwHash)
327 return E_INVALIDARG;
328
329 val = This->URLName;
330 len = lstrlenW(val);
331
332 if(len < 16) {
333 for(i = len ; i > 0; i--) {
334 h = (h * 37) + val[off++];
335 }
336 }else {
337 /* only sample some characters */
338 skip = len / 8;
339 for(i = len; i > 0; i -= skip, off += skip) {
340 h = (h * 39) + val[off];
341 }
342 }
343 *pdwHash = h;
344 return S_OK;
345 }
346
347 static HRESULT WINAPI URLMoniker_IsRunning(IMoniker* iface, IBindCtx* pbc,
348 IMoniker *pmkToLeft, IMoniker *pmkNewlyRunning)
349 {
350 URLMoniker *This = MONIKER_THIS(iface);
351 FIXME("(%p)->(%p,%p,%p): stub\n",This,pbc,pmkToLeft,pmkNewlyRunning);
352 return E_NOTIMPL;
353 }
354
355 static HRESULT WINAPI URLMoniker_GetTimeOfLastChange(IMoniker *iface,
356 IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pFileTime)
357 {
358 URLMoniker *This = MONIKER_THIS(iface);
359 FIXME("(%p)->(%p,%p,%p): stub\n", This, pbc, pmkToLeft, pFileTime);
360 return E_NOTIMPL;
361 }
362
363 static HRESULT WINAPI URLMoniker_Inverse(IMoniker *iface, IMoniker **ppmk)
364 {
365 URLMoniker *This = MONIKER_THIS(iface);
366 TRACE("(%p,%p)\n",This,ppmk);
367 return MK_E_NOINVERSE;
368 }
369
370 static HRESULT WINAPI URLMoniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther, IMoniker **ppmkPrefix)
371 {
372 URLMoniker *This = MONIKER_THIS(iface);
373 FIXME("(%p)->(%p,%p): stub\n",This,pmkOther,ppmkPrefix);
374 return E_NOTIMPL;
375 }
376
377 static HRESULT WINAPI URLMoniker_RelativePathTo(IMoniker *iface, IMoniker *pmOther, IMoniker **ppmkRelPath)
378 {
379 URLMoniker *This = MONIKER_THIS(iface);
380 FIXME("(%p)->(%p,%p): stub\n",This,pmOther,ppmkRelPath);
381 return E_NOTIMPL;
382 }
383
384 static HRESULT WINAPI URLMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
385 LPOLESTR *ppszDisplayName)
386 {
387 URLMoniker *This = MONIKER_THIS(iface);
388 int len;
389
390 TRACE("(%p,%p,%p,%p)\n", This, pbc, pmkToLeft, ppszDisplayName);
391
392 if(!ppszDisplayName)
393 return E_INVALIDARG;
394
395 if(!This->URLName)
396 return E_OUTOFMEMORY;
397
398 /* FIXME: If this is a partial URL, try and get a URL moniker from SZ_URLCONTEXT in the bind context,
399 then look at pmkToLeft to try and complete the URL
400 */
401 len = lstrlenW(This->URLName)+1;
402 *ppszDisplayName = CoTaskMemAlloc(len*sizeof(WCHAR));
403 if(!*ppszDisplayName)
404 return E_OUTOFMEMORY;
405 lstrcpyW(*ppszDisplayName, This->URLName);
406 return S_OK;
407 }
408
409 static HRESULT WINAPI URLMoniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
410 LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
411 {
412 URLMoniker *This = MONIKER_THIS(iface);
413 FIXME("(%p)->(%p,%p,%p,%p,%p): stub\n",This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
414 return E_NOTIMPL;
415 }
416
417 static HRESULT WINAPI URLMoniker_IsSystemMoniker(IMoniker *iface, DWORD *pwdMksys)
418 {
419 URLMoniker *This = MONIKER_THIS(iface);
420
421 TRACE("(%p,%p)\n",This,pwdMksys);
422
423 if(!pwdMksys)
424 return E_INVALIDARG;
425
426 *pwdMksys = MKSYS_URLMONIKER;
427 return S_OK;
428 }
429
430 static const IMonikerVtbl URLMonikerVtbl =
431 {
432 URLMoniker_QueryInterface,
433 URLMoniker_AddRef,
434 URLMoniker_Release,
435 URLMoniker_GetClassID,
436 URLMoniker_IsDirty,
437 URLMoniker_Load,
438 URLMoniker_Save,
439 URLMoniker_GetSizeMax,
440 URLMoniker_BindToObject,
441 URLMoniker_BindToStorage,
442 URLMoniker_Reduce,
443 URLMoniker_ComposeWith,
444 URLMoniker_Enum,
445 URLMoniker_IsEqual,
446 URLMoniker_Hash,
447 URLMoniker_IsRunning,
448 URLMoniker_GetTimeOfLastChange,
449 URLMoniker_Inverse,
450 URLMoniker_CommonPrefixWith,
451 URLMoniker_RelativePathTo,
452 URLMoniker_GetDisplayName,
453 URLMoniker_ParseDisplayName,
454 URLMoniker_IsSystemMoniker
455 };
456
457 static URLMoniker *alloc_moniker(void)
458 {
459 URLMoniker *ret;
460
461 ret = heap_alloc(sizeof(URLMoniker));
462 if(!ret)
463 return NULL;
464
465 ret->lpIMonikerVtbl = &URLMonikerVtbl;
466 ret->ref = 1;
467 ret->URLName = NULL;
468
469 return ret;
470 }
471
472 static HRESULT URLMoniker_Init(URLMoniker *This, LPCOLESTR lpszLeftURLName, LPCOLESTR lpszURLName)
473 {
474 HRESULT hres;
475 DWORD sizeStr = 0;
476
477 TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszLeftURLName),debugstr_w(lpszURLName));
478
479 This->URLName = heap_alloc(INTERNET_MAX_URL_LENGTH*sizeof(WCHAR));
480
481 if(lpszLeftURLName)
482 hres = CoInternetCombineUrl(lpszLeftURLName, lpszURLName, URL_FILE_USE_PATHURL,
483 This->URLName, INTERNET_MAX_URL_LENGTH, &sizeStr, 0);
484 else
485 hres = CoInternetParseUrl(lpszURLName, PARSE_CANONICALIZE, URL_FILE_USE_PATHURL,
486 This->URLName, INTERNET_MAX_URL_LENGTH, &sizeStr, 0);
487
488 if(FAILED(hres)) {
489 heap_free(This->URLName);
490 return hres;
491 }
492
493 URLMON_LockModule();
494
495 if(sizeStr != INTERNET_MAX_URL_LENGTH)
496 This->URLName = heap_realloc(This->URLName, (sizeStr+1)*sizeof(WCHAR));
497
498 TRACE("URLName = %s\n", debugstr_w(This->URLName));
499
500 return S_OK;
501 }
502
503 HRESULT StdURLMoniker_Construct(IUnknown *outer, void **ppv)
504 {
505 TRACE("(%p %p)\n", outer, ppv);
506
507 *ppv = alloc_moniker();
508 return *ppv ? S_OK : E_OUTOFMEMORY;
509 }
510
511 /***********************************************************************
512 * CreateURLMonikerEx (URLMON.@)
513 *
514 * Create a url moniker.
515 *
516 * PARAMS
517 * pmkContext [I] Context
518 * szURL [I] Url to create the moniker for
519 * ppmk [O] Destination for created moniker.
520 * dwFlags [I] Flags.
521 *
522 * RETURNS
523 * Success: S_OK. ppmk contains the created IMoniker object.
524 * Failure: MK_E_SYNTAX if szURL is not a valid url, or
525 * E_OUTOFMEMORY if memory allocation fails.
526 */
527 HRESULT WINAPI CreateURLMonikerEx(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk, DWORD dwFlags)
528 {
529 URLMoniker *obj;
530 HRESULT hres;
531 LPOLESTR lefturl = NULL;
532
533 TRACE("(%p, %s, %p, %08x)\n", pmkContext, debugstr_w(szURL), ppmk, dwFlags);
534
535 if (ppmk)
536 *ppmk = NULL;
537
538 if (!szURL || !ppmk)
539 return E_INVALIDARG;
540
541 if (dwFlags & URL_MK_UNIFORM) FIXME("ignoring flag URL_MK_UNIFORM\n");
542
543 if(!(obj = alloc_moniker()))
544 return E_OUTOFMEMORY;
545
546 if(pmkContext) {
547 IBindCtx* bind;
548 DWORD dwMksys = 0;
549 IMoniker_IsSystemMoniker(pmkContext, &dwMksys);
550 if(dwMksys == MKSYS_URLMONIKER && SUCCEEDED(CreateBindCtx(0, &bind))) {
551 IMoniker_GetDisplayName(pmkContext, bind, NULL, &lefturl);
552 TRACE("lefturl = %s\n", debugstr_w(lefturl));
553 IBindCtx_Release(bind);
554 }
555 }
556
557 hres = URLMoniker_Init(obj, lefturl, szURL);
558 CoTaskMemFree(lefturl);
559 if(SUCCEEDED(hres))
560 hres = URLMoniker_QueryInterface((IMoniker*)obj, &IID_IMoniker, (void**)ppmk);
561 IMoniker_Release((IMoniker*)obj);
562 return hres;
563 }
564
565 /**********************************************************************
566 * CreateURLMoniker (URLMON.@)
567 *
568 * Create a url moniker.
569 *
570 * PARAMS
571 * pmkContext [I] Context
572 * szURL [I] Url to create the moniker for
573 * ppmk [O] Destination for created moniker.
574 *
575 * RETURNS
576 * Success: S_OK. ppmk contains the created IMoniker object.
577 * Failure: MK_E_SYNTAX if szURL is not a valid url, or
578 * E_OUTOFMEMORY if memory allocation fails.
579 */
580 HRESULT WINAPI CreateURLMoniker(IMoniker *pmkContext, LPCWSTR szURL, IMoniker **ppmk)
581 {
582 return CreateURLMonikerEx(pmkContext, szURL, ppmk, URL_MK_LEGACY);
583 }
584
585 /***********************************************************************
586 * IsAsyncMoniker (URLMON.@)
587 */
588 HRESULT WINAPI IsAsyncMoniker(IMoniker *pmk)
589 {
590 IUnknown *am;
591
592 TRACE("(%p)\n", pmk);
593 if(!pmk)
594 return E_INVALIDARG;
595 if(SUCCEEDED(IMoniker_QueryInterface(pmk, &IID_IAsyncMoniker, (void**)&am))) {
596 IUnknown_Release(am);
597 return S_OK;
598 }
599 return S_FALSE;
600 }
601
602 /***********************************************************************
603 * BindAsyncMoniker (URLMON.@)
604 *
605 * Bind a bind status callback to an asynchronous URL Moniker.
606 *
607 * PARAMS
608 * pmk [I] Moniker object to bind status callback to
609 * grfOpt [I] Options, seems not used
610 * pbsc [I] Status callback to bind
611 * iidResult [I] Interface to return
612 * ppvResult [O] Resulting asynchronous moniker object
613 *
614 * RETURNS
615 * Success: S_OK.
616 * Failure: E_INVALIDARG, if any argument is invalid, or
617 * E_OUTOFMEMORY if memory allocation fails.
618 */
619 HRESULT WINAPI BindAsyncMoniker(IMoniker *pmk, DWORD grfOpt, IBindStatusCallback *pbsc, REFIID iidResult, LPVOID *ppvResult)
620 {
621 LPBC pbc = NULL;
622 HRESULT hr = E_INVALIDARG;
623
624 TRACE("(%p %08x %p %s %p)\n", pmk, grfOpt, pbsc, debugstr_guid(iidResult), ppvResult);
625
626 if (pmk && ppvResult)
627 {
628 *ppvResult = NULL;
629
630 hr = CreateAsyncBindCtx(0, pbsc, NULL, &pbc);
631 if (hr == NOERROR)
632 {
633 hr = IMoniker_BindToObject(pmk, pbc, NULL, iidResult, ppvResult);
634 IBindCtx_Release(pbc);
635 }
636 }
637 return hr;
638 }
639
640 /***********************************************************************
641 * MkParseDisplayNameEx (URLMON.@)
642 */
643 HRESULT WINAPI MkParseDisplayNameEx(IBindCtx *pbc, LPCWSTR szDisplayName, ULONG *pchEaten, LPMONIKER *ppmk)
644 {
645 TRACE("(%p %s %p %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
646
647 if (!pbc || !szDisplayName || !*szDisplayName || !pchEaten || !ppmk)
648 return E_INVALIDARG;
649
650 if(is_registered_protocol(szDisplayName)) {
651 HRESULT hres;
652
653 hres = CreateURLMoniker(NULL, szDisplayName, ppmk);
654 if(SUCCEEDED(hres)) {
655 *pchEaten = strlenW(szDisplayName);
656 return hres;
657 }
658 }
659
660 return MkParseDisplayName(pbc, szDisplayName, pchEaten, ppmk);
661 }
662
663
664 /***********************************************************************
665 * URLDownloadToCacheFileA (URLMON.@)
666 */
667 HRESULT WINAPI URLDownloadToCacheFileA(LPUNKNOWN lpUnkCaller, LPCSTR szURL, LPSTR szFileName,
668 DWORD dwBufLength, DWORD dwReserved, LPBINDSTATUSCALLBACK pBSC)
669 {
670 LPWSTR url = NULL, file_name = NULL;
671 int len;
672 HRESULT hres;
673
674 TRACE("(%p %s %p %d %d %p)\n", lpUnkCaller, debugstr_a(szURL), szFileName,
675 dwBufLength, dwReserved, pBSC);
676
677 if(szURL) {
678 len = MultiByteToWideChar(CP_ACP, 0, szURL, -1, NULL, 0);
679 url = heap_alloc(len*sizeof(WCHAR));
680 MultiByteToWideChar(CP_ACP, 0, szURL, -1, url, len);
681 }
682
683 if(szFileName)
684 file_name = heap_alloc(dwBufLength*sizeof(WCHAR));
685
686 hres = URLDownloadToCacheFileW(lpUnkCaller, url, file_name, dwBufLength*sizeof(WCHAR),
687 dwReserved, pBSC);
688
689 if(SUCCEEDED(hres) && file_name)
690 WideCharToMultiByte(CP_ACP, 0, file_name, -1, szFileName, dwBufLength, NULL, NULL);
691
692 heap_free(url);
693 heap_free(file_name);
694
695 return hres;
696 }
697
698 /***********************************************************************
699 * URLDownloadToCacheFileW (URLMON.@)
700 */
701 HRESULT WINAPI URLDownloadToCacheFileW(LPUNKNOWN lpUnkCaller, LPCWSTR szURL, LPWSTR szFileName,
702 DWORD dwBufLength, DWORD dwReserved, LPBINDSTATUSCALLBACK pBSC)
703 {
704 WCHAR cache_path[MAX_PATH + 1];
705 FILETIME expire, modified;
706 HRESULT hr;
707 LPWSTR ext;
708
709 static WCHAR header[] = {
710 'H','T','T','P','/','1','.','0',' ','2','0','0',' ',
711 'O','K','\\','r','\\','n','\\','r','\\','n',0
712 };
713
714 TRACE("(%p, %s, %p, %d, %d, %p)\n", lpUnkCaller, debugstr_w(szURL),
715 szFileName, dwBufLength, dwReserved, pBSC);
716
717 if (!szURL || !szFileName)
718 return E_INVALIDARG;
719
720 ext = PathFindExtensionW(szURL);
721
722 if (!CreateUrlCacheEntryW(szURL, 0, ext, cache_path, 0))
723 return E_FAIL;
724
725 hr = URLDownloadToFileW(lpUnkCaller, szURL, cache_path, 0, pBSC);
726 if (FAILED(hr))
727 return hr;
728
729 expire.dwHighDateTime = 0;
730 expire.dwLowDateTime = 0;
731 modified.dwHighDateTime = 0;
732 modified.dwLowDateTime = 0;
733
734 if (!CommitUrlCacheEntryW(szURL, cache_path, expire, modified, NORMAL_CACHE_ENTRY,
735 header, sizeof(header), NULL, NULL))
736 return E_FAIL;
737
738 if (strlenW(cache_path) > dwBufLength)
739 return E_OUTOFMEMORY;
740
741 lstrcpyW(szFileName, cache_path);
742
743 return S_OK;
744 }
745
746 /***********************************************************************
747 * HlinkSimpleNavigateToMoniker (URLMON.@)
748 */
749 HRESULT WINAPI HlinkSimpleNavigateToMoniker(IMoniker *pmkTarget,
750 LPCWSTR szLocation, LPCWSTR szTargetFrameName, IUnknown *pUnk,
751 IBindCtx *pbc, IBindStatusCallback *pbsc, DWORD grfHLNF, DWORD dwReserved)
752 {
753 LPWSTR target;
754 HRESULT hres;
755
756 TRACE("\n");
757
758 hres = IMoniker_GetDisplayName(pmkTarget, pbc, 0, &target);
759 if(hres == S_OK)
760 hres = HlinkSimpleNavigateToString( target, szLocation, szTargetFrameName,
761 pUnk, pbc, pbsc, grfHLNF, dwReserved );
762 CoTaskMemFree(target);
763
764 return hres;
765 }
766
767 /***********************************************************************
768 * HlinkSimpleNavigateToString (URLMON.@)
769 */
770 HRESULT WINAPI HlinkSimpleNavigateToString( LPCWSTR szTarget,
771 LPCWSTR szLocation, LPCWSTR szTargetFrameName, IUnknown *pUnk,
772 IBindCtx *pbc, IBindStatusCallback *pbsc, DWORD grfHLNF, DWORD dwReserved)
773 {
774 FIXME("%s %s %s %p %p %p %u %u partial stub\n", debugstr_w( szTarget ), debugstr_w( szLocation ),
775 debugstr_w( szTargetFrameName ), pUnk, pbc, pbsc, grfHLNF, dwReserved);
776
777 /* undocumented: 0 means HLNF_OPENINNEWWINDOW*/
778 if (!grfHLNF) grfHLNF = HLNF_OPENINNEWWINDOW;
779
780 if (grfHLNF == HLNF_OPENINNEWWINDOW)
781 {
782 SHELLEXECUTEINFOW sei;
783 static const WCHAR openW[] = { 'o', 'p', 'e', 'n', 0 };
784
785 memset(&sei, 0, sizeof(sei));
786 sei.cbSize = sizeof(sei);
787 sei.lpVerb = openW;
788 sei.nShow = SW_SHOWNORMAL;
789 sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NO_CONSOLE;
790 sei.lpFile = szTarget;
791
792 if (ShellExecuteExW(&sei)) return S_OK;
793 }
794
795 return E_NOTIMPL;
796 }
797
798 /***********************************************************************
799 * HlinkNavigateString (URLMON.@)
800 */
801 HRESULT WINAPI HlinkNavigateString( IUnknown *pUnk, LPCWSTR szTarget )
802 {
803 TRACE("%p %s\n", pUnk, debugstr_w( szTarget ) );
804 return HlinkSimpleNavigateToString(
805 szTarget, NULL, NULL, pUnk, NULL, NULL, 0, 0 );
806 }
807
808 /***********************************************************************
809 * GetSoftwareUpdateInfo (URLMON.@)
810 */
811 HRESULT WINAPI GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi )
812 {
813 FIXME("%s %p\n", debugstr_w(szDistUnit), psdi );
814 return E_FAIL;
815 }
816
817 /***********************************************************************
818 * AsyncInstallDistributionUnit (URLMON.@)
819 */
820 HRESULT WINAPI AsyncInstallDistributionUnit( LPCWSTR szDistUnit, LPCWSTR szTYPE,
821 LPCWSTR szExt, DWORD dwFileVersionMS, DWORD dwFileVersionLS,
822 LPCWSTR szURL, IBindCtx *pbc, LPVOID pvReserved, DWORD flags )
823 {
824 FIXME(": stub\n");
825 return E_NOTIMPL;
826 }