user32/tests: Prevent writing to not allocated memory.
[wine.git] / dlls / urlmon / urlmon_main.c
blobbc3de934b35319ccc38a159dcb0fa9c13dc65d10
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 HttpProtocolCF =
177 { &ClassFactoryVtbl, HttpProtocol_Construct};
178 static const ClassFactory HttpSProtocolCF =
179 { &ClassFactoryVtbl, HttpSProtocol_Construct};
180 static const ClassFactory MkProtocolCF =
181 { &ClassFactoryVtbl, MkProtocol_Construct};
182 static const ClassFactory SecurityManagerCF =
183 { &ClassFactoryVtbl, SecManagerImpl_Construct};
184 static const ClassFactory ZoneManagerCF =
185 { &ClassFactoryVtbl, ZoneMgrImpl_Construct};
187 struct object_creation_info
189 const CLSID *clsid;
190 IClassFactory *cf;
191 LPCWSTR protocol;
194 static const WCHAR wszFile[] = {'f','i','l','e',0};
195 static const WCHAR wszFtp[] = {'f','t','p',0};
196 static const WCHAR wszHttp[] = {'h','t','t','p',0};
197 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
198 static const WCHAR wszMk[] = {'m','k',0};
200 static const struct object_creation_info object_creation[] =
202 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
203 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
204 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
205 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
206 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
207 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
208 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL }
211 static void init_session(BOOL init)
213 int i;
215 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
217 if(object_creation[i].protocol)
218 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
219 object_creation[i].protocol, init);
223 /*******************************************************************************
224 * DllGetClassObject [URLMON.@]
225 * Retrieves class object from a DLL object
227 * NOTES
228 * Docs say returns STDAPI
230 * PARAMS
231 * rclsid [I] CLSID for the class object
232 * riid [I] Reference to identifier of interface for class object
233 * ppv [O] Address of variable to receive interface pointer for riid
235 * RETURNS
236 * Success: S_OK
237 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
238 * E_UNEXPECTED
241 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
243 int i;
245 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
247 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
249 if (IsEqualGUID(object_creation[i].clsid, rclsid))
250 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
253 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
254 return CLASS_E_CLASSNOTAVAILABLE;
258 /***********************************************************************
259 * DllRegisterServerEx (URLMON.@)
261 HRESULT WINAPI DllRegisterServerEx(void)
263 FIXME("(void): stub\n");
265 return E_FAIL;
268 /**************************************************************************
269 * UrlMkSetSessionOption (URLMON.@)
271 HRESULT WINAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
272 DWORD Reserved)
274 FIXME("(%#x, %p, %#x): stub\n", dwOption, pBuffer, dwBufferLength);
276 return S_OK;
279 static const CHAR Agent[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
281 /**************************************************************************
282 * ObtainUserAgentString (URLMON.@)
284 HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPSTR pcszUAOut, DWORD *cbSize)
286 FIXME("(%d, %p, %p): stub\n", dwOption, pcszUAOut, cbSize);
288 if (pcszUAOut == NULL || cbSize == NULL)
289 return E_INVALIDARG;
291 if (*cbSize < sizeof(Agent))
293 *cbSize = sizeof(Agent);
294 return E_OUTOFMEMORY;
297 if (sizeof(Agent) < *cbSize)
298 *cbSize = sizeof(Agent);
299 lstrcpynA(pcszUAOut, Agent, *cbSize);
301 return S_OK;
304 /**************************************************************************
305 * IsValidURL (URLMON.@)
307 * Determines if a specified string is a valid URL.
309 * PARAMS
310 * pBC [I] ignored, must be NULL.
311 * szURL [I] string that represents the URL in question.
312 * dwReserved [I] reserved and must be zero.
314 * RETURNS
315 * Success: S_OK.
316 * Failure: S_FALSE.
317 * returns E_INVALIDARG if one or more of the args is invalid.
319 * TODO:
320 * test functionality against windows to see what a valid URL is.
322 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
324 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
326 if (pBC != NULL || dwReserved != 0)
327 return E_INVALIDARG;
329 return S_OK;
332 /**************************************************************************
333 * FaultInIEFeature (URLMON.@)
335 * Undocumented. Appears to be used by native shdocvw.dll.
337 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
338 QUERYCONTEXT *pQuery, DWORD flags )
340 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
341 return E_NOTIMPL;
344 /**************************************************************************
345 * CoGetClassObjectFromURL (URLMON.@)
347 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
348 DWORD dwFileVersionLS, LPCWSTR szContentType,
349 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
350 REFIID riid, LPVOID *ppv )
352 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
353 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
354 debugstr_guid(riid), ppv);
355 return E_NOINTERFACE;
358 /***********************************************************************
359 * ReleaseBindInfo (URLMON.@)
361 * Release the resources used by the specified BINDINFO structure.
363 * PARAMS
364 * pbindinfo [I] BINDINFO to release.
366 * RETURNS
367 * Nothing.
369 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
371 DWORD size;
373 TRACE("(%p)\n", pbindinfo);
375 if(!pbindinfo || !(size = pbindinfo->cbSize))
376 return;
378 CoTaskMemFree(pbindinfo->szExtraInfo);
379 ReleaseStgMedium(&pbindinfo->stgmedData);
381 if(offsetof(BINDINFO, szExtraInfo) < size)
382 CoTaskMemFree(pbindinfo->szCustomVerb);
384 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
385 IUnknown_Release(pbindinfo->pUnk);
387 memset(pbindinfo, 0, size);
388 pbindinfo->cbSize = size;
391 /***********************************************************************
392 * CopyStgMedium (URLMON.@)
394 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
396 TRACE("(%p %p)\n", src, dst);
398 if(!src || !dst)
399 return E_POINTER;
401 *dst = *src;
403 switch(dst->tymed) {
404 case TYMED_NULL:
405 break;
406 case TYMED_FILE:
407 if(src->u.lpszFileName && !src->pUnkForRelease) {
408 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
409 dst->u.lpszFileName = CoTaskMemAlloc(size);
410 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
412 break;
413 case TYMED_ISTREAM:
414 if(dst->u.pstm)
415 IStream_AddRef(dst->u.pstm);
416 break;
417 case TYMED_ISTORAGE:
418 if(dst->u.pstg)
419 IStorage_AddRef(dst->u.pstg);
420 break;
421 default:
422 FIXME("Unimplemented tymed %d\n", src->tymed);
425 if(dst->pUnkForRelease)
426 IUnknown_AddRef(dst->pUnkForRelease);
428 return S_OK;
431 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
433 return size > 5 && !memcmp(b, "{\\rtf", 5);
436 static BOOL text_html_filter(const BYTE *b, DWORD size)
438 int i;
440 if(size < 5)
441 return FALSE;
443 for(i=0; i < size-5; i++) {
444 if(b[i] == '<'
445 && (b[i+1] == 'h' || b[i+1] == 'H')
446 && (b[i+2] == 't' || b[i+2] == 'T')
447 && (b[i+3] == 'm' || b[i+3] == 'M')
448 && (b[i+4] == 'l' || b[i+4] == 'L'))
449 return TRUE;
452 return FALSE;
455 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
457 return size > 4
458 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
461 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
463 return size > 12
464 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
465 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
468 static BOOL image_gif_filter(const BYTE *b, DWORD size)
470 return size >= 6
471 && (b[0] == 'G' || b[0] == 'g')
472 && (b[1] == 'I' || b[1] == 'i')
473 && (b[2] == 'F' || b[2] == 'f')
474 && b[3] == '8'
475 && (b[4] == '7' || b[4] == '9')
476 && (b[5] == 'A' || b[5] == 'a');
479 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
481 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
484 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
486 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
489 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
491 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
492 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
495 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
497 return size >= 14
498 && b[0] == 0x42 && b[1] == 0x4d
499 && *(const DWORD *)(b+6) == 0;
502 static BOOL video_avi_filter(const BYTE *b, DWORD size)
504 return size > 12
505 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
506 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
509 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
511 return size > 4
512 && !b[0] && !b[1] && b[2] == 0x01
513 && (b[3] == 0xb3 || b[3] == 0xba);
516 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
518 return size > 2 && b[0] == '%' && b[1] == '!';
521 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
523 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
526 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
528 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
531 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
533 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
536 static BOOL application_java_filter(const BYTE *b, DWORD size)
538 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
541 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
543 return size > 2 && b[0] == 'M' && b[1] == 'Z';
546 static BOOL text_plain_filter(const BYTE *b, DWORD size)
548 const BYTE *ptr;
550 for(ptr = b; ptr < b+size-1; ptr++) {
551 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
552 return FALSE;
555 return TRUE;
558 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
560 return TRUE;
563 /***********************************************************************
564 * FindMimeFromData (URLMON.@)
566 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
568 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
569 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
570 LPWSTR* ppwzMimeOut, DWORD dwReserved)
572 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
573 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
575 if(dwMimeFlags)
576 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
577 if(dwReserved)
578 WARN("dwReserved=%d\n", dwReserved);
580 /* pBC seams to not be used */
582 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
583 return E_INVALIDARG;
585 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
586 DWORD len;
588 if(!pwzMimeProposed)
589 return E_FAIL;
591 len = strlenW(pwzMimeProposed)+1;
592 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
593 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
594 return S_OK;
597 if(pBuffer) {
598 const BYTE *buf = pBuffer;
599 DWORD len;
600 LPCWSTR ret = NULL;
601 int i;
603 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
604 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
605 static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
606 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
607 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
608 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
609 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
610 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
611 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
612 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
613 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
614 static const WCHAR wszAppPostscript[] =
615 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
616 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
617 'p','d','f',0};
618 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
619 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
620 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
621 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
622 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
623 'j','a','v','a',0};
624 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
625 'x','-','m','s','d','o','w','n','l','o','a','d',0};
626 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
627 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
628 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
630 static const struct {
631 LPCWSTR mime;
632 BOOL (*filter)(const BYTE *,DWORD);
633 } mime_filters[] = {
634 {wszTextHtml, text_html_filter},
635 {wszTextRichtext, text_richtext_filter},
636 /* {wszAudioXAiff, audio_xaiff_filter}, */
637 {wszAudioBasic, audio_basic_filter},
638 {wszAudioWav, audio_wav_filter},
639 {wszImageGif, image_gif_filter},
640 {wszImagePjpeg, image_pjpeg_filter},
641 {wszImageTiff, image_tiff_filter},
642 {wszImageXPng, image_xpng_filter},
643 /* {wszImageXBitmap, image_xbitmap_filter}, */
644 {wszImageBmp, image_bmp_filter},
645 /* {wszImageXJg, image_xjg_filter}, */
646 /* {wszImageXEmf, image_xemf_filter}, */
647 /* {wszImageXWmf, image_xwmf_filter}, */
648 {wszVideoAvi, video_avi_filter},
649 {wszVideoMpeg, video_mpeg_filter},
650 {wszAppPostscript, application_postscript_filter},
651 /* {wszAppBase64, application_base64_filter}, */
652 /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
653 {wszAppPdf, application_pdf_filter},
654 /* {wszAppXCompressed, application_xcompressed_filter}, */
655 {wszAppXZip, application_xzip_filter},
656 {wszAppXGzip, application_xgzip_filter},
657 {wszAppJava, application_java_filter},
658 {wszAppXMSDownload, application_xmsdownload},
659 {wszTextPlain, text_plain_filter},
660 {wszAppOctetStream, application_octet_stream_filter}
663 if(!cbSize)
664 return E_FAIL;
666 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
667 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
668 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
669 break;
672 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
673 || mime_filters[i].filter(buf, cbSize)) {
674 len = strlenW(pwzMimeProposed)+1;
675 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
676 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
677 return S_OK;
681 i=0;
682 while(!ret) {
683 if(mime_filters[i].filter(buf, cbSize))
684 ret = mime_filters[i].mime;
685 i++;
688 TRACE("found %s for data\n"
689 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
690 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
691 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
693 if(pwzMimeProposed) {
694 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
695 ret = pwzMimeProposed;
697 /* text/html is a special case */
698 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
699 ret = wszTextHtml;
702 len = strlenW(ret)+1;
703 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
704 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
705 return S_OK;
708 if(pwzUrl) {
709 HKEY hkey;
710 DWORD res, size;
711 LPCWSTR ptr;
712 WCHAR mime[64];
714 static const WCHAR wszContentType[] =
715 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
717 ptr = strrchrW(pwzUrl, '.');
718 if(!ptr)
719 return E_FAIL;
721 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
722 if(res != ERROR_SUCCESS)
723 return HRESULT_FROM_WIN32(res);
725 size = sizeof(mime);
726 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
727 RegCloseKey(hkey);
728 if(res != ERROR_SUCCESS)
729 return HRESULT_FROM_WIN32(res);
731 *ppwzMimeOut = CoTaskMemAlloc(size);
732 memcpy(*ppwzMimeOut, mime, size);
733 return S_OK;
736 return E_FAIL;
739 /***********************************************************************
740 * GetClassFileOrMime (URLMON.@)
742 * Determines the class ID from the bind context, file name or MIME type.
744 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
745 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
746 CLSID *pclsid)
748 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
749 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
750 dwReserved, pclsid);
751 return E_NOTIMPL;
754 /***********************************************************************
755 * Extract (URLMON.@)
757 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
759 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
761 if (!hCabinet)
762 hCabinet = LoadLibraryA("cabinet.dll");
764 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
765 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
766 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
768 return pExtract(dest, szCabName);