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
31 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
37 LONG URLMON_refCount = 0;
39 static HMODULE hCabinet = NULL;
40 static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
42 static void init_session(BOOL);
44 static struct list tls_list = LIST_INIT(tls_list);
46 static CRITICAL_SECTION tls_cs;
47 static CRITICAL_SECTION_DEBUG tls_cs_dbg =
50 { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList },
51 0, 0, { (DWORD_PTR)(__FILE__ ": tls") }
54 static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 };
56 tls_data_t *get_tls_data(void)
60 if(urlmon_tls == TLS_OUT_OF_INDEXES) {
61 DWORD tls = TlsAlloc();
62 if(tls == TLS_OUT_OF_INDEXES)
65 tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES);
70 data = TlsGetValue(urlmon_tls);
72 data = heap_alloc_zero(sizeof(tls_data_t));
76 EnterCriticalSection(&tls_cs);
77 list_add_tail(&tls_list, &data->entry);
78 LeaveCriticalSection(&tls_cs);
80 TlsSetValue(urlmon_tls, data);
86 static void free_tls_list(void)
90 if(urlmon_tls == TLS_OUT_OF_INDEXES)
93 while(!list_empty(&tls_list)) {
94 data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry);
95 list_remove(&data->entry);
102 static void detach_thread(void)
106 if(urlmon_tls == TLS_OUT_OF_INDEXES)
109 data = TlsGetValue(urlmon_tls);
113 EnterCriticalSection(&tls_cs);
114 list_remove(&data->entry);
115 LeaveCriticalSection(&tls_cs);
117 if(data->notif_hwnd) {
118 WARN("notif_hwnd not destroyed\n");
119 DestroyWindow(data->notif_hwnd);
125 static void process_detach(void)
127 HINTERNET internet_session;
129 internet_session = get_internet_session(NULL);
131 InternetCloseHandle(internet_session);
134 FreeLibrary(hCabinet);
141 /***********************************************************************
142 * DllMain (URLMON.init)
144 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
146 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
148 URLMON_DllMain( hinstDLL, fdwReason, fImpLoad );
151 case DLL_PROCESS_ATTACH:
155 case DLL_PROCESS_DETACH:
159 case DLL_THREAD_DETACH:
167 /***********************************************************************
168 * DllInstall (URLMON.@)
170 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
172 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
173 debugstr_w(cmdline));
178 /***********************************************************************
179 * DllCanUnloadNow (URLMON.@)
181 HRESULT WINAPI DllCanUnloadNow(void)
183 return URLMON_refCount != 0 ? S_FALSE : S_OK;
188 /******************************************************************************
189 * Urlmon ClassFactory
192 IClassFactory IClassFactory_iface;
194 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
197 static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface)
199 return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
202 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
206 if(IsEqualGUID(riid, &IID_IUnknown)) {
207 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
209 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
210 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
215 IUnknown_AddRef((IUnknown*)*ppv);
219 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
220 return E_NOINTERFACE;
223 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
229 static ULONG WINAPI CF_Release(IClassFactory *iface)
231 URLMON_UnlockModule();
236 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
237 REFIID riid, LPVOID *ppobj)
239 ClassFactory *This = impl_from_IClassFactory(iface);
243 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
246 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
247 hres = IUnknown_QueryInterface(punk, riid, ppobj);
248 IUnknown_Release(punk);
253 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
255 TRACE("(%d)\n", dolock);
260 URLMON_UnlockModule();
265 static const IClassFactoryVtbl ClassFactoryVtbl =
274 static ClassFactory FileProtocolCF =
275 { { &ClassFactoryVtbl }, FileProtocol_Construct};
276 static ClassFactory FtpProtocolCF =
277 { { &ClassFactoryVtbl }, FtpProtocol_Construct};
278 static ClassFactory GopherProtocolCF =
279 { { &ClassFactoryVtbl }, GopherProtocol_Construct};
280 static ClassFactory HttpProtocolCF =
281 { { &ClassFactoryVtbl }, HttpProtocol_Construct};
282 static ClassFactory HttpSProtocolCF =
283 { { &ClassFactoryVtbl }, HttpSProtocol_Construct};
284 static ClassFactory MkProtocolCF =
285 { { &ClassFactoryVtbl }, MkProtocol_Construct};
286 static ClassFactory SecurityManagerCF =
287 { { &ClassFactoryVtbl }, SecManagerImpl_Construct};
288 static ClassFactory ZoneManagerCF =
289 { { &ClassFactoryVtbl }, ZoneMgrImpl_Construct};
290 static ClassFactory StdURLMonikerCF =
291 { { &ClassFactoryVtbl }, StdURLMoniker_Construct};
292 static ClassFactory MimeFilterCF =
293 { { &ClassFactoryVtbl }, MimeFilter_Construct};
295 struct object_creation_info
302 static const WCHAR wszFile[] = {'f','i','l','e',0};
303 static const WCHAR wszFtp[] = {'f','t','p',0};
304 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
305 static const WCHAR wszHttp[] = {'h','t','t','p',0};
306 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
307 static const WCHAR wszMk[] = {'m','k',0};
309 static const struct object_creation_info object_creation[] =
311 { &CLSID_FileProtocol, &FileProtocolCF.IClassFactory_iface, wszFile },
312 { &CLSID_FtpProtocol, &FtpProtocolCF.IClassFactory_iface, wszFtp },
313 { &CLSID_GopherProtocol, &GopherProtocolCF.IClassFactory_iface, wszGopher },
314 { &CLSID_HttpProtocol, &HttpProtocolCF.IClassFactory_iface, wszHttp },
315 { &CLSID_HttpSProtocol, &HttpSProtocolCF.IClassFactory_iface, wszHttps },
316 { &CLSID_MkProtocol, &MkProtocolCF.IClassFactory_iface, wszMk },
317 { &CLSID_InternetSecurityManager, &SecurityManagerCF.IClassFactory_iface, NULL },
318 { &CLSID_InternetZoneManager, &ZoneManagerCF.IClassFactory_iface, NULL },
319 { &CLSID_StdURLMoniker, &StdURLMonikerCF.IClassFactory_iface, NULL },
320 { &CLSID_DeCompMimeFilter, &MimeFilterCF.IClassFactory_iface, NULL }
323 static void init_session(BOOL init)
327 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
329 if(object_creation[i].protocol)
330 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
331 object_creation[i].protocol, init);
335 /*******************************************************************************
336 * DllGetClassObject [URLMON.@]
337 * Retrieves class object from a DLL object
340 * Docs say returns STDAPI
343 * rclsid [I] CLSID for the class object
344 * riid [I] Reference to identifier of interface for class object
345 * ppv [O] Address of variable to receive interface pointer for riid
349 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
353 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
358 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
360 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
362 if (IsEqualGUID(object_creation[i].clsid, rclsid))
363 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
366 hr = URLMON_DllGetClassObject(rclsid, riid, ppv);
370 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
371 return CLASS_E_CLASSNOTAVAILABLE;
374 static HRESULT register_inf(BOOL doregister)
376 HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
379 static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
381 hAdvpack = LoadLibraryW(wszAdvpack);
382 pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
384 return pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", NULL);
387 /***********************************************************************
388 * DllRegisterServer (URLMON.@)
390 HRESULT WINAPI DllRegisterServer(void)
396 hr = URLMON_DllRegisterServer();
397 return SUCCEEDED(hr) ? register_inf(TRUE) : hr;
400 /***********************************************************************
401 * DllUnregisterServer (URLMON.@)
403 HRESULT WINAPI DllUnregisterServer(void)
409 hr = URLMON_DllUnregisterServer();
410 return SUCCEEDED(hr) ? register_inf(FALSE) : hr;
413 /***********************************************************************
414 * DllRegisterServerEx (URLMON.@)
416 HRESULT WINAPI DllRegisterServerEx(void)
418 FIXME("(void): stub\n");
423 /**************************************************************************
424 * IsValidURL (URLMON.@)
426 * Determines if a specified string is a valid URL.
429 * pBC [I] ignored, should be NULL.
430 * szURL [I] string that represents the URL in question.
431 * dwReserved [I] reserved and must be zero.
436 * returns E_INVALIDARG if one or more of the args is invalid.
439 * test functionality against windows to see what a valid URL is.
441 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
443 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
445 if (dwReserved || !szURL)
451 /**************************************************************************
452 * FaultInIEFeature (URLMON.@)
454 * Undocumented. Appears to be used by native shdocvw.dll.
456 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
457 QUERYCONTEXT *pQuery, DWORD flags )
459 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
463 /**************************************************************************
464 * CoGetClassObjectFromURL (URLMON.@)
466 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
467 DWORD dwFileVersionLS, LPCWSTR szContentType,
468 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
469 REFIID riid, LPVOID *ppv )
471 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
472 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
473 debugstr_guid(riid), ppv);
474 return E_NOINTERFACE;
477 /***********************************************************************
478 * ReleaseBindInfo (URLMON.@)
480 * Release the resources used by the specified BINDINFO structure.
483 * pbindinfo [I] BINDINFO to release.
488 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
492 TRACE("(%p)\n", pbindinfo);
494 if(!pbindinfo || !(size = pbindinfo->cbSize))
497 CoTaskMemFree(pbindinfo->szExtraInfo);
498 ReleaseStgMedium(&pbindinfo->stgmedData);
500 if(offsetof(BINDINFO, szExtraInfo) < size)
501 CoTaskMemFree(pbindinfo->szCustomVerb);
503 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
504 IUnknown_Release(pbindinfo->pUnk);
506 memset(pbindinfo, 0, size);
507 pbindinfo->cbSize = size;
510 /***********************************************************************
511 * CopyStgMedium (URLMON.@)
513 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
515 TRACE("(%p %p)\n", src, dst);
526 if(src->u.lpszFileName && !src->pUnkForRelease) {
527 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
528 dst->u.lpszFileName = CoTaskMemAlloc(size);
529 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
534 IStream_AddRef(dst->u.pstm);
538 IStorage_AddRef(dst->u.pstg);
541 FIXME("Unimplemented tymed %d\n", src->tymed);
544 if(dst->pUnkForRelease)
545 IUnknown_AddRef(dst->pUnkForRelease);
550 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
552 return size > 5 && !memcmp(b, "{\\rtf", 5);
555 static BOOL text_html_filter(const BYTE *b, DWORD size)
562 for(i=0; i < size-5; i++) {
564 && (b[i+1] == 'h' || b[i+1] == 'H')
565 && (b[i+2] == 't' || b[i+2] == 'T')
566 && (b[i+3] == 'm' || b[i+3] == 'M')
567 && (b[i+4] == 'l' || b[i+4] == 'L'))
574 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
577 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
580 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
583 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
584 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
587 static BOOL image_gif_filter(const BYTE *b, DWORD size)
590 && (b[0] == 'G' || b[0] == 'g')
591 && (b[1] == 'I' || b[1] == 'i')
592 && (b[2] == 'F' || b[2] == 'f')
594 && (b[4] == '7' || b[4] == '9')
595 && (b[5] == 'A' || b[5] == 'a');
598 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
600 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
603 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
605 static const BYTE magic1[] = {0x4d,0x4d,0x00,0x2a};
606 static const BYTE magic2[] = {0x49,0x49,0x2a,0xff};
608 return size >= 4 && (!memcmp(b, magic1, 4) || !memcmp(b, magic2, 4));
611 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
613 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
614 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
617 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
620 && b[0] == 0x42 && b[1] == 0x4d
621 && *(const DWORD *)(b+6) == 0;
624 static BOOL video_avi_filter(const BYTE *b, DWORD size)
627 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
628 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
631 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
634 && !b[0] && !b[1] && b[2] == 0x01
635 && (b[3] == 0xb3 || b[3] == 0xba);
638 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
640 return size > 2 && b[0] == '%' && b[1] == '!';
643 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
645 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
648 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
650 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
653 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
655 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
658 static BOOL application_java_filter(const BYTE *b, DWORD size)
660 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
663 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
665 return size > 2 && b[0] == 'M' && b[1] == 'Z';
668 static BOOL text_plain_filter(const BYTE *b, DWORD size)
672 for(ptr = b; ptr < b+size-1; ptr++) {
673 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
680 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
685 static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime)
690 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
691 static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
692 static const WCHAR audio_basicW[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
693 static const WCHAR audio_wavW[] = {'a','u','d','i','o','/','w','a','v',0};
694 static const WCHAR image_gifW[] = {'i','m','a','g','e','/','g','i','f',0};
695 static const WCHAR image_pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
696 static const WCHAR image_tiffW[] = {'i','m','a','g','e','/','t','i','f','f',0};
697 static const WCHAR image_xpngW[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
698 static const WCHAR image_bmpW[] = {'i','m','a','g','e','/','b','m','p',0};
699 static const WCHAR video_aviW[] = {'v','i','d','e','o','/','a','v','i',0};
700 static const WCHAR video_mpegW[] = {'v','i','d','e','o','/','m','p','e','g',0};
701 static const WCHAR app_postscriptW[] =
702 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
703 static const WCHAR app_pdfW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','p','d','f',0};
704 static const WCHAR app_xzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
705 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
706 static const WCHAR app_xgzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
707 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
708 static const WCHAR app_javaW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
710 static const WCHAR app_xmsdownloadW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
711 'x','-','m','s','d','o','w','n','l','o','a','d',0};
712 static const WCHAR text_plainW[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
713 static const WCHAR app_octetstreamW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
714 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
716 static const struct {
718 BOOL (*filter)(const BYTE *,DWORD);
720 {text_htmlW, text_html_filter},
721 {text_richtextW, text_richtext_filter},
722 /* {audio_xaiffW, audio_xaiff_filter}, */
723 {audio_basicW, audio_basic_filter},
724 {audio_wavW, audio_wav_filter},
725 {image_gifW, image_gif_filter},
726 {image_pjpegW, image_pjpeg_filter},
727 {image_tiffW, image_tiff_filter},
728 {image_xpngW, image_xpng_filter},
729 /* {image_xbitmapW, image_xbitmap_filter}, */
730 {image_bmpW, image_bmp_filter},
731 /* {image_xjgW, image_xjg_filter}, */
732 /* {image_xemfW, image_xemf_filter}, */
733 /* {image_xwmfW, image_xwmf_filter}, */
734 {video_aviW, video_avi_filter},
735 {video_mpegW, video_mpeg_filter},
736 {app_postscriptW, application_postscript_filter},
737 /* {app_base64W, application_base64_filter}, */
738 /* {app_macbinhex40W, application_macbinhex40_filter}, */
739 {app_pdfW, application_pdf_filter},
740 /* {app_zcompressedW, application_xcompressed_filter}, */
741 {app_xzipW, application_xzip_filter},
742 {app_xgzipW, application_xgzip_filter},
743 {app_javaW, application_java_filter},
744 {app_xmsdownloadW, application_xmsdownload},
745 {text_plainW, text_plain_filter},
746 {app_octetstreamW, application_octet_stream_filter}
753 len = strlenW(proposed_mime)+1;
754 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
756 return E_OUTOFMEMORY;
758 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
762 if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) {
763 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
764 if(!strcmpW(proposed_mime, mime_filters[i].mime))
768 if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) {
769 len = strlenW(proposed_mime)+1;
770 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
772 return E_OUTOFMEMORY;
774 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
781 if(mime_filters[i].filter(buf, size))
782 ret = mime_filters[i].mime;
786 TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
789 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
792 /* text/html is a special case */
793 if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW))
797 len = strlenW(ret)+1;
798 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
800 return E_OUTOFMEMORY;
802 memcpy(*ret_mime, ret, len*sizeof(WCHAR));
806 /***********************************************************************
807 * FindMimeFromData (URLMON.@)
809 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
811 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
812 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
813 LPWSTR* ppwzMimeOut, DWORD dwReserved)
815 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
816 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
819 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
821 WARN("dwReserved=%d\n", dwReserved);
823 /* pBC seams to not be used */
825 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
828 if(pwzMimeProposed || pBuffer)
829 return find_mime_from_buffer(pBuffer, cbSize, pwzMimeProposed, ppwzMimeOut);
837 static const WCHAR wszContentType[] =
838 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
840 ptr = strrchrW(pwzUrl, '.');
844 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
845 if(res != ERROR_SUCCESS)
846 return HRESULT_FROM_WIN32(res);
849 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
851 if(res != ERROR_SUCCESS)
852 return HRESULT_FROM_WIN32(res);
854 *ppwzMimeOut = CoTaskMemAlloc(size);
855 memcpy(*ppwzMimeOut, mime, size);
862 /***********************************************************************
863 * GetClassFileOrMime (URLMON.@)
865 * Determines the class ID from the bind context, file name or MIME type.
867 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
868 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
871 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
872 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
877 /***********************************************************************
880 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
882 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
885 hCabinet = LoadLibraryA("cabinet.dll");
887 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
888 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
889 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
891 return pExtract(dest, szCabName);
894 /***********************************************************************
895 * IsLoggingEnabledA (URLMON.@)
897 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
899 FIXME("(%s)\n", debugstr_a(url));
903 /***********************************************************************
904 * IsLoggingEnabledW (URLMON.@)
906 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
908 FIXME("(%s)\n", debugstr_w(url));
912 /***********************************************************************
913 * IsProtectedModeURL (URLMON.111)
914 * Undocumented, added in IE7
916 BOOL WINAPI IsProtectedModeURL(const WCHAR *url)
918 FIXME("stub: %s\n", debugstr_w(url));
922 /***********************************************************************
923 * URLMON_410 (URLMON.410)
924 * Undocumented, added in IE8
926 BOOL WINAPI URLMON_410(DWORD unknown1, DWORD unknown2)
928 FIXME("stub: %d %d\n", unknown1, unknown2);
932 /***********************************************************************
933 * URLMON_423 (URLMON.423)
934 * Undocumented, added in IE8
936 BOOL WINAPI URLMON_423(DWORD unknown1, DWORD unknown2, DWORD unknown3, DWORD unknown4)
938 FIXME("stub: %d %d %d %d\n", unknown1, unknown2, unknown3, unknown4);
942 /***********************************************************************
944 * Added in IE3, registers known MIME-type strings.
946 HRESULT WINAPI RegisterMediaTypes(UINT types, LPCSTR *szTypes, CLIPFORMAT *cfTypes)
948 FIXME("stub: %u %p %p\n", types, szTypes, cfTypes);