push bd0608bf727e2241b2885edad5c5c753477ffd22
[wine/hacks.git] / dlls / urlmon / urlmon_main.c
blob10d3d9587d7d8eb588d70be61b65d3c2c47ceb32
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 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
29 #define NO_SHLWAPI_REG
30 #include "shlwapi.h"
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
34 #include "winuser.h"
35 #include "urlmon.h"
36 #include "urlmon_main.h"
37 #include "ole2.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
41 LONG URLMON_refCount = 0;
43 HINSTANCE URLMON_hInstance = 0;
44 static HMODULE hCabinet = NULL;
46 static void init_session(BOOL);
48 /***********************************************************************
49 * DllMain (URLMON.init)
51 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
53 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
55 switch(fdwReason) {
56 case DLL_PROCESS_ATTACH:
57 DisableThreadLibraryCalls(hinstDLL);
58 URLMON_hInstance = hinstDLL;
59 init_session(TRUE);
60 break;
62 case DLL_PROCESS_DETACH:
63 if (hCabinet)
64 FreeLibrary(hCabinet);
65 hCabinet = NULL;
66 init_session(FALSE);
67 URLMON_hInstance = 0;
68 break;
70 return TRUE;
74 /***********************************************************************
75 * DllInstall (URLMON.@)
77 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
79 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
80 debugstr_w(cmdline));
82 return S_OK;
85 /***********************************************************************
86 * DllCanUnloadNow (URLMON.@)
88 HRESULT WINAPI DllCanUnloadNow(void)
90 return URLMON_refCount != 0 ? S_FALSE : S_OK;
95 /******************************************************************************
96 * Urlmon ClassFactory
98 typedef struct {
99 const IClassFactoryVtbl *lpClassFactoryVtbl;
101 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
102 } ClassFactory;
104 #define CLASSFACTORY(x) ((IClassFactory*) &(x)->lpClassFactoryVtbl)
106 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
108 *ppv = NULL;
110 if(IsEqualGUID(riid, &IID_IUnknown)) {
111 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
112 *ppv = iface;
113 }else if(IsEqualGUID(riid, &IID_IClassFactory)) {
114 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv);
115 *ppv = iface;
118 if(*ppv) {
119 IUnknown_AddRef((IUnknown*)*ppv);
120 return S_OK;
123 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv);
124 return E_NOINTERFACE;
127 static ULONG WINAPI CF_AddRef(IClassFactory *iface)
129 URLMON_LockModule();
130 return 2;
133 static ULONG WINAPI CF_Release(IClassFactory *iface)
135 URLMON_UnlockModule();
136 return 1;
140 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
141 REFIID riid, LPVOID *ppobj)
143 ClassFactory *This = (ClassFactory*)iface;
144 HRESULT hres;
145 LPUNKNOWN punk;
147 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
149 *ppobj = NULL;
150 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
151 hres = IUnknown_QueryInterface(punk, riid, ppobj);
152 IUnknown_Release(punk);
154 return hres;
157 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
159 TRACE("(%d)\n", dolock);
161 if (dolock)
162 URLMON_LockModule();
163 else
164 URLMON_UnlockModule();
166 return S_OK;
169 static const IClassFactoryVtbl ClassFactoryVtbl =
171 CF_QueryInterface,
172 CF_AddRef,
173 CF_Release,
174 CF_CreateInstance,
175 CF_LockServer
178 static const ClassFactory FileProtocolCF =
179 { &ClassFactoryVtbl, FileProtocol_Construct};
180 static const ClassFactory FtpProtocolCF =
181 { &ClassFactoryVtbl, FtpProtocol_Construct};
182 static const ClassFactory HttpProtocolCF =
183 { &ClassFactoryVtbl, HttpProtocol_Construct};
184 static const ClassFactory HttpSProtocolCF =
185 { &ClassFactoryVtbl, HttpSProtocol_Construct};
186 static const ClassFactory MkProtocolCF =
187 { &ClassFactoryVtbl, MkProtocol_Construct};
188 static const ClassFactory SecurityManagerCF =
189 { &ClassFactoryVtbl, SecManagerImpl_Construct};
190 static const ClassFactory ZoneManagerCF =
191 { &ClassFactoryVtbl, ZoneMgrImpl_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 wszHttp[] = {'h','t','t','p',0};
203 static const WCHAR wszHttps[] = {'h','t','t','p','s',0};
204 static const WCHAR wszMk[] = {'m','k',0};
206 static const struct object_creation_info object_creation[] =
208 { &CLSID_FileProtocol, CLASSFACTORY(&FileProtocolCF), wszFile },
209 { &CLSID_FtpProtocol, CLASSFACTORY(&FtpProtocolCF), wszFtp },
210 { &CLSID_HttpProtocol, CLASSFACTORY(&HttpProtocolCF), wszHttp },
211 { &CLSID_HttpSProtocol, CLASSFACTORY(&HttpSProtocolCF), wszHttps },
212 { &CLSID_MkProtocol, CLASSFACTORY(&MkProtocolCF), wszMk },
213 { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL },
214 { &CLSID_InternetZoneManager, CLASSFACTORY(&ZoneManagerCF), NULL }
217 static void init_session(BOOL init)
219 IInternetSession *session;
220 int i;
222 CoInternetGetSession(0, &session, 0);
224 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) {
225 if(object_creation[i].protocol) {
226 if(init)
228 IInternetSession_RegisterNameSpace(session, object_creation[i].cf,
229 object_creation[i].clsid, object_creation[i].protocol, 0, NULL, 0);
230 /* make sure that the AddRef on the class factory doesn't keep us loaded */
231 URLMON_UnlockModule();
233 else
235 /* make sure that the Release on the class factory doesn't unload us */
236 URLMON_LockModule();
237 IInternetSession_UnregisterNameSpace(session, object_creation[i].cf,
238 object_creation[i].protocol);
243 IInternetSession_Release(session);
246 /*******************************************************************************
247 * DllGetClassObject [URLMON.@]
248 * Retrieves class object from a DLL object
250 * NOTES
251 * Docs say returns STDAPI
253 * PARAMS
254 * rclsid [I] CLSID for the class object
255 * riid [I] Reference to identifier of interface for class object
256 * ppv [O] Address of variable to receive interface pointer for riid
258 * RETURNS
259 * Success: S_OK
260 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
261 * E_UNEXPECTED
264 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
266 int i;
268 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
270 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
272 if (IsEqualGUID(object_creation[i].clsid, rclsid))
273 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv);
276 FIXME("%s: no class found.\n", debugstr_guid(rclsid));
277 return CLASS_E_CLASSNOTAVAILABLE;
281 /***********************************************************************
282 * DllRegisterServerEx (URLMON.@)
284 HRESULT WINAPI DllRegisterServerEx(void)
286 FIXME("(void): stub\n");
288 return E_FAIL;
291 /**************************************************************************
292 * UrlMkSetSessionOption (URLMON.@)
294 HRESULT WINAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
295 DWORD Reserved)
297 FIXME("(%#x, %p, %#x): stub\n", dwOption, pBuffer, dwBufferLength);
299 return S_OK;
302 static const CHAR Agent[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
304 /**************************************************************************
305 * ObtainUserAgentString (URLMON.@)
307 HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPSTR pcszUAOut, DWORD *cbSize)
309 FIXME("(%d, %p, %p): stub\n", dwOption, pcszUAOut, cbSize);
311 if (pcszUAOut == NULL || cbSize == NULL)
312 return E_INVALIDARG;
314 if (*cbSize < sizeof(Agent))
316 *cbSize = sizeof(Agent);
317 return E_OUTOFMEMORY;
320 if (sizeof(Agent) < *cbSize)
321 *cbSize = sizeof(Agent);
322 lstrcpynA(pcszUAOut, Agent, *cbSize);
324 return S_OK;
327 /**************************************************************************
328 * IsValidURL (URLMON.@)
330 * Determines if a specified string is a valid URL.
332 * PARAMS
333 * pBC [I] ignored, must be NULL.
334 * szURL [I] string that represents the URL in question.
335 * dwReserved [I] reserved and must be zero.
337 * RETURNS
338 * Success: S_OK.
339 * Failure: S_FALSE.
340 * returns E_INVALIDARG if one or more of the args is invalid.
342 * TODO:
343 * test functionality against windows to see what a valid URL is.
345 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
347 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
349 if (pBC != NULL || dwReserved != 0)
350 return E_INVALIDARG;
352 return S_OK;
355 /**************************************************************************
356 * FaultInIEFeature (URLMON.@)
358 * Undocumented. Appears to be used by native shdocvw.dll.
360 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
361 QUERYCONTEXT *pQuery, DWORD flags )
363 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags);
364 return E_NOTIMPL;
367 /**************************************************************************
368 * CoGetClassObjectFromURL (URLMON.@)
370 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
371 DWORD dwFileVersionLS, LPCWSTR szContentType,
372 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
373 REFIID riid, LPVOID *ppv )
375 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
376 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
377 debugstr_guid(riid), ppv);
378 return E_NOINTERFACE;
381 /***********************************************************************
382 * ReleaseBindInfo (URLMON.@)
384 * Release the resources used by the specified BINDINFO structure.
386 * PARAMS
387 * pbindinfo [I] BINDINFO to release.
389 * RETURNS
390 * Nothing.
392 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
394 DWORD size;
396 TRACE("(%p)\n", pbindinfo);
398 if(!pbindinfo || !(size = pbindinfo->cbSize))
399 return;
401 CoTaskMemFree(pbindinfo->szExtraInfo);
402 ReleaseStgMedium(&pbindinfo->stgmedData);
404 if(offsetof(BINDINFO, szExtraInfo) < size)
405 CoTaskMemFree(pbindinfo->szCustomVerb);
408 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size)
409 IUnknown_Release(pbindinfo->pUnk);
411 memset(pbindinfo, 0, size);
412 pbindinfo->cbSize = size;
415 static BOOL text_richtext_filter(const BYTE *b, DWORD size)
417 return size > 5 && !memcmp(b, "{\\rtf", 5);
420 static BOOL text_html_filter(const BYTE *b, DWORD size)
422 int i;
424 if(size < 5)
425 return FALSE;
427 for(i=0; i < size-5; i++) {
428 if(b[i] == '<'
429 && (b[i+1] == 'h' || b[i+1] == 'H')
430 && (b[i+2] == 't' || b[i+2] == 'T')
431 && (b[i+3] == 'm' || b[i+3] == 'M')
432 && (b[i+4] == 'l' || b[i+4] == 'L'))
433 return TRUE;
436 return FALSE;
439 static BOOL audio_wav_filter(const BYTE *b, DWORD size)
441 return size > 12
442 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
443 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E';
446 static BOOL image_gif_filter(const BYTE *b, DWORD size)
448 return size >= 6
449 && (b[0] == 'G' || b[0] == 'g')
450 && (b[1] == 'I' || b[1] == 'i')
451 && (b[2] == 'F' || b[2] == 'f')
452 && b[3] == '8'
453 && (b[4] == '7' || b[4] == '9')
454 && (b[5] == 'A' || b[5] == 'a');
457 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size)
459 return size > 2 && b[0] == 0xff && b[1] == 0xd8;
462 static BOOL image_tiff_filter(const BYTE *b, DWORD size)
464 return size > 2 && b[0] == 0x4d && b[1] == 0x4d;
467 static BOOL image_xpng_filter(const BYTE *b, DWORD size)
469 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
470 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header));
473 static BOOL image_bmp_filter(const BYTE *b, DWORD size)
475 return size >= 14
476 && b[0] == 0x42 && b[1] == 0x4d
477 && *(const DWORD *)(b+6) == 0;
480 static BOOL video_avi_filter(const BYTE *b, DWORD size)
482 return size > 12
483 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F'
484 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20;
487 static BOOL video_mpeg_filter(const BYTE *b, DWORD size)
489 return size > 4
490 && !b[0] && !b[1] && b[2] == 0x01
491 && (b[3] == 0xb3 || b[3] == 0xba);
494 static BOOL application_postscript_filter(const BYTE *b, DWORD size)
496 return size > 2 && b[0] == '%' && b[1] == '!';
499 static BOOL application_pdf_filter(const BYTE *b, DWORD size)
501 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46;
504 static BOOL application_xzip_filter(const BYTE *b, DWORD size)
506 return size > 2 && b[0] == 0x50 && b[1] == 0x4b;
509 static BOOL application_xgzip_filter(const BYTE *b, DWORD size)
511 return size > 2 && b[0] == 0x1f && b[1] == 0x8b;
514 static BOOL application_java_filter(const BYTE *b, DWORD size)
516 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe;
519 static BOOL application_xmsdownload(const BYTE *b, DWORD size)
521 return size > 2 && b[0] == 'M' && b[1] == 'Z';
524 static BOOL text_plain_filter(const BYTE *b, DWORD size)
526 const BYTE *ptr;
528 for(ptr = b; ptr < b+size-1; ptr++) {
529 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t')
530 return FALSE;
533 return TRUE;
536 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size)
538 return TRUE;
541 /***********************************************************************
542 * FindMimeFromData (URLMON.@)
544 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
546 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer,
547 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags,
548 LPWSTR* ppwzMimeOut, DWORD dwReserved)
550 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize,
551 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved);
553 if(dwMimeFlags)
554 WARN("dwMimeFlags=%08x\n", dwMimeFlags);
555 if(dwReserved)
556 WARN("dwReserved=%d\n", dwReserved);
558 /* pBC seams to not be used */
560 if(!ppwzMimeOut || (!pwzUrl && !pBuffer))
561 return E_INVALIDARG;
563 if(pwzMimeProposed && (!pBuffer || (pBuffer && !cbSize))) {
564 DWORD len;
566 if(!pwzMimeProposed)
567 return E_FAIL;
569 len = strlenW(pwzMimeProposed)+1;
570 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
571 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
572 return S_OK;
575 if(pBuffer) {
576 const BYTE *buf = pBuffer;
577 DWORD len;
578 LPCWSTR ret = NULL;
579 int i;
581 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
582 static const WCHAR wszTextRichtext[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0};
583 static const WCHAR wszAudioWav[] = {'a','u','d','i','o','/','w','a','v',0};
584 static const WCHAR wszImageGif[] = {'i','m','a','g','e','/','g','i','f',0};
585 static const WCHAR wszImagePjpeg[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
586 static const WCHAR wszImageTiff[] = {'i','m','a','g','e','/','t','i','f','f',0};
587 static const WCHAR wszImageXPng[] = {'i','m','a','g','e','/','x','-','p','n','g',0};
588 static const WCHAR wszImageBmp[] = {'i','m','a','g','e','/','b','m','p',0};
589 static const WCHAR wszVideoAvi[] = {'v','i','d','e','o','/','a','v','i',0};
590 static const WCHAR wszVideoMpeg[] = {'v','i','d','e','o','/','m','p','e','g',0};
591 static const WCHAR wszAppPostscript[] =
592 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0};
593 static const WCHAR wszAppPdf[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
594 'p','d','f',0};
595 static const WCHAR wszAppXZip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
596 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
597 static const WCHAR wszAppXGzip[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
598 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0};
599 static const WCHAR wszAppJava[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
600 'j','a','v','a',0};
601 static const WCHAR wszAppXMSDownload[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
602 'x','-','m','s','d','o','w','n','l','o','a','d',0};
603 static const WCHAR wszTextPlain[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
604 static const WCHAR wszAppOctetStream[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
605 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
607 static const struct {
608 LPCWSTR mime;
609 BOOL (*filter)(const BYTE *,DWORD);
610 } mime_filters[] = {
611 {wszTextHtml, text_html_filter},
612 {wszTextRichtext, text_richtext_filter},
613 {wszAudioWav, audio_wav_filter},
614 {wszImageGif, image_gif_filter},
615 {wszImagePjpeg, image_pjpeg_filter},
616 {wszImageTiff, image_tiff_filter},
617 {wszImageXPng, image_xpng_filter},
618 {wszImageBmp, image_bmp_filter},
619 {wszVideoAvi, video_avi_filter},
620 {wszVideoMpeg, video_mpeg_filter},
621 {wszAppPostscript, application_postscript_filter},
622 {wszAppPdf, application_pdf_filter},
623 {wszAppXZip, application_xzip_filter},
624 {wszAppXGzip, application_xgzip_filter},
625 {wszAppJava, application_java_filter},
626 {wszAppXMSDownload, application_xmsdownload},
627 {wszTextPlain, text_plain_filter},
628 {wszAppOctetStream, application_octet_stream_filter}
631 if(!cbSize)
632 return E_FAIL;
634 if(pwzMimeProposed && strcmpW(pwzMimeProposed, wszAppOctetStream)) {
635 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) {
636 if(!strcmpW(pwzMimeProposed, mime_filters[i].mime))
637 break;
640 if(i == sizeof(mime_filters)/sizeof(*mime_filters)
641 || mime_filters[i].filter(buf, cbSize)) {
642 len = strlenW(pwzMimeProposed)+1;
643 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
644 memcpy(*ppwzMimeOut, pwzMimeProposed, len*sizeof(WCHAR));
645 return S_OK;
649 i=0;
650 while(!ret) {
651 if(mime_filters[i].filter(buf, cbSize))
652 ret = mime_filters[i].mime;
653 i++;
656 TRACE("found %s for data\n"
657 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
658 debugstr_w(ret), buf[0],buf[1],buf[2],buf[3], buf[4],buf[5],buf[6],buf[7],
659 buf[8],buf[9],buf[10],buf[11], buf[12],buf[13],buf[14],buf[15]);
661 if(pwzMimeProposed) {
662 if(i == sizeof(mime_filters)/sizeof(*mime_filters))
663 ret = pwzMimeProposed;
665 /* text/html is a special case */
666 if(!strcmpW(pwzMimeProposed, wszTextHtml) && !strcmpW(ret, wszTextPlain))
667 ret = wszTextHtml;
670 len = strlenW(ret)+1;
671 *ppwzMimeOut = CoTaskMemAlloc(len*sizeof(WCHAR));
672 memcpy(*ppwzMimeOut, ret, len*sizeof(WCHAR));
673 return S_OK;
676 if(pwzUrl) {
677 HKEY hkey;
678 DWORD res, size;
679 LPCWSTR ptr;
680 WCHAR mime[64];
682 static const WCHAR wszContentType[] =
683 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
685 ptr = strrchrW(pwzUrl, '.');
686 if(!ptr)
687 return E_FAIL;
689 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey);
690 if(res != ERROR_SUCCESS)
691 return HRESULT_FROM_WIN32(res);
693 size = sizeof(mime);
694 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size);
695 RegCloseKey(hkey);
696 if(res != ERROR_SUCCESS)
697 return HRESULT_FROM_WIN32(res);
699 *ppwzMimeOut = CoTaskMemAlloc(size);
700 memcpy(*ppwzMimeOut, mime, size);
701 return S_OK;
704 return E_FAIL;
707 /***********************************************************************
708 * GetClassFileOrMime (URLMON.@)
710 * Determines the class ID from the bind context, file name or MIME type.
712 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename,
713 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved,
714 CLSID *pclsid)
716 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC,
717 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType),
718 dwReserved, pclsid);
719 return E_NOTIMPL;
722 /***********************************************************************
723 * Extract (URLMON.@)
725 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName)
727 HRESULT (WINAPI *pExtract)(void *, LPCSTR);
729 if (!hCabinet)
730 hCabinet = LoadLibraryA("cabinet.dll");
732 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError());
733 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
734 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError());
736 return pExtract(dest, szCabName);