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 /***********************************************************************
125 * DllMain (URLMON.init)
127 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
129 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
132 case DLL_PROCESS_ATTACH:
133 URLMON_hInstance = hinstDLL;
137 case DLL_PROCESS_DETACH:
139 FreeLibrary(hCabinet);
144 URLMON_hInstance = 0;
147 case DLL_THREAD_DETACH:
155 /***********************************************************************
156 * DllInstall (URLMON.@)
158 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
160 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
161 debugstr_w(cmdline));
166 /***********************************************************************
167 * DllCanUnloadNow (URLMON.@)
169 HRESULT WINAPI DllCanUnloadNow(void)
171 return URLMON_refCount != 0 ? S_FALSE : S_OK;
176 /******************************************************************************
177 * Urlmon ClassFactory
180 const IClassFactoryVtbl *lpClassFactoryVtbl;
182 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
185 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
187 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
191 if(IsEqualGUID(riid, &IID_IUnknown)) {
192 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
194 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
195 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
200 IUnknown_AddRef((IUnknown*)*ppv);
204 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
205 return E_NOINTERFACE;
208 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
214 static ULONG WINAPI CF_Release(IClassFactory *iface)
216 URLMON_UnlockModule();
221 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
222 REFIID riid, LPVOID *ppobj)
224 ClassFactory *This = (ClassFactory*)iface;
228 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
231 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
232 hres = IUnknown_QueryInterface(punk, riid, ppobj);
233 IUnknown_Release(punk);
238 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
240 TRACE("(%d)\n", dolock);
245 URLMON_UnlockModule();
250 static const IClassFactoryVtbl ClassFactoryVtbl =
259 static const ClassFactory FileProtocolCF =
260 { &ClassFactoryVtbl, FileProtocol_Construct};
261 static const ClassFactory FtpProtocolCF =
262 { &ClassFactoryVtbl, FtpProtocol_Construct};
263 static const ClassFactory GopherProtocolCF =
264 { &ClassFactoryVtbl, GopherProtocol_Construct};
265 static const ClassFactory HttpProtocolCF =
266 { &ClassFactoryVtbl, HttpProtocol_Construct};
267 static const ClassFactory HttpSProtocolCF =
268 { &ClassFactoryVtbl, HttpSProtocol_Construct};
269 static const ClassFactory MkProtocolCF =
270 { &ClassFactoryVtbl, MkProtocol_Construct};
271 static const ClassFactory SecurityManagerCF =
272 { &ClassFactoryVtbl, SecManagerImpl_Construct};
273 static const ClassFactory ZoneManagerCF =
274 { &ClassFactoryVtbl, ZoneMgrImpl_Construct};
275 static const ClassFactory StdURLMonikerCF =
276 { &ClassFactoryVtbl, StdURLMoniker_Construct};
277 static const ClassFactory MimeFilterCF =
278 { &ClassFactoryVtbl, MimeFilter_Construct};
280 struct object_creation_info
287 static const WCHAR wszFile[] = {'f','i','l','e',0};
288 static const WCHAR wszFtp[] = {'f','t','p',0};
289 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
290 static const WCHAR wszHttp[] = {'h','t','t','p',0};
291 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
292 static const WCHAR wszMk[] = {'m','k',0};
294 static const struct object_creation_info object_creation[] =
296 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
297 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
298 { &CLSID_GopherProtocol, CLASSFACTORY(&GopherProtocolCF), wszGopher },
299 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
300 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
301 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
302 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
303 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL },
304 { &CLSID_StdURLMoniker, CLASSFACTORY(&StdURLMonikerCF), NULL },
305 { &CLSID_DeCompMimeFilter, CLASSFACTORY(&MimeFilterCF), NULL }
308 static void init_session(BOOL init)
312 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
314 if(object_creation[i].protocol)
315 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
316 object_creation[i].protocol, init);
320 /*******************************************************************************
321 * DllGetClassObject [URLMON.@]
322 * Retrieves class object from a DLL object
325 * Docs say returns STDAPI
328 * rclsid [I] CLSID for the class object
329 * riid [I] Reference to identifier of interface for class object
330 * ppv [O] Address of variable to receive interface pointer for riid
334 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
338 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
342 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
344 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
346 if (IsEqualGUID(object_creation[i].clsid, rclsid))
347 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
350 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
351 return CLASS_E_CLASSNOTAVAILABLE;
355 /***********************************************************************
356 * DllRegisterServerEx (URLMON.@)
358 HRESULT WINAPI DllRegisterServerEx(void)
360 FIXME("(void): stub\n");
365 /**************************************************************************
366 * UrlMkSetSessionOption (URLMON.@)
368 HRESULT WINAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
371 FIXME("(%#x, %p, %#x): stub\n", dwOption, pBuffer, dwBufferLength);
376 static const CHAR Agent[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
378 /**************************************************************************
379 * ObtainUserAgentString (URLMON.@)
381 HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPSTR pcszUAOut, DWORD *cbSize)
383 FIXME("(%d, %p, %p): stub\n", dwOption, pcszUAOut, cbSize);
385 if (pcszUAOut == NULL || cbSize == NULL)
388 if (*cbSize < sizeof(Agent))
390 *cbSize = sizeof(Agent);
391 return E_OUTOFMEMORY;
394 if (sizeof(Agent) < *cbSize)
395 *cbSize = sizeof(Agent);
396 lstrcpynA(pcszUAOut, Agent, *cbSize);
401 /**************************************************************************
402 * IsValidURL (URLMON.@)
404 * Determines if a specified string is a valid URL.
407 * pBC [I] ignored, must be NULL.
408 * szURL [I] string that represents the URL in question.
409 * dwReserved [I] reserved and must be zero.
414 * returns E_INVALIDARG if one or more of the args is invalid.
417 * test functionality against windows to see what a valid URL is.
419 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
421 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
423 if (pBC != NULL || dwReserved != 0)
429 /**************************************************************************
430 * FaultInIEFeature (URLMON.@)
432 * Undocumented. Appears to be used by native shdocvw.dll.
434 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
435 QUERYCONTEXT *pQuery, DWORD flags )
437 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
441 /**************************************************************************
442 * CoGetClassObjectFromURL (URLMON.@)
444 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
445 DWORD dwFileVersionLS, LPCWSTR szContentType,
446 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
447 REFIID riid, LPVOID *ppv )
449 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
450 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
451 debugstr_guid(riid), ppv);
452 return E_NOINTERFACE;
455 /***********************************************************************
456 * ReleaseBindInfo (URLMON.@)
458 * Release the resources used by the specified BINDINFO structure.
461 * pbindinfo [I] BINDINFO to release.
466 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
470 TRACE("(%p)\n", pbindinfo);
472 if(!pbindinfo || !(size = pbindinfo->cbSize))
475 CoTaskMemFree(pbindinfo->szExtraInfo);
476 ReleaseStgMedium(&pbindinfo->stgmedData);
478 if(offsetof(BINDINFO, szExtraInfo) < size)
479 CoTaskMemFree(pbindinfo->szCustomVerb);
481 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
482 IUnknown_Release(pbindinfo->pUnk);
484 memset(pbindinfo, 0, size);
485 pbindinfo->cbSize = size;
488 /***********************************************************************
489 * CopyStgMedium (URLMON.@)
491 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
493 TRACE("(%p %p)\n", src, dst);
504 if(src->u.lpszFileName && !src->pUnkForRelease) {
505 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
506 dst->u.lpszFileName = CoTaskMemAlloc(size);
507 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
512 IStream_AddRef(dst->u.pstm);
516 IStorage_AddRef(dst->u.pstg);
519 FIXME("Unimplemented tymed %d\n", src->tymed);
522 if(dst->pUnkForRelease)
523 IUnknown_AddRef(dst->pUnkForRelease);
528 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
530 return size > 5 && !memcmp(b, "{\\rtf", 5);
533 static BOOL text_html_filter(const BYTE *b, DWORD size)
540 for(i=0; i < size-5; i++) {
542 && (b[i+1] == 'h' || b[i+1] == 'H')
543 && (b[i+2] == 't' || b[i+2] == 'T')
544 && (b[i+3] == 'm' || b[i+3] == 'M')
545 && (b[i+4] == 'l' || b[i+4] == 'L'))
552 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
555 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
558 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
561 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
562 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
565 static BOOL image_gif_filter(const BYTE *b, DWORD size)
568 && (b[0] == 'G' || b[0] == 'g')
569 && (b[1] == 'I' || b[1] == 'i')
570 && (b[2] == 'F' || b[2] == 'f')
572 && (b[4] == '7' || b[4] == '9')
573 && (b[5] == 'A' || b[5] == 'a');
576 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
578 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
581 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
583 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
586 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
588 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
589 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
592 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
595 && b[0] == 0x42 && b[1] == 0x4d
596 && *(const DWORD *)(b+6) == 0;
599 static BOOL video_avi_filter(const BYTE *b, DWORD size)
602 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
603 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
606 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
609 && !b[0] && !b[1] && b[2] == 0x01
610 && (b[3] == 0xb3 || b[3] == 0xba);
613 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
615 return size > 2 && b[0] == '%' && b[1] == '!';
618 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
620 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
623 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
625 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
628 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
630 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
633 static BOOL application_java_filter(const BYTE *b, DWORD size)
635 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
638 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
640 return size > 2 && b[0] == 'M' && b[1] == 'Z';
643 static BOOL text_plain_filter(const BYTE *b, DWORD size)
647 for(ptr = b; ptr < b+size-1; ptr++) {
648 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
655 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
660 /***********************************************************************
661 * FindMimeFromData (URLMON.@)
663 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
665 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
666 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
667 LPWSTR* ppwzMimeOut, DWORD dwReserved)
669 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
670 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
673 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
675 WARN("dwReserved=%d\n", dwReserved);
677 /* pBC seams to not be used */
679 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
682 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
688 len = strlenW(pwzMimeProposed)+1;
689 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
690 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
695 const BYTE *buf = pBuffer;
700 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
701 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
702 static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
703 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
704 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
705 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
706 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
707 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
708 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
709 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
710 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
711 static const WCHAR wszAppPostscript[] =
712 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
713 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
715 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
716 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
717 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
718 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
719 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
721 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
722 'x','-','m','s','d','o','w','n','l','o','a','d',0};
723 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
724 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
725 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
727 static const struct {
729 BOOL (*filter)(const BYTE *,DWORD);
731 {wszTextHtml, text_html_filter},
732 {wszTextRichtext, text_richtext_filter},
733 /* {wszAudioXAiff, audio_xaiff_filter}, */
734 {wszAudioBasic, audio_basic_filter},
735 {wszAudioWav, audio_wav_filter},
736 {wszImageGif, image_gif_filter},
737 {wszImagePjpeg, image_pjpeg_filter},
738 {wszImageTiff, image_tiff_filter},
739 {wszImageXPng, image_xpng_filter},
740 /* {wszImageXBitmap, image_xbitmap_filter}, */
741 {wszImageBmp, image_bmp_filter},
742 /* {wszImageXJg, image_xjg_filter}, */
743 /* {wszImageXEmf, image_xemf_filter}, */
744 /* {wszImageXWmf, image_xwmf_filter}, */
745 {wszVideoAvi, video_avi_filter},
746 {wszVideoMpeg, video_mpeg_filter},
747 {wszAppPostscript, application_postscript_filter},
748 /* {wszAppBase64, application_base64_filter}, */
749 /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
750 {wszAppPdf, application_pdf_filter},
751 /* {wszAppXCompressed, application_xcompressed_filter}, */
752 {wszAppXZip, application_xzip_filter},
753 {wszAppXGzip, application_xgzip_filter},
754 {wszAppJava, application_java_filter},
755 {wszAppXMSDownload, application_xmsdownload},
756 {wszTextPlain, text_plain_filter},
757 {wszAppOctetStream, application_octet_stream_filter}
763 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
764 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
765 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
769 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
770 || mime_filters[i].filter(buf, cbSize)) {
771 len = strlenW(pwzMimeProposed)+1;
772 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
773 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
780 if(mime_filters[i].filter(buf, cbSize))
781 ret = mime_filters[i].mime;
785 TRACE("found %s for data\n"
786 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
787 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
788 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
790 if(pwzMimeProposed) {
791 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
792 ret = pwzMimeProposed;
794 /* text/html is a special case */
795 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
799 len = strlenW(ret)+1;
800 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
801 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
811 static const WCHAR wszContentType[] =
812 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
814 ptr = strrchrW(pwzUrl, '.');
818 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
819 if(res != ERROR_SUCCESS)
820 return HRESULT_FROM_WIN32(res);
823 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
825 if(res != ERROR_SUCCESS)
826 return HRESULT_FROM_WIN32(res);
828 *ppwzMimeOut = CoTaskMemAlloc(size);
829 memcpy(*ppwzMimeOut, mime, size);
836 /***********************************************************************
837 * GetClassFileOrMime (URLMON.@)
839 * Determines the class ID from the bind context, file name or MIME type.
841 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
842 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
845 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
846 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
851 /***********************************************************************
854 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
856 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
859 hCabinet = LoadLibraryA("cabinet.dll");
861 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
862 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
863 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
865 return pExtract(dest, szCabName);
868 /***********************************************************************
869 * IsLoggingEnabledA (URLMON.@)
871 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
873 FIXME("(%s)\n", debugstr_a(url));
877 /***********************************************************************
878 * IsLoggingEnabledW (URLMON.@)
880 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
882 FIXME("(%s)\n", debugstr_w(url));