oleacc: Build language resource files separately.
[wine/multimedia.git] / dlls / urlmon / urlmon_main.c
blob2e624fb97c28475a4a60e91228b847b325f13f38
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 /***********************************************************************
125 * DllMain (URLMON.init)
127 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
129 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
131 switch(fdwReason) {
132 case DLL_PROCESS_ATTACH:
133 URLMON_hInstance = hinstDLL;
134 init_session(TRUE);
135 break;
137 case DLL_PROCESS_DETACH:
138 if (hCabinet)
139 FreeLibrary(hCabinet);
140 hCabinet = NULL;
141 init_session(FALSE);
142 free_session();
143 free_tls_list();
144 URLMON_hInstance = 0;
145 break;
147 case DLL_THREAD_DETACH:
148 detach_thread();
149 break;
151 return TRUE;
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));
163 return S_OK;
166 /***********************************************************************
167 * DllCanUnloadNow (URLMON.@)
169 HRESULT WINAPI DllCanUnloadNow(void)
171 return URLMON_refCount != 0 ? S_FALSE : S_OK;
176 /******************************************************************************
177 * Urlmon ClassFactory
179 typedef struct {
180 const IClassFactoryVtbl *lpClassFactoryVtbl;
182 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
183 } ClassFactory;
185 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
187 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
189 *ppv = NULL;
191 if(IsEqualGUID(riid, &IID_IUnknown)) {
192 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
193 *ppv = iface;
194 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
195 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
196 *ppv = iface;
199 if(*ppv) {
200 IUnknown_AddRef((IUnknown*)*ppv);
201 return S_OK;
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)
210 URLMON_LockModule();
211 return 2;
214 static ULONG WINAPI CF_Release(IClassFactory *iface)
216 URLMON_UnlockModule();
217 return 1;
221 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
222 REFIID riid, LPVOID *ppobj)
224 ClassFactory *This = (ClassFactory*)iface;
225 HRESULT hres;
226 LPUNKNOWN punk;
228 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
230 *ppobj = NULL;
231 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
232 hres = IUnknown_QueryInterface(punk, riid, ppobj);
233 IUnknown_Release(punk);
235 return hres;
238 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
240 TRACE("(%d)\n", dolock);
242 if (dolock)
243 URLMON_LockModule();
244 else
245 URLMON_UnlockModule();
247 return S_OK;
250 static const IClassFactoryVtbl ClassFactoryVtbl =
252 CF_QueryInterface,
253 CF_AddRef,
254 CF_Release,
255 CF_CreateInstance,
256 CF_LockServer
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
282 const CLSID *clsid;
283 IClassFactory *cf;
284 LPCWSTR protocol;
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)
310 unsigned int i;
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
324 * NOTES
325 * Docs say returns STDAPI
327 * PARAMS
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
332 * RETURNS
333 * Success: S_OK
334 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
335 * E_UNEXPECTED
338 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
340 unsigned int i;
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");
362 return E_FAIL;
365 /**************************************************************************
366 * IsValidURL (URLMON.@)
368 * Determines if a specified string is a valid URL.
370 * PARAMS
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.
375 * RETURNS
376 * Success: S_OK.
377 * Failure: S_FALSE.
378 * returns E_INVALIDARG if one or more of the args is invalid.
380 * TODO:
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)
388 return E_INVALIDARG;
390 return S_OK;
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);
402 return E_NOTIMPL;
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.
424 * PARAMS
425 * pbindinfo [I] BINDINFO to release.
427 * RETURNS
428 * Nothing.
430 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
432 DWORD size;
434 TRACE("(%p)\n", pbindinfo);
436 if(!pbindinfo || !(size = pbindinfo->cbSize))
437 return;
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);
459 if(!src || !dst)
460 return E_POINTER;
462 *dst = *src;
464 switch(dst->tymed) {
465 case TYMED_NULL:
466 break;
467 case TYMED_FILE:
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);
473 break;
474 case TYMED_ISTREAM:
475 if(dst->u.pstm)
476 IStream_AddRef(dst->u.pstm);
477 break;
478 case TYMED_ISTORAGE:
479 if(dst->u.pstg)
480 IStorage_AddRef(dst->u.pstg);
481 break;
482 default:
483 FIXME("Unimplemented tymed %d\n", src->tymed);
486 if(dst->pUnkForRelease)
487 IUnknown_AddRef(dst->pUnkForRelease);
489 return S_OK;
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)
499 DWORD i;
501 if(size < 5)
502 return FALSE;
504 for(i=0; i < size-5; i++) {
505 if(b[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'))
510 return TRUE;
513 return FALSE;
516 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
518 return size > 4
519 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
522 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
524 return size > 12
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)
531 return size >= 6
532 && (b[0] == 'G' || b[0] == 'g')
533 && (b[1] == 'I' || b[1] == 'i')
534 && (b[2] == 'F' || b[2] == 'f')
535 && b[3] == '8'
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)
558 return size >= 14
559 && b[0] == 0x42 && b[1] == 0x4d
560 && *(const DWORD *)(b+6) == 0;
563 static BOOL video_avi_filter(const BYTE *b, DWORD size)
565 return size > 12
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)
572 return size > 4
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)
609 const BYTE *ptr;
611 for(ptr = b; ptr < b+size-1; ptr++) {
612 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
613 return FALSE;
616 return TRUE;
619 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
621 return TRUE;
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);
636 if(dwMimeFlags)
637 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
638 if(dwReserved)
639 WARN("dwReserved=%d\n", dwReserved);
641 /* pBC seams to not be used */
643 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
644 return E_INVALIDARG;
646 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
647 DWORD len;
649 if(!pwzMimeProposed)
650 return E_FAIL;
652 len = strlenW(pwzMimeProposed)+1;
653 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
654 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
655 return S_OK;
658 if(pBuffer) {
659 const BYTE *buf = pBuffer;
660 DWORD len;
661 LPCWSTR ret = NULL;
662 unsigned int i;
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','/',
678 'p','d','f',0};
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','/',
684 'j','a','v','a',0};
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 {
692 LPCWSTR mime;
693 BOOL (*filter)(const BYTE *,DWORD);
694 } mime_filters[] = {
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}
724 if(!cbSize)
725 return E_FAIL;
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))
730 break;
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));
738 return S_OK;
742 i=0;
743 while(!ret) {
744 if(mime_filters[i].filter(buf, cbSize))
745 ret = mime_filters[i].mime;
746 i++;
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))
760 ret = wszTextHtml;
763 len = strlenW(ret)+1;
764 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
765 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
766 return S_OK;
769 if(pwzUrl) {
770 HKEY hkey;
771 DWORD res, size;
772 LPCWSTR ptr;
773 WCHAR mime[64];
775 static const WCHAR wszContentType[] =
776 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
778 ptr = strrchrW(pwzUrl, '.');
779 if(!ptr)
780 return E_FAIL;
782 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
783 if(res != ERROR_SUCCESS)
784 return HRESULT_FROM_WIN32(res);
786 size = sizeof(mime);
787 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
788 RegCloseKey(hkey);
789 if(res != ERROR_SUCCESS)
790 return HRESULT_FROM_WIN32(res);
792 *ppwzMimeOut = CoTaskMemAlloc(size);
793 memcpy(*ppwzMimeOut, mime, size);
794 return S_OK;
797 return E_FAIL;
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,
807 CLSID *pclsid)
809 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
810 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
811 dwReserved, pclsid);
812 return E_NOTIMPL;
815 /***********************************************************************
816 * Extract (URLMON.@)
818 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
820 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
822 if (!hCabinet)
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));
838 return FALSE;
841 /***********************************************************************
842 * IsLoggingEnabledW (URLMON.@)
844 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
846 FIXME("(%s)\n", debugstr_w(url));
847 return FALSE;