push 5aff8350ceade24f8243f07a9cf7ecb816236fb1
[wine/hacks.git] / dlls / urlmon / urlmon_main.c
blob3640adcff2c288382f7576d1205e907efaaeb1dd
1 /*
2 * UrlMon
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
21 #include <stdarg.h>
23 #include "urlmon_main.h"
25 #include "winreg.h"
27 #define NO_SHLWAPI_REG
28 #include "shlwapi.h"
29 #include "wine/debug.h"
31 #include "urlmon.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 =
48 0, 0, &tls_cs,
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)
57 tls_data_t *data;
59 if(urlmon_tls == TLS_OUT_OF_INDEXES) {
60 DWORD tls = TlsAlloc();
61 if(tls == TLS_OUT_OF_INDEXES)
62 return NULL;
64 tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES);
65 if(tls != urlmon_tls)
66 TlsFree(tls);
69 data = TlsGetValue(urlmon_tls);
70 if(!data) {
71 data = heap_alloc_zero(sizeof(tls_data_t));
72 if(!data)
73 return NULL;
75 EnterCriticalSection(&tls_cs);
76 list_add_tail(&tls_list, &data->entry);
77 LeaveCriticalSection(&tls_cs);
79 TlsSetValue(urlmon_tls, data);
82 return data;
85 static void free_tls_list(void)
87 tls_data_t *data;
89 if(urlmon_tls == TLS_OUT_OF_INDEXES)
90 return;
92 while(!list_empty(&tls_list)) {
93 data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry);
94 list_remove(&data->entry);
95 heap_free(data);
98 TlsFree(urlmon_tls);
101 static void detach_thread(void)
103 tls_data_t *data;
105 if(urlmon_tls == TLS_OUT_OF_INDEXES)
106 return;
108 data = TlsGetValue(urlmon_tls);
109 if(!data)
110 return;
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);
121 heap_free(data);
124 static void process_detach(void)
126 HINTERNET internet_session;
128 internet_session = get_internet_session(NULL);
129 if(internet_session)
130 InternetCloseHandle(internet_session);
132 if (hCabinet)
133 FreeLibrary(hCabinet);
135 init_session(FALSE);
136 free_session();
137 free_tls_list();
140 /***********************************************************************
141 * DllMain (URLMON.init)
143 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
145 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
147 switch(fdwReason) {
148 case DLL_PROCESS_ATTACH:
149 URLMON_hInstance = hinstDLL;
150 init_session(TRUE);
151 break;
153 case DLL_PROCESS_DETACH:
154 process_detach();
155 break;
157 case DLL_THREAD_DETACH:
158 detach_thread();
159 break;
161 return TRUE;
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));
173 return S_OK;
176 /***********************************************************************
177 * DllCanUnloadNow (URLMON.@)
179 HRESULT WINAPI DllCanUnloadNow(void)
181 return URLMON_refCount != 0 ? S_FALSE : S_OK;
186 /******************************************************************************
187 * Urlmon ClassFactory
189 typedef struct {
190 const IClassFactoryVtbl *lpClassFactoryVtbl;
192 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
193 } ClassFactory;
195 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
197 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
199 *ppv = NULL;
201 if(IsEqualGUID(riid, &IID_IUnknown)) {
202 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
203 *ppv = iface;
204 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
205 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
206 *ppv = iface;
209 if(*ppv) {
210 IUnknown_AddRef((IUnknown*)*ppv);
211 return S_OK;
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)
220 URLMON_LockModule();
221 return 2;
224 static ULONG WINAPI CF_Release(IClassFactory *iface)
226 URLMON_UnlockModule();
227 return 1;
231 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
232 REFIID riid, LPVOID *ppobj)
234 ClassFactory *This = (ClassFactory*)iface;
235 HRESULT hres;
236 LPUNKNOWN punk;
238 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
240 *ppobj = NULL;
241 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
242 hres = IUnknown_QueryInterface(punk, riid, ppobj);
243 IUnknown_Release(punk);
245 return hres;
248 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
250 TRACE("(%d)\n", dolock);
252 if (dolock)
253 URLMON_LockModule();
254 else
255 URLMON_UnlockModule();
257 return S_OK;
260 static const IClassFactoryVtbl ClassFactoryVtbl =
262 CF_QueryInterface,
263 CF_AddRef,
264 CF_Release,
265 CF_CreateInstance,
266 CF_LockServer
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
292 const CLSID *clsid;
293 IClassFactory *cf;
294 LPCWSTR protocol;
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)
320 unsigned int i;
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
334 * NOTES
335 * Docs say returns STDAPI
337 * PARAMS
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
342 * RETURNS
343 * Success: S_OK
344 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
345 * E_UNEXPECTED
348 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
350 unsigned int i;
352 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
354 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
356 if (IsEqualGUID(object_creation[i].clsid, rclsid))
357 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
360 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
361 return CLASS_E_CLASSNOTAVAILABLE;
365 /***********************************************************************
366 * DllRegisterServerEx (URLMON.@)
368 HRESULT WINAPI DllRegisterServerEx(void)
370 FIXME("(void): stub\n");
372 return E_FAIL;
375 /**************************************************************************
376 * IsValidURL (URLMON.@)
378 * Determines if a specified string is a valid URL.
380 * PARAMS
381 * pBC [I] ignored, must be NULL.
382 * szURL [I] string that represents the URL in question.
383 * dwReserved [I] reserved and must be zero.
385 * RETURNS
386 * Success: S_OK.
387 * Failure: S_FALSE.
388 * returns E_INVALIDARG if one or more of the args is invalid.
390 * TODO:
391 * test functionality against windows to see what a valid URL is.
393 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
395 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
397 if (pBC != NULL || dwReserved != 0)
398 return E_INVALIDARG;
400 return S_OK;
403 /**************************************************************************
404 * FaultInIEFeature (URLMON.@)
406 * Undocumented. Appears to be used by native shdocvw.dll.
408 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
409 QUERYCONTEXT *pQuery, DWORD flags )
411 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
412 return E_NOTIMPL;
415 /**************************************************************************
416 * CoGetClassObjectFromURL (URLMON.@)
418 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
419 DWORD dwFileVersionLS, LPCWSTR szContentType,
420 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
421 REFIID riid, LPVOID *ppv )
423 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
424 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
425 debugstr_guid(riid), ppv);
426 return E_NOINTERFACE;
429 /***********************************************************************
430 * ReleaseBindInfo (URLMON.@)
432 * Release the resources used by the specified BINDINFO structure.
434 * PARAMS
435 * pbindinfo [I] BINDINFO to release.
437 * RETURNS
438 * Nothing.
440 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
442 DWORD size;
444 TRACE("(%p)\n", pbindinfo);
446 if(!pbindinfo || !(size = pbindinfo->cbSize))
447 return;
449 CoTaskMemFree(pbindinfo->szExtraInfo);
450 ReleaseStgMedium(&pbindinfo->stgmedData);
452 if(offsetof(BINDINFO, szExtraInfo) < size)
453 CoTaskMemFree(pbindinfo->szCustomVerb);
455 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
456 IUnknown_Release(pbindinfo->pUnk);
458 memset(pbindinfo, 0, size);
459 pbindinfo->cbSize = size;
462 /***********************************************************************
463 * CopyStgMedium (URLMON.@)
465 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
467 TRACE("(%p %p)\n", src, dst);
469 if(!src || !dst)
470 return E_POINTER;
472 *dst = *src;
474 switch(dst->tymed) {
475 case TYMED_NULL:
476 break;
477 case TYMED_FILE:
478 if(src->u.lpszFileName && !src->pUnkForRelease) {
479 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
480 dst->u.lpszFileName = CoTaskMemAlloc(size);
481 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
483 break;
484 case TYMED_ISTREAM:
485 if(dst->u.pstm)
486 IStream_AddRef(dst->u.pstm);
487 break;
488 case TYMED_ISTORAGE:
489 if(dst->u.pstg)
490 IStorage_AddRef(dst->u.pstg);
491 break;
492 default:
493 FIXME("Unimplemented tymed %d\n", src->tymed);
496 if(dst->pUnkForRelease)
497 IUnknown_AddRef(dst->pUnkForRelease);
499 return S_OK;
502 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
504 return size > 5 && !memcmp(b, "{\\rtf", 5);
507 static BOOL text_html_filter(const BYTE *b, DWORD size)
509 DWORD i;
511 if(size < 5)
512 return FALSE;
514 for(i=0; i < size-5; i++) {
515 if(b[i] == '<'
516 && (b[i+1] == 'h' || b[i+1] == 'H')
517 && (b[i+2] == 't' || b[i+2] == 'T')
518 && (b[i+3] == 'm' || b[i+3] == 'M')
519 && (b[i+4] == 'l' || b[i+4] == 'L'))
520 return TRUE;
523 return FALSE;
526 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
528 return size > 4
529 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
532 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
534 return size > 12
535 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
536 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
539 static BOOL image_gif_filter(const BYTE *b, DWORD size)
541 return size >= 6
542 && (b[0] == 'G' || b[0] == 'g')
543 && (b[1] == 'I' || b[1] == 'i')
544 && (b[2] == 'F' || b[2] == 'f')
545 && b[3] == '8'
546 && (b[4] == '7' || b[4] == '9')
547 && (b[5] == 'A' || b[5] == 'a');
550 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
552 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
555 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
557 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
560 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
562 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
563 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
566 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
568 return size >= 14
569 && b[0] == 0x42 && b[1] == 0x4d
570 && *(const DWORD *)(b+6) == 0;
573 static BOOL video_avi_filter(const BYTE *b, DWORD size)
575 return size > 12
576 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
577 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
580 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
582 return size > 4
583 && !b[0] && !b[1] && b[2] == 0x01
584 && (b[3] == 0xb3 || b[3] == 0xba);
587 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
589 return size > 2 && b[0] == '%' && b[1] == '!';
592 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
594 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
597 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
599 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
602 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
604 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
607 static BOOL application_java_filter(const BYTE *b, DWORD size)
609 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
612 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
614 return size > 2 && b[0] == 'M' && b[1] == 'Z';
617 static BOOL text_plain_filter(const BYTE *b, DWORD size)
619 const BYTE *ptr;
621 for(ptr = b; ptr < b+size-1; ptr++) {
622 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
623 return FALSE;
626 return TRUE;
629 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
631 return TRUE;
634 /***********************************************************************
635 * FindMimeFromData (URLMON.@)
637 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
639 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
640 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
641 LPWSTR* ppwzMimeOut, DWORD dwReserved)
643 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
644 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
646 if(dwMimeFlags)
647 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
648 if(dwReserved)
649 WARN("dwReserved=%d\n", dwReserved);
651 /* pBC seams to not be used */
653 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
654 return E_INVALIDARG;
656 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
657 DWORD len;
659 if(!pwzMimeProposed)
660 return E_FAIL;
662 len = strlenW(pwzMimeProposed)+1;
663 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
664 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
665 return S_OK;
668 if(pBuffer) {
669 const BYTE *buf = pBuffer;
670 DWORD len;
671 LPCWSTR ret = NULL;
672 unsigned int i;
674 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
675 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
676 static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
677 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
678 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
679 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
680 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
681 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
682 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
683 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
684 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
685 static const WCHAR wszAppPostscript[] =
686 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
687 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
688 'p','d','f',0};
689 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
690 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
691 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
692 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
693 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
694 'j','a','v','a',0};
695 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
696 'x','-','m','s','d','o','w','n','l','o','a','d',0};
697 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
698 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
699 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
701 static const struct {
702 LPCWSTR mime;
703 BOOL (*filter)(const BYTE *,DWORD);
704 } mime_filters[] = {
705 {wszTextHtml, text_html_filter},
706 {wszTextRichtext, text_richtext_filter},
707 /* {wszAudioXAiff, audio_xaiff_filter}, */
708 {wszAudioBasic, audio_basic_filter},
709 {wszAudioWav, audio_wav_filter},
710 {wszImageGif, image_gif_filter},
711 {wszImagePjpeg, image_pjpeg_filter},
712 {wszImageTiff, image_tiff_filter},
713 {wszImageXPng, image_xpng_filter},
714 /* {wszImageXBitmap, image_xbitmap_filter}, */
715 {wszImageBmp, image_bmp_filter},
716 /* {wszImageXJg, image_xjg_filter}, */
717 /* {wszImageXEmf, image_xemf_filter}, */
718 /* {wszImageXWmf, image_xwmf_filter}, */
719 {wszVideoAvi, video_avi_filter},
720 {wszVideoMpeg, video_mpeg_filter},
721 {wszAppPostscript, application_postscript_filter},
722 /* {wszAppBase64, application_base64_filter}, */
723 /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
724 {wszAppPdf, application_pdf_filter},
725 /* {wszAppXCompressed, application_xcompressed_filter}, */
726 {wszAppXZip, application_xzip_filter},
727 {wszAppXGzip, application_xgzip_filter},
728 {wszAppJava, application_java_filter},
729 {wszAppXMSDownload, application_xmsdownload},
730 {wszTextPlain, text_plain_filter},
731 {wszAppOctetStream, application_octet_stream_filter}
734 if(!cbSize)
735 return E_FAIL;
737 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
738 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
739 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
740 break;
743 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
744 || mime_filters[i].filter(buf, cbSize)) {
745 len = strlenW(pwzMimeProposed)+1;
746 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
747 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
748 return S_OK;
752 i=0;
753 while(!ret) {
754 if(mime_filters[i].filter(buf, cbSize))
755 ret = mime_filters[i].mime;
756 i++;
759 TRACE("found %s for data\n"
760 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
761 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
762 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
764 if(pwzMimeProposed) {
765 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
766 ret = pwzMimeProposed;
768 /* text/html is a special case */
769 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
770 ret = wszTextHtml;
773 len = strlenW(ret)+1;
774 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
775 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
776 return S_OK;
779 if(pwzUrl) {
780 HKEY hkey;
781 DWORD res, size;
782 LPCWSTR ptr;
783 WCHAR mime[64];
785 static const WCHAR wszContentType[] =
786 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
788 ptr = strrchrW(pwzUrl, '.');
789 if(!ptr)
790 return E_FAIL;
792 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
793 if(res != ERROR_SUCCESS)
794 return HRESULT_FROM_WIN32(res);
796 size = sizeof(mime);
797 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
798 RegCloseKey(hkey);
799 if(res != ERROR_SUCCESS)
800 return HRESULT_FROM_WIN32(res);
802 *ppwzMimeOut = CoTaskMemAlloc(size);
803 memcpy(*ppwzMimeOut, mime, size);
804 return S_OK;
807 return E_FAIL;
810 /***********************************************************************
811 * GetClassFileOrMime (URLMON.@)
813 * Determines the class ID from the bind context, file name or MIME type.
815 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
816 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
817 CLSID *pclsid)
819 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
820 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
821 dwReserved, pclsid);
822 return E_NOTIMPL;
825 /***********************************************************************
826 * Extract (URLMON.@)
828 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
830 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
832 if (!hCabinet)
833 hCabinet = LoadLibraryA("cabinet.dll");
835 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
836 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
837 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
839 return pExtract(dest, szCabName);
842 /***********************************************************************
843 * IsLoggingEnabledA (URLMON.@)
845 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
847 FIXME("(%s)\n", debugstr_a(url));
848 return FALSE;
851 /***********************************************************************
852 * IsLoggingEnabledW (URLMON.@)
854 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
856 FIXME("(%s)\n", debugstr_w(url));
857 return FALSE;