msvcrt: Add _snwprintf_l.
[wine/multimedia.git] / dlls / urlmon / urlmon_main.c
blob13c61dea771f995512ae69924bb346718d2dfe48
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 "advpub.h"
31 #include "wine/debug.h"
33 #include "urlmon.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
37 LONG URLMON_refCount = 0;
39 static HMODULE hCabinet = NULL;
40 static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
42 static void init_session(BOOL);
44 static struct list tls_list = LIST_INIT(tls_list);
46 static CRITICAL_SECTION tls_cs;
47 static CRITICAL_SECTION_DEBUG tls_cs_dbg =
49 0, 0, &tls_cs,
50 { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList },
51 0, 0, { (DWORD_PTR)(__FILE__ ": tls") }
54 static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 };
56 tls_data_t *get_tls_data(void)
58 tls_data_t *data;
60 if(urlmon_tls == TLS_OUT_OF_INDEXES) {
61 DWORD tls = TlsAlloc();
62 if(tls == TLS_OUT_OF_INDEXES)
63 return NULL;
65 tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES);
66 if(tls != urlmon_tls)
67 TlsFree(tls);
70 data = TlsGetValue(urlmon_tls);
71 if(!data) {
72 data = heap_alloc_zero(sizeof(tls_data_t));
73 if(!data)
74 return NULL;
76 EnterCriticalSection(&tls_cs);
77 list_add_tail(&tls_list, &data->entry);
78 LeaveCriticalSection(&tls_cs);
80 TlsSetValue(urlmon_tls, data);
83 return data;
86 static void free_tls_list(void)
88 tls_data_t *data;
90 if(urlmon_tls == TLS_OUT_OF_INDEXES)
91 return;
93 while(!list_empty(&tls_list)) {
94 data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry);
95 list_remove(&data->entry);
96 heap_free(data);
99 TlsFree(urlmon_tls);
102 static void detach_thread(void)
104 tls_data_t *data;
106 if(urlmon_tls == TLS_OUT_OF_INDEXES)
107 return;
109 data = TlsGetValue(urlmon_tls);
110 if(!data)
111 return;
113 EnterCriticalSection(&tls_cs);
114 list_remove(&data->entry);
115 LeaveCriticalSection(&tls_cs);
117 if(data->notif_hwnd) {
118 WARN("notif_hwnd not destroyed\n");
119 DestroyWindow(data->notif_hwnd);
122 heap_free(data);
125 static void process_detach(void)
127 HINTERNET internet_session;
129 internet_session = get_internet_session(NULL);
130 if(internet_session)
131 InternetCloseHandle(internet_session);
133 if (hCabinet)
134 FreeLibrary(hCabinet);
136 init_session(FALSE);
137 free_session();
138 free_tls_list();
141 /***********************************************************************
142 * DllMain (URLMON.init)
144 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
146 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
148 URLMON_DllMain( hinstDLL, fdwReason, fImpLoad );
150 switch(fdwReason) {
151 case DLL_PROCESS_ATTACH:
152 init_session(TRUE);
153 break;
155 case DLL_PROCESS_DETACH:
156 process_detach();
157 DeleteCriticalSection(&tls_cs);
158 break;
160 case DLL_THREAD_DETACH:
161 detach_thread();
162 break;
164 return TRUE;
168 /***********************************************************************
169 * DllInstall (URLMON.@)
171 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
173 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
174 debugstr_w(cmdline));
176 return S_OK;
179 /***********************************************************************
180 * DllCanUnloadNow (URLMON.@)
182 HRESULT WINAPI DllCanUnloadNow(void)
184 return URLMON_refCount != 0 ? S_FALSE : S_OK;
189 /******************************************************************************
190 * Urlmon ClassFactory
192 typedef struct {
193 IClassFactory IClassFactory_iface;
195 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
196 } ClassFactory;
198 static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface)
200 return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
203 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
205 *ppv = NULL;
207 if(IsEqualGUID(riid, &IID_IUnknown)) {
208 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
209 *ppv = iface;
210 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
211 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
212 *ppv = iface;
215 if(*ppv) {
216 IUnknown_AddRef((IUnknown*)*ppv);
217 return S_OK;
220 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
221 return E_NOINTERFACE;
224 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
226 URLMON_LockModule();
227 return 2;
230 static ULONG WINAPI CF_Release(IClassFactory *iface)
232 URLMON_UnlockModule();
233 return 1;
237 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
238 REFIID riid, LPVOID *ppobj)
240 ClassFactory *This = impl_from_IClassFactory(iface);
241 HRESULT hres;
242 LPUNKNOWN punk;
244 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
246 *ppobj = NULL;
247 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
248 hres = IUnknown_QueryInterface(punk, riid, ppobj);
249 IUnknown_Release(punk);
251 return hres;
254 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
256 TRACE("(%d)\n", dolock);
258 if (dolock)
259 URLMON_LockModule();
260 else
261 URLMON_UnlockModule();
263 return S_OK;
266 static const IClassFactoryVtbl ClassFactoryVtbl =
268 CF_QueryInterface,
269 CF_AddRef,
270 CF_Release,
271 CF_CreateInstance,
272 CF_LockServer
275 static ClassFactory FileProtocolCF =
276 { { &ClassFactoryVtbl }, FileProtocol_Construct};
277 static ClassFactory FtpProtocolCF =
278 { { &ClassFactoryVtbl }, FtpProtocol_Construct};
279 static ClassFactory GopherProtocolCF =
280 { { &ClassFactoryVtbl }, GopherProtocol_Construct};
281 static ClassFactory HttpProtocolCF =
282 { { &ClassFactoryVtbl }, HttpProtocol_Construct};
283 static ClassFactory HttpSProtocolCF =
284 { { &ClassFactoryVtbl }, HttpSProtocol_Construct};
285 static ClassFactory MkProtocolCF =
286 { { &ClassFactoryVtbl }, MkProtocol_Construct};
287 static ClassFactory SecurityManagerCF =
288 { { &ClassFactoryVtbl }, SecManagerImpl_Construct};
289 static ClassFactory ZoneManagerCF =
290 { { &ClassFactoryVtbl }, ZoneMgrImpl_Construct};
291 static ClassFactory StdURLMonikerCF =
292 { { &ClassFactoryVtbl }, StdURLMoniker_Construct};
293 static ClassFactory MimeFilterCF =
294 { { &ClassFactoryVtbl }, MimeFilter_Construct};
296 struct object_creation_info
298 const CLSID *clsid;
299 IClassFactory *cf;
300 LPCWSTR protocol;
303 static const WCHAR wszFile[] = {'f','i','l','e',0};
304 static const WCHAR wszFtp[] = {'f','t','p',0};
305 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
306 static const WCHAR wszHttp[] = {'h','t','t','p',0};
307 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
308 static const WCHAR wszMk[] = {'m','k',0};
310 static const struct object_creation_info object_creation[] =
312 { &CLSID_FileProtocol, &FileProtocolCF.IClassFactory_iface, wszFile },
313 { &CLSID_FtpProtocol, &FtpProtocolCF.IClassFactory_iface, wszFtp },
314 { &CLSID_GopherProtocol, &GopherProtocolCF.IClassFactory_iface, wszGopher },
315 { &CLSID_HttpProtocol, &HttpProtocolCF.IClassFactory_iface, wszHttp },
316 { &CLSID_HttpSProtocol, &HttpSProtocolCF.IClassFactory_iface, wszHttps },
317 { &CLSID_MkProtocol, &MkProtocolCF.IClassFactory_iface, wszMk },
318 { &CLSID_InternetSecurityManager, &SecurityManagerCF.IClassFactory_iface, NULL },
319 { &CLSID_InternetZoneManager, &ZoneManagerCF.IClassFactory_iface, NULL },
320 { &CLSID_StdURLMoniker, &StdURLMonikerCF.IClassFactory_iface, NULL },
321 { &CLSID_DeCompMimeFilter, &MimeFilterCF.IClassFactory_iface, NULL }
324 static void init_session(BOOL init)
326 unsigned int i;
328 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
330 if(object_creation[i].protocol)
331 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
332 object_creation[i].protocol, init);
336 /*******************************************************************************
337 * DllGetClassObject [URLMON.@]
338 * Retrieves class object from a DLL object
340 * NOTES
341 * Docs say returns STDAPI
343 * PARAMS
344 * rclsid [I] CLSID for the class object
345 * riid [I] Reference to identifier of interface for class object
346 * ppv [O] Address of variable to receive interface pointer for riid
348 * RETURNS
349 * Success: S_OK
350 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
351 * E_UNEXPECTED
354 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
356 unsigned int i;
357 HRESULT hr;
359 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
361 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
363 if (IsEqualGUID(object_creation[i].clsid, rclsid))
364 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
367 hr = URLMON_DllGetClassObject(rclsid, riid, ppv);
368 if(SUCCEEDED(hr))
369 return hr;
371 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
372 return CLASS_E_CLASSNOTAVAILABLE;
375 static HRESULT register_inf(BOOL doregister)
377 HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
378 HMODULE hAdvpack;
380 static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
382 hAdvpack = LoadLibraryW(wszAdvpack);
383 pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
385 return pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", NULL);
388 /***********************************************************************
389 * DllRegisterServer (URLMON.@)
391 HRESULT WINAPI DllRegisterServer(void)
393 HRESULT hr;
395 TRACE("\n");
397 hr = URLMON_DllRegisterServer();
398 return SUCCEEDED(hr) ? register_inf(TRUE) : hr;
401 /***********************************************************************
402 * DllUnregisterServer (URLMON.@)
404 HRESULT WINAPI DllUnregisterServer(void)
406 HRESULT hr;
408 TRACE("\n");
410 hr = URLMON_DllUnregisterServer();
411 return SUCCEEDED(hr) ? register_inf(FALSE) : hr;
414 /***********************************************************************
415 * DllRegisterServerEx (URLMON.@)
417 HRESULT WINAPI DllRegisterServerEx(void)
419 FIXME("(void): stub\n");
421 return E_FAIL;
424 /**************************************************************************
425 * IsValidURL (URLMON.@)
427 * Determines if a specified string is a valid URL.
429 * PARAMS
430 * pBC [I] ignored, should be NULL.
431 * szURL [I] string that represents the URL in question.
432 * dwReserved [I] reserved and must be zero.
434 * RETURNS
435 * Success: S_OK.
436 * Failure: S_FALSE.
437 * returns E_INVALIDARG if one or more of the args is invalid.
439 * TODO:
440 * test functionality against windows to see what a valid URL is.
442 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
444 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
446 if (dwReserved || !szURL)
447 return E_INVALIDARG;
449 return S_OK;
452 /**************************************************************************
453 * FaultInIEFeature (URLMON.@)
455 * Undocumented. Appears to be used by native shdocvw.dll.
457 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
458 QUERYCONTEXT *pQuery, DWORD flags )
460 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
461 return E_NOTIMPL;
464 /**************************************************************************
465 * CoGetClassObjectFromURL (URLMON.@)
467 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
468 DWORD dwFileVersionLS, LPCWSTR szContentType,
469 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
470 REFIID riid, LPVOID *ppv )
472 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
473 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
474 debugstr_guid(riid), ppv);
475 return E_NOINTERFACE;
478 /***********************************************************************
479 * ReleaseBindInfo (URLMON.@)
481 * Release the resources used by the specified BINDINFO structure.
483 * PARAMS
484 * pbindinfo [I] BINDINFO to release.
486 * RETURNS
487 * Nothing.
489 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
491 DWORD size;
493 TRACE("(%p)\n", pbindinfo);
495 if(!pbindinfo || !(size = pbindinfo->cbSize))
496 return;
498 CoTaskMemFree(pbindinfo->szExtraInfo);
499 ReleaseStgMedium(&pbindinfo->stgmedData);
501 if(offsetof(BINDINFO, szExtraInfo) < size)
502 CoTaskMemFree(pbindinfo->szCustomVerb);
504 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
505 IUnknown_Release(pbindinfo->pUnk);
507 memset(pbindinfo, 0, size);
508 pbindinfo->cbSize = size;
511 /***********************************************************************
512 * CopyStgMedium (URLMON.@)
514 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
516 TRACE("(%p %p)\n", src, dst);
518 if(!src || !dst)
519 return E_POINTER;
521 *dst = *src;
523 switch(dst->tymed) {
524 case TYMED_NULL:
525 break;
526 case TYMED_FILE:
527 if(src->u.lpszFileName && !src->pUnkForRelease) {
528 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
529 dst->u.lpszFileName = CoTaskMemAlloc(size);
530 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
532 break;
533 case TYMED_ISTREAM:
534 if(dst->u.pstm)
535 IStream_AddRef(dst->u.pstm);
536 break;
537 case TYMED_ISTORAGE:
538 if(dst->u.pstg)
539 IStorage_AddRef(dst->u.pstg);
540 break;
541 default:
542 FIXME("Unimplemented tymed %d\n", src->tymed);
545 if(dst->pUnkForRelease)
546 IUnknown_AddRef(dst->pUnkForRelease);
548 return S_OK;
551 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
553 return size > 5 && !memcmp(b, "{\\rtf", 5);
556 static BOOL text_html_filter(const BYTE *b, DWORD size)
558 DWORD i;
560 if(size < 5)
561 return FALSE;
563 for(i=0; i < size-5; i++) {
564 if(b[i] == '<'
565 && (b[i+1] == 'h' || b[i+1] == 'H')
566 && (b[i+2] == 't' || b[i+2] == 'T')
567 && (b[i+3] == 'm' || b[i+3] == 'M')
568 && (b[i+4] == 'l' || b[i+4] == 'L'))
569 return TRUE;
572 return FALSE;
575 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
577 return size > 4
578 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
581 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
583 return size > 12
584 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
585 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
588 static BOOL image_gif_filter(const BYTE *b, DWORD size)
590 return size >= 6
591 && (b[0] == 'G' || b[0] == 'g')
592 && (b[1] == 'I' || b[1] == 'i')
593 && (b[2] == 'F' || b[2] == 'f')
594 && b[3] == '8'
595 && (b[4] == '7' || b[4] == '9')
596 && (b[5] == 'A' || b[5] == 'a');
599 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
601 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
604 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
606 static const BYTE magic1[] = {0x4d,0x4d,0x00,0x2a};
607 static const BYTE magic2[] = {0x49,0x49,0x2a,0xff};
609 return size >= 4 && (!memcmp(b, magic1, 4) || !memcmp(b, magic2, 4));
612 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
614 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
615 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
618 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
620 return size >= 14
621 && b[0] == 0x42 && b[1] == 0x4d
622 && *(const DWORD *)(b+6) == 0;
625 static BOOL video_avi_filter(const BYTE *b, DWORD size)
627 return size > 12
628 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
629 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
632 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
634 return size > 4
635 && !b[0] && !b[1] && b[2] == 0x01
636 && (b[3] == 0xb3 || b[3] == 0xba);
639 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
641 return size > 2 && b[0] == '%' && b[1] == '!';
644 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
646 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
649 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
651 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
654 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
656 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
659 static BOOL application_java_filter(const BYTE *b, DWORD size)
661 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
664 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
666 return size > 2 && b[0] == 'M' && b[1] == 'Z';
669 static BOOL text_plain_filter(const BYTE *b, DWORD size)
671 const BYTE *ptr;
673 for(ptr = b; ptr < b+size-1; ptr++) {
674 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
675 return FALSE;
678 return TRUE;
681 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
683 return TRUE;
686 static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime)
688 LPCWSTR ret = NULL;
689 DWORD len, i;
691 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
692 static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
693 static const WCHAR audio_basicW[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
694 static const WCHAR audio_wavW[] = {'a','u','d','i','o','/','w','a','v',0};
695 static const WCHAR image_gifW[] = {'i','m','a','g','e','/','g','i','f',0};
696 static const WCHAR image_pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
697 static const WCHAR image_tiffW[] = {'i','m','a','g','e','/','t','i','f','f',0};
698 static const WCHAR image_xpngW[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
699 static const WCHAR image_bmpW[] = {'i','m','a','g','e','/','b','m','p',0};
700 static const WCHAR video_aviW[] = {'v','i','d','e','o','/','a','v','i',0};
701 static const WCHAR video_mpegW[] = {'v','i','d','e','o','/','m','p','e','g',0};
702 static const WCHAR app_postscriptW[] =
703 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
704 static const WCHAR app_pdfW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','p','d','f',0};
705 static const WCHAR app_xzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
706 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
707 static const WCHAR app_xgzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
708 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
709 static const WCHAR app_javaW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
710 'j','a','v','a',0};
711 static const WCHAR app_xmsdownloadW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
712 'x','-','m','s','d','o','w','n','l','o','a','d',0};
713 static const WCHAR text_plainW[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
714 static const WCHAR app_octetstreamW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
715 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
717 static const struct {
718 LPCWSTR mime;
719 BOOL (*filter)(const BYTE *,DWORD);
720 } mime_filters[] = {
721 {text_htmlW, text_html_filter},
722 {text_richtextW, text_richtext_filter},
723 /* {audio_xaiffW, audio_xaiff_filter}, */
724 {audio_basicW, audio_basic_filter},
725 {audio_wavW, audio_wav_filter},
726 {image_gifW, image_gif_filter},
727 {image_pjpegW, image_pjpeg_filter},
728 {image_tiffW, image_tiff_filter},
729 {image_xpngW, image_xpng_filter},
730 /* {image_xbitmapW, image_xbitmap_filter}, */
731 {image_bmpW, image_bmp_filter},
732 /* {image_xjgW, image_xjg_filter}, */
733 /* {image_xemfW, image_xemf_filter}, */
734 /* {image_xwmfW, image_xwmf_filter}, */
735 {video_aviW, video_avi_filter},
736 {video_mpegW, video_mpeg_filter},
737 {app_postscriptW, application_postscript_filter},
738 /* {app_base64W, application_base64_filter}, */
739 /* {app_macbinhex40W, application_macbinhex40_filter}, */
740 {app_pdfW, application_pdf_filter},
741 /* {app_zcompressedW, application_xcompressed_filter}, */
742 {app_xzipW, application_xzip_filter},
743 {app_xgzipW, application_xgzip_filter},
744 {app_javaW, application_java_filter},
745 {app_xmsdownloadW, application_xmsdownload},
746 {text_plainW, text_plain_filter},
747 {app_octetstreamW, application_octet_stream_filter}
750 if(!buf || !size) {
751 if(!proposed_mime)
752 return E_FAIL;
754 len = strlenW(proposed_mime)+1;
755 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
756 if(!*ret_mime)
757 return E_OUTOFMEMORY;
759 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
760 return S_OK;
763 if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) {
764 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
765 if(!strcmpW(proposed_mime, mime_filters[i].mime))
766 break;
769 if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) {
770 len = strlenW(proposed_mime)+1;
771 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
772 if(!*ret_mime)
773 return E_OUTOFMEMORY;
775 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR));
776 return S_OK;
780 i=0;
781 while(!ret) {
782 if(mime_filters[i].filter(buf, size))
783 ret = mime_filters[i].mime;
784 i++;
787 TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size)));
789 if(proposed_mime) {
790 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
791 ret = proposed_mime;
793 /* text/html is a special case */
794 if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW))
795 ret = text_htmlW;
798 len = strlenW(ret)+1;
799 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR));
800 if(!*ret_mime)
801 return E_OUTOFMEMORY;
803 memcpy(*ret_mime, ret, len*sizeof(WCHAR));
804 return S_OK;
807 /***********************************************************************
808 * FindMimeFromData (URLMON.@)
810 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
812 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
813 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
814 LPWSTR* ppwzMimeOut, DWORD dwReserved)
816 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
817 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
819 if(dwMimeFlags)
820 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
821 if(dwReserved)
822 WARN("dwReserved=%d\n", dwReserved);
824 /* pBC seams to not be used */
826 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
827 return E_INVALIDARG;
829 if(pwzMimeProposed || pBuffer)
830 return find_mime_from_buffer(pBuffer, cbSize, pwzMimeProposed, ppwzMimeOut);
832 if(pwzUrl) {
833 HKEY hkey;
834 DWORD res, size;
835 LPCWSTR ptr;
836 WCHAR mime[64];
838 static const WCHAR wszContentType[] =
839 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
841 ptr = strrchrW(pwzUrl, '.');
842 if(!ptr)
843 return E_FAIL;
845 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
846 if(res != ERROR_SUCCESS)
847 return HRESULT_FROM_WIN32(res);
849 size = sizeof(mime);
850 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
851 RegCloseKey(hkey);
852 if(res != ERROR_SUCCESS)
853 return HRESULT_FROM_WIN32(res);
855 *ppwzMimeOut = CoTaskMemAlloc(size);
856 memcpy(*ppwzMimeOut, mime, size);
857 return S_OK;
860 return E_FAIL;
863 /***********************************************************************
864 * GetClassFileOrMime (URLMON.@)
866 * Determines the class ID from the bind context, file name or MIME type.
868 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
869 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
870 CLSID *pclsid)
872 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
873 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
874 dwReserved, pclsid);
875 return E_NOTIMPL;
878 /***********************************************************************
879 * Extract (URLMON.@)
881 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
883 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
885 if (!hCabinet)
886 hCabinet = LoadLibraryA("cabinet.dll");
888 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
889 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
890 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
892 return pExtract(dest, szCabName);
895 /***********************************************************************
896 * IsLoggingEnabledA (URLMON.@)
898 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
900 FIXME("(%s)\n", debugstr_a(url));
901 return FALSE;
904 /***********************************************************************
905 * IsLoggingEnabledW (URLMON.@)
907 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
909 FIXME("(%s)\n", debugstr_w(url));
910 return FALSE;
913 /***********************************************************************
914 * IsProtectedModeURL (URLMON.111)
915 * Undocumented, added in IE7
917 BOOL WINAPI IsProtectedModeURL(const WCHAR *url)
919 FIXME("stub: %s\n", debugstr_w(url));
920 return TRUE;
923 /***********************************************************************
924 * LogSqmBits (URLMON.410)
925 * Undocumented, added in IE8
927 int WINAPI LogSqmBits(DWORD unk1, DWORD unk2)
929 FIXME("stub: %d %d\n", unk1, unk2);
930 return 0;
933 /***********************************************************************
934 * LogSqmUXCommandOffsetInternal (URLMON.423)
935 * Undocumented, added in IE8
937 void WINAPI LogSqmUXCommandOffsetInternal(DWORD unk1, DWORD unk2, DWORD unk3, DWORD unk4)
939 FIXME("stub: %d %d %d %d\n", unk1, unk2, unk3, unk4);
942 /***********************************************************************
943 * MapUriToBrowserEmulationState (URLMON.444)
944 * Undocumented, added in IE8
946 int WINAPI MapUriToBrowserEmulationState(DWORD unk1, DWORD unk2, DWORD unk3)
948 FIXME("stub: %d %d %d\n", unk1, unk2, unk3);
949 return 0;
952 /***********************************************************************
953 * MapBrowserEmulationModeToUserAgent (URLMON.445)
954 * Undocumented, added in IE8
956 int WINAPI MapBrowserEmulationModeToUserAgent(DWORD unk1, DWORD unk2)
958 FIXME("stub: %d %d\n", unk1, unk2);
959 return 0;
962 /***********************************************************************
963 * RegisterMediaTypes
964 * Added in IE3, registers known MIME-type strings.
966 HRESULT WINAPI RegisterMediaTypes(UINT types, LPCSTR *szTypes, CLIPFORMAT *cfTypes)
968 FIXME("stub: %u %p %p\n", types, szTypes, cfTypes);
969 return E_INVALIDARG;