#include "priv.h" #pragma hdrstop #include "objidl.h" #include "urlmon.h" #include "exdisp.h" // IWebBrowserApp #include "shlobj.h" // IShellBrowser #include "inetreg.h" #include // 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; }