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
29 #define NO_SHLWAPI_REG
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
36 #include "urlmon_main.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(urlmon
);
41 LONG URLMON_refCount
= 0;
43 HINSTANCE URLMON_hInstance
= 0;
47 /***********************************************************************
48 * DllMain (URLMON.init)
50 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID fImpLoad
)
52 TRACE("%p 0x%lx %p\n", hinstDLL
, fdwReason
, fImpLoad
);
55 case DLL_PROCESS_ATTACH
:
56 DisableThreadLibraryCalls(hinstDLL
);
57 URLMON_hInstance
= hinstDLL
;
60 case DLL_PROCESS_DETACH
:
70 /***********************************************************************
71 * DllInstall (URLMON.@)
73 HRESULT WINAPI
DllInstall(BOOL bInstall
, LPCWSTR cmdline
)
75 FIXME("(%s, %s): stub\n", bInstall
?"TRUE":"FALSE",
81 /***********************************************************************
82 * DllCanUnloadNow (URLMON.@)
84 HRESULT WINAPI
DllCanUnloadNow(void)
86 return URLMON_refCount
!= 0 ? S_FALSE
: S_OK
;
91 /******************************************************************************
95 IClassFactory ITF_IClassFactory
;
98 HRESULT (*pfnCreateInstance
)(IUnknown
*pUnkOuter
, LPVOID
*ppObj
);
101 struct object_creation_info
104 HRESULT (*pfnCreateInstance
)(IUnknown
*pUnkOuter
, LPVOID
*ppObj
);
107 static const struct object_creation_info object_creation
[] =
109 { &CLSID_FileProtocol
, FileProtocol_Construct
},
110 { &CLSID_FtpProtocol
, FtpProtocol_Construct
},
111 { &CLSID_HttpProtocol
, HttpProtocol_Construct
},
112 { &CLSID_InternetSecurityManager
, &SecManagerImpl_Construct
},
113 { &CLSID_InternetZoneManager
, ZoneMgrImpl_Construct
}
116 static HRESULT WINAPI
117 CF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
)
119 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
121 if (IsEqualGUID(riid
, &IID_IUnknown
)
122 || IsEqualGUID(riid
, &IID_IClassFactory
))
124 IClassFactory_AddRef(iface
);
129 WARN("(%p)->(%s,%p),not found\n",This
,debugstr_guid(riid
),ppobj
);
130 return E_NOINTERFACE
;
133 static ULONG WINAPI
CF_AddRef(LPCLASSFACTORY iface
)
135 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
136 return InterlockedIncrement(&This
->ref
);
139 static ULONG WINAPI
CF_Release(LPCLASSFACTORY iface
)
141 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
143 ULONG ref
= InterlockedDecrement(&This
->ref
);
146 HeapFree(GetProcessHeap(), 0, This
);
147 URLMON_UnlockModule();
154 static HRESULT WINAPI
CF_CreateInstance(LPCLASSFACTORY iface
, LPUNKNOWN pOuter
,
155 REFIID riid
, LPVOID
*ppobj
)
157 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
161 TRACE("(%p)->(%p,%s,%p)\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
164 if(SUCCEEDED(hres
= This
->pfnCreateInstance(pOuter
, (LPVOID
*) &punk
))) {
165 hres
= IUnknown_QueryInterface(punk
, riid
, ppobj
);
166 IUnknown_Release(punk
);
171 static HRESULT WINAPI
CF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
)
173 TRACE("(%d)\n", dolock
);
178 URLMON_UnlockModule();
183 static const IClassFactoryVtbl CF_Vtbl
=
192 /*******************************************************************************
193 * DllGetClassObject [URLMON.@]
194 * Retrieves class object from a DLL object
197 * Docs say returns STDAPI
200 * rclsid [I] CLSID for the class object
201 * riid [I] Reference to identifier of interface for class object
202 * ppv [O] Address of variable to receive interface pointer for riid
206 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
210 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
*ppv
)
213 IClassFactoryImpl
*factory
;
215 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
217 if ( !IsEqualGUID( &IID_IClassFactory
, riid
)
218 && ! IsEqualGUID( &IID_IUnknown
, riid
) )
219 return E_NOINTERFACE
;
221 for (i
=0; i
< sizeof(object_creation
)/sizeof(object_creation
[0]); i
++)
223 if (IsEqualGUID(object_creation
[i
].clsid
, rclsid
))
227 if (i
== sizeof(object_creation
)/sizeof(object_creation
[0]))
229 FIXME("%s: no class found.\n", debugstr_guid(rclsid
));
230 return CLASS_E_CLASSNOTAVAILABLE
;
233 factory
= HeapAlloc(GetProcessHeap(), 0, sizeof(*factory
));
234 if (factory
== NULL
) return E_OUTOFMEMORY
;
236 factory
->ITF_IClassFactory
.lpVtbl
= &CF_Vtbl
;
238 factory
->pfnCreateInstance
= object_creation
[i
].pfnCreateInstance
;
240 *ppv
= &(factory
->ITF_IClassFactory
);
248 /***********************************************************************
249 * DllRegisterServerEx (URLMON.@)
251 HRESULT WINAPI
DllRegisterServerEx(void)
253 FIXME("(void): stub\n");
258 /**************************************************************************
259 * UrlMkSetSessionOption (URLMON.@)
261 HRESULT WINAPI
UrlMkSetSessionOption(DWORD dwOption
, LPVOID pBuffer
, DWORD dwBufferLength
,
264 FIXME("(%#lx, %p, %#lx): stub\n", dwOption
, pBuffer
, dwBufferLength
);
269 /**************************************************************************
270 * UrlMkGetSessionOption (URLMON.@)
272 HRESULT WINAPI
UrlMkGetSessionOption(DWORD dwOption
, LPVOID pBuffer
, DWORD dwBufferLength
,
273 DWORD
* pdwBufferLength
, DWORD dwReserved
)
275 FIXME("(%#lx, %p, %#lx, %p): stub\n", dwOption
, pBuffer
, dwBufferLength
, pdwBufferLength
);
280 static const CHAR Agent
[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
282 /**************************************************************************
283 * ObtainUserAgentString (URLMON.@)
285 HRESULT WINAPI
ObtainUserAgentString(DWORD dwOption
, LPSTR pcszUAOut
, DWORD
*cbSize
)
287 FIXME("(%ld, %p, %p): stub\n", dwOption
, pcszUAOut
, cbSize
);
290 ERR("dwOption: %ld, must be zero\n", dwOption
);
293 if (sizeof(Agent
) < *cbSize
)
294 *cbSize
= sizeof(Agent
);
295 lstrcpynA(pcszUAOut
, Agent
, *cbSize
);
300 HRESULT WINAPI
CoInternetCompareUrl(LPCWSTR pwzUrl1
, LPCWSTR pwzUrl2
, DWORD dwCompareFlags
)
302 TRACE("(%s,%s,%08lx)\n", debugstr_w(pwzUrl1
), debugstr_w(pwzUrl2
), dwCompareFlags
);
303 return UrlCompareW(pwzUrl1
, pwzUrl2
, dwCompareFlags
)==0?S_OK
:S_FALSE
;
306 /**************************************************************************
307 * IsValidURL (URLMON.@)
309 * Determines if a specified string is a valid URL.
312 * pBC [I] ignored, must be NULL.
313 * szURL [I] string that represents the URL in question.
314 * dwReserved [I] reserved and must be zero.
319 * returns E_INVALIDARG if one or more of the args is invalid.
322 * test functionality against windows to see what a valid URL is.
324 HRESULT WINAPI
IsValidURL(LPBC pBC
, LPCWSTR szURL
, DWORD dwReserved
)
326 FIXME("(%p, %s, %ld): stub\n", pBC
, debugstr_w(szURL
), dwReserved
);
328 if (pBC
!= NULL
|| dwReserved
!= 0)
334 /**************************************************************************
335 * FaultInIEFeature (URLMON.@)
337 * Undocumented. Appears to be used by native shdocvw.dll.
339 HRESULT WINAPI
FaultInIEFeature( HWND hwnd
, uCLSSPEC
* pClassSpec
,
340 QUERYCONTEXT
*pQuery
, DWORD flags
)
342 FIXME("%p %p %p %08lx\n", hwnd
, pClassSpec
, pQuery
, flags
);
346 /**************************************************************************
347 * CoGetClassObjectFromURL (URLMON.@)
349 HRESULT WINAPI
CoGetClassObjectFromURL( REFCLSID rclsid
, LPCWSTR szCodeURL
, DWORD dwFileVersionMS
,
350 DWORD dwFileVersionLS
, LPCWSTR szContentType
,
351 LPBINDCTX pBindCtx
, DWORD dwClsContext
, LPVOID pvReserved
,
352 REFIID riid
, LPVOID
*ppv
)
354 FIXME("(%s %s %ld %ld %s %p %ld %p %s %p) Stub!\n", debugstr_guid(rclsid
), debugstr_w(szCodeURL
),
355 dwFileVersionMS
, dwFileVersionLS
, debugstr_w(szContentType
), pBindCtx
, dwClsContext
, pvReserved
,
356 debugstr_guid(riid
), ppv
);
357 return E_NOINTERFACE
;
360 /***********************************************************************
361 * ReleaseBindInfo (URLMON.@)
363 * Release the resources used by the specified BINDINFO structure.
366 * pbindinfo [I] BINDINFO to release.
371 void WINAPI
ReleaseBindInfo(BINDINFO
* pbindinfo
)
375 TRACE("(%p)\n", pbindinfo
);
377 if(!pbindinfo
|| !(size
= pbindinfo
->cbSize
))
380 CoTaskMemFree(pbindinfo
->szExtraInfo
);
381 ReleaseStgMedium(&pbindinfo
->stgmedData
);
383 if(offsetof(BINDINFO
, szExtraInfo
) < size
)
384 CoTaskMemFree(pbindinfo
->szCustomVerb
);
387 if(pbindinfo
->pUnk
&& offsetof(BINDINFO
, pUnk
) < size
)
388 IUnknown_Release(pbindinfo
->pUnk
);
390 memset(pbindinfo
, 0, size
);
391 pbindinfo
->cbSize
= size
;
394 /***********************************************************************
395 * FindMimeFromData (URLMON.@)
397 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided.
399 static BOOL
text_html_filter(LPVOID buf
, DWORD size
)
407 for(i
=0; i
< size
-5; i
++) {
409 && (b
[i
+1] == 'h' || b
[i
+1] == 'H')
410 && (b
[i
+2] == 't' || b
[i
+2] == 'T')
411 && (b
[i
+3] == 'm' || b
[i
+3] == 'M')
412 && (b
[i
+4] == 'l' || b
[i
+4] == 'L'))
419 static BOOL
image_gif_filter(LPVOID buf
, DWORD size
)
421 const BYTE
const *b
= buf
;
424 && (b
[0] == 'G' || b
[0] == 'g')
425 && (b
[1] == 'I' || b
[1] == 'i')
426 && (b
[2] == 'F' || b
[2] == 'f')
428 && (b
[4] == '7' || b
[4] == '9')
429 && (b
[5] == 'A' || b
[5] == 'a');
432 static BOOL
image_pjpeg_filter(LPVOID buf
, DWORD size
)
434 return size
> 2 && *(BYTE
*)buf
== 0xff && *((BYTE
*)buf
+1) == 0xd8;
437 static BOOL
text_plain_filter(LPVOID buf
, DWORD size
)
441 for(ptr
= buf
; ptr
< (UCHAR
*)buf
+size
-1; ptr
++) {
442 if(*ptr
< 0x20 && *ptr
!= '\n' && *ptr
!= '\r' && *ptr
!= '\t')
449 static BOOL
application_octet_stream_filter(LPVOID buf
, DWORD size
)
454 HRESULT WINAPI
FindMimeFromData(LPBC pBC
, LPCWSTR pwzUrl
, LPVOID pBuffer
,
455 DWORD cbSize
, LPCWSTR pwzMimeProposed
, DWORD dwMimeFlags
,
456 LPWSTR
* ppwzMimeOut
, DWORD dwReserved
)
458 TRACE("(%p,%s,%p,%ld,%s,0x%lx,%p,0x%lx)\n", pBC
, debugstr_w(pwzUrl
), pBuffer
, cbSize
,
459 debugstr_w(pwzMimeProposed
), dwMimeFlags
, ppwzMimeOut
, dwReserved
);
462 WARN("dwMimeFlags=%08lx\n", dwMimeFlags
);
464 WARN("dwReserved=%ld\n", dwReserved
);
466 /* pBC seams to not be used */
468 if(!ppwzMimeOut
|| (!pwzUrl
&& !pBuffer
))
471 if(pwzMimeProposed
&& (!pBuffer
|| (pBuffer
&& !cbSize
))) {
477 len
= strlenW(pwzMimeProposed
)+1;
478 *ppwzMimeOut
= CoTaskMemAlloc(len
*sizeof(WCHAR
));
479 memcpy(*ppwzMimeOut
, pwzMimeProposed
, len
*sizeof(WCHAR
));
488 static const WCHAR wszTextHtml
[] = {'t','e','x','t','/','h','t','m','l',0};
489 static const WCHAR wszImageGif
[] = {'i','m','a','g','e','/','g','i','f',0};
490 static const WCHAR wszImagePjpeg
[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
491 static const WCHAR wszTextPlain
[] = {'t','e','x','t','/','p','l','a','i','n','\0'};
492 static const WCHAR wszAppOctetStream
[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
493 'o','c','t','e','t','-','s','t','r','e','a','m','\0'};
495 static const struct {
497 BOOL (*filter
)(LPVOID
,DWORD
);
499 {wszTextHtml
, text_html_filter
},
500 {wszImageGif
, image_gif_filter
},
501 {wszImagePjpeg
, image_pjpeg_filter
},
502 {wszTextPlain
, text_plain_filter
},
503 {wszAppOctetStream
, application_octet_stream_filter
}
509 if(pwzMimeProposed
&& strcmpW(pwzMimeProposed
, wszAppOctetStream
)) {
510 for(i
=0; i
< sizeof(mime_filters
)/sizeof(*mime_filters
); i
++) {
511 if(!strcmpW(pwzMimeProposed
, mime_filters
[i
].mime
))
515 if(i
== sizeof(mime_filters
)/sizeof(*mime_filters
)
516 || mime_filters
[i
].filter(pBuffer
, cbSize
)) {
517 len
= strlenW(pwzMimeProposed
)+1;
518 *ppwzMimeOut
= CoTaskMemAlloc(len
*sizeof(WCHAR
));
519 memcpy(*ppwzMimeOut
, pwzMimeProposed
, len
*sizeof(WCHAR
));
526 if(mime_filters
[i
].filter(pBuffer
, cbSize
))
527 ret
= mime_filters
[i
].mime
;
531 if(pwzMimeProposed
) {
532 if(i
== sizeof(mime_filters
)/sizeof(*mime_filters
))
533 ret
= pwzMimeProposed
;
535 /* text/html is a special case */
536 if(!strcmpW(pwzMimeProposed
, wszTextHtml
) && !strcmpW(ret
, wszTextPlain
))
540 len
= strlenW(ret
)+1;
541 *ppwzMimeOut
= CoTaskMemAlloc(len
*sizeof(WCHAR
));
542 memcpy(*ppwzMimeOut
, ret
, len
*sizeof(WCHAR
));
552 static const WCHAR wszContentType
[] =
553 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
555 ptr
= strrchrW(pwzUrl
, '.');
559 res
= RegOpenKeyW(HKEY_CLASSES_ROOT
, ptr
, &hkey
);
560 if(res
!= ERROR_SUCCESS
)
564 res
= RegQueryValueExW(hkey
, wszContentType
, NULL
, NULL
, (LPBYTE
)mime
, &size
);
566 if(res
!= ERROR_SUCCESS
)
569 *ppwzMimeOut
= CoTaskMemAlloc(size
);
570 memcpy(*ppwzMimeOut
, mime
, size
);