push 5b1efc32b5a8acb1d5b5e60584746392dd0c436e
[wine/hacks.git] / dlls / urlmon / urlmon_main.c
blob272884eb2a67fd42ad2af15b60b01629e97ff8b3
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;
351 HRESULT hr;
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);
362 if(SUCCEEDED(hr))
363 return hr;
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");
377 return E_FAIL;
380 /**************************************************************************
381 * IsValidURL (URLMON.@)
383 * Determines if a specified string is a valid URL.
385 * PARAMS
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.
390 * RETURNS
391 * Success: S_OK.
392 * Failure: S_FALSE.
393 * returns E_INVALIDARG if one or more of the args is invalid.
395 * TODO:
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)
403 return E_INVALIDARG;
405 return S_OK;
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);
417 return E_NOTIMPL;
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.
439 * PARAMS
440 * pbindinfo [I] BINDINFO to release.
442 * RETURNS
443 * Nothing.
445 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
447 DWORD size;
449 TRACE("(%p)\n", pbindinfo);
451 if(!pbindinfo || !(size = pbindinfo->cbSize))
452 return;
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);
474 if(!src || !dst)
475 return E_POINTER;
477 *dst = *src;
479 switch(dst->tymed) {
480 case TYMED_NULL:
481 break;
482 case TYMED_FILE:
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);
488 break;
489 case TYMED_ISTREAM:
490 if(dst->u.pstm)
491 IStream_AddRef(dst->u.pstm);
492 break;
493 case TYMED_ISTORAGE:
494 if(dst->u.pstg)
495 IStorage_AddRef(dst->u.pstg);
496 break;
497 default:
498 FIXME("Unimplemented tymed %d\n", src->tymed);
501 if(dst->pUnkForRelease)
502 IUnknown_AddRef(dst->pUnkForRelease);
504 return S_OK;
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)
514 DWORD i;
516 if(size < 5)
517 return FALSE;
519 for(i=0; i < size-5; i++) {
520 if(b[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'))
525 return TRUE;
528 return FALSE;
531 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
533 return size > 4
534 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
537 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
539 return size > 12
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)
546 return size >= 6
547 && (b[0] == 'G' || b[0] == 'g')
548 && (b[1] == 'I' || b[1] == 'i')
549 && (b[2] == 'F' || b[2] == 'f')
550 && b[3] == '8'
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)
573 return size >= 14
574 && b[0] == 0x42 && b[1] == 0x4d
575 && *(const DWORD *)(b+6) == 0;
578 static BOOL video_avi_filter(const BYTE *b, DWORD size)
580 return size > 12
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)
587 return size > 4
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)
624 const BYTE *ptr;
626 for(ptr = b; ptr < b+size-1; ptr++) {
627 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
628 return FALSE;
631 return TRUE;
634 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
636 return TRUE;
639 /***********************************************************************
640 * FindMimeFromData (URLMON.@)
642 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
644 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
645 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
646 LPWSTR* ppwzMimeOut, DWORD dwReserved)
648 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
649 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
651 if(dwMimeFlags)
652 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
653 if(dwReserved)
654 WARN("dwReserved=%d\n", dwReserved);
656 /* pBC seams to not be used */
658 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
659 return E_INVALIDARG;
661 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
662 DWORD len;
664 if(!pwzMimeProposed)
665 return E_FAIL;
667 len = strlenW(pwzMimeProposed)+1;
668 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
669 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
670 return S_OK;
673 if(pBuffer) {
674 const BYTE *buf = pBuffer;
675 DWORD len;
676 LPCWSTR ret = NULL;
677 unsigned int i;
679 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
680 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
681 static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
682 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
683 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
684 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
685 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
686 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
687 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
688 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
689 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
690 static const WCHAR wszAppPostscript[] =
691 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
692 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
693 'p','d','f',0};
694 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
695 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
696 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
697 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
698 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
699 'j','a','v','a',0};
700 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
701 'x','-','m','s','d','o','w','n','l','o','a','d',0};
702 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
703 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
704 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
706 static const struct {
707 LPCWSTR mime;
708 BOOL (*filter)(const BYTE *,DWORD);
709 } mime_filters[] = {
710 {wszTextHtml, text_html_filter},
711 {wszTextRichtext, text_richtext_filter},
712 /* {wszAudioXAiff, audio_xaiff_filter}, */
713 {wszAudioBasic, audio_basic_filter},
714 {wszAudioWav, audio_wav_filter},
715 {wszImageGif, image_gif_filter},
716 {wszImagePjpeg, image_pjpeg_filter},
717 {wszImageTiff, image_tiff_filter},
718 {wszImageXPng, image_xpng_filter},
719 /* {wszImageXBitmap, image_xbitmap_filter}, */
720 {wszImageBmp, image_bmp_filter},
721 /* {wszImageXJg, image_xjg_filter}, */
722 /* {wszImageXEmf, image_xemf_filter}, */
723 /* {wszImageXWmf, image_xwmf_filter}, */
724 {wszVideoAvi, video_avi_filter},
725 {wszVideoMpeg, video_mpeg_filter},
726 {wszAppPostscript, application_postscript_filter},
727 /* {wszAppBase64, application_base64_filter}, */
728 /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
729 {wszAppPdf, application_pdf_filter},
730 /* {wszAppXCompressed, application_xcompressed_filter}, */
731 {wszAppXZip, application_xzip_filter},
732 {wszAppXGzip, application_xgzip_filter},
733 {wszAppJava, application_java_filter},
734 {wszAppXMSDownload, application_xmsdownload},
735 {wszTextPlain, text_plain_filter},
736 {wszAppOctetStream, application_octet_stream_filter}
739 if(!cbSize)
740 return E_FAIL;
742 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
743 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
744 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
745 break;
748 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
749 || mime_filters[i].filter(buf, cbSize)) {
750 len = strlenW(pwzMimeProposed)+1;
751 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
752 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
753 return S_OK;
757 i=0;
758 while(!ret) {
759 if(mime_filters[i].filter(buf, cbSize))
760 ret = mime_filters[i].mime;
761 i++;
764 TRACE("found %s for data\n"
765 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
766 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
767 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
769 if(pwzMimeProposed) {
770 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
771 ret = pwzMimeProposed;
773 /* text/html is a special case */
774 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
775 ret = wszTextHtml;
778 len = strlenW(ret)+1;
779 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
780 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
781 return S_OK;
784 if(pwzUrl) {
785 HKEY hkey;
786 DWORD res, size;
787 LPCWSTR ptr;
788 WCHAR mime[64];
790 static const WCHAR wszContentType[] =
791 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
793 ptr = strrchrW(pwzUrl, '.');
794 if(!ptr)
795 return E_FAIL;
797 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
798 if(res != ERROR_SUCCESS)
799 return HRESULT_FROM_WIN32(res);
801 size = sizeof(mime);
802 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
803 RegCloseKey(hkey);
804 if(res != ERROR_SUCCESS)
805 return HRESULT_FROM_WIN32(res);
807 *ppwzMimeOut = CoTaskMemAlloc(size);
808 memcpy(*ppwzMimeOut, mime, size);
809 return S_OK;
812 return E_FAIL;
815 /***********************************************************************
816 * GetClassFileOrMime (URLMON.@)
818 * Determines the class ID from the bind context, file name or MIME type.
820 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
821 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
822 CLSID *pclsid)
824 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
825 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
826 dwReserved, pclsid);
827 return E_NOTIMPL;
830 /***********************************************************************
831 * Extract (URLMON.@)
833 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
835 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
837 if (!hCabinet)
838 hCabinet = LoadLibraryA("cabinet.dll");
840 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
841 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
842 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
844 return pExtract(dest, szCabName);
847 /***********************************************************************
848 * IsLoggingEnabledA (URLMON.@)
850 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
852 FIXME("(%s)\n", debugstr_a(url));
853 return FALSE;
856 /***********************************************************************
857 * IsLoggingEnabledW (URLMON.@)
859 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
861 FIXME("(%s)\n", debugstr_w(url));
862 return FALSE;