push 4c10733ce69b31d47c27c6c508d6169199a0e387
[wine/hacks.git] / dlls / urlmon / urlmon_main.c
blob8561937643ab31eb04c40a727b2eb0d6c17992c2
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;
40 static void init_session(BOOL);
42 /***********************************************************************
43 * DllMain (URLMON.init)
45 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
47 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
49 switch(fdwReason) {
50 case DLL_PROCESS_ATTACH:
51 DisableThreadLibraryCalls(hinstDLL);
52 URLMON_hInstance = hinstDLL;
53 init_session(TRUE);
54 break;
56 case DLL_PROCESS_DETACH:
57 if (hCabinet)
58 FreeLibrary(hCabinet);
59 hCabinet = NULL;
60 init_session(FALSE);
61 URLMON_hInstance = 0;
62 break;
64 return TRUE;
68 /***********************************************************************
69 * DllInstall (URLMON.@)
71 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
73 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
74 debugstr_w(cmdline));
76 return S_OK;
79 /***********************************************************************
80 * DllCanUnloadNow (URLMON.@)
82 HRESULT WINAPI DllCanUnloadNow(void)
84 return URLMON_refCount != 0 ? S_FALSE : S_OK;
89 /******************************************************************************
90 * Urlmon ClassFactory
92 typedef struct {
93 const IClassFactoryVtbl *lpClassFactoryVtbl;
95 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
96 } ClassFactory;
98 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
100 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
102 *ppv = NULL;
104 if(IsEqualGUID(riid, &IID_IUnknown)) {
105 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
106 *ppv = iface;
107 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
108 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
109 *ppv = iface;
112 if(*ppv) {
113 IUnknown_AddRef((IUnknown*)*ppv);
114 return S_OK;
117 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
118 return E_NOINTERFACE;
121 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
123 URLMON_LockModule();
124 return 2;
127 static ULONG WINAPI CF_Release(IClassFactory *iface)
129 URLMON_UnlockModule();
130 return 1;
134 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
135 REFIID riid, LPVOID *ppobj)
137 ClassFactory *This = (ClassFactory*)iface;
138 HRESULT hres;
139 LPUNKNOWN punk;
141 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
143 *ppobj = NULL;
144 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
145 hres = IUnknown_QueryInterface(punk, riid, ppobj);
146 IUnknown_Release(punk);
148 return hres;
151 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
153 TRACE("(%d)\n", dolock);
155 if (dolock)
156 URLMON_LockModule();
157 else
158 URLMON_UnlockModule();
160 return S_OK;
163 static const IClassFactoryVtbl ClassFactoryVtbl =
165 CF_QueryInterface,
166 CF_AddRef,
167 CF_Release,
168 CF_CreateInstance,
169 CF_LockServer
172 static const ClassFactory FileProtocolCF =
173 { &ClassFactoryVtbl, FileProtocol_Construct};
174 static const ClassFactory FtpProtocolCF =
175 { &ClassFactoryVtbl, FtpProtocol_Construct};
176 static const ClassFactory GopherProtocolCF =
177 { &ClassFactoryVtbl, GopherProtocol_Construct};
178 static const ClassFactory HttpProtocolCF =
179 { &ClassFactoryVtbl, HttpProtocol_Construct};
180 static const ClassFactory HttpSProtocolCF =
181 { &ClassFactoryVtbl, HttpSProtocol_Construct};
182 static const ClassFactory MkProtocolCF =
183 { &ClassFactoryVtbl, MkProtocol_Construct};
184 static const ClassFactory SecurityManagerCF =
185 { &ClassFactoryVtbl, SecManagerImpl_Construct};
186 static const ClassFactory ZoneManagerCF =
187 { &ClassFactoryVtbl, ZoneMgrImpl_Construct};
188 static const ClassFactory StdURLMonikerCF =
189 { &ClassFactoryVtbl, StdURLMoniker_Construct};
190 static const ClassFactory MimeFilterCF =
191 { &ClassFactoryVtbl, MimeFilter_Construct};
193 struct object_creation_info
195 const CLSID *clsid;
196 IClassFactory *cf;
197 LPCWSTR protocol;
200 static const WCHAR wszFile[] = {'f','i','l','e',0};
201 static const WCHAR wszFtp[] = {'f','t','p',0};
202 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
203 static const WCHAR wszHttp[] = {'h','t','t','p',0};
204 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
205 static const WCHAR wszMk[] = {'m','k',0};
207 static const struct object_creation_info object_creation[] =
209 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
210 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
211 { &CLSID_GopherProtocol, CLASSFACTORY(&GopherProtocolCF), wszGopher },
212 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
213 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
214 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
215 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
216 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL },
217 { &CLSID_StdURLMoniker, CLASSFACTORY(&StdURLMonikerCF), NULL },
218 { &CLSID_DeCompMimeFilter, CLASSFACTORY(&MimeFilterCF), NULL }
221 static void init_session(BOOL init)
223 unsigned int i;
225 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
227 if(object_creation[i].protocol)
228 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
229 object_creation[i].protocol, init);
233 /*******************************************************************************
234 * DllGetClassObject [URLMON.@]
235 * Retrieves class object from a DLL object
237 * NOTES
238 * Docs say returns STDAPI
240 * PARAMS
241 * rclsid [I] CLSID for the class object
242 * riid [I] Reference to identifier of interface for class object
243 * ppv [O] Address of variable to receive interface pointer for riid
245 * RETURNS
246 * Success: S_OK
247 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
248 * E_UNEXPECTED
251 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
253 unsigned int i;
255 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
257 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
259 if (IsEqualGUID(object_creation[i].clsid, rclsid))
260 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
263 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
264 return CLASS_E_CLASSNOTAVAILABLE;
268 /***********************************************************************
269 * DllRegisterServerEx (URLMON.@)
271 HRESULT WINAPI DllRegisterServerEx(void)
273 FIXME("(void): stub\n");
275 return E_FAIL;
278 /**************************************************************************
279 * UrlMkSetSessionOption (URLMON.@)
281 HRESULT WINAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
282 DWORD Reserved)
284 FIXME("(%#x, %p, %#x): stub\n", dwOption, pBuffer, dwBufferLength);
286 return S_OK;
289 static const CHAR Agent[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
291 /**************************************************************************
292 * ObtainUserAgentString (URLMON.@)
294 HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPSTR pcszUAOut, DWORD *cbSize)
296 FIXME("(%d, %p, %p): stub\n", dwOption, pcszUAOut, cbSize);
298 if (pcszUAOut == NULL || cbSize == NULL)
299 return E_INVALIDARG;
301 if (*cbSize < sizeof(Agent))
303 *cbSize = sizeof(Agent);
304 return E_OUTOFMEMORY;
307 if (sizeof(Agent) < *cbSize)
308 *cbSize = sizeof(Agent);
309 lstrcpynA(pcszUAOut, Agent, *cbSize);
311 return S_OK;
314 /**************************************************************************
315 * IsValidURL (URLMON.@)
317 * Determines if a specified string is a valid URL.
319 * PARAMS
320 * pBC [I] ignored, must be NULL.
321 * szURL [I] string that represents the URL in question.
322 * dwReserved [I] reserved and must be zero.
324 * RETURNS
325 * Success: S_OK.
326 * Failure: S_FALSE.
327 * returns E_INVALIDARG if one or more of the args is invalid.
329 * TODO:
330 * test functionality against windows to see what a valid URL is.
332 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
334 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
336 if (pBC != NULL || dwReserved != 0)
337 return E_INVALIDARG;
339 return S_OK;
342 /**************************************************************************
343 * FaultInIEFeature (URLMON.@)
345 * Undocumented. Appears to be used by native shdocvw.dll.
347 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
348 QUERYCONTEXT *pQuery, DWORD flags )
350 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
351 return E_NOTIMPL;
354 /**************************************************************************
355 * CoGetClassObjectFromURL (URLMON.@)
357 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
358 DWORD dwFileVersionLS, LPCWSTR szContentType,
359 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
360 REFIID riid, LPVOID *ppv )
362 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
363 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
364 debugstr_guid(riid), ppv);
365 return E_NOINTERFACE;
368 /***********************************************************************
369 * ReleaseBindInfo (URLMON.@)
371 * Release the resources used by the specified BINDINFO structure.
373 * PARAMS
374 * pbindinfo [I] BINDINFO to release.
376 * RETURNS
377 * Nothing.
379 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
381 DWORD size;
383 TRACE("(%p)\n", pbindinfo);
385 if(!pbindinfo || !(size = pbindinfo->cbSize))
386 return;
388 CoTaskMemFree(pbindinfo->szExtraInfo);
389 ReleaseStgMedium(&pbindinfo->stgmedData);
391 if(offsetof(BINDINFO, szExtraInfo) < size)
392 CoTaskMemFree(pbindinfo->szCustomVerb);
394 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
395 IUnknown_Release(pbindinfo->pUnk);
397 memset(pbindinfo, 0, size);
398 pbindinfo->cbSize = size;
401 /***********************************************************************
402 * CopyStgMedium (URLMON.@)
404 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
406 TRACE("(%p %p)\n", src, dst);
408 if(!src || !dst)
409 return E_POINTER;
411 *dst = *src;
413 switch(dst->tymed) {
414 case TYMED_NULL:
415 break;
416 case TYMED_FILE:
417 if(src->u.lpszFileName && !src->pUnkForRelease) {
418 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
419 dst->u.lpszFileName = CoTaskMemAlloc(size);
420 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
422 break;
423 case TYMED_ISTREAM:
424 if(dst->u.pstm)
425 IStream_AddRef(dst->u.pstm);
426 break;
427 case TYMED_ISTORAGE:
428 if(dst->u.pstg)
429 IStorage_AddRef(dst->u.pstg);
430 break;
431 default:
432 FIXME("Unimplemented tymed %d\n", src->tymed);
435 if(dst->pUnkForRelease)
436 IUnknown_AddRef(dst->pUnkForRelease);
438 return S_OK;
441 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
443 return size > 5 && !memcmp(b, "{\\rtf", 5);
446 static BOOL text_html_filter(const BYTE *b, DWORD size)
448 DWORD i;
450 if(size < 5)
451 return FALSE;
453 for(i=0; i < size-5; i++) {
454 if(b[i] == '<'
455 && (b[i+1] == 'h' || b[i+1] == 'H')
456 && (b[i+2] == 't' || b[i+2] == 'T')
457 && (b[i+3] == 'm' || b[i+3] == 'M')
458 && (b[i+4] == 'l' || b[i+4] == 'L'))
459 return TRUE;
462 return FALSE;
465 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
467 return size > 4
468 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
471 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
473 return size > 12
474 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
475 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
478 static BOOL image_gif_filter(const BYTE *b, DWORD size)
480 return size >= 6
481 && (b[0] == 'G' || b[0] == 'g')
482 && (b[1] == 'I' || b[1] == 'i')
483 && (b[2] == 'F' || b[2] == 'f')
484 && b[3] == '8'
485 && (b[4] == '7' || b[4] == '9')
486 && (b[5] == 'A' || b[5] == 'a');
489 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
491 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
494 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
496 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
499 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
501 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
502 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
505 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
507 return size >= 14
508 && b[0] == 0x42 && b[1] == 0x4d
509 && *(const DWORD *)(b+6) == 0;
512 static BOOL video_avi_filter(const BYTE *b, DWORD size)
514 return size > 12
515 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
516 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
519 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
521 return size > 4
522 && !b[0] && !b[1] && b[2] == 0x01
523 && (b[3] == 0xb3 || b[3] == 0xba);
526 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
528 return size > 2 && b[0] == '%' && b[1] == '!';
531 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
533 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
536 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
538 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
541 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
543 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
546 static BOOL application_java_filter(const BYTE *b, DWORD size)
548 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
551 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
553 return size > 2 && b[0] == 'M' && b[1] == 'Z';
556 static BOOL text_plain_filter(const BYTE *b, DWORD size)
558 const BYTE *ptr;
560 for(ptr = b; ptr < b+size-1; ptr++) {
561 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
562 return FALSE;
565 return TRUE;
568 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
570 return TRUE;
573 /***********************************************************************
574 * FindMimeFromData (URLMON.@)
576 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
578 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
579 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
580 LPWSTR* ppwzMimeOut, DWORD dwReserved)
582 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
583 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
585 if(dwMimeFlags)
586 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
587 if(dwReserved)
588 WARN("dwReserved=%d\n", dwReserved);
590 /* pBC seams to not be used */
592 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
593 return E_INVALIDARG;
595 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
596 DWORD len;
598 if(!pwzMimeProposed)
599 return E_FAIL;
601 len = strlenW(pwzMimeProposed)+1;
602 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
603 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
604 return S_OK;
607 if(pBuffer) {
608 const BYTE *buf = pBuffer;
609 DWORD len;
610 LPCWSTR ret = NULL;
611 unsigned int i;
613 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
614 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
615 static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
616 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
617 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
618 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
619 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
620 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
621 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
622 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
623 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
624 static const WCHAR wszAppPostscript[] =
625 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
626 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
627 'p','d','f',0};
628 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
629 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
630 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
631 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
632 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
633 'j','a','v','a',0};
634 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
635 'x','-','m','s','d','o','w','n','l','o','a','d',0};
636 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
637 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
638 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
640 static const struct {
641 LPCWSTR mime;
642 BOOL (*filter)(const BYTE *,DWORD);
643 } mime_filters[] = {
644 {wszTextHtml, text_html_filter},
645 {wszTextRichtext, text_richtext_filter},
646 /* {wszAudioXAiff, audio_xaiff_filter}, */
647 {wszAudioBasic, audio_basic_filter},
648 {wszAudioWav, audio_wav_filter},
649 {wszImageGif, image_gif_filter},
650 {wszImagePjpeg, image_pjpeg_filter},
651 {wszImageTiff, image_tiff_filter},
652 {wszImageXPng, image_xpng_filter},
653 /* {wszImageXBitmap, image_xbitmap_filter}, */
654 {wszImageBmp, image_bmp_filter},
655 /* {wszImageXJg, image_xjg_filter}, */
656 /* {wszImageXEmf, image_xemf_filter}, */
657 /* {wszImageXWmf, image_xwmf_filter}, */
658 {wszVideoAvi, video_avi_filter},
659 {wszVideoMpeg, video_mpeg_filter},
660 {wszAppPostscript, application_postscript_filter},
661 /* {wszAppBase64, application_base64_filter}, */
662 /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
663 {wszAppPdf, application_pdf_filter},
664 /* {wszAppXCompressed, application_xcompressed_filter}, */
665 {wszAppXZip, application_xzip_filter},
666 {wszAppXGzip, application_xgzip_filter},
667 {wszAppJava, application_java_filter},
668 {wszAppXMSDownload, application_xmsdownload},
669 {wszTextPlain, text_plain_filter},
670 {wszAppOctetStream, application_octet_stream_filter}
673 if(!cbSize)
674 return E_FAIL;
676 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
677 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
678 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
679 break;
682 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
683 || mime_filters[i].filter(buf, cbSize)) {
684 len = strlenW(pwzMimeProposed)+1;
685 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
686 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
687 return S_OK;
691 i=0;
692 while(!ret) {
693 if(mime_filters[i].filter(buf, cbSize))
694 ret = mime_filters[i].mime;
695 i++;
698 TRACE("found %s for data\n"
699 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
700 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
701 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
703 if(pwzMimeProposed) {
704 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
705 ret = pwzMimeProposed;
707 /* text/html is a special case */
708 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
709 ret = wszTextHtml;
712 len = strlenW(ret)+1;
713 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
714 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
715 return S_OK;
718 if(pwzUrl) {
719 HKEY hkey;
720 DWORD res, size;
721 LPCWSTR ptr;
722 WCHAR mime[64];
724 static const WCHAR wszContentType[] =
725 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
727 ptr = strrchrW(pwzUrl, '.');
728 if(!ptr)
729 return E_FAIL;
731 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
732 if(res != ERROR_SUCCESS)
733 return HRESULT_FROM_WIN32(res);
735 size = sizeof(mime);
736 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
737 RegCloseKey(hkey);
738 if(res != ERROR_SUCCESS)
739 return HRESULT_FROM_WIN32(res);
741 *ppwzMimeOut = CoTaskMemAlloc(size);
742 memcpy(*ppwzMimeOut, mime, size);
743 return S_OK;
746 return E_FAIL;
749 /***********************************************************************
750 * GetClassFileOrMime (URLMON.@)
752 * Determines the class ID from the bind context, file name or MIME type.
754 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
755 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
756 CLSID *pclsid)
758 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
759 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
760 dwReserved, pclsid);
761 return E_NOTIMPL;
764 /***********************************************************************
765 * Extract (URLMON.@)
767 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
769 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
771 if (!hCabinet)
772 hCabinet = LoadLibraryA("cabinet.dll");
774 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
775 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
776 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
778 return pExtract(dest, szCabName);
781 /***********************************************************************
782 * IsLoggingEnabledA (URLMON.@)
784 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
786 FIXME("(%s)\n", debugstr_a(url));
787 return FALSE;
790 /***********************************************************************
791 * IsLoggingEnabledW (URLMON.@)
793 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
795 FIXME("(%s)\n", debugstr_w(url));
796 return FALSE;