windows-nt/Source/XPSP1/NT/shell/shlwapi/httpfnc.cpp
2020-09-26 16:20:57 +08:00

304 lines
9.4 KiB
C++

#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 (RegOpenKey(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Accepted Documents"),
&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 ((RegOpenKey (HKEY_CURRENT_USER, REGSTR_PATH_INTERNATIONAL, &hk) == ERROR_SUCCESS) && hk)
{
DWORD dwType;
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;
}