ntdll: Move the copy_context function into the respective CPU-specific files.
[wine/hacks.git] / dlls / urlmon / urlmon_main.c
blob159b57dbcb3f43fd9b98fa5da7948b7847db81ce
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};
189 struct object_creation_info
191 const CLSID *clsid;
192 IClassFactory *cf;
193 LPCWSTR protocol;
196 static const WCHAR wszFile[] = {'f','i','l','e',0};
197 static const WCHAR wszFtp[] = {'f','t','p',0};
198 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0};
199 static const WCHAR wszHttp[] = {'h','t','t','p',0};
200 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
201 static const WCHAR wszMk[] = {'m','k',0};
203 static const struct object_creation_info object_creation[] =
205 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
206 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
207 { &CLSID_GopherProtocol, CLASSFACTORY(&GopherProtocolCF), wszGopher },
208 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
209 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
210 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
211 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
212 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL }
215 static void init_session(BOOL init)
217 unsigned int i;
219 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
221 if(object_creation[i].protocol)
222 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid,
223 object_creation[i].protocol, init);
227 /*******************************************************************************
228 * DllGetClassObject [URLMON.@]
229 * Retrieves class object from a DLL object
231 * NOTES
232 * Docs say returns STDAPI
234 * PARAMS
235 * rclsid [I] CLSID for the class object
236 * riid [I] Reference to identifier of interface for class object
237 * ppv [O] Address of variable to receive interface pointer for riid
239 * RETURNS
240 * Success: S_OK
241 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
242 * E_UNEXPECTED
245 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
247 unsigned int i;
249 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
251 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
253 if (IsEqualGUID(object_creation[i].clsid, rclsid))
254 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
257 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
258 return CLASS_E_CLASSNOTAVAILABLE;
262 /***********************************************************************
263 * DllRegisterServerEx (URLMON.@)
265 HRESULT WINAPI DllRegisterServerEx(void)
267 FIXME("(void): stub\n");
269 return E_FAIL;
272 /**************************************************************************
273 * UrlMkSetSessionOption (URLMON.@)
275 HRESULT WINAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
276 DWORD Reserved)
278 FIXME("(%#x, %p, %#x): stub\n", dwOption, pBuffer, dwBufferLength);
280 return S_OK;
283 static const CHAR Agent[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
285 /**************************************************************************
286 * ObtainUserAgentString (URLMON.@)
288 HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPSTR pcszUAOut, DWORD *cbSize)
290 FIXME("(%d, %p, %p): stub\n", dwOption, pcszUAOut, cbSize);
292 if (pcszUAOut == NULL || cbSize == NULL)
293 return E_INVALIDARG;
295 if (*cbSize < sizeof(Agent))
297 *cbSize = sizeof(Agent);
298 return E_OUTOFMEMORY;
301 if (sizeof(Agent) < *cbSize)
302 *cbSize = sizeof(Agent);
303 lstrcpynA(pcszUAOut, Agent, *cbSize);
305 return S_OK;
308 /**************************************************************************
309 * IsValidURL (URLMON.@)
311 * Determines if a specified string is a valid URL.
313 * PARAMS
314 * pBC [I] ignored, must be NULL.
315 * szURL [I] string that represents the URL in question.
316 * dwReserved [I] reserved and must be zero.
318 * RETURNS
319 * Success: S_OK.
320 * Failure: S_FALSE.
321 * returns E_INVALIDARG if one or more of the args is invalid.
323 * TODO:
324 * test functionality against windows to see what a valid URL is.
326 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
328 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
330 if (pBC != NULL || dwReserved != 0)
331 return E_INVALIDARG;
333 return S_OK;
336 /**************************************************************************
337 * FaultInIEFeature (URLMON.@)
339 * Undocumented. Appears to be used by native shdocvw.dll.
341 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
342 QUERYCONTEXT *pQuery, DWORD flags )
344 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
345 return E_NOTIMPL;
348 /**************************************************************************
349 * CoGetClassObjectFromURL (URLMON.@)
351 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
352 DWORD dwFileVersionLS, LPCWSTR szContentType,
353 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
354 REFIID riid, LPVOID *ppv )
356 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
357 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
358 debugstr_guid(riid), ppv);
359 return E_NOINTERFACE;
362 /***********************************************************************
363 * ReleaseBindInfo (URLMON.@)
365 * Release the resources used by the specified BINDINFO structure.
367 * PARAMS
368 * pbindinfo [I] BINDINFO to release.
370 * RETURNS
371 * Nothing.
373 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
375 DWORD size;
377 TRACE("(%p)\n", pbindinfo);
379 if(!pbindinfo || !(size = pbindinfo->cbSize))
380 return;
382 CoTaskMemFree(pbindinfo->szExtraInfo);
383 ReleaseStgMedium(&pbindinfo->stgmedData);
385 if(offsetof(BINDINFO, szExtraInfo) < size)
386 CoTaskMemFree(pbindinfo->szCustomVerb);
388 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
389 IUnknown_Release(pbindinfo->pUnk);
391 memset(pbindinfo, 0, size);
392 pbindinfo->cbSize = size;
395 /***********************************************************************
396 * CopyStgMedium (URLMON.@)
398 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst)
400 TRACE("(%p %p)\n", src, dst);
402 if(!src || !dst)
403 return E_POINTER;
405 *dst = *src;
407 switch(dst->tymed) {
408 case TYMED_NULL:
409 break;
410 case TYMED_FILE:
411 if(src->u.lpszFileName && !src->pUnkForRelease) {
412 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR);
413 dst->u.lpszFileName = CoTaskMemAlloc(size);
414 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size);
416 break;
417 case TYMED_ISTREAM:
418 if(dst->u.pstm)
419 IStream_AddRef(dst->u.pstm);
420 break;
421 case TYMED_ISTORAGE:
422 if(dst->u.pstg)
423 IStorage_AddRef(dst->u.pstg);
424 break;
425 default:
426 FIXME("Unimplemented tymed %d\n", src->tymed);
429 if(dst->pUnkForRelease)
430 IUnknown_AddRef(dst->pUnkForRelease);
432 return S_OK;
435 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
437 return size > 5 && !memcmp(b, "{\\rtf", 5);
440 static BOOL text_html_filter(const BYTE *b, DWORD size)
442 DWORD i;
444 if(size < 5)
445 return FALSE;
447 for(i=0; i < size-5; i++) {
448 if(b[i] == '<'
449 && (b[i+1] == 'h' || b[i+1] == 'H')
450 && (b[i+2] == 't' || b[i+2] == 'T')
451 && (b[i+3] == 'm' || b[i+3] == 'M')
452 && (b[i+4] == 'l' || b[i+4] == 'L'))
453 return TRUE;
456 return FALSE;
459 static BOOL audio_basic_filter(const BYTE *b, DWORD size)
461 return size > 4
462 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd';
465 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
467 return size > 12
468 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
469 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
472 static BOOL image_gif_filter(const BYTE *b, DWORD size)
474 return size >= 6
475 && (b[0] == 'G' || b[0] == 'g')
476 && (b[1] == 'I' || b[1] == 'i')
477 && (b[2] == 'F' || b[2] == 'f')
478 && b[3] == '8'
479 && (b[4] == '7' || b[4] == '9')
480 && (b[5] == 'A' || b[5] == 'a');
483 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
485 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
488 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
490 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
493 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
495 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
496 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
499 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
501 return size >= 14
502 && b[0] == 0x42 && b[1] == 0x4d
503 && *(const DWORD *)(b+6) == 0;
506 static BOOL video_avi_filter(const BYTE *b, DWORD size)
508 return size > 12
509 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
510 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
513 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
515 return size > 4
516 && !b[0] && !b[1] && b[2] == 0x01
517 && (b[3] == 0xb3 || b[3] == 0xba);
520 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
522 return size > 2 && b[0] == '%' && b[1] == '!';
525 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
527 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
530 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
532 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
535 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
537 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
540 static BOOL application_java_filter(const BYTE *b, DWORD size)
542 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
545 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
547 return size > 2 && b[0] == 'M' && b[1] == 'Z';
550 static BOOL text_plain_filter(const BYTE *b, DWORD size)
552 const BYTE *ptr;
554 for(ptr = b; ptr < b+size-1; ptr++) {
555 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
556 return FALSE;
559 return TRUE;
562 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
564 return TRUE;
567 /***********************************************************************
568 * FindMimeFromData (URLMON.@)
570 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
572 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
573 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
574 LPWSTR* ppwzMimeOut, DWORD dwReserved)
576 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
577 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
579 if(dwMimeFlags)
580 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
581 if(dwReserved)
582 WARN("dwReserved=%d\n", dwReserved);
584 /* pBC seams to not be used */
586 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
587 return E_INVALIDARG;
589 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
590 DWORD len;
592 if(!pwzMimeProposed)
593 return E_FAIL;
595 len = strlenW(pwzMimeProposed)+1;
596 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
597 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
598 return S_OK;
601 if(pBuffer) {
602 const BYTE *buf = pBuffer;
603 DWORD len;
604 LPCWSTR ret = NULL;
605 unsigned int i;
607 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
608 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
609 static const WCHAR wszAudioBasic[] = {'a','u','d','i','o','/','b','a','s','i','c',0};
610 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
611 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
612 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
613 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
614 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
615 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
616 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
617 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
618 static const WCHAR wszAppPostscript[] =
619 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
620 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
621 'p','d','f',0};
622 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
623 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
624 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
625 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
626 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
627 'j','a','v','a',0};
628 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
629 'x','-','m','s','d','o','w','n','l','o','a','d',0};
630 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
631 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
632 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
634 static const struct {
635 LPCWSTR mime;
636 BOOL (*filter)(const BYTE *,DWORD);
637 } mime_filters[] = {
638 {wszTextHtml, text_html_filter},
639 {wszTextRichtext, text_richtext_filter},
640 /* {wszAudioXAiff, audio_xaiff_filter}, */
641 {wszAudioBasic, audio_basic_filter},
642 {wszAudioWav, audio_wav_filter},
643 {wszImageGif, image_gif_filter},
644 {wszImagePjpeg, image_pjpeg_filter},
645 {wszImageTiff, image_tiff_filter},
646 {wszImageXPng, image_xpng_filter},
647 /* {wszImageXBitmap, image_xbitmap_filter}, */
648 {wszImageBmp, image_bmp_filter},
649 /* {wszImageXJg, image_xjg_filter}, */
650 /* {wszImageXEmf, image_xemf_filter}, */
651 /* {wszImageXWmf, image_xwmf_filter}, */
652 {wszVideoAvi, video_avi_filter},
653 {wszVideoMpeg, video_mpeg_filter},
654 {wszAppPostscript, application_postscript_filter},
655 /* {wszAppBase64, application_base64_filter}, */
656 /* {wszAppMacbinhex40, application_macbinhex40_filter}, */
657 {wszAppPdf, application_pdf_filter},
658 /* {wszAppXCompressed, application_xcompressed_filter}, */
659 {wszAppXZip, application_xzip_filter},
660 {wszAppXGzip, application_xgzip_filter},
661 {wszAppJava, application_java_filter},
662 {wszAppXMSDownload, application_xmsdownload},
663 {wszTextPlain, text_plain_filter},
664 {wszAppOctetStream, application_octet_stream_filter}
667 if(!cbSize)
668 return E_FAIL;
670 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
671 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
672 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
673 break;
676 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
677 || mime_filters[i].filter(buf, cbSize)) {
678 len = strlenW(pwzMimeProposed)+1;
679 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
680 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
681 return S_OK;
685 i=0;
686 while(!ret) {
687 if(mime_filters[i].filter(buf, cbSize))
688 ret = mime_filters[i].mime;
689 i++;
692 TRACE("found %s for data\n"
693 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
694 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
695 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
697 if(pwzMimeProposed) {
698 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
699 ret = pwzMimeProposed;
701 /* text/html is a special case */
702 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
703 ret = wszTextHtml;
706 len = strlenW(ret)+1;
707 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
708 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
709 return S_OK;
712 if(pwzUrl) {
713 HKEY hkey;
714 DWORD res, size;
715 LPCWSTR ptr;
716 WCHAR mime[64];
718 static const WCHAR wszContentType[] =
719 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
721 ptr = strrchrW(pwzUrl, '.');
722 if(!ptr)
723 return E_FAIL;
725 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
726 if(res != ERROR_SUCCESS)
727 return HRESULT_FROM_WIN32(res);
729 size = sizeof(mime);
730 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
731 RegCloseKey(hkey);
732 if(res != ERROR_SUCCESS)
733 return HRESULT_FROM_WIN32(res);
735 *ppwzMimeOut = CoTaskMemAlloc(size);
736 memcpy(*ppwzMimeOut, mime, size);
737 return S_OK;
740 return E_FAIL;
743 /***********************************************************************
744 * GetClassFileOrMime (URLMON.@)
746 * Determines the class ID from the bind context, file name or MIME type.
748 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
749 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
750 CLSID *pclsid)
752 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
753 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
754 dwReserved, pclsid);
755 return E_NOTIMPL;
758 /***********************************************************************
759 * Extract (URLMON.@)
761 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
763 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
765 if (!hCabinet)
766 hCabinet = LoadLibraryA("cabinet.dll");
768 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
769 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
770 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
772 return pExtract(dest, szCabName);
775 /***********************************************************************
776 * IsLoggingEnabledA (URLMON.@)
778 BOOL WINAPI IsLoggingEnabledA(LPCSTR url)
780 FIXME("(%s)\n", debugstr_a(url));
781 return FALSE;
784 /***********************************************************************
785 * IsLoggingEnabledW (URLMON.@)
787 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
789 FIXME("(%s)\n", debugstr_w(url));
790 return FALSE;