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:
157 DeleteCriticalSection(&tls_cs);
160 case DLL_THREAD_DETACH:
168 /***********************************************************************
169 * DllInstall (URLMON.@)
171 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
173 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
174 debugstr_w(cmdline));
179 /***********************************************************************
180 * DllCanUnloadNow (URLMON.@)
182 HRESULT WINAPI DllCanUnloadNow(void)
184 return URLMON_refCount != 0 ? S_FALSE : S_OK;
189 /******************************************************************************
190 * Urlmon ClassFactory
193 IClassFactory IClassFactory_iface;
195 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
198 static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface)
200 return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
203 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
207 if(IsEqualGUID(riid, &IID_IUnknown)) {
208 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
210 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
211 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
216 IUnknown_AddRef((IUnknown*)*ppv);
220 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
221 return E_NOINTERFACE;
224 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
230 static ULONG WINAPI CF_Release(IClassFactory *iface)
232 URLMON_UnlockModule();
237 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
238 REFIID riid, LPVOID *ppobj)
240 ClassFactory *This = impl_from_IClassFactory(iface);
244 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
247 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
248 hres = IUnknown_QueryInterface(punk, riid, ppobj);
249 IUnknown_Release(punk);
254 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
256 TRACE("(%d)\n", dolock);
261 URLMON_UnlockModule();
266 static const IClassFactoryVtbl ClassFactoryVtbl =
275 static ClassFactory FileProtocolCF =
276 { { &ClassFactoryVtbl }, FileProtocol_Construct};
277 static ClassFactory FtpProtocolCF =
278 { { &ClassFactoryVtbl }, FtpProtocol_Construct};
279 static ClassFactory GopherProtocolCF =
280 { { &ClassFactoryVtbl }, GopherProtocol_Construct};
281 static ClassFactory HttpProtocolCF =
282 { { &ClassFactoryVtbl }, HttpProtocol_Construct};
283 static ClassFactory HttpSProtocolCF =
284 { { &ClassFactoryVtbl }, HttpSProtocol_Construct};
285 static ClassFactory MkProtocolCF =
286 { { &ClassFactoryVtbl }, MkProtocol_Construct};
287 static ClassFactory SecurityManagerCF =
288 { { &ClassFactoryVtbl }, SecManagerImpl_Construct};
289 static ClassFactory ZoneManagerCF =
290 { { &ClassFactoryVtbl }, ZoneMgrImpl_Construct};
291 static ClassFactory StdURLMonikerCF =
292 { { &ClassFactoryVtbl }, StdURLMoniker_Construct};
293 static ClassFactory MimeFilterCF =
294 { { &ClassFactoryVtbl }, MimeFilter_Construct};
296 struct object_creation_info
303 static const WCHAR wszFile[] = {'f','i','l','e',0};
304 static const WCHAR wszFtp[] = {'f','t','p',0};
305 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
306 static const WCHAR wszHttp[] = {'h','t','t','p',0};
307 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
308 static const WCHAR wszMk[] = {'m','k',0};
310 static const struct object_creation_info object_creation[] =
312 { &CLSID_FileProtocol, &FileProtocolCF.IClassFactory_iface, wszFile },
313 { &CLSID_FtpProtocol, &FtpProtocolCF.IClassFactory_iface, wszFtp },
314 { &CLSID_GopherProtocol, &GopherProtocolCF.IClassFactory_iface, wszGopher },
315 { &CLSID_HttpProtocol, &HttpProtocolCF.IClassFactory_iface, wszHttp },
316 { &CLSID_HttpSProtocol, &HttpSProtocolCF.IClassFactory_iface, wszHttps },
317 { &CLSID_MkProtocol, &MkProtocolCF.IClassFactory_iface, wszMk },
318 { &CLSID_InternetSecurityManager, &SecurityManagerCF.IClassFactory_iface, NULL },
319 { &CLSID_InternetZoneManager, &ZoneManagerCF.IClassFactory_iface, NULL },
320 { &CLSID_StdURLMoniker, &StdURLMonikerCF.IClassFactory_iface, NULL },
321 { &CLSID_DeCompMimeFilter, &MimeFilterCF.IClassFactory_iface, NULL }
324 static void init_session(BOOL init)
328 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
330 if(object_creation[i].protocol)
331 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
332 object_creation[i].protocol, init);
336 /*******************************************************************************
337 * DllGetClassObject [URLMON.@]
338 * Retrieves class object from a DLL object
341 * Docs say returns STDAPI
344 * rclsid [I] CLSID for the class object
345 * riid [I] Reference to identifier of interface for class object
346 * ppv [O] Address of variable to receive interface pointer for riid
350 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
354 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
359 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
361 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
363 if (IsEqualGUID(object_creation[i].clsid, rclsid))
364 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
367 hr = URLMON_DllGetClassObject(rclsid, riid, ppv);
371 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
372 return CLASS_E_CLASSNOTAVAILABLE;
375 static HRESULT register_inf(BOOL doregister)
377 HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
380 static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
382 hAdvpack = LoadLibraryW(wszAdvpack);
383 pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
385 return pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", NULL);
388 /***********************************************************************
389 * DllRegisterServer (URLMON.@)
391 HRESULT WINAPI DllRegisterServer(void)
397 hr = URLMON_DllRegisterServer();
398 return SUCCEEDED(hr) ? register_inf(TRUE) : hr;
401 /***********************************************************************
402 * DllUnregisterServer (URLMON.@)
404 HRESULT WINAPI DllUnregisterServer(void)
410 hr = URLMON_DllUnregisterServer();
411 return SUCCEEDED(hr) ? register_inf(FALSE) : hr;
414 /***********************************************************************
415 * DllRegisterServerEx (URLMON.@)
417 HRESULT WINAPI DllRegisterServerEx(void)
419 FIXME("(void): stub\n");
424 /**************************************************************************
425 * IsValidURL (URLMON.@)
427 * Determines if a specified string is a valid URL.
430 * pBC [I] ignored, should be NULL.
431 * szURL [I] string that represents the URL in question.
432 * dwReserved [I] reserved and must be zero.
437 * returns E_INVALIDARG if one or more of the args is invalid.
440 * test functionality against windows to see what a valid URL is.
442 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
444 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
446 if (dwReserved || !szURL)
452 /**************************************************************************
453 * FaultInIEFeature (URLMON.@)
455 * Undocumented. Appears to be used by native shdocvw.dll.
457 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
458 QUERYCONTEXT *pQuery, DWORD flags )
460 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
464 /**************************************************************************
465 * CoGetClassObjectFromURL (URLMON.@)
467 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
468 DWORD dwFileVersionLS, LPCWSTR szContentType,
469 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
470 REFIID riid, LPVOID *ppv )
472 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
473 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
474 debugstr_guid(riid), ppv);
475 return E_NOINTERFACE;
478 /***********************************************************************
479 * ReleaseBindInfo (URLMON.@)
481 * Release the resources used by the specified BINDINFO structure.
484 * pbindinfo [I] BINDINFO to release.
489 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
493 TRACE("(%p)\n", pbindinfo);
495 if(!pbindinfo || !(size = pbindinfo->cbSize))
498 CoTaskMemFree(pbindinfo->szExtraInfo);
499 ReleaseStgMedium(&pbindinfo->stgmedData);
501 if(offsetof(BINDINFO, szExtraInfo) < size)
502 CoTaskMemFree(pbindinfo->szCustomVerb);
504 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
505 IUnknown_Release(pbindinfo->pUnk);
507 memset(pbindinfo, 0, size);
508 pbindinfo->cbSize = size;
511 /***********************************************************************
512 * CopyStgMedium (URLMON.@)
514 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
516 TRACE("(%p %p)\n", src, dst);
527 if(src->u.lpszFileName && !src->pUnkForRelease) {
528 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
529 dst->u.lpszFileName = CoTaskMemAlloc(size);
530 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
535 IStream_AddRef(dst->u.pstm);
539 IStorage_AddRef(dst->u.pstg);
542 FIXME("Unimplemented tymed %d\n", src->tymed);
545 if(dst->pUnkForRelease)
546 IUnknown_AddRef(dst->pUnkForRelease);
551 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
553 return size > 5 && !memcmp(b, "{\\rtf", 5);
556 static BOOL text_html_filter(const BYTE *b, DWORD size)
563 for(i=0; i < size-5; i++) {
565 && (b[i+1] == 'h' || b[i+1] == 'H')
566 && (b[i+2] == 't' || b[i+2] == 'T')
567 && (b[i+3] == 'm' || b[i+3] == 'M')
568 && (b[i+4] == 'l' || b[i+4] == 'L'))
575 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
578 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
581 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
584 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
585 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
588 static BOOL image_gif_filter(const BYTE *b, DWORD size)
591 && (b[0] == 'G' || b[0] == 'g')
592 && (b[1] == 'I' || b[1] == 'i')
593 && (b[2] == 'F' || b[2] == 'f')
595 && (b[4] == '7' || b[4] == '9')
596 && (b[5] == 'A' || b[5] == 'a');
599 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
601 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
604 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
606 static const BYTE magic1[] = {0x4d,0x4d,0x00,0x2a};
607 static const BYTE magic2[] = {0x49,0x49,0x2a,0xff};
609 return size >= 4 && (!memcmp(b, magic1, 4) || !memcmp(b, magic2, 4));
612 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
614 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
615 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
618 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
621 && b[0] == 0x42 && b[1] == 0x4d
622 && *(const DWORD *)(b+6) == 0;
625 static BOOL video_avi_filter(const BYTE *b, DWORD size)
628 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
629 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
632 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
635 && !b[0] && !b[1] && b[2] == 0x01
636 && (b[3] == 0xb3 || b[3] == 0xba);
639 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
641 return size > 2 && b[0] == '%' && b[1] == '!';
644 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
646 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
649 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
651 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
654 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
656 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
659 static BOOL application_java_filter(const BYTE *b, DWORD size)
661 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
664 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
666 return size > 2 && b[0] == 'M' && b[1] == 'Z';
669 static BOOL text_plain_filter(const BYTE *b, DWORD size)
673 for(ptr = b; ptr < b+size-1; ptr++) {
674 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
681 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
686 static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime)
691 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
692 static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
693 static const WCHAR audio_basicW[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
694 static const WCHAR audio_wavW[] = {'a','u','d','i','o','/','w','a','v',0};
695 static const WCHAR image_gifW[] = {'i','m','a','g','e','/','g','i','f',0};
696 static const WCHAR image_pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
697 static const WCHAR image_tiffW[] = {'i','m','a','g','e','/','t','i','f','f',0};
698 static const WCHAR image_xpngW[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
699 static const WCHAR image_bmpW[] = {'i','m','a','g','e','/','b','m','p',0};
700 static const WCHAR video_aviW[] = {'v','i','d','e','o','/','a','v','i',0};
701 static const WCHAR video_mpegW[] = {'v','i','d','e','o','/','m','p','e','g',0};
702 static const WCHAR app_postscriptW[] =
703 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
704 static const WCHAR app_pdfW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','p','d','f',0};
705 static const WCHAR app_xzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
706 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
707 static const WCHAR app_xgzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
708 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
709 static const WCHAR app_javaW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
711 static const WCHAR app_xmsdownloadW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
712 'x','-','m','s','d','o','w','n','l','o','a','d',0};
713 static const WCHAR text_plainW[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
714 static const WCHAR app_octetstreamW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
715 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
717 static const struct {
719 BOOL (*filter)(const BYTE *,DWORD);
721 {text_htmlW, text_html_filter},
722 {text_richtextW, text_richtext_filter},
723 /* {audio_xaiffW, audio_xaiff_filter}, */
724 {audio_basicW, audio_basic_filter},
725 {audio_wavW, audio_wav_filter},
726 {image_gifW, image_gif_filter},
727 {image_pjpegW, image_pjpeg_filter},
728 {image_tiffW, image_tiff_filter},
729 {image_xpngW, image_xpng_filter},
730 /* {image_xbitmapW, image_xbitmap_filter}, */
731 {image_bmpW, image_bmp_filter},
732 /* {image_xjgW, image_xjg_filter}, */
733 /* {image_xemfW, image_xemf_filter}, */
734 /* {image_xwmfW, image_xwmf_filter}, */
735 {video_aviW, video_avi_filter},
736 {video_mpegW, video_mpeg_filter},
737 {app_postscriptW, application_postscript_filter},
738 /* {app_base64W, application_base64_filter}, */
739 /* {app_macbinhex40W, application_macbinhex40_filter}, */
740 {app_pdfW, application_pdf_filter},
741 /* {app_zcompressedW, application_xcompressed_filter}, */
742 {app_xzipW, application_xzip_filter},
743 {app_xgzipW, application_xgzip_filter},
744 {app_javaW, application_java_filter},
745 {app_xmsdownloadW, application_xmsdownload},
746 {text_plainW, text_plain_filter},
747 {app_octetstreamW, application_octet_stream_filter}
754 len = strlenW(proposed_mime)+1;
755 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
757 return E_OUTOFMEMORY;
759 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
763 if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) {
764 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
765 if(!strcmpW(proposed_mime, mime_filters[i].mime))
769 if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) {
770 len = strlenW(proposed_mime)+1;
771 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
773 return E_OUTOFMEMORY;
775 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
782 if(mime_filters[i].filter(buf, size))
783 ret = mime_filters[i].mime;
787 TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
790 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
793 /* text/html is a special case */
794 if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW))
798 len = strlenW(ret)+1;
799 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
801 return E_OUTOFMEMORY;
803 memcpy(*ret_mime, ret, len*sizeof(WCHAR));
807 /***********************************************************************
808 * FindMimeFromData (URLMON.@)
810 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
812 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
813 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
814 LPWSTR* ppwzMimeOut, DWORD dwReserved)
816 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
817 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
820 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
822 WARN("dwReserved=%d\n", dwReserved);
824 /* pBC seams to not be used */
826 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
829 if(pwzMimeProposed || pBuffer)
830 return find_mime_from_buffer(pBuffer, cbSize, pwzMimeProposed, ppwzMimeOut);
838 static const WCHAR wszContentType[] =
839 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
841 ptr = strrchrW(pwzUrl, '.');
845 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
846 if(res != ERROR_SUCCESS)
847 return HRESULT_FROM_WIN32(res);
850 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
852 if(res != ERROR_SUCCESS)
853 return HRESULT_FROM_WIN32(res);
855 *ppwzMimeOut = CoTaskMemAlloc(size);
856 memcpy(*ppwzMimeOut, mime, size);
863 /***********************************************************************
864 * GetClassFileOrMime (URLMON.@)
866 * Determines the class ID from the bind context, file name or MIME type.
868 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
869 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
872 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
873 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
878 /***********************************************************************
881 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
883 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
886 hCabinet = LoadLibraryA("cabinet.dll");
888 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
889 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
890 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
892 return pExtract(dest, szCabName);
895 /***********************************************************************
896 * IsLoggingEnabledA (URLMON.@)
898 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
900 FIXME("(%s)\n", debugstr_a(url));
904 /***********************************************************************
905 * IsLoggingEnabledW (URLMON.@)
907 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
909 FIXME("(%s)\n", debugstr_w(url));
913 /***********************************************************************
914 * IsProtectedModeURL (URLMON.111)
915 * Undocumented, added in IE7
917 BOOL WINAPI IsProtectedModeURL(const WCHAR *url)
919 FIXME("stub: %s\n", debugstr_w(url));
923 /***********************************************************************
924 * LogSqmBits (URLMON.410)
925 * Undocumented, added in IE8
927 int WINAPI LogSqmBits(DWORD unk1, DWORD unk2)
929 FIXME("stub: %d %d\n", unk1, unk2);
933 /***********************************************************************
934 * LogSqmUXCommandOffsetInternal (URLMON.423)
935 * Undocumented, added in IE8
937 void WINAPI LogSqmUXCommandOffsetInternal(DWORD unk1, DWORD unk2, DWORD unk3, DWORD unk4)
939 FIXME("stub: %d %d %d %d\n", unk1, unk2, unk3, unk4);
942 /***********************************************************************
943 * MapUriToBrowserEmulationState (URLMON.444)
944 * Undocumented, added in IE8
946 int WINAPI MapUriToBrowserEmulationState(DWORD unk1, DWORD unk2, DWORD unk3)
948 FIXME("stub: %d %d %d\n", unk1, unk2, unk3);
952 /***********************************************************************
953 * MapBrowserEmulationModeToUserAgent (URLMON.445)
954 * Undocumented, added in IE8
956 int WINAPI MapBrowserEmulationModeToUserAgent(DWORD unk1, DWORD unk2)
958 FIXME("stub: %d %d\n", unk1, unk2);
962 /***********************************************************************
964 * Added in IE3, registers known MIME-type strings.
966 HRESULT WINAPI RegisterMediaTypes(UINT types, LPCSTR *szTypes, CLIPFORMAT *cfTypes)
968 FIXME("stub: %u %p %p\n", types, szTypes, cfTypes);