4 * Copyright (c) 2000 Patrik Stridvall
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "urlmon_main.h"
27 #define NO_SHLWAPI_REG
29 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
35 LONG URLMON_refCount = 0;
37 static HMODULE hCabinet = NULL;
38 static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
40 static void init_session(BOOL);
42 static struct list tls_list = LIST_INIT(tls_list);
44 static CRITICAL_SECTION tls_cs;
45 static CRITICAL_SECTION_DEBUG tls_cs_dbg =
48 { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList },
49 0, 0, { (DWORD_PTR)(__FILE__ ": tls") }
52 static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 };
54 tls_data_t *get_tls_data(void)
58 if(urlmon_tls == TLS_OUT_OF_INDEXES) {
59 DWORD tls = TlsAlloc();
60 if(tls == TLS_OUT_OF_INDEXES)
63 tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES);
68 data = TlsGetValue(urlmon_tls);
70 data = heap_alloc_zero(sizeof(tls_data_t));
74 EnterCriticalSection(&tls_cs);
75 list_add_tail(&tls_list, &data->entry);
76 LeaveCriticalSection(&tls_cs);
78 TlsSetValue(urlmon_tls, data);
84 static void free_tls_list(void)
88 if(urlmon_tls == TLS_OUT_OF_INDEXES)
91 while(!list_empty(&tls_list)) {
92 data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry);
93 list_remove(&data->entry);
100 static void detach_thread(void)
104 if(urlmon_tls == TLS_OUT_OF_INDEXES)
107 data = TlsGetValue(urlmon_tls);
111 EnterCriticalSection(&tls_cs);
112 list_remove(&data->entry);
113 LeaveCriticalSection(&tls_cs);
115 if(data->notif_hwnd) {
116 WARN("notif_hwnd not destroyed\n");
117 DestroyWindow(data->notif_hwnd);
123 static void process_detach(void)
125 HINTERNET internet_session;
127 internet_session = get_internet_session(NULL);
129 InternetCloseHandle(internet_session);
132 FreeLibrary(hCabinet);
139 /***********************************************************************
140 * DllMain (URLMON.init)
142 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
144 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
146 URLMON_DllMain( hinstDLL, fdwReason, fImpLoad );
149 case DLL_PROCESS_ATTACH:
153 case DLL_PROCESS_DETACH:
157 case DLL_THREAD_DETACH:
165 /***********************************************************************
166 * DllInstall (URLMON.@)
168 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
170 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
171 debugstr_w(cmdline));
176 /***********************************************************************
177 * DllCanUnloadNow (URLMON.@)
179 HRESULT WINAPI DllCanUnloadNow(void)
181 return URLMON_refCount != 0 ? S_FALSE : S_OK;
186 /******************************************************************************
187 * Urlmon ClassFactory
190 const IClassFactoryVtbl *lpClassFactoryVtbl;
192 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
195 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
197 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
201 if(IsEqualGUID(riid, &IID_IUnknown)) {
202 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
204 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
205 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
210 IUnknown_AddRef((IUnknown*)*ppv);
214 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
215 return E_NOINTERFACE;
218 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
224 static ULONG WINAPI CF_Release(IClassFactory *iface)
226 URLMON_UnlockModule();
231 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
232 REFIID riid, LPVOID *ppobj)
234 ClassFactory *This = (ClassFactory*)iface;
238 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
241 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
242 hres = IUnknown_QueryInterface(punk, riid, ppobj);
243 IUnknown_Release(punk);
248 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
250 TRACE("(%d)\n", dolock);
255 URLMON_UnlockModule();
260 static const IClassFactoryVtbl ClassFactoryVtbl =
269 static const ClassFactory FileProtocolCF =
270 { &ClassFactoryVtbl, FileProtocol_Construct};
271 static const ClassFactory FtpProtocolCF =
272 { &ClassFactoryVtbl, FtpProtocol_Construct};
273 static const ClassFactory GopherProtocolCF =
274 { &ClassFactoryVtbl, GopherProtocol_Construct};
275 static const ClassFactory HttpProtocolCF =
276 { &ClassFactoryVtbl, HttpProtocol_Construct};
277 static const ClassFactory HttpSProtocolCF =
278 { &ClassFactoryVtbl, HttpSProtocol_Construct};
279 static const ClassFactory MkProtocolCF =
280 { &ClassFactoryVtbl, MkProtocol_Construct};
281 static const ClassFactory SecurityManagerCF =
282 { &ClassFactoryVtbl, SecManagerImpl_Construct};
283 static const ClassFactory ZoneManagerCF =
284 { &ClassFactoryVtbl, ZoneMgrImpl_Construct};
285 static const ClassFactory StdURLMonikerCF =
286 { &ClassFactoryVtbl, StdURLMoniker_Construct};
287 static const ClassFactory MimeFilterCF =
288 { &ClassFactoryVtbl, MimeFilter_Construct};
290 struct object_creation_info
297 static const WCHAR wszFile[] = {'f','i','l','e',0};
298 static const WCHAR wszFtp[] = {'f','t','p',0};
299 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
300 static const WCHAR wszHttp[] = {'h','t','t','p',0};
301 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
302 static const WCHAR wszMk[] = {'m','k',0};
304 static const struct object_creation_info object_creation[] =
306 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
307 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
308 { &CLSID_GopherProtocol, CLASSFACTORY(&GopherProtocolCF), wszGopher },
309 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
310 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
311 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
312 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
313 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL },
314 { &CLSID_StdURLMoniker, CLASSFACTORY(&StdURLMonikerCF), NULL },
315 { &CLSID_DeCompMimeFilter, CLASSFACTORY(&MimeFilterCF), NULL }
318 static void init_session(BOOL init)
322 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
324 if(object_creation[i].protocol)
325 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
326 object_creation[i].protocol, init);
330 /*******************************************************************************
331 * DllGetClassObject [URLMON.@]
332 * Retrieves class object from a DLL object
335 * Docs say returns STDAPI
338 * rclsid [I] CLSID for the class object
339 * riid [I] Reference to identifier of interface for class object
340 * ppv [O] Address of variable to receive interface pointer for riid
344 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
348 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
353 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
355 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
357 if (IsEqualGUID(object_creation[i].clsid, rclsid))
358 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
361 hr = URLMON_DllGetClassObject(rclsid, riid, ppv);
365 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
366 return CLASS_E_CLASSNOTAVAILABLE;
370 /***********************************************************************
371 * DllRegisterServerEx (URLMON.@)
373 HRESULT WINAPI DllRegisterServerEx(void)
375 FIXME("(void): stub\n");
380 /**************************************************************************
381 * IsValidURL (URLMON.@)
383 * Determines if a specified string is a valid URL.
386 * pBC [I] ignored, must be NULL.
387 * szURL [I] string that represents the URL in question.
388 * dwReserved [I] reserved and must be zero.
393 * returns E_INVALIDARG if one or more of the args is invalid.
396 * test functionality against windows to see what a valid URL is.
398 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
400 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
402 if (pBC || dwReserved || !szURL)
408 /**************************************************************************
409 * FaultInIEFeature (URLMON.@)
411 * Undocumented. Appears to be used by native shdocvw.dll.
413 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
414 QUERYCONTEXT *pQuery, DWORD flags )
416 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
420 /**************************************************************************
421 * CoGetClassObjectFromURL (URLMON.@)
423 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
424 DWORD dwFileVersionLS, LPCWSTR szContentType,
425 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
426 REFIID riid, LPVOID *ppv )
428 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
429 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
430 debugstr_guid(riid), ppv);
431 return E_NOINTERFACE;
434 /***********************************************************************
435 * ReleaseBindInfo (URLMON.@)
437 * Release the resources used by the specified BINDINFO structure.
440 * pbindinfo [I] BINDINFO to release.
445 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
449 TRACE("(%p)\n", pbindinfo);
451 if(!pbindinfo || !(size = pbindinfo->cbSize))
454 CoTaskMemFree(pbindinfo->szExtraInfo);
455 ReleaseStgMedium(&pbindinfo->stgmedData);
457 if(offsetof(BINDINFO, szExtraInfo) < size)
458 CoTaskMemFree(pbindinfo->szCustomVerb);
460 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
461 IUnknown_Release(pbindinfo->pUnk);
463 memset(pbindinfo, 0, size);
464 pbindinfo->cbSize = size;
467 /***********************************************************************
468 * CopyStgMedium (URLMON.@)
470 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
472 TRACE("(%p %p)\n", src, dst);
483 if(src->u.lpszFileName && !src->pUnkForRelease) {
484 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
485 dst->u.lpszFileName = CoTaskMemAlloc(size);
486 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
491 IStream_AddRef(dst->u.pstm);
495 IStorage_AddRef(dst->u.pstg);
498 FIXME("Unimplemented tymed %d\n", src->tymed);
501 if(dst->pUnkForRelease)
502 IUnknown_AddRef(dst->pUnkForRelease);
507 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
509 return size > 5 && !memcmp(b, "{\\rtf", 5);
512 static BOOL text_html_filter(const BYTE *b, DWORD size)
519 for(i=0; i < size-5; i++) {
521 && (b[i+1] == 'h' || b[i+1] == 'H')
522 && (b[i+2] == 't' || b[i+2] == 'T')
523 && (b[i+3] == 'm' || b[i+3] == 'M')
524 && (b[i+4] == 'l' || b[i+4] == 'L'))
531 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
534 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
537 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
540 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
541 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
544 static BOOL image_gif_filter(const BYTE *b, DWORD size)
547 && (b[0] == 'G' || b[0] == 'g')
548 && (b[1] == 'I' || b[1] == 'i')
549 && (b[2] == 'F' || b[2] == 'f')
551 && (b[4] == '7' || b[4] == '9')
552 && (b[5] == 'A' || b[5] == 'a');
555 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
557 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
560 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
562 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
565 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
567 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
568 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
571 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
574 && b[0] == 0x42 && b[1] == 0x4d
575 && *(const DWORD *)(b+6) == 0;
578 static BOOL video_avi_filter(const BYTE *b, DWORD size)
581 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
582 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
585 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
588 && !b[0] && !b[1] && b[2] == 0x01
589 && (b[3] == 0xb3 || b[3] == 0xba);
592 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
594 return size > 2 && b[0] == '%' && b[1] == '!';
597 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
599 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
602 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
604 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
607 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
609 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
612 static BOOL application_java_filter(const BYTE *b, DWORD size)
614 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
617 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
619 return size > 2 && b[0] == 'M' && b[1] == 'Z';
622 static BOOL text_plain_filter(const BYTE *b, DWORD size)
626 for(ptr = b; ptr < b+size-1; ptr++) {
627 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
634 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
639 static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime)
644 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
645 static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
646 static const WCHAR audio_basicW[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
647 static const WCHAR audio_wavW[] = {'a','u','d','i','o','/','w','a','v',0};
648 static const WCHAR image_gifW[] = {'i','m','a','g','e','/','g','i','f',0};
649 static const WCHAR image_pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
650 static const WCHAR image_tiffW[] = {'i','m','a','g','e','/','t','i','f','f',0};
651 static const WCHAR image_xpngW[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
652 static const WCHAR image_bmpW[] = {'i','m','a','g','e','/','b','m','p',0};
653 static const WCHAR video_aviW[] = {'v','i','d','e','o','/','a','v','i',0};
654 static const WCHAR video_mpegW[] = {'v','i','d','e','o','/','m','p','e','g',0};
655 static const WCHAR app_postscriptW[] =
656 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
657 static const WCHAR app_pdfW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','p','d','f',0};
658 static const WCHAR app_xzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
659 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
660 static const WCHAR app_xgzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
661 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
662 static const WCHAR app_javaW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
664 static const WCHAR app_xmsdownloadW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
665 'x','-','m','s','d','o','w','n','l','o','a','d',0};
666 static const WCHAR text_plainW[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
667 static const WCHAR app_octetstreamW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
668 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
670 static const struct {
672 BOOL (*filter)(const BYTE *,DWORD);
674 {text_htmlW, text_html_filter},
675 {text_richtextW, text_richtext_filter},
676 /* {audio_xaiffW, audio_xaiff_filter}, */
677 {audio_basicW, audio_basic_filter},
678 {audio_wavW, audio_wav_filter},
679 {image_gifW, image_gif_filter},
680 {image_pjpegW, image_pjpeg_filter},
681 {image_tiffW, image_tiff_filter},
682 {image_xpngW, image_xpng_filter},
683 /* {image_xbitmapW, image_xbitmap_filter}, */
684 {image_bmpW, image_bmp_filter},
685 /* {image_xjgW, image_xjg_filter}, */
686 /* {image_xemfW, image_xemf_filter}, */
687 /* {image_xwmfW, image_xwmf_filter}, */
688 {video_aviW, video_avi_filter},
689 {video_mpegW, video_mpeg_filter},
690 {app_postscriptW, application_postscript_filter},
691 /* {app_base64W, application_base64_filter}, */
692 /* {app_macbinhex40W, application_macbinhex40_filter}, */
693 {app_pdfW, application_pdf_filter},
694 /* {app_zcompressedW, application_xcompressed_filter}, */
695 {app_xzipW, application_xzip_filter},
696 {app_xgzipW, application_xgzip_filter},
697 {app_javaW, application_java_filter},
698 {app_xmsdownloadW, application_xmsdownload},
699 {text_plainW, text_plain_filter},
700 {app_octetstreamW, application_octet_stream_filter}
707 len = strlenW(proposed_mime)+1;
708 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
710 return E_OUTOFMEMORY;
712 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
716 if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) {
717 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
718 if(!strcmpW(proposed_mime, mime_filters[i].mime))
722 if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) {
723 len = strlenW(proposed_mime)+1;
724 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
726 return E_OUTOFMEMORY;
728 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
735 if(mime_filters[i].filter(buf, size))
736 ret = mime_filters[i].mime;
740 TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
743 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
746 /* text/html is a special case */
747 if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW))
751 len = strlenW(ret)+1;
752 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
754 return E_OUTOFMEMORY;
756 memcpy(*ret_mime, ret, len*sizeof(WCHAR));
760 /***********************************************************************
761 * FindMimeFromData (URLMON.@)
763 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
765 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
766 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
767 LPWSTR* ppwzMimeOut, DWORD dwReserved)
769 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
770 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
773 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
775 WARN("dwReserved=%d\n", dwReserved);
777 /* pBC seams to not be used */
779 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
782 if(pwzMimeProposed || pBuffer)
783 return find_mime_from_buffer(pBuffer, cbSize, pwzMimeProposed, ppwzMimeOut);
791 static const WCHAR wszContentType[] =
792 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
794 ptr = strrchrW(pwzUrl, '.');
798 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
799 if(res != ERROR_SUCCESS)
800 return HRESULT_FROM_WIN32(res);
803 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
805 if(res != ERROR_SUCCESS)
806 return HRESULT_FROM_WIN32(res);
808 *ppwzMimeOut = CoTaskMemAlloc(size);
809 memcpy(*ppwzMimeOut, mime, size);
816 /***********************************************************************
817 * GetClassFileOrMime (URLMON.@)
819 * Determines the class ID from the bind context, file name or MIME type.
821 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
822 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
825 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
826 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
831 /***********************************************************************
834 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
836 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
839 hCabinet = LoadLibraryA("cabinet.dll");
841 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
842 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
843 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
845 return pExtract(dest, szCabName);
848 /***********************************************************************
849 * IsLoggingEnabledA (URLMON.@)
851 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
853 FIXME("(%s)\n", debugstr_a(url));
857 /***********************************************************************
858 * IsLoggingEnabledW (URLMON.@)
860 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
862 FIXME("(%s)\n", debugstr_w(url));