ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

urlmon_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.