4 * Copyright (c) 2000 Patrik Stridvall
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "urlmon_main.h"
27 #define NO_SHLWAPI_REG
29 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
35 LONG URLMON_refCount = 0;
37 HINSTANCE URLMON_hInstance = 0;
38 static HMODULE hCabinet = NULL;
39 static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
41 static void init_session(BOOL);
43 static struct list tls_list = LIST_INIT(tls_list);
45 static CRITICAL_SECTION tls_cs;
46 static CRITICAL_SECTION_DEBUG tls_cs_dbg =
49 { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList },
50 0, 0, { (DWORD_PTR)(__FILE__ ": tls") }
53 static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 };
55 tls_data_t *get_tls_data(void)
59 if(urlmon_tls == TLS_OUT_OF_INDEXES) {
60 DWORD tls = TlsAlloc();
61 if(tls == TLS_OUT_OF_INDEXES)
64 tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES);
69 data = TlsGetValue(urlmon_tls);
71 data = heap_alloc_zero(sizeof(tls_data_t));
75 EnterCriticalSection(&tls_cs);
76 list_add_tail(&tls_list, &data->entry);
77 LeaveCriticalSection(&tls_cs);
79 TlsSetValue(urlmon_tls, data);
85 static void free_tls_list(void)
89 if(urlmon_tls == TLS_OUT_OF_INDEXES)
92 while(!list_empty(&tls_list)) {
93 data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry);
94 list_remove(&data->entry);
101 static void detach_thread(void)
105 if(urlmon_tls == TLS_OUT_OF_INDEXES)
108 data = TlsGetValue(urlmon_tls);
112 EnterCriticalSection(&tls_cs);
113 list_remove(&data->entry);
114 LeaveCriticalSection(&tls_cs);
116 if(data->notif_hwnd) {
117 WARN("notif_hwnd not destroyed\n");
118 DestroyWindow(data->notif_hwnd);
124 static void process_detach(void)
126 HINTERNET internet_session;
128 internet_session = get_internet_session(NULL);
130 InternetCloseHandle(internet_session);
133 FreeLibrary(hCabinet);
140 /***********************************************************************
141 * DllMain (URLMON.init)
143 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
145 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
148 case DLL_PROCESS_ATTACH:
149 URLMON_hInstance = hinstDLL;
153 case DLL_PROCESS_DETACH:
157 case DLL_THREAD_DETACH:
165 /***********************************************************************
166 * DllInstall (URLMON.@)
168 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
170 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
171 debugstr_w(cmdline));
176 /***********************************************************************
177 * DllCanUnloadNow (URLMON.@)
179 HRESULT WINAPI DllCanUnloadNow(void)
181 return URLMON_refCount != 0 ? S_FALSE : S_OK;
186 /******************************************************************************
187 * Urlmon ClassFactory
190 const IClassFactoryVtbl *lpClassFactoryVtbl;
192 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
195 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
197 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
201 if(IsEqualGUID(riid, &IID_IUnknown)) {
202 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
204 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
205 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
210 IUnknown_AddRef((IUnknown*)*ppv);
214 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
215 return E_NOINTERFACE;
218 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
224 static ULONG WINAPI CF_Release(IClassFactory *iface)
226 URLMON_UnlockModule();
231 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
232 REFIID riid, LPVOID *ppobj)
234 ClassFactory *This = (ClassFactory*)iface;
238 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
241 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
242 hres = IUnknown_QueryInterface(punk, riid, ppobj);
243 IUnknown_Release(punk);
248 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
250 TRACE("(%d)\n", dolock);
255 URLMON_UnlockModule();
260 static const IClassFactoryVtbl ClassFactoryVtbl =
269 static const ClassFactory FileProtocolCF =
270 { &ClassFactoryVtbl, FileProtocol_Construct};
271 static const ClassFactory FtpProtocolCF =
272 { &ClassFactoryVtbl, FtpProtocol_Construct};
273 static const ClassFactory GopherProtocolCF =
274 { &ClassFactoryVtbl, GopherProtocol_Construct};
275 static const ClassFactory HttpProtocolCF =
276 { &ClassFactoryVtbl, HttpProtocol_Construct};
277 static const ClassFactory HttpSProtocolCF =
278 { &ClassFactoryVtbl, HttpSProtocol_Construct};
279 static const ClassFactory MkProtocolCF =
280 { &ClassFactoryVtbl, MkProtocol_Construct};
281 static const ClassFactory SecurityManagerCF =
282 { &ClassFactoryVtbl, SecManagerImpl_Construct};
283 static const ClassFactory ZoneManagerCF =
284 { &ClassFactoryVtbl, ZoneMgrImpl_Construct};
285 static const ClassFactory StdURLMonikerCF =
286 { &ClassFactoryVtbl, StdURLMoniker_Construct};
287 static const ClassFactory MimeFilterCF =
288 { &ClassFactoryVtbl, MimeFilter_Construct};
290 struct object_creation_info
297 static const WCHAR wszFile[] = {'f','i','l','e',0};
298 static const WCHAR wszFtp[] = {'f','t','p',0};
299 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
300 static const WCHAR wszHttp[] = {'h','t','t','p',0};
301 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
302 static const WCHAR wszMk[] = {'m','k',0};
304 static const struct object_creation_info object_creation[] =
306 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
307 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
308 { &CLSID_GopherProtocol, CLASSFACTORY(&GopherProtocolCF), wszGopher },
309 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
310 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
311 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
312 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
313 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL },
314 { &CLSID_StdURLMoniker, CLASSFACTORY(&StdURLMonikerCF), NULL },
315 { &CLSID_DeCompMimeFilter, CLASSFACTORY(&MimeFilterCF), NULL }
318 static void init_session(BOOL init)
322 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
324 if(object_creation[i].protocol)
325 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
326 object_creation[i].protocol, init);
330 /*******************************************************************************
331 * DllGetClassObject [URLMON.@]
332 * Retrieves class object from a DLL object
335 * Docs say returns STDAPI
338 * rclsid [I] CLSID for the class object
339 * riid [I] Reference to identifier of interface for class object
340 * ppv [O] Address of variable to receive interface pointer for riid
344 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
348 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
352 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
354 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
356 if (IsEqualGUID(object_creation[i].clsid, rclsid))
357 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
360 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
361 return CLASS_E_CLASSNOTAVAILABLE;
365 /***********************************************************************
366 * DllRegisterServerEx (URLMON.@)
368 HRESULT WINAPI DllRegisterServerEx(void)
370 FIXME("(void): stub\n");
375 /**************************************************************************
376 * IsValidURL (URLMON.@)
378 * Determines if a specified string is a valid URL.
381 * pBC [I] ignored, must be NULL.
382 * szURL [I] string that represents the URL in question.
383 * dwReserved [I] reserved and must be zero.
388 * returns E_INVALIDARG if one or more of the args is invalid.
391 * test functionality against windows to see what a valid URL is.
393 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
395 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
397 if (pBC || dwReserved || !szURL)
403 /**************************************************************************
404 * FaultInIEFeature (URLMON.@)
406 * Undocumented. Appears to be used by native shdocvw.dll.
408 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
409 QUERYCONTEXT *pQuery, DWORD flags )
411 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
415 /**************************************************************************
416 * CoGetClassObjectFromURL (URLMON.@)
418 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
419 DWORD dwFileVersionLS, LPCWSTR szContentType,
420 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
421 REFIID riid, LPVOID *ppv )
423 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
424 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
425 debugstr_guid(riid), ppv);
426 return E_NOINTERFACE;
429 /***********************************************************************
430 * ReleaseBindInfo (URLMON.@)
432 * Release the resources used by the specified BINDINFO structure.
435 * pbindinfo [I] BINDINFO to release.
440 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
444 TRACE("(%p)\n", pbindinfo);
446 if(!pbindinfo || !(size = pbindinfo->cbSize))
449 CoTaskMemFree(pbindinfo->szExtraInfo);
450 ReleaseStgMedium(&pbindinfo->stgmedData);
452 if(offsetof(BINDINFO, szExtraInfo) < size)
453 CoTaskMemFree(pbindinfo->szCustomVerb);
455 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
456 IUnknown_Release(pbindinfo->pUnk);
458 memset(pbindinfo, 0, size);
459 pbindinfo->cbSize = size;
462 /***********************************************************************
463 * CopyStgMedium (URLMON.@)
465 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
467 TRACE("(%p %p)\n", src, dst);
478 if(src->u.lpszFileName && !src->pUnkForRelease) {
479 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
480 dst->u.lpszFileName = CoTaskMemAlloc(size);
481 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
486 IStream_AddRef(dst->u.pstm);
490 IStorage_AddRef(dst->u.pstg);
493 FIXME("Unimplemented tymed %d\n", src->tymed);
496 if(dst->pUnkForRelease)
497 IUnknown_AddRef(dst->pUnkForRelease);
502 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
504 return size > 5 && !memcmp(b, "{\\rtf", 5);
507 static BOOL text_html_filter(const BYTE *b, DWORD size)
514 for(i=0; i < size-5; i++) {
516 && (b[i+1] == 'h' || b[i+1] == 'H')
517 && (b[i+2] == 't' || b[i+2] == 'T')
518 && (b[i+3] == 'm' || b[i+3] == 'M')
519 && (b[i+4] == 'l' || b[i+4] == 'L'))
526 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
529 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
532 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
535 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
536 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
539 static BOOL image_gif_filter(const BYTE *b, DWORD size)
542 && (b[0] == 'G' || b[0] == 'g')
543 && (b[1] == 'I' || b[1] == 'i')
544 && (b[2] == 'F' || b[2] == 'f')
546 && (b[4] == '7' || b[4] == '9')
547 && (b[5] == 'A' || b[5] == 'a');
550 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
552 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
555 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
557 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
560 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
562 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
563 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
566 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
569 && b[0] == 0x42 && b[1] == 0x4d
570 && *(const DWORD *)(b+6) == 0;
573 static BOOL video_avi_filter(const BYTE *b, DWORD size)
576 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
577 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
580 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
583 && !b[0] && !b[1] && b[2] == 0x01
584 && (b[3] == 0xb3 || b[3] == 0xba);
587 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
589 return size > 2 && b[0] == '%' && b[1] == '!';
592 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
594 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
597 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
599 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
602 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
604 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
607 static BOOL application_java_filter(const BYTE *b, DWORD size)
609 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
612 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
614 return size > 2 && b[0] == 'M' && b[1] == 'Z';
617 static BOOL text_plain_filter(const BYTE *b, DWORD size)
621 for(ptr = b; ptr < b+size-1; ptr++) {
622 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
629 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
634 /***********************************************************************
635 * FindMimeFromData (URLMON.@)
637 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
639 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
640 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
641 LPWSTR* ppwzMimeOut, DWORD dwReserved)
643 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
644 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
647 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
649 WARN("dwReserved=%d\n", dwReserved);
651 /* pBC seams to not be used */
653 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
656 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
662 len = strlenW(pwzMimeProposed)+1;
663 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
664 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
669 const BYTE *buf = pBuffer;
674 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
675 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
676 static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
677 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
678 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
679 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
680 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
681 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
682 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
683 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
684 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
685 static const WCHAR wszAppPostscript[] =
686 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
687 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
689 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
690 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
691 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
692 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
693 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
695 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
696 'x','-','m','s','d','o','w','n','l','o','a','d',0};
697 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
698 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
699 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
701 static const struct {
703 BOOL (*filter)(const BYTE *,DWORD);
705 {wszTextHtml, text_html_filter},
706 {wszTextRichtext, text_richtext_filter},
707 /* {wszAudioXAiff, audio_xaiff_filter}, */
708 {wszAudioBasic, audio_basic_filter},
709 {wszAudioWav, audio_wav_filter},
710 {wszImageGif, image_gif_filter},
711 {wszImagePjpeg, image_pjpeg_filter},
712 {wszImageTiff, image_tiff_filter},
713 {wszImageXPng, image_xpng_filter},
714 /* {wszImageXBitmap, image_xbitmap_filter}, */
715 {wszImageBmp, image_bmp_filter},
716 /* {wszImageXJg, image_xjg_filter}, */
717 /* {wszImageXEmf, image_xemf_filter}, */
718 /* {wszImageXWmf, image_xwmf_filter}, */
719 {wszVideoAvi, video_avi_filter},
720 {wszVideoMpeg, video_mpeg_filter},
721 {wszAppPostscript, application_postscript_filter},
722 /* {wszAppBase64, application_base64_filter}, */
723 /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
724 {wszAppPdf, application_pdf_filter},
725 /* {wszAppXCompressed, application_xcompressed_filter}, */
726 {wszAppXZip, application_xzip_filter},
727 {wszAppXGzip, application_xgzip_filter},
728 {wszAppJava, application_java_filter},
729 {wszAppXMSDownload, application_xmsdownload},
730 {wszTextPlain, text_plain_filter},
731 {wszAppOctetStream, application_octet_stream_filter}
737 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
738 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
739 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
743 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
744 || mime_filters[i].filter(buf, cbSize)) {
745 len = strlenW(pwzMimeProposed)+1;
746 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
747 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
754 if(mime_filters[i].filter(buf, cbSize))
755 ret = mime_filters[i].mime;
759 TRACE("found %s for data\n"
760 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
761 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
762 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
764 if(pwzMimeProposed) {
765 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
766 ret = pwzMimeProposed;
768 /* text/html is a special case */
769 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
773 len = strlenW(ret)+1;
774 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
775 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
785 static const WCHAR wszContentType[] =
786 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
788 ptr = strrchrW(pwzUrl, '.');
792 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
793 if(res != ERROR_SUCCESS)
794 return HRESULT_FROM_WIN32(res);
797 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
799 if(res != ERROR_SUCCESS)
800 return HRESULT_FROM_WIN32(res);
802 *ppwzMimeOut = CoTaskMemAlloc(size);
803 memcpy(*ppwzMimeOut, mime, size);
810 /***********************************************************************
811 * GetClassFileOrMime (URLMON.@)
813 * Determines the class ID from the bind context, file name or MIME type.
815 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
816 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
819 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
820 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
825 /***********************************************************************
828 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
830 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
833 hCabinet = LoadLibraryA("cabinet.dll");
835 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
836 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
837 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
839 return pExtract(dest, szCabName);
842 /***********************************************************************
843 * IsLoggingEnabledA (URLMON.@)
845 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
847 FIXME("(%s)\n", debugstr_a(url));
851 /***********************************************************************
852 * IsLoggingEnabledW (URLMON.@)
854 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
856 FIXME("(%s)\n", debugstr_w(url));