|
|
#include "priv.h"
#pragma hdrstop
#include "objidl.h"
#include "urlmon.h"
#include "exdisp.h" // IWebBrowserApp
#include "shlobj.h" // IShellBrowser
#include "inetreg.h"
#include <mlang.h>
// Internal helper functions
HRESULT wrap_CreateFormatEnumerator( UINT cfmtetc, FORMATETC* rgfmtetc, IEnumFORMATETC** ppenumfmtetc); HRESULT wrap_RegisterFormatEnumerator(LPBC pBC, IEnumFORMATETC *pEFetc, DWORD reserved); STDAPI common_GetAcceptLanguages(CHAR *psz, LPDWORD pcch);
#define SETFMTETC(p, a) {(p)->cfFormat = (a); \
(p)->dwAspect = DVASPECT_CONTENT; \ (p)->lindex = -1; \ (p)->tymed = TYMED_ISTREAM; \ (p)->ptd = NULL;}
const SA_BSTRGUID s_sstrEFM = { 38 * sizeof(WCHAR), L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}" };
STDAPI CreateDefaultAcceptHeaders(VARIANT* pvar, IWebBrowserApp* pdie) { IEnumFORMATETC* pEFM; HKEY hkey; HRESULT hr = S_OK;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Accepted Documents"), 0, KEY_READ, &hkey) == ERROR_SUCCESS) { DWORD iValue = 0; DWORD iValidEntries = 0; TCHAR szValueName[128]; DWORD cchValueName = ARRAYSIZE(szValueName); DWORD dwType;
// Count the types in the registry
while (RegEnumValue(hkey, iValue++, szValueName, &cchValueName, NULL, &dwType, NULL, NULL)==ERROR_SUCCESS) { // purpose is to increment iValue
cchValueName = ARRAYSIZE(szValueName); }
// Previous loop ends +1, so no need to add +1 for CF_NULL
FORMATETC *prgfmtetc = (FORMATETC *)LocalAlloc(LPTR, iValue * sizeof(FORMATETC)); if (prgfmtetc) { FORMATETC *pcurfmtetc = prgfmtetc; for (DWORD nValue=0; SUCCEEDED(hr) && (nValue < (iValue -1)); nValue++) { TCHAR szFormatName[128]; DWORD cchFormatName = ARRAYSIZE(szFormatName);
cchValueName = ARRAYSIZE(szValueName); if (RegEnumValue(hkey, nValue, szValueName, &cchValueName, NULL, &dwType, (LPBYTE) szFormatName, &cchFormatName)==ERROR_SUCCESS) { pcurfmtetc->cfFormat = (CLIPFORMAT) RegisterClipboardFormat(szFormatName); if (pcurfmtetc->cfFormat) { SETFMTETC (pcurfmtetc, pcurfmtetc->cfFormat); pcurfmtetc++; // move to next fmtetc
iValidEntries++; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } } // if RegEnum
} // for nValue
if (SUCCEEDED(hr)) { // for the last pcurfmtetc, we fill in for CF_NULL
// no need to do RegisterClipboardFormat("*/*")
SETFMTETC(pcurfmtetc, CF_NULL); iValidEntries++; hr = wrap_CreateFormatEnumerator (iValidEntries, prgfmtetc, &pEFM); if (SUCCEEDED(hr)) { ASSERT(pvar->vt == VT_EMPTY); pvar->vt = VT_UNKNOWN; pvar->punkVal = (IUnknown *)pEFM; hr = pdie->PutProperty((BSTR)s_sstrEFM.wsz, *pvar); if (FAILED(hr)) { pEFM->Release(); // if we failed to pass ownership on, free EFM
pvar->vt = VT_EMPTY; pvar->punkVal = NULL; } } } LocalFree (prgfmtetc); } else { hr = E_OUTOFMEMORY; }
RegCloseKey(hkey); } else { DebugMsg(TF_ERROR, TEXT("RegOpenkey failed!")); hr = E_FAIL; }
return hr; }
STDAPI RegisterDefaultAcceptHeaders(IBindCtx* pbc, LPSHELLBROWSER psb) { IEnumFORMATETC* pEFM; IWebBrowserApp* pdie;
ASSERT(pbc); ASSERT(psb); HRESULT hres = IUnknown_QueryService(psb, IID_IWebBrowserApp, IID_IWebBrowserApp, (LPVOID*)&pdie); if (SUCCEEDED(hres)) { VARIANT var; hres = pdie->GetProperty((BSTR)s_sstrEFM.wsz, &var); if (SUCCEEDED(hres)) { if (var.vt == VT_EMPTY) { #ifdef FULL_DEBUG
DebugMsg(DM_TRACE, TEXT("RegisterDefaultAcceptHeaders var.vt == VT_EMPTY")); #endif
CreateDefaultAcceptHeaders(&var, pdie); } else if (var.vt == VT_UNKNOWN) { #ifdef FULL_DEBUG
DebugMsg(DM_TRACE, TEXT("RegisterDefaultAcceptHeaders var.vt == VT_UNKNOWN")); #endif
hres = var.punkVal->QueryInterface(IID_IEnumFORMATETC, (LPVOID*)&pEFM); if (SUCCEEDED(hres)) { IEnumFORMATETC* pEFMClone = NULL; hres = pEFM->Clone(&pEFMClone); if (SUCCEEDED(hres)) { #ifdef FULL_DEBUG
DebugMsg(DM_TRACE, TEXT("RegisterDefaultAcceptHeaders registering FormatEnum %x"), pEFMClone); #endif
hres = wrap_RegisterFormatEnumerator(pbc, pEFMClone, 0); pEFMClone->Release(); } else { DebugMsg(TF_ERROR, TEXT("RegisterDefaultAcceptHeaders Clone failed %x"), hres); } pEFM->Release(); } } else { DebugMsg(TF_ERROR, TEXT("GetProperty() returned illegal Variant Type: %x"), var.vt); DebugMsg(TF_ERROR, TEXT("RegisterDefaultAcceptHeaders not registering FormatEnum")); }
VariantClear(&var); } else { DebugMsg(TF_ERROR, TEXT("RegisterDefaultAcceptHeaders pdie->GetProperty() failed %x"), hres); }
pdie->Release(); } else { DebugMsg(TF_ERROR, TEXT("RegisterDefaultAcceptHeaders QueryService(ISP) failed %x"), hres); }
return hres; } // RegisterDefaultAcceptHeaders
STDAPI GetAcceptLanguagesA(LPSTR pszLanguages, LPDWORD pcchLanguages) { return common_GetAcceptLanguages(pszLanguages, pcchLanguages); } // GetAcceptLanguagesA
STDAPI GetAcceptLanguagesW(LPWSTR pwzLanguages, LPDWORD pcchLanguages) { if (!pwzLanguages || !pcchLanguages || !*pcchLanguages) return E_FAIL;
DWORD dwcchMaxOut = *pcchLanguages;
LPSTR psz = (LPSTR) LocalAlloc (LPTR, dwcchMaxOut); if (!psz) return E_OUTOFMEMORY;
HRESULT hr = common_GetAcceptLanguages(psz, &dwcchMaxOut); if (SUCCEEDED(hr)) { *pcchLanguages = MultiByteToWideChar(CP_ACP, 0, psz, -1, pwzLanguages, *pcchLanguages - 1);
pwzLanguages[*pcchLanguages] = 0; }
LocalFree(psz); return hr; } // GetAcceptLanguagesW
STDAPI common_GetAcceptLanguages(CHAR *psz, LPDWORD pcch) { HKEY hk; HRESULT hr = E_FAIL;
if (!psz || !pcch || !*pcch) return hr;
if ((RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_INTERNATIONAL, 0, KEY_READ, &hk) == ERROR_SUCCESS) && hk) { DWORD dwType;
// pcch == pcb
if (RegQueryValueEx(hk, REGSTR_VAL_ACCEPT_LANGUAGE, NULL, &dwType, (UCHAR *)psz, pcch) != ERROR_SUCCESS) {
// When there is no AcceptLanguage key, we have to default
DWORD LCID = GetUserDefaultLCID();
// Use MLang for RFC1766 language name
hr = LcidToRfc1766A(LCID, psz, *pcch); if (S_OK == hr) *pcch = lstrlenA(psz); else { *pcch = 0; AssertMsg(FALSE, TEXT("We should add LCID 0x%lx to MLang RFC1766 table"), LCID); } } else { hr = S_OK; if (!*psz) { // A NULL AcceptLanguage means send no A-L: header
hr = S_FALSE; } }
RegCloseKey (hk); }
return hr; } // w_GetAcceptLanguages
//
// Both of these functions will be called only once per browser session - the
// first time we create the FormatEnumerator. After that, we will use the one
// we created, rather than needing to call these to allocate a new one.
//
HRESULT wrap_RegisterFormatEnumerator(LPBC pBC, IEnumFORMATETC *pEFetc, DWORD reserved) { HRESULT hr = E_FAIL; HINSTANCE hurl = LoadLibrary(TEXT("URLMON.DLL")); if (hurl) { HRESULT (*pfnRFE)(LPBC pBC, IEnumFORMATETC * pEFetc, DWORD reserved);
pfnRFE = (HRESULT (*)(LPBC, IEnumFORMATETC*, DWORD))GetProcAddress (hurl, "RegisterFormatEnumerator"); if (pfnRFE) { hr = pfnRFE(pBC, pEFetc, reserved); }
FreeLibrary(hurl); }
return hr; }
HRESULT wrap_CreateFormatEnumerator(UINT cfmtetc, FORMATETC* rgfmtetc, IEnumFORMATETC** ppenumfmtetc) { HRESULT hr = E_FAIL; HINSTANCE hurl = LoadLibrary(TEXT("URLMON.DLL")); if (hurl) { HRESULT (*pfnCFE)(UINT cfmtetc, FORMATETC* rgfmtetc, IEnumFORMATETC **ppenumfmtetc);
pfnCFE = (HRESULT (*)(UINT, FORMATETC*, IEnumFORMATETC **))GetProcAddress (hurl, "CreateFormatEnumerator"); if (pfnCFE) { hr = pfnCFE(cfmtetc, rgfmtetc, ppenumfmtetc); }
FreeLibrary(hurl); }
return hr; }
|