wined3d: Call SetGlTextureDesc() from BindTexture() rather than from PreLoad().
[wine/testsucceed.git] / dlls / urlmon / urlmon_main.c
blob1661bb66c2d09ca821f3fdfdca7173d0fecf2fca
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 IInternetSession *session;
214 int i;
216 CoInternetGetSession(0, &session, 0);
218 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
219 if(object_creation[i].protocol) {
220 if(init)
222 IInternetSession_RegisterNameSpace(session, object_creation[i].cf,
223 object_creation[i].clsid, object_creation[i].protocol, 0, NULL, 0);
224 /* make sure that the AddRef on the class factory doesn't keep us loaded */
225 URLMON_UnlockModule();
227 else
229 /* make sure that the Release on the class factory doesn't unload us */
230 URLMON_LockModule();
231 IInternetSession_UnregisterNameSpace(session, object_creation[i].cf,
232 object_creation[i].protocol);
237 IInternetSession_Release(session);
240 /*******************************************************************************
241 * DllGetClassObject [URLMON.@]
242 * Retrieves class object from a DLL object
244 * NOTES
245 * Docs say returns STDAPI
247 * PARAMS
248 * rclsid [I] CLSID for the class object
249 * riid [I] Reference to identifier of interface for class object
250 * ppv [O] Address of variable to receive interface pointer for riid
252 * RETURNS
253 * Success: S_OK
254 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
255 * E_UNEXPECTED
258 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
260 int i;
262 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
264 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
266 if (IsEqualGUID(object_creation[i].clsid, rclsid))
267 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
270 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
271 return CLASS_E_CLASSNOTAVAILABLE;
275 /***********************************************************************
276 * DllRegisterServerEx (URLMON.@)
278 HRESULT WINAPI DllRegisterServerEx(void)
280 FIXME("(void): stub\n");
282 return E_FAIL;
285 /**************************************************************************
286 * UrlMkSetSessionOption (URLMON.@)
288 HRESULT WINAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
289 DWORD Reserved)
291 FIXME("(%#x, %p, %#x): stub\n", dwOption, pBuffer, dwBufferLength);
293 return S_OK;
296 static const CHAR Agent[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
298 /**************************************************************************
299 * ObtainUserAgentString (URLMON.@)
301 HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPSTR pcszUAOut, DWORD *cbSize)
303 FIXME("(%d, %p, %p): stub\n", dwOption, pcszUAOut, cbSize);
305 if (pcszUAOut == NULL || cbSize == NULL)
306 return E_INVALIDARG;
308 if (*cbSize < sizeof(Agent))
310 *cbSize = sizeof(Agent);
311 return E_OUTOFMEMORY;
314 if (sizeof(Agent) < *cbSize)
315 *cbSize = sizeof(Agent);
316 lstrcpynA(pcszUAOut, Agent, *cbSize);
318 return S_OK;
321 /**************************************************************************
322 * IsValidURL (URLMON.@)
324 * Determines if a specified string is a valid URL.
326 * PARAMS
327 * pBC [I] ignored, must be NULL.
328 * szURL [I] string that represents the URL in question.
329 * dwReserved [I] reserved and must be zero.
331 * RETURNS
332 * Success: S_OK.
333 * Failure: S_FALSE.
334 * returns E_INVALIDARG if one or more of the args is invalid.
336 * TODO:
337 * test functionality against windows to see what a valid URL is.
339 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
341 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
343 if (pBC != NULL || dwReserved != 0)
344 return E_INVALIDARG;
346 return S_OK;
349 /**************************************************************************
350 * FaultInIEFeature (URLMON.@)
352 * Undocumented. Appears to be used by native shdocvw.dll.
354 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
355 QUERYCONTEXT *pQuery, DWORD flags )
357 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
358 return E_NOTIMPL;
361 /**************************************************************************
362 * CoGetClassObjectFromURL (URLMON.@)
364 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
365 DWORD dwFileVersionLS, LPCWSTR szContentType,
366 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
367 REFIID riid, LPVOID *ppv )
369 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
370 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
371 debugstr_guid(riid), ppv);
372 return E_NOINTERFACE;
375 /***********************************************************************
376 * ReleaseBindInfo (URLMON.@)
378 * Release the resources used by the specified BINDINFO structure.
380 * PARAMS
381 * pbindinfo [I] BINDINFO to release.
383 * RETURNS
384 * Nothing.
386 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
388 DWORD size;
390 TRACE("(%p)\n", pbindinfo);
392 if(!pbindinfo || !(size = pbindinfo->cbSize))
393 return;
395 CoTaskMemFree(pbindinfo->szExtraInfo);
396 ReleaseStgMedium(&pbindinfo->stgmedData);
398 if(offsetof(BINDINFO, szExtraInfo) < size)
399 CoTaskMemFree(pbindinfo->szCustomVerb);
402 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
403 IUnknown_Release(pbindinfo->pUnk);
405 memset(pbindinfo, 0, size);
406 pbindinfo->cbSize = size;
409 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
411 return size > 5 && !memcmp(b, "{\\rtf", 5);
414 static BOOL text_html_filter(const BYTE *b, DWORD size)
416 int i;
418 if(size < 5)
419 return FALSE;
421 for(i=0; i < size-5; i++) {
422 if(b[i] == '<'
423 && (b[i+1] == 'h' || b[i+1] == 'H')
424 && (b[i+2] == 't' || b[i+2] == 'T')
425 && (b[i+3] == 'm' || b[i+3] == 'M')
426 && (b[i+4] == 'l' || b[i+4] == 'L'))
427 return TRUE;
430 return FALSE;
433 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
435 return size > 12
436 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
437 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
440 static BOOL image_gif_filter(const BYTE *b, DWORD size)
442 return size >= 6
443 && (b[0] == 'G' || b[0] == 'g')
444 && (b[1] == 'I' || b[1] == 'i')
445 && (b[2] == 'F' || b[2] == 'f')
446 && b[3] == '8'
447 && (b[4] == '7' || b[4] == '9')
448 && (b[5] == 'A' || b[5] == 'a');
451 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
453 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
456 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
458 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
461 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
463 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
464 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
467 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
469 return size >= 14
470 && b[0] == 0x42 && b[1] == 0x4d
471 && *(const DWORD *)(b+6) == 0;
474 static BOOL video_avi_filter(const BYTE *b, DWORD size)
476 return size > 12
477 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
478 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
481 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
483 return size > 4
484 && !b[0] && !b[1] && b[2] == 0x01
485 && (b[3] == 0xb3 || b[3] == 0xba);
488 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
490 return size > 2 && b[0] == '%' && b[1] == '!';
493 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
495 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
498 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
500 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
503 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
505 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
508 static BOOL application_java_filter(const BYTE *b, DWORD size)
510 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
513 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
515 return size > 2 && b[0] == 'M' && b[1] == 'Z';
518 static BOOL text_plain_filter(const BYTE *b, DWORD size)
520 const BYTE *ptr;
522 for(ptr = b; ptr < b+size-1; ptr++) {
523 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
524 return FALSE;
527 return TRUE;
530 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
532 return TRUE;
535 /***********************************************************************
536 * FindMimeFromData (URLMON.@)
538 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
540 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
541 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
542 LPWSTR* ppwzMimeOut, DWORD dwReserved)
544 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
545 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
547 if(dwMimeFlags)
548 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
549 if(dwReserved)
550 WARN("dwReserved=%d\n", dwReserved);
552 /* pBC seams to not be used */
554 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
555 return E_INVALIDARG;
557 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
558 DWORD len;
560 if(!pwzMimeProposed)
561 return E_FAIL;
563 len = strlenW(pwzMimeProposed)+1;
564 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
565 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
566 return S_OK;
569 if(pBuffer) {
570 const BYTE *buf = pBuffer;
571 DWORD len;
572 LPCWSTR ret = NULL;
573 int i;
575 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
576 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
577 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
578 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
579 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
580 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
581 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
582 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
583 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
584 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
585 static const WCHAR wszAppPostscript[] =
586 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
587 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
588 'p','d','f',0};
589 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
590 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
591 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
592 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
593 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
594 'j','a','v','a',0};
595 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
596 'x','-','m','s','d','o','w','n','l','o','a','d',0};
597 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
598 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
599 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
601 static const struct {
602 LPCWSTR mime;
603 BOOL (*filter)(const BYTE *,DWORD);
604 } mime_filters[] = {
605 {wszTextHtml, text_html_filter},
606 {wszTextRichtext, text_richtext_filter},
607 {wszAudioWav, audio_wav_filter},
608 {wszImageGif, image_gif_filter},
609 {wszImagePjpeg, image_pjpeg_filter},
610 {wszImageTiff, image_tiff_filter},
611 {wszImageXPng, image_xpng_filter},
612 {wszImageBmp, image_bmp_filter},
613 {wszVideoAvi, video_avi_filter},
614 {wszVideoMpeg, video_mpeg_filter},
615 {wszAppPostscript, application_postscript_filter},
616 {wszAppPdf, application_pdf_filter},
617 {wszAppXZip, application_xzip_filter},
618 {wszAppXGzip, application_xgzip_filter},
619 {wszAppJava, application_java_filter},
620 {wszAppXMSDownload, application_xmsdownload},
621 {wszTextPlain, text_plain_filter},
622 {wszAppOctetStream, application_octet_stream_filter}
625 if(!cbSize)
626 return E_FAIL;
628 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
629 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
630 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
631 break;
634 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
635 || mime_filters[i].filter(buf, cbSize)) {
636 len = strlenW(pwzMimeProposed)+1;
637 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
638 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
639 return S_OK;
643 i=0;
644 while(!ret) {
645 if(mime_filters[i].filter(buf, cbSize))
646 ret = mime_filters[i].mime;
647 i++;
650 TRACE("found %s for data\n"
651 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
652 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
653 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
655 if(pwzMimeProposed) {
656 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
657 ret = pwzMimeProposed;
659 /* text/html is a special case */
660 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
661 ret = wszTextHtml;
664 len = strlenW(ret)+1;
665 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
666 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
667 return S_OK;
670 if(pwzUrl) {
671 HKEY hkey;
672 DWORD res, size;
673 LPCWSTR ptr;
674 WCHAR mime[64];
676 static const WCHAR wszContentType[] =
677 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
679 ptr = strrchrW(pwzUrl, '.');
680 if(!ptr)
681 return E_FAIL;
683 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
684 if(res != ERROR_SUCCESS)
685 return HRESULT_FROM_WIN32(res);
687 size = sizeof(mime);
688 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
689 RegCloseKey(hkey);
690 if(res != ERROR_SUCCESS)
691 return HRESULT_FROM_WIN32(res);
693 *ppwzMimeOut = CoTaskMemAlloc(size);
694 memcpy(*ppwzMimeOut, mime, size);
695 return S_OK;
698 return E_FAIL;
701 /***********************************************************************
702 * GetClassFileOrMime (URLMON.@)
704 * Determines the class ID from the bind context, file name or MIME type.
706 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
707 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
708 CLSID *pclsid)
710 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
711 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
712 dwReserved, pclsid);
713 return E_NOTIMPL;
716 /***********************************************************************
717 * Extract (URLMON.@)
719 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
721 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
723 if (!hCabinet)
724 hCabinet = LoadLibraryA("cabinet.dll");
726 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
727 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
728 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
730 return pExtract(dest, szCabName);