Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenurlmon_main.c
Go to the documentation of this file.
00001 /* 00002 * UrlMon 00003 * 00004 * Copyright (c) 2000 Patrik Stridvall 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <stdarg.h> 00022 00023 #include "urlmon_main.h" 00024 00025 #include "winreg.h" 00026 00027 #define NO_SHLWAPI_REG 00028 #include "shlwapi.h" 00029 #include "advpub.h" 00030 00031 #include "wine/debug.h" 00032 00033 #include "urlmon.h" 00034 00035 WINE_DEFAULT_DEBUG_CHANNEL(urlmon); 00036 00037 LONG URLMON_refCount = 0; 00038 00039 static HMODULE hCabinet = NULL; 00040 static DWORD urlmon_tls = TLS_OUT_OF_INDEXES; 00041 00042 static void init_session(BOOL); 00043 00044 static struct list tls_list = LIST_INIT(tls_list); 00045 00046 static CRITICAL_SECTION tls_cs; 00047 static CRITICAL_SECTION_DEBUG tls_cs_dbg = 00048 { 00049 0, 0, &tls_cs, 00050 { &tls_cs_dbg.ProcessLocksList, &tls_cs_dbg.ProcessLocksList }, 00051 0, 0, { (DWORD_PTR)(__FILE__ ": tls") } 00052 }; 00053 00054 static CRITICAL_SECTION tls_cs = { &tls_cs_dbg, -1, 0, 0, 0, 0 }; 00055 00056 tls_data_t *get_tls_data(void) 00057 { 00058 tls_data_t *data; 00059 00060 if(urlmon_tls == TLS_OUT_OF_INDEXES) { 00061 DWORD tls = TlsAlloc(); 00062 if(tls == TLS_OUT_OF_INDEXES) 00063 return NULL; 00064 00065 tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES); 00066 if(tls != urlmon_tls) 00067 TlsFree(tls); 00068 } 00069 00070 data = TlsGetValue(urlmon_tls); 00071 if(!data) { 00072 data = heap_alloc_zero(sizeof(tls_data_t)); 00073 if(!data) 00074 return NULL; 00075 00076 EnterCriticalSection(&tls_cs); 00077 list_add_tail(&tls_list, &data->entry); 00078 LeaveCriticalSection(&tls_cs); 00079 00080 TlsSetValue(urlmon_tls, data); 00081 } 00082 00083 return data; 00084 } 00085 00086 static void free_tls_list(void) 00087 { 00088 tls_data_t *data; 00089 00090 if(urlmon_tls == TLS_OUT_OF_INDEXES) 00091 return; 00092 00093 while(!list_empty(&tls_list)) { 00094 data = LIST_ENTRY(list_head(&tls_list), tls_data_t, entry); 00095 list_remove(&data->entry); 00096 heap_free(data); 00097 } 00098 00099 TlsFree(urlmon_tls); 00100 } 00101 00102 static void detach_thread(void) 00103 { 00104 tls_data_t *data; 00105 00106 if(urlmon_tls == TLS_OUT_OF_INDEXES) 00107 return; 00108 00109 data = TlsGetValue(urlmon_tls); 00110 if(!data) 00111 return; 00112 00113 EnterCriticalSection(&tls_cs); 00114 list_remove(&data->entry); 00115 LeaveCriticalSection(&tls_cs); 00116 00117 if(data->notif_hwnd) { 00118 WARN("notif_hwnd not destroyed\n"); 00119 DestroyWindow(data->notif_hwnd); 00120 } 00121 00122 heap_free(data); 00123 } 00124 00125 static void process_detach(void) 00126 { 00127 HINTERNET internet_session; 00128 00129 internet_session = get_internet_session(NULL); 00130 if(internet_session) 00131 InternetCloseHandle(internet_session); 00132 00133 if (hCabinet) 00134 FreeLibrary(hCabinet); 00135 00136 init_session(FALSE); 00137 free_session(); 00138 free_tls_list(); 00139 } 00140 00141 /*********************************************************************** 00142 * DllMain (URLMON.init) 00143 */ 00144 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) 00145 { 00146 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad); 00147 00148 URLMON_DllMain( hinstDLL, fdwReason, fImpLoad ); 00149 00150 switch(fdwReason) { 00151 case DLL_PROCESS_ATTACH: 00152 init_session(TRUE); 00153 break; 00154 00155 case DLL_PROCESS_DETACH: 00156 process_detach(); 00157 break; 00158 00159 case DLL_THREAD_DETACH: 00160 detach_thread(); 00161 break; 00162 } 00163 return TRUE; 00164 } 00165 00166 00167 /*********************************************************************** 00168 * DllInstall (URLMON.@) 00169 */ 00170 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline) 00171 { 00172 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE", 00173 debugstr_w(cmdline)); 00174 00175 return S_OK; 00176 } 00177 00178 /*********************************************************************** 00179 * DllCanUnloadNow (URLMON.@) 00180 */ 00181 HRESULT WINAPI DllCanUnloadNow(void) 00182 { 00183 return URLMON_refCount != 0 ? S_FALSE : S_OK; 00184 } 00185 00186 00187 00188 /****************************************************************************** 00189 * Urlmon ClassFactory 00190 */ 00191 typedef struct { 00192 IClassFactory IClassFactory_iface; 00193 00194 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); 00195 } ClassFactory; 00196 00197 static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface) 00198 { 00199 return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface); 00200 } 00201 00202 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv) 00203 { 00204 *ppv = NULL; 00205 00206 if(IsEqualGUID(riid, &IID_IUnknown)) { 00207 TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); 00208 *ppv = iface; 00209 }else if(IsEqualGUID(riid, &IID_IClassFactory)) { 00210 TRACE("(%p)->(IID_IClassFactory %p)\n", iface, ppv); 00211 *ppv = iface; 00212 } 00213 00214 if(*ppv) { 00215 IUnknown_AddRef((IUnknown*)*ppv); 00216 return S_OK; 00217 } 00218 00219 WARN("(%p)->(%s,%p),not found\n", iface, debugstr_guid(riid), ppv); 00220 return E_NOINTERFACE; 00221 } 00222 00223 static ULONG WINAPI CF_AddRef(IClassFactory *iface) 00224 { 00225 URLMON_LockModule(); 00226 return 2; 00227 } 00228 00229 static ULONG WINAPI CF_Release(IClassFactory *iface) 00230 { 00231 URLMON_UnlockModule(); 00232 return 1; 00233 } 00234 00235 00236 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter, 00237 REFIID riid, LPVOID *ppobj) 00238 { 00239 ClassFactory *This = impl_from_IClassFactory(iface); 00240 HRESULT hres; 00241 LPUNKNOWN punk; 00242 00243 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); 00244 00245 *ppobj = NULL; 00246 if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) { 00247 hres = IUnknown_QueryInterface(punk, riid, ppobj); 00248 IUnknown_Release(punk); 00249 } 00250 return hres; 00251 } 00252 00253 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock) 00254 { 00255 TRACE("(%d)\n", dolock); 00256 00257 if (dolock) 00258 URLMON_LockModule(); 00259 else 00260 URLMON_UnlockModule(); 00261 00262 return S_OK; 00263 } 00264 00265 static const IClassFactoryVtbl ClassFactoryVtbl = 00266 { 00267 CF_QueryInterface, 00268 CF_AddRef, 00269 CF_Release, 00270 CF_CreateInstance, 00271 CF_LockServer 00272 }; 00273 00274 static ClassFactory FileProtocolCF = 00275 { { &ClassFactoryVtbl }, FileProtocol_Construct}; 00276 static ClassFactory FtpProtocolCF = 00277 { { &ClassFactoryVtbl }, FtpProtocol_Construct}; 00278 static ClassFactory GopherProtocolCF = 00279 { { &ClassFactoryVtbl }, GopherProtocol_Construct}; 00280 static ClassFactory HttpProtocolCF = 00281 { { &ClassFactoryVtbl }, HttpProtocol_Construct}; 00282 static ClassFactory HttpSProtocolCF = 00283 { { &ClassFactoryVtbl }, HttpSProtocol_Construct}; 00284 static ClassFactory MkProtocolCF = 00285 { { &ClassFactoryVtbl }, MkProtocol_Construct}; 00286 static ClassFactory SecurityManagerCF = 00287 { { &ClassFactoryVtbl }, SecManagerImpl_Construct}; 00288 static ClassFactory ZoneManagerCF = 00289 { { &ClassFactoryVtbl }, ZoneMgrImpl_Construct}; 00290 static ClassFactory StdURLMonikerCF = 00291 { { &ClassFactoryVtbl }, StdURLMoniker_Construct}; 00292 static ClassFactory MimeFilterCF = 00293 { { &ClassFactoryVtbl }, MimeFilter_Construct}; 00294 00295 struct object_creation_info 00296 { 00297 const CLSID *clsid; 00298 IClassFactory *cf; 00299 LPCWSTR protocol; 00300 }; 00301 00302 static const WCHAR wszFile[] = {'f','i','l','e',0}; 00303 static const WCHAR wszFtp[] = {'f','t','p',0}; 00304 static const WCHAR wszGopher[] = {'g','o','p','h','e','r',0}; 00305 static const WCHAR wszHttp[] = {'h','t','t','p',0}; 00306 static const WCHAR wszHttps[] = {'h','t','t','p','s',0}; 00307 static const WCHAR wszMk[] = {'m','k',0}; 00308 00309 static const struct object_creation_info object_creation[] = 00310 { 00311 { &CLSID_FileProtocol, &FileProtocolCF.IClassFactory_iface, wszFile }, 00312 { &CLSID_FtpProtocol, &FtpProtocolCF.IClassFactory_iface, wszFtp }, 00313 { &CLSID_GopherProtocol, &GopherProtocolCF.IClassFactory_iface, wszGopher }, 00314 { &CLSID_HttpProtocol, &HttpProtocolCF.IClassFactory_iface, wszHttp }, 00315 { &CLSID_HttpSProtocol, &HttpSProtocolCF.IClassFactory_iface, wszHttps }, 00316 { &CLSID_MkProtocol, &MkProtocolCF.IClassFactory_iface, wszMk }, 00317 { &CLSID_InternetSecurityManager, &SecurityManagerCF.IClassFactory_iface, NULL }, 00318 { &CLSID_InternetZoneManager, &ZoneManagerCF.IClassFactory_iface, NULL }, 00319 { &CLSID_StdURLMoniker, &StdURLMonikerCF.IClassFactory_iface, NULL }, 00320 { &CLSID_DeCompMimeFilter, &MimeFilterCF.IClassFactory_iface, NULL } 00321 }; 00322 00323 static void init_session(BOOL init) 00324 { 00325 unsigned int i; 00326 00327 for(i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) { 00328 00329 if(object_creation[i].protocol) 00330 register_urlmon_namespace(object_creation[i].cf, object_creation[i].clsid, 00331 object_creation[i].protocol, init); 00332 } 00333 } 00334 00335 /******************************************************************************* 00336 * DllGetClassObject [URLMON.@] 00337 * Retrieves class object from a DLL object 00338 * 00339 * NOTES 00340 * Docs say returns STDAPI 00341 * 00342 * PARAMS 00343 * rclsid [I] CLSID for the class object 00344 * riid [I] Reference to identifier of interface for class object 00345 * ppv [O] Address of variable to receive interface pointer for riid 00346 * 00347 * RETURNS 00348 * Success: S_OK 00349 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG, 00350 * E_UNEXPECTED 00351 */ 00352 00353 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 00354 { 00355 unsigned int i; 00356 HRESULT hr; 00357 00358 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); 00359 00360 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) 00361 { 00362 if (IsEqualGUID(object_creation[i].clsid, rclsid)) 00363 return IClassFactory_QueryInterface(object_creation[i].cf, riid, ppv); 00364 } 00365 00366 hr = URLMON_DllGetClassObject(rclsid, riid, ppv); 00367 if(SUCCEEDED(hr)) 00368 return hr; 00369 00370 FIXME("%s: no class found.\n", debugstr_guid(rclsid)); 00371 return CLASS_E_CLASSNOTAVAILABLE; 00372 } 00373 00374 static HRESULT register_inf(BOOL doregister) 00375 { 00376 HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable); 00377 HMODULE hAdvpack; 00378 00379 static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0}; 00380 00381 hAdvpack = LoadLibraryW(wszAdvpack); 00382 pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall"); 00383 00384 return pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", NULL); 00385 } 00386 00387 /*********************************************************************** 00388 * DllRegisterServer (URLMON.@) 00389 */ 00390 HRESULT WINAPI DllRegisterServer(void) 00391 { 00392 HRESULT hr; 00393 00394 TRACE("\n"); 00395 00396 hr = URLMON_DllRegisterServer(); 00397 return SUCCEEDED(hr) ? register_inf(TRUE) : hr; 00398 } 00399 00400 /*********************************************************************** 00401 * DllUnregisterServer (URLMON.@) 00402 */ 00403 HRESULT WINAPI DllUnregisterServer(void) 00404 { 00405 HRESULT hr; 00406 00407 TRACE("\n"); 00408 00409 hr = URLMON_DllUnregisterServer(); 00410 return SUCCEEDED(hr) ? register_inf(FALSE) : hr; 00411 } 00412 00413 /*********************************************************************** 00414 * DllRegisterServerEx (URLMON.@) 00415 */ 00416 HRESULT WINAPI DllRegisterServerEx(void) 00417 { 00418 FIXME("(void): stub\n"); 00419 00420 return E_FAIL; 00421 } 00422 00423 /************************************************************************** 00424 * IsValidURL (URLMON.@) 00425 * 00426 * Determines if a specified string is a valid URL. 00427 * 00428 * PARAMS 00429 * pBC [I] ignored, should be NULL. 00430 * szURL [I] string that represents the URL in question. 00431 * dwReserved [I] reserved and must be zero. 00432 * 00433 * RETURNS 00434 * Success: S_OK. 00435 * Failure: S_FALSE. 00436 * returns E_INVALIDARG if one or more of the args is invalid. 00437 * 00438 * TODO: 00439 * test functionality against windows to see what a valid URL is. 00440 */ 00441 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved) 00442 { 00443 FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved); 00444 00445 if (dwReserved || !szURL) 00446 return E_INVALIDARG; 00447 00448 return S_OK; 00449 } 00450 00451 /************************************************************************** 00452 * FaultInIEFeature (URLMON.@) 00453 * 00454 * Undocumented. Appears to be used by native shdocvw.dll. 00455 */ 00456 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec, 00457 QUERYCONTEXT *pQuery, DWORD flags ) 00458 { 00459 FIXME("%p %p %p %08x\n", hwnd, pClassSpec, pQuery, flags); 00460 return E_NOTIMPL; 00461 } 00462 00463 /************************************************************************** 00464 * CoGetClassObjectFromURL (URLMON.@) 00465 */ 00466 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS, 00467 DWORD dwFileVersionLS, LPCWSTR szContentType, 00468 LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved, 00469 REFIID riid, LPVOID *ppv ) 00470 { 00471 FIXME("(%s %s %d %d %s %p %d %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL), 00472 dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved, 00473 debugstr_guid(riid), ppv); 00474 return E_NOINTERFACE; 00475 } 00476 00477 /*********************************************************************** 00478 * ReleaseBindInfo (URLMON.@) 00479 * 00480 * Release the resources used by the specified BINDINFO structure. 00481 * 00482 * PARAMS 00483 * pbindinfo [I] BINDINFO to release. 00484 * 00485 * RETURNS 00486 * Nothing. 00487 */ 00488 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo) 00489 { 00490 DWORD size; 00491 00492 TRACE("(%p)\n", pbindinfo); 00493 00494 if(!pbindinfo || !(size = pbindinfo->cbSize)) 00495 return; 00496 00497 CoTaskMemFree(pbindinfo->szExtraInfo); 00498 ReleaseStgMedium(&pbindinfo->stgmedData); 00499 00500 if(offsetof(BINDINFO, szExtraInfo) < size) 00501 CoTaskMemFree(pbindinfo->szCustomVerb); 00502 00503 if(pbindinfo->pUnk && offsetof(BINDINFO, pUnk) < size) 00504 IUnknown_Release(pbindinfo->pUnk); 00505 00506 memset(pbindinfo, 0, size); 00507 pbindinfo->cbSize = size; 00508 } 00509 00510 /*********************************************************************** 00511 * CopyStgMedium (URLMON.@) 00512 */ 00513 HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst) 00514 { 00515 TRACE("(%p %p)\n", src, dst); 00516 00517 if(!src || !dst) 00518 return E_POINTER; 00519 00520 *dst = *src; 00521 00522 switch(dst->tymed) { 00523 case TYMED_NULL: 00524 break; 00525 case TYMED_FILE: 00526 if(src->u.lpszFileName && !src->pUnkForRelease) { 00527 DWORD size = (strlenW(src->u.lpszFileName)+1)*sizeof(WCHAR); 00528 dst->u.lpszFileName = CoTaskMemAlloc(size); 00529 memcpy(dst->u.lpszFileName, src->u.lpszFileName, size); 00530 } 00531 break; 00532 case TYMED_ISTREAM: 00533 if(dst->u.pstm) 00534 IStream_AddRef(dst->u.pstm); 00535 break; 00536 case TYMED_ISTORAGE: 00537 if(dst->u.pstg) 00538 IStorage_AddRef(dst->u.pstg); 00539 break; 00540 default: 00541 FIXME("Unimplemented tymed %d\n", src->tymed); 00542 } 00543 00544 if(dst->pUnkForRelease) 00545 IUnknown_AddRef(dst->pUnkForRelease); 00546 00547 return S_OK; 00548 } 00549 00550 static BOOL text_richtext_filter(const BYTE *b, DWORD size) 00551 { 00552 return size > 5 && !memcmp(b, "{\\rtf", 5); 00553 } 00554 00555 static BOOL text_html_filter(const BYTE *b, DWORD size) 00556 { 00557 DWORD i; 00558 00559 if(size < 5) 00560 return FALSE; 00561 00562 for(i=0; i < size-5; i++) { 00563 if(b[i] == '<' 00564 && (b[i+1] == 'h' || b[i+1] == 'H') 00565 && (b[i+2] == 't' || b[i+2] == 'T') 00566 && (b[i+3] == 'm' || b[i+3] == 'M') 00567 && (b[i+4] == 'l' || b[i+4] == 'L')) 00568 return TRUE; 00569 } 00570 00571 return FALSE; 00572 } 00573 00574 static BOOL audio_basic_filter(const BYTE *b, DWORD size) 00575 { 00576 return size > 4 00577 && b[0] == '.' && b[1] == 's' && b[2] == 'n' && b[3] == 'd'; 00578 } 00579 00580 static BOOL audio_wav_filter(const BYTE *b, DWORD size) 00581 { 00582 return size > 12 00583 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F' 00584 && b[8] == 'W' && b[9] == 'A' && b[10] == 'V' && b[11] == 'E'; 00585 } 00586 00587 static BOOL image_gif_filter(const BYTE *b, DWORD size) 00588 { 00589 return size >= 6 00590 && (b[0] == 'G' || b[0] == 'g') 00591 && (b[1] == 'I' || b[1] == 'i') 00592 && (b[2] == 'F' || b[2] == 'f') 00593 && b[3] == '8' 00594 && (b[4] == '7' || b[4] == '9') 00595 && (b[5] == 'A' || b[5] == 'a'); 00596 } 00597 00598 static BOOL image_pjpeg_filter(const BYTE *b, DWORD size) 00599 { 00600 return size > 2 && b[0] == 0xff && b[1] == 0xd8; 00601 } 00602 00603 static BOOL image_tiff_filter(const BYTE *b, DWORD size) 00604 { 00605 return size > 2 && b[0] == 0x4d && b[1] == 0x4d; 00606 } 00607 00608 static BOOL image_xpng_filter(const BYTE *b, DWORD size) 00609 { 00610 static const BYTE xpng_header[] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a}; 00611 return size > sizeof(xpng_header) && !memcmp(b, xpng_header, sizeof(xpng_header)); 00612 } 00613 00614 static BOOL image_bmp_filter(const BYTE *b, DWORD size) 00615 { 00616 return size >= 14 00617 && b[0] == 0x42 && b[1] == 0x4d 00618 && *(const DWORD *)(b+6) == 0; 00619 } 00620 00621 static BOOL video_avi_filter(const BYTE *b, DWORD size) 00622 { 00623 return size > 12 00624 && b[0] == 'R' && b[1] == 'I' && b[2] == 'F' && b[3] == 'F' 00625 && b[8] == 'A' && b[9] == 'V' && b[10] == 'I' && b[11] == 0x20; 00626 } 00627 00628 static BOOL video_mpeg_filter(const BYTE *b, DWORD size) 00629 { 00630 return size > 4 00631 && !b[0] && !b[1] && b[2] == 0x01 00632 && (b[3] == 0xb3 || b[3] == 0xba); 00633 } 00634 00635 static BOOL application_postscript_filter(const BYTE *b, DWORD size) 00636 { 00637 return size > 2 && b[0] == '%' && b[1] == '!'; 00638 } 00639 00640 static BOOL application_pdf_filter(const BYTE *b, DWORD size) 00641 { 00642 return size > 4 && b[0] == 0x25 && b[1] == 0x50 && b[2] == 0x44 && b[3] == 0x46; 00643 } 00644 00645 static BOOL application_xzip_filter(const BYTE *b, DWORD size) 00646 { 00647 return size > 2 && b[0] == 0x50 && b[1] == 0x4b; 00648 } 00649 00650 static BOOL application_xgzip_filter(const BYTE *b, DWORD size) 00651 { 00652 return size > 2 && b[0] == 0x1f && b[1] == 0x8b; 00653 } 00654 00655 static BOOL application_java_filter(const BYTE *b, DWORD size) 00656 { 00657 return size > 4 && b[0] == 0xca && b[1] == 0xfe && b[2] == 0xba && b[3] == 0xbe; 00658 } 00659 00660 static BOOL application_xmsdownload(const BYTE *b, DWORD size) 00661 { 00662 return size > 2 && b[0] == 'M' && b[1] == 'Z'; 00663 } 00664 00665 static BOOL text_plain_filter(const BYTE *b, DWORD size) 00666 { 00667 const BYTE *ptr; 00668 00669 for(ptr = b; ptr < b+size-1; ptr++) { 00670 if(*ptr < 0x20 && *ptr != '\n' && *ptr != '\r' && *ptr != '\t') 00671 return FALSE; 00672 } 00673 00674 return TRUE; 00675 } 00676 00677 static BOOL application_octet_stream_filter(const BYTE *b, DWORD size) 00678 { 00679 return TRUE; 00680 } 00681 00682 static HRESULT find_mime_from_buffer(const BYTE *buf, DWORD size, const WCHAR *proposed_mime, WCHAR **ret_mime) 00683 { 00684 LPCWSTR ret = NULL; 00685 DWORD len, i; 00686 00687 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0}; 00688 static const WCHAR text_richtextW[] = {'t','e','x','t','/','r','i','c','h','t','e','x','t',0}; 00689 static const WCHAR audio_basicW[] = {'a','u','d','i','o','/','b','a','s','i','c',0}; 00690 static const WCHAR audio_wavW[] = {'a','u','d','i','o','/','w','a','v',0}; 00691 static const WCHAR image_gifW[] = {'i','m','a','g','e','/','g','i','f',0}; 00692 static const WCHAR image_pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0}; 00693 static const WCHAR image_tiffW[] = {'i','m','a','g','e','/','t','i','f','f',0}; 00694 static const WCHAR image_xpngW[] = {'i','m','a','g','e','/','x','-','p','n','g',0}; 00695 static const WCHAR image_bmpW[] = {'i','m','a','g','e','/','b','m','p',0}; 00696 static const WCHAR video_aviW[] = {'v','i','d','e','o','/','a','v','i',0}; 00697 static const WCHAR video_mpegW[] = {'v','i','d','e','o','/','m','p','e','g',0}; 00698 static const WCHAR app_postscriptW[] = 00699 {'a','p','p','l','i','c','a','t','i','o','n','/','p','o','s','t','s','c','r','i','p','t',0}; 00700 static const WCHAR app_pdfW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','p','d','f',0}; 00701 static const WCHAR app_xzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 00702 'x','-','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0}; 00703 static const WCHAR app_xgzipW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 00704 'x','-','g','z','i','p','-','c','o','m','p','r','e','s','s','e','d',0}; 00705 static const WCHAR app_javaW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 00706 'j','a','v','a',0}; 00707 static const WCHAR app_xmsdownloadW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 00708 'x','-','m','s','d','o','w','n','l','o','a','d',0}; 00709 static const WCHAR text_plainW[] = {'t','e','x','t','/','p','l','a','i','n','\0'}; 00710 static const WCHAR app_octetstreamW[] = {'a','p','p','l','i','c','a','t','i','o','n','/', 00711 'o','c','t','e','t','-','s','t','r','e','a','m','\0'}; 00712 00713 static const struct { 00714 LPCWSTR mime; 00715 BOOL (*filter)(const BYTE *,DWORD); 00716 } mime_filters[] = { 00717 {text_htmlW, text_html_filter}, 00718 {text_richtextW, text_richtext_filter}, 00719 /* {audio_xaiffW, audio_xaiff_filter}, */ 00720 {audio_basicW, audio_basic_filter}, 00721 {audio_wavW, audio_wav_filter}, 00722 {image_gifW, image_gif_filter}, 00723 {image_pjpegW, image_pjpeg_filter}, 00724 {image_tiffW, image_tiff_filter}, 00725 {image_xpngW, image_xpng_filter}, 00726 /* {image_xbitmapW, image_xbitmap_filter}, */ 00727 {image_bmpW, image_bmp_filter}, 00728 /* {image_xjgW, image_xjg_filter}, */ 00729 /* {image_xemfW, image_xemf_filter}, */ 00730 /* {image_xwmfW, image_xwmf_filter}, */ 00731 {video_aviW, video_avi_filter}, 00732 {video_mpegW, video_mpeg_filter}, 00733 {app_postscriptW, application_postscript_filter}, 00734 /* {app_base64W, application_base64_filter}, */ 00735 /* {app_macbinhex40W, application_macbinhex40_filter}, */ 00736 {app_pdfW, application_pdf_filter}, 00737 /* {app_zcompressedW, application_xcompressed_filter}, */ 00738 {app_xzipW, application_xzip_filter}, 00739 {app_xgzipW, application_xgzip_filter}, 00740 {app_javaW, application_java_filter}, 00741 {app_xmsdownloadW, application_xmsdownload}, 00742 {text_plainW, text_plain_filter}, 00743 {app_octetstreamW, application_octet_stream_filter} 00744 }; 00745 00746 if(!buf || !size) { 00747 if(!proposed_mime) 00748 return E_FAIL; 00749 00750 len = strlenW(proposed_mime)+1; 00751 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR)); 00752 if(!*ret_mime) 00753 return E_OUTOFMEMORY; 00754 00755 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR)); 00756 return S_OK; 00757 } 00758 00759 if(proposed_mime && strcmpW(proposed_mime, app_octetstreamW)) { 00760 for(i=0; i < sizeof(mime_filters)/sizeof(*mime_filters); i++) { 00761 if(!strcmpW(proposed_mime, mime_filters[i].mime)) 00762 break; 00763 } 00764 00765 if(i == sizeof(mime_filters)/sizeof(*mime_filters) || mime_filters[i].filter(buf, size)) { 00766 len = strlenW(proposed_mime)+1; 00767 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR)); 00768 if(!*ret_mime) 00769 return E_OUTOFMEMORY; 00770 00771 memcpy(*ret_mime, proposed_mime, len*sizeof(WCHAR)); 00772 return S_OK; 00773 } 00774 } 00775 00776 i=0; 00777 while(!ret) { 00778 if(mime_filters[i].filter(buf, size)) 00779 ret = mime_filters[i].mime; 00780 i++; 00781 } 00782 00783 TRACE("found %s for %s\n", debugstr_w(ret), debugstr_an((const char*)buf, min(32, size))); 00784 00785 if(proposed_mime) { 00786 if(i == sizeof(mime_filters)/sizeof(*mime_filters)) 00787 ret = proposed_mime; 00788 00789 /* text/html is a special case */ 00790 if(!strcmpW(proposed_mime, text_htmlW) && !strcmpW(ret, text_plainW)) 00791 ret = text_htmlW; 00792 } 00793 00794 len = strlenW(ret)+1; 00795 *ret_mime = CoTaskMemAlloc(len*sizeof(WCHAR)); 00796 if(!*ret_mime) 00797 return E_OUTOFMEMORY; 00798 00799 memcpy(*ret_mime, ret, len*sizeof(WCHAR)); 00800 return S_OK; 00801 } 00802 00803 /*********************************************************************** 00804 * FindMimeFromData (URLMON.@) 00805 * 00806 * Determines the Multipurpose Internet Mail Extensions (MIME) type from the data provided. 00807 */ 00808 HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer, 00809 DWORD cbSize, LPCWSTR pwzMimeProposed, DWORD dwMimeFlags, 00810 LPWSTR* ppwzMimeOut, DWORD dwReserved) 00811 { 00812 TRACE("(%p,%s,%p,%d,%s,0x%x,%p,0x%x)\n", pBC, debugstr_w(pwzUrl), pBuffer, cbSize, 00813 debugstr_w(pwzMimeProposed), dwMimeFlags, ppwzMimeOut, dwReserved); 00814 00815 if(dwMimeFlags) 00816 WARN("dwMimeFlags=%08x\n", dwMimeFlags); 00817 if(dwReserved) 00818 WARN("dwReserved=%d\n", dwReserved); 00819 00820 /* pBC seams to not be used */ 00821 00822 if(!ppwzMimeOut || (!pwzUrl && !pBuffer)) 00823 return E_INVALIDARG; 00824 00825 if(pwzMimeProposed || pBuffer) 00826 return find_mime_from_buffer(pBuffer, cbSize, pwzMimeProposed, ppwzMimeOut); 00827 00828 if(pwzUrl) { 00829 HKEY hkey; 00830 DWORD res, size; 00831 LPCWSTR ptr; 00832 WCHAR mime[64]; 00833 00834 static const WCHAR wszContentType[] = 00835 {'C','o','n','t','e','n','t',' ','T','y','p','e','\0'}; 00836 00837 ptr = strrchrW(pwzUrl, '.'); 00838 if(!ptr) 00839 return E_FAIL; 00840 00841 res = RegOpenKeyW(HKEY_CLASSES_ROOT, ptr, &hkey); 00842 if(res != ERROR_SUCCESS) 00843 return HRESULT_FROM_WIN32(res); 00844 00845 size = sizeof(mime); 00846 res = RegQueryValueExW(hkey, wszContentType, NULL, NULL, (LPBYTE)mime, &size); 00847 RegCloseKey(hkey); 00848 if(res != ERROR_SUCCESS) 00849 return HRESULT_FROM_WIN32(res); 00850 00851 *ppwzMimeOut = CoTaskMemAlloc(size); 00852 memcpy(*ppwzMimeOut, mime, size); 00853 return S_OK; 00854 } 00855 00856 return E_FAIL; 00857 } 00858 00859 /*********************************************************************** 00860 * GetClassFileOrMime (URLMON.@) 00861 * 00862 * Determines the class ID from the bind context, file name or MIME type. 00863 */ 00864 HRESULT WINAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pszFilename, 00865 LPVOID pBuffer, DWORD cbBuffer, LPCWSTR pszMimeType, DWORD dwReserved, 00866 CLSID *pclsid) 00867 { 00868 FIXME("(%p, %s, %p, %d, %p, 0x%08x, %p): stub\n", pBC, 00869 debugstr_w(pszFilename), pBuffer, cbBuffer, debugstr_w(pszMimeType), 00870 dwReserved, pclsid); 00871 return E_NOTIMPL; 00872 } 00873 00874 /*********************************************************************** 00875 * Extract (URLMON.@) 00876 */ 00877 HRESULT WINAPI Extract(void *dest, LPCSTR szCabName) 00878 { 00879 HRESULT (WINAPI *pExtract)(void *, LPCSTR); 00880 00881 if (!hCabinet) 00882 hCabinet = LoadLibraryA("cabinet.dll"); 00883 00884 if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError()); 00885 pExtract = (void *)GetProcAddress(hCabinet, "Extract"); 00886 if (!pExtract) return HRESULT_FROM_WIN32(GetLastError()); 00887 00888 return pExtract(dest, szCabName); 00889 } 00890 00891 /*********************************************************************** 00892 * IsLoggingEnabledA (URLMON.@) 00893 */ 00894 BOOL WINAPI IsLoggingEnabledA(LPCSTR url) 00895 { 00896 FIXME("(%s)\n", debugstr_a(url)); 00897 return FALSE; 00898 } 00899 00900 /*********************************************************************** 00901 * IsLoggingEnabledW (URLMON.@) 00902 */ 00903 BOOL WINAPI IsLoggingEnabledW(LPCWSTR url) 00904 { 00905 FIXME("(%s)\n", debugstr_w(url)); 00906 return FALSE; 00907 } 00908 00909 /*********************************************************************** 00910 * URLMON_410 (URLMON.410) 00911 * Undocumented, added in IE8 00912 */ 00913 BOOL WINAPI URLMON_410(DWORD unknown1, DWORD unknown2) 00914 { 00915 FIXME("stub: %d %d\n", unknown1, unknown2); 00916 return FALSE; 00917 } 00918 00919 /*********************************************************************** 00920 * URLMON_423 (URLMON.423) 00921 * Undocumented, added in IE8 00922 */ 00923 BOOL WINAPI URLMON_423(DWORD unknown1, DWORD unknown2, DWORD unknown3, DWORD unknown4) 00924 { 00925 FIXME("stub: %d %d %d %d\n", unknown1, unknown2, unknown3, unknown4); 00926 return FALSE; 00927 } Generated on Sat May 26 2012 04:25:17 for ReactOS by
1.7.6.1
|