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 HINSTANCE URLMON_hInstance = 0;
38 static HMODULE hCabinet = NULL;
39 static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
41 static void init_session(BOOL);
43 static struct list tls_list = LIST_INIT(tls_list);
45 static CRITICAL_SECTION tls_cs;
46 static CRITICAL_SECTION_DEBUG tls_cs_dbg =
49 { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList },
50 0, 0, { (DWORD_PTR)(__FILE__ ": tls") }
53 static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 };
55 tls_data_t *get_tls_data(void)
59 if(urlmon_tls == TLS_OUT_OF_INDEXES) {
60 DWORD tls = TlsAlloc();
61 if(tls == TLS_OUT_OF_INDEXES)
64 tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES);
69 data = TlsGetValue(urlmon_tls);
71 data = heap_alloc_zero(sizeof(tls_data_t));
75 EnterCriticalSection(&tls_cs);
76 list_add_tail(&tls_list, &data->entry);
77 LeaveCriticalSection(&tls_cs);
79 TlsSetValue(urlmon_tls, data);
85 static void free_tls_list(void)
89 if(urlmon_tls == TLS_OUT_OF_INDEXES)
92 while(!list_empty(&tls_list)) {
93 data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry);
94 list_remove(&data->entry);
101 static void detach_thread(void)
105 if(urlmon_tls == TLS_OUT_OF_INDEXES)
108 data = TlsGetValue(urlmon_tls);
112 EnterCriticalSection(&tls_cs);
113 list_remove(&data->entry);
114 LeaveCriticalSection(&tls_cs);
116 if(data->notif_hwnd) {
117 WARN("notif_hwnd not destroyed\n");
118 DestroyWindow(data->notif_hwnd);
124 /***********************************************************************
125 * DllMain (URLMON.init)
127 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
129 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
132 case DLL_PROCESS_ATTACH:
133 URLMON_hInstance = hinstDLL;
137 case DLL_PROCESS_DETACH:
139 FreeLibrary(hCabinet);
144 URLMON_hInstance = 0;
147 case DLL_THREAD_DETACH:
155 /***********************************************************************
156 * DllInstall (URLMON.@)
158 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
160 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
161 debugstr_w(cmdline));
166 /***********************************************************************
167 * DllCanUnloadNow (URLMON.@)
169 HRESULT WINAPI DllCanUnloadNow(void)
171 return URLMON_refCount != 0 ? S_FALSE : S_OK;
176 /******************************************************************************
177 * Urlmon ClassFactory
180 const IClassFactoryVtbl *lpClassFactoryVtbl;
182 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
185 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
187 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
191 if(IsEqualGUID(riid, &IID_IUnknown)) {
192 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
194 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
195 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
200 IUnknown_AddRef((IUnknown*)*ppv);
204 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
205 return E_NOINTERFACE;
208 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
214 static ULONG WINAPI CF_Release(IClassFactory *iface)
216 URLMON_UnlockModule();
221 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
222 REFIID riid, LPVOID *ppobj)
224 ClassFactory *This = (ClassFactory*)iface;
228 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
231 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
232 hres = IUnknown_QueryInterface(punk, riid, ppobj);
233 IUnknown_Release(punk);
238 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
240 TRACE("(%d)\n", dolock);
245 URLMON_UnlockModule();
250 static const IClassFactoryVtbl ClassFactoryVtbl =
259 static const ClassFactory FileProtocolCF =
260 { &ClassFactoryVtbl, FileProtocol_Construct};
261 static const ClassFactory FtpProtocolCF =
262 { &ClassFactoryVtbl, FtpProtocol_Construct};
263 static const ClassFactory GopherProtocolCF =
264 { &ClassFactoryVtbl, GopherProtocol_Construct};
265 static const ClassFactory HttpProtocolCF =
266 { &ClassFactoryVtbl, HttpProtocol_Construct};
267 static const ClassFactory HttpSProtocolCF =
268 { &ClassFactoryVtbl, HttpSProtocol_Construct};
269 static const ClassFactory MkProtocolCF =
270 { &ClassFactoryVtbl, MkProtocol_Construct};
271 static const ClassFactory SecurityManagerCF =
272 { &ClassFactoryVtbl, SecManagerImpl_Construct};
273 static const ClassFactory ZoneManagerCF =
274 { &ClassFactoryVtbl, ZoneMgrImpl_Construct};
275 static const ClassFactory StdURLMonikerCF =
276 { &ClassFactoryVtbl, StdURLMoniker_Construct};
277 static const ClassFactory MimeFilterCF =
278 { &ClassFactoryVtbl, MimeFilter_Construct};
280 struct object_creation_info
287 static const WCHAR wszFile[] = {'f','i','l','e',0};
288 static const WCHAR wszFtp[] = {'f','t','p',0};
289 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
290 static const WCHAR wszHttp[] = {'h','t','t','p',0};
291 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
292 static const WCHAR wszMk[] = {'m','k',0};
294 static const struct object_creation_info object_creation[] =
296 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
297 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
298 { &CLSID_GopherProtocol, CLASSFACTORY(&GopherProtocolCF), wszGopher },
299 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
300 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
301 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
302 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
303 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL },
304 { &CLSID_StdURLMoniker, CLASSFACTORY(&StdURLMonikerCF), NULL },
305 { &CLSID_DeCompMimeFilter, CLASSFACTORY(&MimeFilterCF), NULL }
308 static void init_session(BOOL init)
312 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
314 if(object_creation[i].protocol)
315 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
316 object_creation[i].protocol, init);
320 /*******************************************************************************
321 * DllGetClassObject [URLMON.@]
322 * Retrieves class object from a DLL object
325 * Docs say returns STDAPI
328 * rclsid [I] CLSID for the class object
329 * riid [I] Reference to identifier of interface for class object
330 * ppv [O] Address of variable to receive interface pointer for riid
334 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
338 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
342 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
344 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
346 if (IsEqualGUID(object_creation[i].clsid, rclsid))
347 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
350 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
351 return CLASS_E_CLASSNOTAVAILABLE;
355 /***********************************************************************
356 * DllRegisterServerEx (URLMON.@)
358 HRESULT WINAPI DllRegisterServerEx(void)
360 FIXME("(void): stub\n");
365 /**************************************************************************
366 * IsValidURL (URLMON.@)
368 * Determines if a specified string is a valid URL.
371 * pBC [I] ignored, must be NULL.
372 * szURL [I] string that represents the URL in question.
373 * dwReserved [I] reserved and must be zero.
378 * returns E_INVALIDARG if one or more of the args is invalid.
381 * test functionality against windows to see what a valid URL is.
383 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
385 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
387 if (pBC != NULL || dwReserved != 0)
393 /**************************************************************************
394 * FaultInIEFeature (URLMON.@)
396 * Undocumented. Appears to be used by native shdocvw.dll.
398 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
399 QUERYCONTEXT *pQuery, DWORD flags )
401 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
405 /**************************************************************************
406 * CoGetClassObjectFromURL (URLMON.@)
408 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
409 DWORD dwFileVersionLS, LPCWSTR szContentType,
410 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
411 REFIID riid, LPVOID *ppv )
413 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
414 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
415 debugstr_guid(riid), ppv);
416 return E_NOINTERFACE;
419 /***********************************************************************
420 * ReleaseBindInfo (URLMON.@)
422 * Release the resources used by the specified BINDINFO structure.
425 * pbindinfo [I] BINDINFO to release.
430 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
434 TRACE("(%p)\n", pbindinfo);
436 if(!pbindinfo || !(size = pbindinfo->cbSize))
439 CoTaskMemFree(pbindinfo->szExtraInfo);
440 ReleaseStgMedium(&pbindinfo->stgmedData);
442 if(offsetof(BINDINFO, szExtraInfo) < size)
443 CoTaskMemFree(pbindinfo->szCustomVerb);
445 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
446 IUnknown_Release(pbindinfo->pUnk);
448 memset(pbindinfo, 0, size);
449 pbindinfo->cbSize = size;
452 /***********************************************************************
453 * CopyStgMedium (URLMON.@)
455 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
457 TRACE("(%p %p)\n", src, dst);
468 if(src->u.lpszFileName && !src->pUnkForRelease) {
469 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
470 dst->u.lpszFileName = CoTaskMemAlloc(size);
471 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
476 IStream_AddRef(dst->u.pstm);
480 IStorage_AddRef(dst->u.pstg);
483 FIXME("Unimplemented tymed %d\n", src->tymed);
486 if(dst->pUnkForRelease)
487 IUnknown_AddRef(dst->pUnkForRelease);
492 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
494 return size > 5 && !memcmp(b, "{\\rtf", 5);
497 static BOOL text_html_filter(const BYTE *b, DWORD size)
504 for(i=0; i < size-5; i++) {
506 && (b[i+1] == 'h' || b[i+1] == 'H')
507 && (b[i+2] == 't' || b[i+2] == 'T')
508 && (b[i+3] == 'm' || b[i+3] == 'M')
509 && (b[i+4] == 'l' || b[i+4] == 'L'))
516 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
519 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
522 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
525 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
526 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
529 static BOOL image_gif_filter(const BYTE *b, DWORD size)
532 && (b[0] == 'G' || b[0] == 'g')
533 && (b[1] == 'I' || b[1] == 'i')
534 && (b[2] == 'F' || b[2] == 'f')
536 && (b[4] == '7' || b[4] == '9')
537 && (b[5] == 'A' || b[5] == 'a');
540 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
542 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
545 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
547 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
550 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
552 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
553 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
556 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
559 && b[0] == 0x42 && b[1] == 0x4d
560 && *(const DWORD *)(b+6) == 0;
563 static BOOL video_avi_filter(const BYTE *b, DWORD size)
566 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
567 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
570 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
573 && !b[0] && !b[1] && b[2] == 0x01
574 && (b[3] == 0xb3 || b[3] == 0xba);
577 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
579 return size > 2 && b[0] == '%' && b[1] == '!';
582 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
584 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
587 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
589 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
592 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
594 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
597 static BOOL application_java_filter(const BYTE *b, DWORD size)
599 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
602 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
604 return size > 2 && b[0] == 'M' && b[1] == 'Z';
607 static BOOL text_plain_filter(const BYTE *b, DWORD size)
611 for(ptr = b; ptr < b+size-1; ptr++) {
612 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
619 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
624 /***********************************************************************
625 * FindMimeFromData (URLMON.@)
627 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
629 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
630 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
631 LPWSTR* ppwzMimeOut, DWORD dwReserved)
633 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
634 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
637 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
639 WARN("dwReserved=%d\n", dwReserved);
641 /* pBC seams to not be used */
643 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
646 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
652 len = strlenW(pwzMimeProposed)+1;
653 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
654 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
659 const BYTE *buf = pBuffer;
664 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
665 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
666 static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
667 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
668 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
669 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
670 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
671 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
672 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
673 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
674 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
675 static const WCHAR wszAppPostscript[] =
676 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
677 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
679 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
680 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
681 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
682 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
683 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
685 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
686 'x','-','m','s','d','o','w','n','l','o','a','d',0};
687 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
688 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
689 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
691 static const struct {
693 BOOL (*filter)(const BYTE *,DWORD);
695 {wszTextHtml, text_html_filter},
696 {wszTextRichtext, text_richtext_filter},
697 /* {wszAudioXAiff, audio_xaiff_filter}, */
698 {wszAudioBasic, audio_basic_filter},
699 {wszAudioWav, audio_wav_filter},
700 {wszImageGif, image_gif_filter},
701 {wszImagePjpeg, image_pjpeg_filter},
702 {wszImageTiff, image_tiff_filter},
703 {wszImageXPng, image_xpng_filter},
704 /* {wszImageXBitmap, image_xbitmap_filter}, */
705 {wszImageBmp, image_bmp_filter},
706 /* {wszImageXJg, image_xjg_filter}, */
707 /* {wszImageXEmf, image_xemf_filter}, */
708 /* {wszImageXWmf, image_xwmf_filter}, */
709 {wszVideoAvi, video_avi_filter},
710 {wszVideoMpeg, video_mpeg_filter},
711 {wszAppPostscript, application_postscript_filter},
712 /* {wszAppBase64, application_base64_filter}, */
713 /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
714 {wszAppPdf, application_pdf_filter},
715 /* {wszAppXCompressed, application_xcompressed_filter}, */
716 {wszAppXZip, application_xzip_filter},
717 {wszAppXGzip, application_xgzip_filter},
718 {wszAppJava, application_java_filter},
719 {wszAppXMSDownload, application_xmsdownload},
720 {wszTextPlain, text_plain_filter},
721 {wszAppOctetStream, application_octet_stream_filter}
727 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
728 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
729 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
733 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
734 || mime_filters[i].filter(buf, cbSize)) {
735 len = strlenW(pwzMimeProposed)+1;
736 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
737 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
744 if(mime_filters[i].filter(buf, cbSize))
745 ret = mime_filters[i].mime;
749 TRACE("found %s for data\n"
750 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
751 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
752 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
754 if(pwzMimeProposed) {
755 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
756 ret = pwzMimeProposed;
758 /* text/html is a special case */
759 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
763 len = strlenW(ret)+1;
764 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
765 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
775 static const WCHAR wszContentType[] =
776 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
778 ptr = strrchrW(pwzUrl, '.');
782 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
783 if(res != ERROR_SUCCESS)
784 return HRESULT_FROM_WIN32(res);
787 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
789 if(res != ERROR_SUCCESS)
790 return HRESULT_FROM_WIN32(res);
792 *ppwzMimeOut = CoTaskMemAlloc(size);
793 memcpy(*ppwzMimeOut, mime, size);
800 /***********************************************************************
801 * GetClassFileOrMime (URLMON.@)
803 * Determines the class ID from the bind context, file name or MIME type.
805 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
806 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
809 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
810 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
815 /***********************************************************************
818 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
820 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
823 hCabinet = LoadLibraryA("cabinet.dll");
825 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
826 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
827 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
829 return pExtract(dest, szCabName);
832 /***********************************************************************
833 * IsLoggingEnabledA (URLMON.@)
835 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
837 FIXME("(%s)\n", debugstr_a(url));
841 /***********************************************************************
842 * IsLoggingEnabledW (URLMON.@)
844 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
846 FIXME("(%s)\n", debugstr_w(url));