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 const IClassFactoryVtbl *lpClassFactoryVtbl;
194 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
197 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
199 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
203 if(IsEqualGUID(riid, &IID_IUnknown)) {
204 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
206 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
207 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
212 IUnknown_AddRef((IUnknown*)*ppv);
216 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
217 return E_NOINTERFACE;
220 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
226 static ULONG WINAPI CF_Release(IClassFactory *iface)
228 URLMON_UnlockModule();
233 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
234 REFIID riid, LPVOID *ppobj)
236 ClassFactory *This = (ClassFactory*)iface;
240 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
243 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
244 hres = IUnknown_QueryInterface(punk, riid, ppobj);
245 IUnknown_Release(punk);
250 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
252 TRACE("(%d)\n", dolock);
257 URLMON_UnlockModule();
262 static const IClassFactoryVtbl ClassFactoryVtbl =
271 static const ClassFactory FileProtocolCF =
272 { &ClassFactoryVtbl, FileProtocol_Construct};
273 static const ClassFactory FtpProtocolCF =
274 { &ClassFactoryVtbl, FtpProtocol_Construct};
275 static const ClassFactory GopherProtocolCF =
276 { &ClassFactoryVtbl, GopherProtocol_Construct};
277 static const ClassFactory HttpProtocolCF =
278 { &ClassFactoryVtbl, HttpProtocol_Construct};
279 static const ClassFactory HttpSProtocolCF =
280 { &ClassFactoryVtbl, HttpSProtocol_Construct};
281 static const ClassFactory MkProtocolCF =
282 { &ClassFactoryVtbl, MkProtocol_Construct};
283 static const ClassFactory SecurityManagerCF =
284 { &ClassFactoryVtbl, SecManagerImpl_Construct};
285 static const ClassFactory ZoneManagerCF =
286 { &ClassFactoryVtbl, ZoneMgrImpl_Construct};
287 static const ClassFactory StdURLMonikerCF =
288 { &ClassFactoryVtbl, StdURLMoniker_Construct};
289 static const ClassFactory MimeFilterCF =
290 { &ClassFactoryVtbl, MimeFilter_Construct};
292 struct object_creation_info
299 static const WCHAR wszFile[] = {'f','i','l','e',0};
300 static const WCHAR wszFtp[] = {'f','t','p',0};
301 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
302 static const WCHAR wszHttp[] = {'h','t','t','p',0};
303 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
304 static const WCHAR wszMk[] = {'m','k',0};
306 static const struct object_creation_info object_creation[] =
308 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
309 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
310 { &CLSID_GopherProtocol, CLASSFACTORY(&GopherProtocolCF), wszGopher },
311 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
312 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
313 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
314 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
315 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL },
316 { &CLSID_StdURLMoniker, CLASSFACTORY(&StdURLMonikerCF), NULL },
317 { &CLSID_DeCompMimeFilter, CLASSFACTORY(&MimeFilterCF), NULL }
320 static void init_session(BOOL init)
324 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
326 if(object_creation[i].protocol)
327 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
328 object_creation[i].protocol, init);
332 /*******************************************************************************
333 * DllGetClassObject [URLMON.@]
334 * Retrieves class object from a DLL object
337 * Docs say returns STDAPI
340 * rclsid [I] CLSID for the class object
341 * riid [I] Reference to identifier of interface for class object
342 * ppv [O] Address of variable to receive interface pointer for riid
346 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
350 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
355 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
357 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
359 if (IsEqualGUID(object_creation[i].clsid, rclsid))
360 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
363 hr = URLMON_DllGetClassObject(rclsid, riid, ppv);
367 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
368 return CLASS_E_CLASSNOTAVAILABLE;
371 static HRESULT register_inf(BOOL doregister)
373 HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
376 static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
378 hAdvpack = LoadLibraryW(wszAdvpack);
379 pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
381 return pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", NULL);
384 /***********************************************************************
385 * DllRegisterServer (URLMON.@)
387 HRESULT WINAPI DllRegisterServer(void)
393 hr = URLMON_DllRegisterServer();
394 return SUCCEEDED(hr) ? register_inf(TRUE) : hr;
397 /***********************************************************************
398 * DllUnregisterServer (URLMON.@)
400 HRESULT WINAPI DllUnregisterServer(void)
406 hr = URLMON_DllUnregisterServer();
407 return SUCCEEDED(hr) ? register_inf(FALSE) : hr;
410 /***********************************************************************
411 * DllRegisterServerEx (URLMON.@)
413 HRESULT WINAPI DllRegisterServerEx(void)
415 FIXME("(void): stub\n");
420 /**************************************************************************
421 * IsValidURL (URLMON.@)
423 * Determines if a specified string is a valid URL.
426 * pBC [I] ignored, must be NULL.
427 * szURL [I] string that represents the URL in question.
428 * dwReserved [I] reserved and must be zero.
433 * returns E_INVALIDARG if one or more of the args is invalid.
436 * test functionality against windows to see what a valid URL is.
438 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
440 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
442 if (pBC || dwReserved || !szURL)
448 /**************************************************************************
449 * FaultInIEFeature (URLMON.@)
451 * Undocumented. Appears to be used by native shdocvw.dll.
453 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
454 QUERYCONTEXT *pQuery, DWORD flags )
456 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
460 /**************************************************************************
461 * CoGetClassObjectFromURL (URLMON.@)
463 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
464 DWORD dwFileVersionLS, LPCWSTR szContentType,
465 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
466 REFIID riid, LPVOID *ppv )
468 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
469 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
470 debugstr_guid(riid), ppv);
471 return E_NOINTERFACE;
474 /***********************************************************************
475 * ReleaseBindInfo (URLMON.@)
477 * Release the resources used by the specified BINDINFO structure.
480 * pbindinfo [I] BINDINFO to release.
485 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
489 TRACE("(%p)\n", pbindinfo);
491 if(!pbindinfo || !(size = pbindinfo->cbSize))
494 CoTaskMemFree(pbindinfo->szExtraInfo);
495 ReleaseStgMedium(&pbindinfo->stgmedData);
497 if(offsetof(BINDINFO, szExtraInfo) < size)
498 CoTaskMemFree(pbindinfo->szCustomVerb);
500 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
501 IUnknown_Release(pbindinfo->pUnk);
503 memset(pbindinfo, 0, size);
504 pbindinfo->cbSize = size;
507 /***********************************************************************
508 * CopyStgMedium (URLMON.@)
510 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
512 TRACE("(%p %p)\n", src, dst);
523 if(src->u.lpszFileName && !src->pUnkForRelease) {
524 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
525 dst->u.lpszFileName = CoTaskMemAlloc(size);
526 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
531 IStream_AddRef(dst->u.pstm);
535 IStorage_AddRef(dst->u.pstg);
538 FIXME("Unimplemented tymed %d\n", src->tymed);
541 if(dst->pUnkForRelease)
542 IUnknown_AddRef(dst->pUnkForRelease);
547 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
549 return size > 5 && !memcmp(b, "{\\rtf", 5);
552 static BOOL text_html_filter(const BYTE *b, DWORD size)
559 for(i=0; i < size-5; i++) {
561 && (b[i+1] == 'h' || b[i+1] == 'H')
562 && (b[i+2] == 't' || b[i+2] == 'T')
563 && (b[i+3] == 'm' || b[i+3] == 'M')
564 && (b[i+4] == 'l' || b[i+4] == 'L'))
571 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
574 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
577 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
580 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
581 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
584 static BOOL image_gif_filter(const BYTE *b, DWORD size)
587 && (b[0] == 'G' || b[0] == 'g')
588 && (b[1] == 'I' || b[1] == 'i')
589 && (b[2] == 'F' || b[2] == 'f')
591 && (b[4] == '7' || b[4] == '9')
592 && (b[5] == 'A' || b[5] == 'a');
595 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
597 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
600 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
602 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
605 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
607 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
608 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
611 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
614 && b[0] == 0x42 && b[1] == 0x4d
615 && *(const DWORD *)(b+6) == 0;
618 static BOOL video_avi_filter(const BYTE *b, DWORD size)
621 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
622 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
625 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
628 && !b[0] && !b[1] && b[2] == 0x01
629 && (b[3] == 0xb3 || b[3] == 0xba);
632 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
634 return size > 2 && b[0] == '%' && b[1] == '!';
637 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
639 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
642 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
644 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
647 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
649 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
652 static BOOL application_java_filter(const BYTE *b, DWORD size)
654 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
657 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
659 return size > 2 && b[0] == 'M' && b[1] == 'Z';
662 static BOOL text_plain_filter(const BYTE *b, DWORD size)
666 for(ptr = b; ptr < b+size-1; ptr++) {
667 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
674 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
679 static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime)
684 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
685 static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
686 static const WCHAR audio_basicW[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
687 static const WCHAR audio_wavW[] = {'a','u','d','i','o','/','w','a','v',0};
688 static const WCHAR image_gifW[] = {'i','m','a','g','e','/','g','i','f',0};
689 static const WCHAR image_pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
690 static const WCHAR image_tiffW[] = {'i','m','a','g','e','/','t','i','f','f',0};
691 static const WCHAR image_xpngW[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
692 static const WCHAR image_bmpW[] = {'i','m','a','g','e','/','b','m','p',0};
693 static const WCHAR video_aviW[] = {'v','i','d','e','o','/','a','v','i',0};
694 static const WCHAR video_mpegW[] = {'v','i','d','e','o','/','m','p','e','g',0};
695 static const WCHAR app_postscriptW[] =
696 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
697 static const WCHAR app_pdfW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','p','d','f',0};
698 static const WCHAR app_xzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
699 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
700 static const WCHAR app_xgzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
701 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
702 static const WCHAR app_javaW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
704 static const WCHAR app_xmsdownloadW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
705 'x','-','m','s','d','o','w','n','l','o','a','d',0};
706 static const WCHAR text_plainW[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
707 static const WCHAR app_octetstreamW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
708 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
710 static const struct {
712 BOOL (*filter)(const BYTE *,DWORD);
714 {text_htmlW, text_html_filter},
715 {text_richtextW, text_richtext_filter},
716 /* {audio_xaiffW, audio_xaiff_filter}, */
717 {audio_basicW, audio_basic_filter},
718 {audio_wavW, audio_wav_filter},
719 {image_gifW, image_gif_filter},
720 {image_pjpegW, image_pjpeg_filter},
721 {image_tiffW, image_tiff_filter},
722 {image_xpngW, image_xpng_filter},
723 /* {image_xbitmapW, image_xbitmap_filter}, */
724 {image_bmpW, image_bmp_filter},
725 /* {image_xjgW, image_xjg_filter}, */
726 /* {image_xemfW, image_xemf_filter}, */
727 /* {image_xwmfW, image_xwmf_filter}, */
728 {video_aviW, video_avi_filter},
729 {video_mpegW, video_mpeg_filter},
730 {app_postscriptW, application_postscript_filter},
731 /* {app_base64W, application_base64_filter}, */
732 /* {app_macbinhex40W, application_macbinhex40_filter}, */
733 {app_pdfW, application_pdf_filter},
734 /* {app_zcompressedW, application_xcompressed_filter}, */
735 {app_xzipW, application_xzip_filter},
736 {app_xgzipW, application_xgzip_filter},
737 {app_javaW, application_java_filter},
738 {app_xmsdownloadW, application_xmsdownload},
739 {text_plainW, text_plain_filter},
740 {app_octetstreamW, application_octet_stream_filter}
747 len = strlenW(proposed_mime)+1;
748 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
750 return E_OUTOFMEMORY;
752 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
756 if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) {
757 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
758 if(!strcmpW(proposed_mime, mime_filters[i].mime))
762 if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) {
763 len = strlenW(proposed_mime)+1;
764 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
766 return E_OUTOFMEMORY;
768 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
775 if(mime_filters[i].filter(buf, size))
776 ret = mime_filters[i].mime;
780 TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
783 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
786 /* text/html is a special case */
787 if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW))
791 len = strlenW(ret)+1;
792 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
794 return E_OUTOFMEMORY;
796 memcpy(*ret_mime, ret, len*sizeof(WCHAR));
800 /***********************************************************************
801 * FindMimeFromData (URLMON.@)
803 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
805 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
806 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
807 LPWSTR* ppwzMimeOut, DWORD dwReserved)
809 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
810 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
813 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
815 WARN("dwReserved=%d\n", dwReserved);
817 /* pBC seams to not be used */
819 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
822 if(pwzMimeProposed || pBuffer)
823 return find_mime_from_buffer(pBuffer, cbSize, pwzMimeProposed, ppwzMimeOut);
831 static const WCHAR wszContentType[] =
832 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
834 ptr = strrchrW(pwzUrl, '.');
838 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
839 if(res != ERROR_SUCCESS)
840 return HRESULT_FROM_WIN32(res);
843 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
845 if(res != ERROR_SUCCESS)
846 return HRESULT_FROM_WIN32(res);
848 *ppwzMimeOut = CoTaskMemAlloc(size);
849 memcpy(*ppwzMimeOut, mime, size);
856 /***********************************************************************
857 * GetClassFileOrMime (URLMON.@)
859 * Determines the class ID from the bind context, file name or MIME type.
861 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
862 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
865 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
866 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
871 /***********************************************************************
874 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
876 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
879 hCabinet = LoadLibraryA("cabinet.dll");
881 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
882 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
883 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
885 return pExtract(dest, szCabName);
888 /***********************************************************************
889 * IsLoggingEnabledA (URLMON.@)
891 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
893 FIXME("(%s)\n", debugstr_a(url));
897 /***********************************************************************
898 * IsLoggingEnabledW (URLMON.@)
900 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
902 FIXME("(%s)\n", debugstr_w(url));
906 /***********************************************************************
907 * URLMON_410 (URLMON.410)
908 * Undocumented, added in IE8
910 BOOL WINAPI URLMON_410(DWORD unknown1, DWORD unknown2)
912 FIXME("stub: %d %d\n", unknown1, unknown2);
916 /***********************************************************************
917 * URLMON_423 (URLMON.423)
918 * Undocumented, added in IE8
920 BOOL WINAPI URLMON_423(DWORD unknown1, DWORD unknown2, DWORD unknown3, DWORD unknown4)
922 FIXME("stub: %d %d %d %d\n", unknown1, unknown2, unknown3, unknown4);