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);
143 URLMON_hInstance = 0;
146 case DLL_THREAD_DETACH:
154 /***********************************************************************
155 * DllInstall (URLMON.@)
157 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
159 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
160 debugstr_w(cmdline));
165 /***********************************************************************
166 * DllCanUnloadNow (URLMON.@)
168 HRESULT WINAPI DllCanUnloadNow(void)
170 return URLMON_refCount != 0 ? S_FALSE : S_OK;
175 /******************************************************************************
176 * Urlmon ClassFactory
179 const IClassFactoryVtbl *lpClassFactoryVtbl;
181 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
184 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
186 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
190 if(IsEqualGUID(riid, &IID_IUnknown)) {
191 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
193 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
194 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
199 IUnknown_AddRef((IUnknown*)*ppv);
203 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
204 return E_NOINTERFACE;
207 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
213 static ULONG WINAPI CF_Release(IClassFactory *iface)
215 URLMON_UnlockModule();
220 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
221 REFIID riid, LPVOID *ppobj)
223 ClassFactory *This = (ClassFactory*)iface;
227 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
230 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
231 hres = IUnknown_QueryInterface(punk, riid, ppobj);
232 IUnknown_Release(punk);
237 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
239 TRACE("(%d)\n", dolock);
244 URLMON_UnlockModule();
249 static const IClassFactoryVtbl ClassFactoryVtbl =
258 static const ClassFactory FileProtocolCF =
259 { &ClassFactoryVtbl, FileProtocol_Construct};
260 static const ClassFactory FtpProtocolCF =
261 { &ClassFactoryVtbl, FtpProtocol_Construct};
262 static const ClassFactory GopherProtocolCF =
263 { &ClassFactoryVtbl, GopherProtocol_Construct};
264 static const ClassFactory HttpProtocolCF =
265 { &ClassFactoryVtbl, HttpProtocol_Construct};
266 static const ClassFactory HttpSProtocolCF =
267 { &ClassFactoryVtbl, HttpSProtocol_Construct};
268 static const ClassFactory MkProtocolCF =
269 { &ClassFactoryVtbl, MkProtocol_Construct};
270 static const ClassFactory SecurityManagerCF =
271 { &ClassFactoryVtbl, SecManagerImpl_Construct};
272 static const ClassFactory ZoneManagerCF =
273 { &ClassFactoryVtbl, ZoneMgrImpl_Construct};
274 static const ClassFactory StdURLMonikerCF =
275 { &ClassFactoryVtbl, StdURLMoniker_Construct};
276 static const ClassFactory MimeFilterCF =
277 { &ClassFactoryVtbl, MimeFilter_Construct};
279 struct object_creation_info
286 static const WCHAR wszFile[] = {'f','i','l','e',0};
287 static const WCHAR wszFtp[] = {'f','t','p',0};
288 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
289 static const WCHAR wszHttp[] = {'h','t','t','p',0};
290 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
291 static const WCHAR wszMk[] = {'m','k',0};
293 static const struct object_creation_info object_creation[] =
295 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
296 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
297 { &CLSID_GopherProtocol, CLASSFACTORY(&GopherProtocolCF), wszGopher },
298 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
299 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
300 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
301 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
302 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL },
303 { &CLSID_StdURLMoniker, CLASSFACTORY(&StdURLMonikerCF), NULL },
304 { &CLSID_DeCompMimeFilter, CLASSFACTORY(&MimeFilterCF), NULL }
307 static void init_session(BOOL init)
311 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
313 if(object_creation[i].protocol)
314 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
315 object_creation[i].protocol, init);
319 /*******************************************************************************
320 * DllGetClassObject [URLMON.@]
321 * Retrieves class object from a DLL object
324 * Docs say returns STDAPI
327 * rclsid [I] CLSID for the class object
328 * riid [I] Reference to identifier of interface for class object
329 * ppv [O] Address of variable to receive interface pointer for riid
333 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
337 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
341 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
343 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
345 if (IsEqualGUID(object_creation[i].clsid, rclsid))
346 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
349 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
350 return CLASS_E_CLASSNOTAVAILABLE;
354 /***********************************************************************
355 * DllRegisterServerEx (URLMON.@)
357 HRESULT WINAPI DllRegisterServerEx(void)
359 FIXME("(void): stub\n");
364 /**************************************************************************
365 * UrlMkSetSessionOption (URLMON.@)
367 HRESULT WINAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
370 FIXME("(%#x, %p, %#x): stub\n", dwOption, pBuffer, dwBufferLength);
375 static const CHAR Agent[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
377 /**************************************************************************
378 * ObtainUserAgentString (URLMON.@)
380 HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPSTR pcszUAOut, DWORD *cbSize)
382 FIXME("(%d, %p, %p): stub\n", dwOption, pcszUAOut, cbSize);
384 if (pcszUAOut == NULL || cbSize == NULL)
387 if (*cbSize < sizeof(Agent))
389 *cbSize = sizeof(Agent);
390 return E_OUTOFMEMORY;
393 if (sizeof(Agent) < *cbSize)
394 *cbSize = sizeof(Agent);
395 lstrcpynA(pcszUAOut, Agent, *cbSize);
400 /**************************************************************************
401 * IsValidURL (URLMON.@)
403 * Determines if a specified string is a valid URL.
406 * pBC [I] ignored, must be NULL.
407 * szURL [I] string that represents the URL in question.
408 * dwReserved [I] reserved and must be zero.
413 * returns E_INVALIDARG if one or more of the args is invalid.
416 * test functionality against windows to see what a valid URL is.
418 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
420 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
422 if (pBC != NULL || dwReserved != 0)
428 /**************************************************************************
429 * FaultInIEFeature (URLMON.@)
431 * Undocumented. Appears to be used by native shdocvw.dll.
433 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
434 QUERYCONTEXT *pQuery, DWORD flags )
436 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
440 /**************************************************************************
441 * CoGetClassObjectFromURL (URLMON.@)
443 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
444 DWORD dwFileVersionLS, LPCWSTR szContentType,
445 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
446 REFIID riid, LPVOID *ppv )
448 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
449 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
450 debugstr_guid(riid), ppv);
451 return E_NOINTERFACE;
454 /***********************************************************************
455 * ReleaseBindInfo (URLMON.@)
457 * Release the resources used by the specified BINDINFO structure.
460 * pbindinfo [I] BINDINFO to release.
465 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
469 TRACE("(%p)\n", pbindinfo);
471 if(!pbindinfo || !(size = pbindinfo->cbSize))
474 CoTaskMemFree(pbindinfo->szExtraInfo);
475 ReleaseStgMedium(&pbindinfo->stgmedData);
477 if(offsetof(BINDINFO, szExtraInfo) < size)
478 CoTaskMemFree(pbindinfo->szCustomVerb);
480 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
481 IUnknown_Release(pbindinfo->pUnk);
483 memset(pbindinfo, 0, size);
484 pbindinfo->cbSize = size;
487 /***********************************************************************
488 * CopyStgMedium (URLMON.@)
490 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
492 TRACE("(%p %p)\n", src, dst);
503 if(src->u.lpszFileName && !src->pUnkForRelease) {
504 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
505 dst->u.lpszFileName = CoTaskMemAlloc(size);
506 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
511 IStream_AddRef(dst->u.pstm);
515 IStorage_AddRef(dst->u.pstg);
518 FIXME("Unimplemented tymed %d\n", src->tymed);
521 if(dst->pUnkForRelease)
522 IUnknown_AddRef(dst->pUnkForRelease);
527 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
529 return size > 5 && !memcmp(b, "{\\rtf", 5);
532 static BOOL text_html_filter(const BYTE *b, DWORD size)
539 for(i=0; i < size-5; i++) {
541 && (b[i+1] == 'h' || b[i+1] == 'H')
542 && (b[i+2] == 't' || b[i+2] == 'T')
543 && (b[i+3] == 'm' || b[i+3] == 'M')
544 && (b[i+4] == 'l' || b[i+4] == 'L'))
551 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
554 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
557 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
560 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
561 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
564 static BOOL image_gif_filter(const BYTE *b, DWORD size)
567 && (b[0] == 'G' || b[0] == 'g')
568 && (b[1] == 'I' || b[1] == 'i')
569 && (b[2] == 'F' || b[2] == 'f')
571 && (b[4] == '7' || b[4] == '9')
572 && (b[5] == 'A' || b[5] == 'a');
575 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
577 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
580 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
582 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
585 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
587 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
588 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
591 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
594 && b[0] == 0x42 && b[1] == 0x4d
595 && *(const DWORD *)(b+6) == 0;
598 static BOOL video_avi_filter(const BYTE *b, DWORD size)
601 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
602 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
605 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
608 && !b[0] && !b[1] && b[2] == 0x01
609 && (b[3] == 0xb3 || b[3] == 0xba);
612 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
614 return size > 2 && b[0] == '%' && b[1] == '!';
617 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
619 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
622 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
624 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
627 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
629 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
632 static BOOL application_java_filter(const BYTE *b, DWORD size)
634 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
637 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
639 return size > 2 && b[0] == 'M' && b[1] == 'Z';
642 static BOOL text_plain_filter(const BYTE *b, DWORD size)
646 for(ptr = b; ptr < b+size-1; ptr++) {
647 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
654 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
659 /***********************************************************************
660 * FindMimeFromData (URLMON.@)
662 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
664 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
665 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
666 LPWSTR* ppwzMimeOut, DWORD dwReserved)
668 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
669 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
672 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
674 WARN("dwReserved=%d\n", dwReserved);
676 /* pBC seams to not be used */
678 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
681 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
687 len = strlenW(pwzMimeProposed)+1;
688 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
689 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
694 const BYTE *buf = pBuffer;
699 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
700 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
701 static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
702 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
703 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
704 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
705 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
706 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
707 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
708 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
709 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
710 static const WCHAR wszAppPostscript[] =
711 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
712 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
714 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
715 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
716 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
717 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
718 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
720 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
721 'x','-','m','s','d','o','w','n','l','o','a','d',0};
722 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
723 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
724 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
726 static const struct {
728 BOOL (*filter)(const BYTE *,DWORD);
730 {wszTextHtml, text_html_filter},
731 {wszTextRichtext, text_richtext_filter},
732 /* {wszAudioXAiff, audio_xaiff_filter}, */
733 {wszAudioBasic, audio_basic_filter},
734 {wszAudioWav, audio_wav_filter},
735 {wszImageGif, image_gif_filter},
736 {wszImagePjpeg, image_pjpeg_filter},
737 {wszImageTiff, image_tiff_filter},
738 {wszImageXPng, image_xpng_filter},
739 /* {wszImageXBitmap, image_xbitmap_filter}, */
740 {wszImageBmp, image_bmp_filter},
741 /* {wszImageXJg, image_xjg_filter}, */
742 /* {wszImageXEmf, image_xemf_filter}, */
743 /* {wszImageXWmf, image_xwmf_filter}, */
744 {wszVideoAvi, video_avi_filter},
745 {wszVideoMpeg, video_mpeg_filter},
746 {wszAppPostscript, application_postscript_filter},
747 /* {wszAppBase64, application_base64_filter}, */
748 /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
749 {wszAppPdf, application_pdf_filter},
750 /* {wszAppXCompressed, application_xcompressed_filter}, */
751 {wszAppXZip, application_xzip_filter},
752 {wszAppXGzip, application_xgzip_filter},
753 {wszAppJava, application_java_filter},
754 {wszAppXMSDownload, application_xmsdownload},
755 {wszTextPlain, text_plain_filter},
756 {wszAppOctetStream, application_octet_stream_filter}
762 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
763 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
764 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
768 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
769 || mime_filters[i].filter(buf, cbSize)) {
770 len = strlenW(pwzMimeProposed)+1;
771 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
772 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
779 if(mime_filters[i].filter(buf, cbSize))
780 ret = mime_filters[i].mime;
784 TRACE("found %s for data\n"
785 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
786 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
787 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
789 if(pwzMimeProposed) {
790 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
791 ret = pwzMimeProposed;
793 /* text/html is a special case */
794 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
798 len = strlenW(ret)+1;
799 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
800 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
810 static const WCHAR wszContentType[] =
811 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
813 ptr = strrchrW(pwzUrl, '.');
817 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
818 if(res != ERROR_SUCCESS)
819 return HRESULT_FROM_WIN32(res);
822 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
824 if(res != ERROR_SUCCESS)
825 return HRESULT_FROM_WIN32(res);
827 *ppwzMimeOut = CoTaskMemAlloc(size);
828 memcpy(*ppwzMimeOut, mime, size);
835 /***********************************************************************
836 * GetClassFileOrMime (URLMON.@)
838 * Determines the class ID from the bind context, file name or MIME type.
840 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
841 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
844 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
845 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
850 /***********************************************************************
853 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
855 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
858 hCabinet = LoadLibraryA("cabinet.dll");
860 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
861 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
862 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
864 return pExtract(dest, szCabName);
867 /***********************************************************************
868 * IsLoggingEnabledA (URLMON.@)
870 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
872 FIXME("(%s)\n", debugstr_a(url));
876 /***********************************************************************
877 * IsLoggingEnabledW (URLMON.@)
879 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
881 FIXME("(%s)\n", debugstr_w(url));