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 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
608 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
610 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
611 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
614 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
617 && b[0] == 0x42 && b[1] == 0x4d
618 && *(const DWORD *)(b+6) == 0;
621 static BOOL video_avi_filter(const BYTE *b, DWORD size)
624 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
625 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
628 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
631 && !b[0] && !b[1] && b[2] == 0x01
632 && (b[3] == 0xb3 || b[3] == 0xba);
635 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
637 return size > 2 && b[0] == '%' && b[1] == '!';
640 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
642 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
645 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
647 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
650 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
652 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
655 static BOOL application_java_filter(const BYTE *b, DWORD size)
657 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
660 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
662 return size > 2 && b[0] == 'M' && b[1] == 'Z';
665 static BOOL text_plain_filter(const BYTE *b, DWORD size)
669 for(ptr = b; ptr < b+size-1; ptr++) {
670 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
677 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
682 static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime)
687 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
688 static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
689 static const WCHAR audio_basicW[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
690 static const WCHAR audio_wavW[] = {'a','u','d','i','o','/','w','a','v',0};
691 static const WCHAR image_gifW[] = {'i','m','a','g','e','/','g','i','f',0};
692 static const WCHAR image_pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
693 static const WCHAR image_tiffW[] = {'i','m','a','g','e','/','t','i','f','f',0};
694 static const WCHAR image_xpngW[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
695 static const WCHAR image_bmpW[] = {'i','m','a','g','e','/','b','m','p',0};
696 static const WCHAR video_aviW[] = {'v','i','d','e','o','/','a','v','i',0};
697 static const WCHAR video_mpegW[] = {'v','i','d','e','o','/','m','p','e','g',0};
698 static const WCHAR app_postscriptW[] =
699 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
700 static const WCHAR app_pdfW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','p','d','f',0};
701 static const WCHAR app_xzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
702 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
703 static const WCHAR app_xgzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
704 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
705 static const WCHAR app_javaW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
707 static const WCHAR app_xmsdownloadW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
708 'x','-','m','s','d','o','w','n','l','o','a','d',0};
709 static const WCHAR text_plainW[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
710 static const WCHAR app_octetstreamW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
711 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
713 static const struct {
715 BOOL (*filter)(const BYTE *,DWORD);
717 {text_htmlW, text_html_filter},
718 {text_richtextW, text_richtext_filter},
719 /* {audio_xaiffW, audio_xaiff_filter}, */
720 {audio_basicW, audio_basic_filter},
721 {audio_wavW, audio_wav_filter},
722 {image_gifW, image_gif_filter},
723 {image_pjpegW, image_pjpeg_filter},
724 {image_tiffW, image_tiff_filter},
725 {image_xpngW, image_xpng_filter},
726 /* {image_xbitmapW, image_xbitmap_filter}, */
727 {image_bmpW, image_bmp_filter},
728 /* {image_xjgW, image_xjg_filter}, */
729 /* {image_xemfW, image_xemf_filter}, */
730 /* {image_xwmfW, image_xwmf_filter}, */
731 {video_aviW, video_avi_filter},
732 {video_mpegW, video_mpeg_filter},
733 {app_postscriptW, application_postscript_filter},
734 /* {app_base64W, application_base64_filter}, */
735 /* {app_macbinhex40W, application_macbinhex40_filter}, */
736 {app_pdfW, application_pdf_filter},
737 /* {app_zcompressedW, application_xcompressed_filter}, */
738 {app_xzipW, application_xzip_filter},
739 {app_xgzipW, application_xgzip_filter},
740 {app_javaW, application_java_filter},
741 {app_xmsdownloadW, application_xmsdownload},
742 {text_plainW, text_plain_filter},
743 {app_octetstreamW, application_octet_stream_filter}
750 len = strlenW(proposed_mime)+1;
751 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
753 return E_OUTOFMEMORY;
755 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
759 if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) {
760 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
761 if(!strcmpW(proposed_mime, mime_filters[i].mime))
765 if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) {
766 len = strlenW(proposed_mime)+1;
767 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
769 return E_OUTOFMEMORY;
771 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
778 if(mime_filters[i].filter(buf, size))
779 ret = mime_filters[i].mime;
783 TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
786 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
789 /* text/html is a special case */
790 if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW))
794 len = strlenW(ret)+1;
795 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
797 return E_OUTOFMEMORY;
799 memcpy(*ret_mime, ret, len*sizeof(WCHAR));
803 /***********************************************************************
804 * FindMimeFromData (URLMON.@)
806 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
808 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
809 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
810 LPWSTR* ppwzMimeOut, DWORD dwReserved)
812 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
813 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
816 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
818 WARN("dwReserved=%d\n", dwReserved);
820 /* pBC seams to not be used */
822 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
825 if(pwzMimeProposed || pBuffer)
826 return find_mime_from_buffer(pBuffer, cbSize, pwzMimeProposed, ppwzMimeOut);
834 static const WCHAR wszContentType[] =
835 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
837 ptr = strrchrW(pwzUrl, '.');
841 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
842 if(res != ERROR_SUCCESS)
843 return HRESULT_FROM_WIN32(res);
846 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
848 if(res != ERROR_SUCCESS)
849 return HRESULT_FROM_WIN32(res);
851 *ppwzMimeOut = CoTaskMemAlloc(size);
852 memcpy(*ppwzMimeOut, mime, size);
859 /***********************************************************************
860 * GetClassFileOrMime (URLMON.@)
862 * Determines the class ID from the bind context, file name or MIME type.
864 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
865 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
868 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
869 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
874 /***********************************************************************
877 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
879 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
882 hCabinet = LoadLibraryA("cabinet.dll");
884 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
885 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
886 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
888 return pExtract(dest, szCabName);
891 /***********************************************************************
892 * IsLoggingEnabledA (URLMON.@)
894 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
896 FIXME("(%s)\n", debugstr_a(url));
900 /***********************************************************************
901 * IsLoggingEnabledW (URLMON.@)
903 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
905 FIXME("(%s)\n", debugstr_w(url));
909 /***********************************************************************
910 * URLMON_410 (URLMON.410)
911 * Undocumented, added in IE8
913 BOOL WINAPI URLMON_410(DWORD unknown1, DWORD unknown2)
915 FIXME("stub: %d %d\n", unknown1, unknown2);
919 /***********************************************************************
920 * URLMON_423 (URLMON.423)
921 * Undocumented, added in IE8
923 BOOL WINAPI URLMON_423(DWORD unknown1, DWORD unknown2, DWORD unknown3, DWORD unknown4)
925 FIXME("stub: %d %d %d %d\n", unknown1, unknown2, unknown3, unknown4);