windows-nt/Source/XPSP1/NT/shell/shdocvw/opsprof.cpp

2785 lines
82 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//
// COPSProfile implementation
//
#include "priv.h"
#include "sccls.h"
#include "hlframe.h"
#include "mshtmdid.h"
#include "wtypes.h"
#include "shlwapi.h"
#include "resource.h"
#include "iehelpid.h"
#include <mluisupp.h>
// Definitions copied from WININET
#define COOKIES_WARN 0 // warn with a dlg if using cookies
#define COOKIES_ALLOW 1 // allow cookies without any warning
#define COOKIES_DENY 2 // disable cookies completely
#ifndef VARIANT_TRUE
#define VARIANT_TRUE ((VARIANT_BOOL)-1) // TRUE for VARIANT_BOOL
#endif
#ifndef VARIANT_FALSE
#define VARIANT_FALSE ((VARIANT_BOOL)0) // FALSE for VARIANT_BOOL
#endif
#define EMPTY_STRINGA(s) ( !s || (s)[0] == '\0' )
#define EMPTY_STRINGW(s) ( !s || (s)[0] == L'\0' )
#ifdef UNICODE
#define EMPTY_STRING(s) EMPTY_STRINGW(s)
#else
#define EMPTY_STRING(s) EMPTY_STRINGA(s)
#endif
// Max number of characters in a friendly OPS attribute name.
const int MAX_PROFILE_NAME = 128;
// Constant non-localizable string definitions
const TCHAR rgszP3Global[] = TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\Security\\P3Global");
const TCHAR rgszP3Sites[] = TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\Security\\P3Sites");
const TCHAR rgszInetKey[] = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
const TCHAR rgszPathTxt[] = TEXT("Path");
const TCHAR rgszDomainTxt[] = TEXT("Domain");
const TCHAR rgszAllowTxt[] = TEXT("Allow");
const TCHAR rgszDenyTxt[] = TEXT("Deny");
const TCHAR rgszExpireTxt[] = TEXT("Expiration");
const TCHAR rgszCookieTxt[] = TEXT("AllowCookies");
const TCHAR rgszEnabled[] = TEXT("Enabled");
const TCHAR rgszRegKey[] = TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\P3\\Write");
const TCHAR rgszRegTxt[] = TEXT("Registration");
const TCHAR GENDER_UNSPECIFIED[] = TEXT("U");
const TCHAR GENDER_FEMALE[] = TEXT("F");
const TCHAR GENDER_MALE[] = TEXT("M");
const WCHAR GENDER_FEMALE_W[] = L"F";
const WCHAR GENDER_MALE_W[] = L"M";
#ifdef _USE_PSTORE_
// {647EC150-DC4A-11d0-A02C-00C0DFA9C763}
EXTERN_C const GUID GUID_PStoreType = { 0x647ec150, 0xdc4a, 0x11d0, { 0xa0, 0x2c, 0x0, 0xc0, 0xdf, 0xa9, 0xc7, 0x63 } };
PST_KEY s_Key = PST_KEY_CURRENT_USER;
#endif // _USE_PSTORE_
// Static helper functions
static WCHAR* _GetNameFromAttrIndex ( int index );
static INT _GetResourceIdFromAttrIndex( int index );
static ULONG _GetPropTagFromAttrIndex( int index );
// This table maintains the list of the suffixes for the Standard OPS attributes
// The names are intentionally kept here because these should not be localized.
struct _ProfileAttribute
{
WCHAR * pwzName;
int id; // resource ID for the friendly name of the attribute.
ULONG ulPropTag;
};
const _ProfileAttribute rgProfAttr [] =
{
{ L"Vcard.DisplayName", IDS_OPS_COMMONNAME, PR_DISPLAY_NAME },
{ L"Vcard.FirstName", IDS_OPS_GIVENNAME, PR_GIVEN_NAME },
{ L"Vcard.LastName", IDS_OPS_LASTNAME, PR_SURNAME },
{ L"Vcard.MiddleName", IDS_OPS_MIDDLENAME, PR_MIDDLE_NAME },
// 0, 1, 2 for Unspecified, Female, Male
{ L"Vcard.Gender", IDS_OPS_GENDER, PR_GENDER },
{ L"Vcard.Cellular", IDS_OPS_CELLULAR, PR_CELLULAR_TELEPHONE_NUMBER},
{ L"Vcard.Email", IDS_OPS_EMAIL, PR_EMAIL_ADDRESS },
{ L"Vcard.HomePage", IDS_OPS_URL, PR_PERSONAL_HOME_PAGE },
{ L"Vcard.Company", IDS_OPS_COMPANY, PR_COMPANY_NAME },
{ L"Vcard.Department", IDS_OPS_DEPARTMENT, PR_DEPARTMENT_NAME },
{ L"Vcard.Office", IDS_OPS_OFFICE, PR_OFFICE_LOCATION, },
{ L"Vcard.JobTitle", IDS_OPS_JOBTITLE, PR_TITLE },
{ L"Vcard.Pager", IDS_OPS_PAGER, PR_PAGER_TELEPHONE_NUMBER },
{ L"Vcard.Home.StreetAddress", IDS_OPS_HOME_ADDRESS, PR_HOME_ADDRESS_STREET },
{ L"Vcard.Home.City", IDS_OPS_HOME_CITY, PR_HOME_ADDRESS_CITY },
{ L"Vcard.Home.ZipCode", IDS_OPS_HOME_ZIPCODE, PR_HOME_ADDRESS_POSTAL_CODE },
{ L"Vcard.Home.State", IDS_OPS_HOME_STATE, PR_HOME_ADDRESS_STATE_OR_PROVINCE },
{ L"Vcard.Home.Country", IDS_OPS_HOME_COUNTRY, PR_HOME_ADDRESS_COUNTRY },
{ L"Vcard.Home.Phone", IDS_OPS_HOME_PHONE, PR_HOME_TELEPHONE_NUMBER },
{ L"Vcard.Home.Fax", IDS_OPS_HOME_FAX, PR_HOME_FAX_NUMBER },
{ L"Vcard.Business.StreetAddress", IDS_OPS_BUSINESS_ADDRESS, PR_BUSINESS_ADDRESS_STREET },
{ L"Vcard.Business.City", IDS_OPS_BUSINESS_CITY, PR_BUSINESS_ADDRESS_CITY },
{ L"Vcard.Business.Zipcode", IDS_OPS_BUSINESS_ZIPCODE, PR_BUSINESS_ADDRESS_POSTAL_CODE},
{ L"Vcard.Business.State", IDS_OPS_BUSINESS_STATE, PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE},
{ L"Vcard.Business.Country", IDS_OPS_BUSINESS_COUNTRY, PR_BUSINESS_ADDRESS_COUNTRY },
{ L"Vcard.Business.Phone", IDS_OPS_BUSINESS_PHONE, PR_BUSINESS_TELEPHONE_NUMBER},
{ L"Vcard.Business.Fax", IDS_OPS_BUSINESS_FAX, PR_BUSINESS_FAX_NUMBER },
{ L"Vcard.Business.URL", IDS_OPS_BUSINESS_URL, PR_BUSINESS_HOME_PAGE },
};
// A sentinel value returned for unsuccessful searches
const int INVALID_ATTRIBUTE_INDEX = 0xFFFFFFFF;
// Compute the number of bytes necessary to hold a bit-vector for the
// Vcard schema where each attribute is represented by one bit.
const DWORD dwVcardCount = ARRAYSIZE(rgProfAttr);
const DWORD dwVcardBytes = (dwVcardCount+7) / 8;
const DWORD defExpireDays = 7; // Default expiration time in days
const DWORD maxExpireDays = 30; // Maximum allowed expiration period
// Number of 100-ns intervals per day
const __int64 intervalsPerDay = (__int64) 10000000 * 3600 * 24;
// Default and maximum expiration time in units of 100 nanoseconds
// (This is the format used for the FILETIME structure)
const __int64 defExpiration = defExpireDays * intervalsPerDay;
const __int64 maxExpiration = maxExpireDays * intervalsPerDay;
// Context-sensitive help IDS
const DWORD aHelpIDs[] =
{
IDC_OPS_INFO_REQUESTED, IDH_PA_OPS_REQUEST,
IDC_OPS_URL, IDH_PA_OPS_REQUEST,
IDC_SITE_IDENTITY, IDH_PA_OPS_REQUEST,
IDC_OPS_LIST, IDH_PA_OPS_LIST,
IDC_USAGE_STRING, IDH_PA_USAGE_STRING,
IDC_VIEW_CERT, IDH_PA_VIEW_CERT,
IDC_EDIT_PROFILE, IDH_EDIT_PROFILE_BTN,
IDC_OPS_PRIVACY, IDH_PA_CONNECTION_SECURITY,
IDC_SECURITY_ICON, IDH_PA_CONNECTION_SECURITY,
IDC_SECURE_CONNECTION, IDH_PA_CONNECTION_SECURITY,
IDC_UNSECURE_CONNECTION, IDH_PA_CONNECTION_SECURITY,
IDC_KEEP_SETTINGS, IDH_PA_ALWAYS_SHARE,
0, 0
};
WCHAR* _GetNameFromAttrIndex ( int index )
{
// Assert that the index is valid.
ASSERT(index>=0 && index<ARRAYSIZE(rgProfAttr));
return rgProfAttr[index].pwzName;
}
INT _GetResourceIdFromAttrIndex( int index )
{
// Assert that the index is valid.
ASSERT(index>=0 && index<ARRAYSIZE(rgProfAttr));
return rgProfAttr[index].id;
}
ULONG _GetPropTagFromAttrIndex( int index )
{
// Assert that the index is valid.
ASSERT(index>=0 && index<ARRAYSIZE(rgProfAttr));
return rgProfAttr[index].ulPropTag;
}
//================================================
// Implementation of the OPSRequestEntry object
//------------------------------------------------
int CIEFrameAuto::COpsProfile::OPSRequestEntry::destWrapper(void *pEntry, void *pUnused)
{
OPSRequestEntry *pReqEntry = (OPSRequestEntry*) pEntry;
if ( pReqEntry )
{
delete pReqEntry;
pReqEntry = NULL;
}
return TRUE;
}
int CIEFrameAuto::COpsProfile::OPSRequestEntry::grantRequest(void *pEntry, void *pUnused)
{
OPSRequestEntry *pReqEntry = (OPSRequestEntry*) pEntry;
pReqEntry->grantRequest();
return TRUE;
}
void CIEFrameAuto::COpsProfile::OPSRequestEntry::grantRequest()
{
m_fQuery = FALSE;
m_fAnswer = TRUE;
}
void CIEFrameAuto::COpsProfile::OPSRequestEntry::denyRequest()
{
m_fQuery = FALSE;
m_fAnswer = FALSE;
}
void CIEFrameAuto::COpsProfile::OPSRequestEntry::clearValue()
{
SysFreeString(m_bstrValue);
m_bstrValue = NULL;
}
CIEFrameAuto::COpsProfile::OPSRequestEntry::OPSRequestEntry()
{
m_fQuery = TRUE;
m_fAnswer = FALSE;
m_bstrValue = NULL;
m_bstrName = NULL;
m_bstrOldVal = NULL;
}
CIEFrameAuto::COpsProfile::OPSRequestEntry::~OPSRequestEntry()
{
SysFreeString(m_bstrName);
SysFreeString(m_bstrValue);
SysFreeString(m_bstrOldVal);
}
//================================================
// Implementation of the COpsProfile object
//------------------------------------------------
CIEFrameAuto::COpsProfile::COpsProfile()
: CAutomationStub( MIN_BROWSER_DISPID, MAX_BROWSER_DISPID, TRUE )
{
#ifdef NEVER
m_pCert = NULL;
#endif // NEVER
#ifdef _USE_PSTORE_
m_provID = GUID_NULL;
m_pStore = NULL;
m_iStoreRef = 0;
#else
m_bWABInit = FALSE;
m_hInstWAB = NULL;
m_lpAdrBook = NULL;
m_lpWABObject = NULL;
m_hrWAB = E_UNEXPECTED;
m_SBMe.cb = 0;
m_SBMe.lpb = NULL;
#endif // _USE_PSTORE_
m_fEnabled = FALSE;
m_bstrLastURL = NULL;
m_hdpaRequests = DPA_Create(0);
m_hdpaChanges = DPA_Create(0);
m_hP3Global = NULL;
m_hP3Sites = NULL;
//Begin a-thkesa Initialize . See Windows BUG:589837.
VariantInit(&m_vUsage);// a-thkesa.
m_vUsage.vt = VT_I4;
m_vUsage.lVal = 8;
//End a-thkesa
}
CIEFrameAuto::COpsProfile::~COpsProfile()
{
clearRequest();
#ifdef NEVER
if (m_pCert)
m_pCert->Release();
#endif // NEVER
for (unsigned i=m_iStoreRef; i>0; i--)
_ReleaseStore();
#ifdef _USE_PSTORE_
if (m_pStore)
ATOMICRELEASE(m_pStore);
#else
if (m_SBMe.lpb)
m_lpWABObject->FreeBuffer(m_SBMe.lpb);
if (m_lpAdrBook)
ATOMICRELEASE(m_lpAdrBook);
if (m_lpWABObject)
ATOMICRELEASE(m_lpWABObject);
if (m_hInstWAB)
FreeLibrary(m_hInstWAB);
#endif // _USE_PSTORE_
// Prevent delay-loading of OLEAUT32.DLL if not necessary
if (m_bstrLastURL)
SysFreeString(m_bstrLastURL);
RegCloseKey(m_hP3Global);
RegCloseKey(m_hP3Sites);
DPA_DestroyCallback(m_hdpaRequests, OPSRequestEntry::destWrapper, NULL);
m_hdpaRequests = NULL;
DPA_DestroyCallback(m_hdpaChanges, OPSRequestEntry::destWrapper, NULL);
m_hdpaChanges = NULL;
}
HRESULT CIEFrameAuto::COpsProfile::_CreateStore()
{
#ifdef _USE_PSTORE_
if (m_iStoreRef == 0)
{
HRESULT hr = PStoreCreateInstance( &m_pStore,
IsEqualGUID(m_provID, GUID_NULL) ? NULL : &m_provID,
NULL,
0);
if (SUCCEEDED(hr))
m_iStoreRef++;
return hr;
}
m_iStoreRef++;
return S_OK;
#else
if (!m_bWABInit)
{
ASSERT(NULL == m_hInstWAB);
ASSERT(NULL == m_lpAdrBook && NULL == m_lpWABObject);
// Don't try initializing the wab again and again
m_bWABInit = TRUE;
{
// Figure out the location of the wab dll and try opening it.
TCHAR szWABDllPath[MAX_PATH];
DWORD dwType = 0;
ULONG cbData = sizeof(szWABDllPath);
HKEY hKey = NULL;
*szWABDllPath = '\0';
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, WAB_DLL_PATH_KEY, 0, KEY_READ, &hKey))
RegQueryValueEx( hKey, TEXT(""), NULL, &dwType, (LPBYTE) szWABDllPath, &cbData);
if(hKey) RegCloseKey(hKey);
if (lstrlen(szWABDllPath) != 0 )
m_hInstWAB = LoadLibrary (szWABDllPath);
else
m_hInstWAB = NULL;
}
HRESULT hr;
if (m_hInstWAB)
{
LPWABOPEN lpfnWABOpen = (LPWABOPEN) GetProcAddress(m_hInstWAB, "WABOpen");
if (lpfnWABOpen)
{
hr = lpfnWABOpen(&m_lpAdrBook, &m_lpWABObject, NULL, 0);
if (NULL == m_lpAdrBook || NULL == m_lpWABObject)
hr = E_UNEXPECTED;
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND); // Not the right dll anyway!!
}
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);
}
// Good so far, call GetMe.
if (!hr)
{
m_SBMe.cb = 0;
m_SBMe.lpb = NULL;
hr = m_lpWABObject->GetMe(m_lpAdrBook, WABOBJECT_ME_NOCREATE | AB_NO_DIALOG, NULL, &m_SBMe, 0);
if (0 == m_SBMe.cb || NULL == m_SBMe.lpb)
hr = E_UNEXPECTED;
}
// Remember the return code for later.
m_hrWAB = hr;
}
if (!m_hrWAB)
m_iStoreRef++;
return m_hrWAB;
#endif
}
HRESULT CIEFrameAuto::COpsProfile::_ReleaseStore()
{
if (m_iStoreRef > 0)
m_iStoreRef--;
return S_OK;
}
HRESULT CIEFrameAuto::COpsProfile::Init()
{
DWORD dwError;
DWORD dwAction;
dwError = RegCreateKeyEx(HKEY_CURRENT_USER,
rgszP3Global,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&m_hP3Global,
&dwAction);
dwError = RegCreateKeyEx(HKEY_CURRENT_USER,
rgszP3Sites,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&m_hP3Sites,
&dwAction);
m_fEnabled = _IsP3Enabled();
CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _profile, this);
return CAutomationStub::Init( SAFECAST(this, IHTMLOpsProfile*), IID_IHTMLOpsProfile,
CLSID_COpsProfile, pauto );
}
HRESULT CIEFrameAuto::COpsProfile::addReadRequest(BSTR bstrName, VARIANT reserved, VARIANT_BOOL *pfSuccess)
{
if ( pfSuccess )
*pfSuccess = VARIANT_FALSE;
if (!m_fEnabled)
return S_FALSE;
if (bstrName==NULL)
return E_POINTER;
BSTR bstrURL = NULL;
HRESULT hr = _pAuto->get_LocationURL(&bstrURL);
if (_DifferentURL())
clearRequest();
SysFreeString(m_bstrLastURL);
m_bstrLastURL = SysAllocString(bstrURL);
if (NULL == m_bstrLastURL)
{
return E_OUTOFMEMORY;
}
int index = _GetAttrIndexFromName(bstrName);
if (index==INVALID_ATTRIBUTE_INDEX)
return S_FALSE;
// If the attribute already exists on the list, return from this function
for (int i=0; i<DPA_GetPtrCount(m_hdpaRequests); i++)
{
OPSRequestEntry *pEntry = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests, i);
if (StrCmpIW(pEntry->m_bstrName,bstrName)==0)
return S_OK;
}
OPSRequestEntry *pNewEntry = new OPSRequestEntry;
if (pNewEntry==NULL)
return E_OUTOFMEMORY;
pNewEntry->m_bstrName = SysAllocString(_GetNameFromAttrIndex(index));
if (pNewEntry->m_bstrName==NULL)
{
delete pNewEntry;
return E_OUTOFMEMORY;
}
pNewEntry->m_bstrValue = NULL;
int eIns = DPA_AppendPtr(m_hdpaRequests, (void*) pNewEntry);
if (eIns==-1)
{
delete pNewEntry;
return E_OUTOFMEMORY;
}
if ( pfSuccess )
*pfSuccess = VARIANT_TRUE;
return S_OK;
}
HRESULT CIEFrameAuto::COpsProfile::clearRequest()
{
m_fEnabled = _IsP3Enabled();
if (!m_fEnabled)
return S_FALSE;
DPA_EnumCallback(m_hdpaRequests, OPSRequestEntry::destWrapper, NULL);
DPA_DeleteAllPtrs(m_hdpaRequests);
return S_OK;
}
HRESULT CIEFrameAuto::COpsProfile::doRequest(VARIANT usage, VARIANT fname,
VARIANT vaDomain, VARIANT vaPath, VARIANT vaExpire,
VARIANT reserved)
{
m_fEnabled = _IsP3Enabled();
if (!m_fEnabled)
return S_FALSE;
int i, k;
HRESULT hr;
BOOL fShowUI = FALSE;
BOOL fPersistent = FALSE;
BSTR bstrURL;
TCHAR rgchURL[MAX_URL_STRING];
TCHAR rgchDomain[INTERNET_MAX_HOST_NAME_LENGTH+1];
TCHAR rgchPath[MAX_PATH+1];
TCHAR rgchScheme[16];
URL_COMPONENTS uc;
AccessSettings acSettings;
HDPA hdpaConfirm = DPA_Create(0);
if (_DifferentURL())
{
clearRequest();
return S_FALSE;
}
hr = _pAuto->get_LocationURL(&bstrURL);
if (FAILED(hr))
return S_FALSE;
_StringFromBSTR(bstrURL, rgchURL, ARRAYSIZE(rgchURL));
ZeroMemory(&uc, sizeof(uc));
uc.dwStructSize = sizeof(URL_COMPONENTS);
uc.lpszHostName = rgchDomain;
uc.dwHostNameLength = ARRAYSIZE(rgchDomain);
uc.lpszUrlPath = rgchPath;
uc.dwUrlPathLength = ARRAYSIZE(rgchPath);
uc.lpszScheme = rgchScheme;
uc.dwSchemeLength = ARRAYSIZE(rgchScheme);
InternetCrackUrl(rgchURL, lstrlen(rgchURL), ICU_DECODE, &uc);
_GetSiteSettings(&uc, vaDomain, vaPath, vaExpire, &acSettings);
hr = _CreateStore();
if (FAILED(hr))
return S_FALSE;
if (DPA_GetPtrCount(m_hdpaRequests)==0)
return S_OK;
for (k=0; k<DPA_GetPtrCount(m_hdpaRequests); k++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,k);
pCurrent->clearValue();
}
HWND hwnd = _pAuto->_GetHWND();
INT_PTR nRet = -1;
// #59340 - don't need special priviliges for local machine zone anymore.
if (FALSE && _IsLocalMachine())
{
// If page is on the local machine, all requested information will be given
DPA_EnumCallback(m_hdpaRequests, OPSRequestEntry::grantRequest, NULL);
nRet = TRUE;
}
else
{
// Process the request list and mark attributes according to the configuration
_ApplyPreferences(&uc, m_hdpaRequests);
// Go through the request list and for each attribute that was not marked as
// grant/deny according to the preferences, add it to the list
for (k=0; k<DPA_GetPtrCount(m_hdpaRequests); k++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,k);
if (pCurrent->m_fQuery)
DPA_AppendPtr(hdpaConfirm, pCurrent);
}
// Determine whether there are any attributes to query
fShowUI = DPA_GetPtrCount(hdpaConfirm)>0;
if (!fShowUI)
{
nRet = TRUE;
goto HandleRequest;
}
// If a UI is going to be shown, all attributes that were going to be
// given or denied silently should also be shown
for (k=0; k<DPA_GetPtrCount(m_hdpaRequests); k++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,k);
if (!pCurrent->m_fQuery &&
(pCurrent->m_fAnswer || (!pCurrent->m_fAnswer && pCurrent->m_dwDecision==P3_SITELEVEL)))
{
DPA_AppendPtr(hdpaConfirm, pCurrent);
pCurrent->m_fQuery = TRUE;
}
}
OPSDlgInfo opsDlgInfo;
opsDlgInfo.m_hdpa = hdpaConfirm;
StrCpyN(opsDlgInfo.m_rgchURL, rgchURL, ARRAYSIZE(opsDlgInfo.m_rgchURL));
opsDlgInfo.m_pOpsProfile = this;
opsDlgInfo.m_pacSettings = &acSettings;
opsDlgInfo.m_fRemember = (_GetCookieSettings()==COOKIES_ALLOW);
if (fname.vt == VT_BSTR && fname.bstrVal && lstrlenW(fname.bstrVal)>0)
opsDlgInfo.m_bstrFName = SysAllocString(fname.bstrVal);
else
opsDlgInfo.m_bstrFName = NULL;
_GetUsageCode(usage, opsDlgInfo.m_rgchUsage, ARRAYSIZE(opsDlgInfo.m_rgchUsage));
//Beign a-thkesa to solve Windows BUG:589837. Assigne the usage member for the next use.
{
m_vUsage.vt = usage.vt;
m_vUsage.lVal = usage.lVal;
}
// End.
OSVERSIONINFOA osvi;
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(osvi);
if (GetVersionExA((OSVERSIONINFOA*)&osvi) && (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId &&
(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 && LOWORD(osvi.dwBuildNumber) == 2600)))
{
HMODULE hmod = LoadLibrary(TEXT("xpsp1res.dll"));
if (hmod)
{
nRet = (UINT) DialogBoxParam(hmod, MAKEINTRESOURCE(IDD_OPS_CONSENT),
hwnd,
_OPSConsent_DlgProc,
(LPARAM) &opsDlgInfo);
FreeLibrary(hmod);
}
}
if(nRet == -1)
nRet = DialogBoxParam(MLGetHinst(),
MAKEINTRESOURCE(IDD_OPS_CONSENT),
hwnd,
_OPSConsent_DlgProc,
(LPARAM) &opsDlgInfo);
fPersistent = opsDlgInfo.m_fRemember;
}
HandleRequest:
if (nRet==-1)
return E_FAIL;
if (!nRet)
{
fPersistent = FALSE;
goto Cleanup;
}
for (i=0; i<DPA_GetPtrCount(m_hdpaRequests); i++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,i);
if (pCurrent->m_fQuery)
{
pCurrent->m_prefs.m_lastRequest = pCurrent->m_fAnswer ? P3_ACCEPT : P3_REJECT;
_PutUserPreference(pCurrent->m_bstrName, pCurrent->m_prefs);
}
if (pCurrent->m_fAnswer)
{
hr = _GetFieldValue(pCurrent->m_bstrName, & (pCurrent->m_bstrValue));
if (FAILED(hr))
pCurrent->clearValue();
}
}
if (fShowUI && fPersistent &&
(uc.nScheme==INTERNET_SCHEME_HTTP || uc.nScheme==INTERNET_SCHEME_HTTPS))
{
_UpdateSiteSettings(&acSettings, m_hdpaRequests);
}
Cleanup:
DPA_Destroy(hdpaConfirm);
hdpaConfirm = NULL;
_ReleaseStore();
return S_OK;
}
HRESULT CIEFrameAuto::COpsProfile::getAttribute(BSTR bstrAttribName, BSTR *pbstrAttribValue)
{
if (!m_fEnabled)
return S_FALSE;
if (pbstrAttribValue==NULL || bstrAttribName==NULL)
return E_POINTER;
*pbstrAttribValue = NULL;
//
// SECURITY: Since shdocvw has no notion of frames,
// we now prompt on every attempt to get attributes.
// See Windows bugs 536637 & 549409 for details.
//
VARIANT_BOOL vbSuccess;
VARIANT vError, vUsage, vName;
VariantInit(&vError);
VariantInit(&vUsage);
VariantInit(&vName);
vError.vt = VT_ERROR;
vError.scode = DISP_E_PARAMNOTFOUND;
//a-thkesa to solve Windows BUG:589837. Assign the usage member for the this use.
//Begin comment a-thkesa
//vUsage.vt = VT_I4;
//vUsage.lVal = 8;
//End
vUsage = m_vUsage ;// a-thkesa to solve Windows BUG:589837
vName.vt = VT_EMPTY;
clearRequest();
addReadRequest(bstrAttribName, vError, &vbSuccess);
if (vbSuccess == VARIANT_FALSE)
return E_FAIL;
doReadRequest(vUsage, vName, vError, vError, vError, vError);
for (int i=0; i<DPA_GetPtrCount(m_hdpaRequests); i++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,i);
if (StrCmpIW(bstrAttribName,pCurrent->m_bstrName) == 0)
{
if (pCurrent->m_bstrValue == NULL)
{
*pbstrAttribValue = SysAllocString(L"");
}
else
{
*pbstrAttribValue = SysAllocString(pCurrent->m_bstrValue);
}
return (*pbstrAttribValue == NULL) ? E_OUTOFMEMORY : S_OK;
}
}
return S_FALSE;
}
HRESULT CIEFrameAuto::COpsProfile::setAttribute(BSTR bstrAttribName, BSTR bstrAttribValue, VARIANT vaPrefs,
VARIANT_BOOL *pfSuccess)
{
BSTR bstrStdName = NULL;
HRESULT hr = S_FALSE;
if (pfSuccess)
*pfSuccess = VARIANT_FALSE;
if (!m_fEnabled)
return S_FALSE;
if (bstrAttribName==NULL)
return E_POINTER;
// If this is a new URL, flush the change queue.
if (_DifferentURL())
{
DPA_EnumCallback(m_hdpaChanges,OPSRequestEntry::destWrapper,NULL);
DPA_DeleteAllPtrs(m_hdpaChanges);
}
// Load the name of the current URL into the last visited URL
SysFreeString(m_bstrLastURL);
_pAuto->get_LocationURL(&m_bstrLastURL);
int index = _GetAttrIndexFromName(bstrAttribName);
if (index==INVALID_ATTRIBUTE_INDEX)
return S_FALSE;
OPSRequestEntry *pNewEntry = new OPSRequestEntry;
if (pNewEntry == NULL)
return E_OUTOFMEMORY;
pNewEntry->m_bstrName = SysAllocString(_GetNameFromAttrIndex(index));
if (pNewEntry->m_bstrName==NULL)
{
delete pNewEntry;
return E_OUTOFMEMORY;
}
if (bstrAttribValue != NULL)
pNewEntry->m_bstrValue = SysAllocString(bstrAttribValue);
else
pNewEntry->m_bstrValue = SysAllocString(L"");
if (pNewEntry->m_bstrValue==NULL)
{
delete pNewEntry;
return E_OUTOFMEMORY;
}
for (int i=0; i<DPA_GetPtrCount(m_hdpaChanges); i++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaChanges,i);
if (StrCmpIW(pCurrent->m_bstrName, bstrAttribName) == 0)
{
SysFreeString(pCurrent->m_bstrValue);
pCurrent->m_bstrValue = SysAllocString(bstrAttribName);
if (*pfSuccess)
*pfSuccess = (pCurrent->m_bstrValue!=NULL) ? VARIANT_TRUE : VARIANT_FALSE;
delete pNewEntry;
return S_OK;
}
}
int eIns = DPA_AppendPtr(m_hdpaChanges, pNewEntry);
if (eIns==-1)
{
delete pNewEntry;
return E_OUTOFMEMORY;
}
if (pfSuccess)
*pfSuccess = VARIANT_TRUE;
return S_OK;
}
HRESULT CIEFrameAuto::COpsProfile::commitChanges(VARIANT_BOOL *pfSuccess) {
if ( pfSuccess )
*pfSuccess = VARIANT_FALSE;
if (!m_fEnabled)
return S_FALSE;
HRESULT hr;
HWND hwnd;
int i;
INT_PTR nRet;
OPSDlgInfo opsDlgInfo;
BSTR bstrURL = NULL;
TCHAR rgchURL[MAX_URL_STRING];
_pAuto->get_LocationURL(&bstrURL);
_StringFromBSTR(bstrURL, rgchURL, ARRAYSIZE(rgchURL));
SysFreeString(bstrURL);
// Crack the URL and get the hostname
TCHAR rgchHostName[INTERNET_MAX_HOST_NAME_LENGTH] = { TEXT('\0') };
DWORD dwcbHostLen = ARRAYSIZE(rgchHostName);
UrlGetPart(rgchURL, rgchHostName, &dwcbHostLen, URL_PART_HOSTNAME, 0);
// Read the hostname for the registration page from the registry
TCHAR rgchRegDomain[INTERNET_MAX_HOST_NAME_LENGTH];
DWORD dwcbReg = sizeof(rgchRegDomain);
HKEY hWriteKey = NULL;
DWORD dwError;
dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, rgszRegKey, 0, KEY_READ, &hWriteKey);
if (dwError==ERROR_SUCCESS)
{
dwError = RegQueryValueEx(hWriteKey, rgszRegTxt, NULL, NULL, (LPBYTE) rgchRegDomain, &dwcbReg);
RegCloseKey(hWriteKey);
}
BOOL fRegDomain = (dwError==ERROR_SUCCESS && _DomainMatch(rgchHostName, rgchRegDomain));
BOOL fCanWrite = _IsLocalMachine() || fRegDomain;
if (!fCanWrite || _DifferentURL())
goto Cleanup;
hr = _CreateStore();
if (hr)
goto Cleanup;
// Look up the old values from the store
for (i=0; i<DPA_GetPtrCount(m_hdpaChanges); i++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaChanges, i);
// Default case: the attribute will be updated
pCurrent->m_fAnswer = TRUE;
hr = _GetFieldValue (pCurrent->m_bstrName, &(pCurrent->m_bstrOldVal));
if (hr)
{
SysFreeString(pCurrent->m_bstrOldVal);
pCurrent->m_bstrOldVal = NULL;
}
}
// Delete nodes in the list if the new value is the same as the old one
// NOTE: The loop counter will remain stationary or increment depending on whether
// the current node in the list is deleted
for (i=0; i<DPA_GetPtrCount(m_hdpaChanges); )
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaChanges, i);
if (StrCmpW(pCurrent->m_bstrValue, pCurrent->m_bstrOldVal)==0)
DPA_DeletePtr(m_hdpaChanges, i);
else
i++;
}
// If nothing has changed, then we do not need to write data back to the storage
if (DPA_GetPtrCount(m_hdpaChanges)==0)
goto Cleanup;
// The registration domain can write profile information silently.
// For all other cases, a UI will be displayed.
if (!fRegDomain)
{
// Pop up a UI to show the items that are being changes and allow the user to
// confirm the changes by selecting check-boxes for each attribute
opsDlgInfo.m_hdpa = m_hdpaChanges;
opsDlgInfo.m_pOpsProfile = this;
hwnd = _pAuto->_GetHWND();
nRet = DialogBoxParam(MLGetHinst(),
MAKEINTRESOURCE(IDD_OPS_UPDATE),
hwnd,
_OPSUpdate_DlgProc,
(LPARAM) &opsDlgInfo
);
// Unrecoverable error: failed to show the dialog box
if (nRet==-1)
return S_FALSE;
// If the user clicked "CANCEL", then no changes will be performed
if (nRet==0)
goto Cleanup;
}
if ( pfSuccess )
*pfSuccess = VARIANT_TRUE;
for (i=0; i<DPA_GetPtrCount(m_hdpaChanges); i++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaChanges, i);
// Registration page should not overwrite existing entries
if (fRegDomain && ! EMPTY_STRINGW(pCurrent->m_bstrOldVal))
continue;
// Update only if the user allowed in the UI
// For the registration page, this condition will hold for all attributes
if (pCurrent->m_fAnswer)
{
hr = _SetFieldValue(pCurrent->m_bstrName, pCurrent->m_bstrValue);
if (hr && pfSuccess)
*pfSuccess = VARIANT_FALSE;
}
}
Cleanup:
// Clear the queue that holds the changes
DPA_EnumCallback(m_hdpaChanges,OPSRequestEntry::destWrapper,NULL);
DPA_DeleteAllPtrs(m_hdpaChanges);
return S_OK;
}
// *** IOpsProfileSimple members ***
STDMETHODIMP CIEFrameAuto::COpsProfile::ReadProperties(long lNumProperties, const LPCWSTR szProperties[], LPWSTR szReturnValues[])
{
HRESULT hr=S_OK;
for (int i=0; i<lNumProperties; i++)
{
BSTR bstrValue=NULL;
LPWSTR pwszRet=NULL;
if (szProperties[i])
{
_GetFieldValue(szProperties[i], &bstrValue);
if (bstrValue)
{
// FEATURE change _GetFieldValue so we don't reallocate twice unnecessarily
int cch = (1 + lstrlenW(bstrValue));
pwszRet = (LPWSTR) CoTaskMemAlloc(sizeof(WCHAR) * cch);
if (pwszRet)
StrCpyNW(pwszRet, bstrValue, cch);
SysFreeString(bstrValue);
}
else
{
hr = S_FALSE;
}
}
szReturnValues[i] = pwszRet;
}
return hr;
}
STDMETHODIMP CIEFrameAuto::COpsProfile::WriteProperties(long lNumProperties, const LPCWSTR szProperties[], const LPCWSTR szValues[])
{
return E_NOTIMPL;
}
#ifdef _USE_PSTORE_
HRESULT CIEFrameAuto::COpsProfile::_GetFieldValue(const OLECHAR *pszField, BSTR * pbstrValue)
{
GUID itemType = GUID_NULL;
GUID itemSubtype = GUID_NULL;
BSTR bstrName = NULL;
DWORD cbData;
BYTE * pbData = NULL;
PST_PROMPTINFO promptInfo;
HRESULT hr;
BOOL fOpen = FALSE;
if (pszField==NULL || pbstrValue==NULL)
return E_POINTER;
ZeroMemory(&promptInfo,sizeof(promptInfo));
promptInfo.cbSize = sizeof(promptInfo);
promptInfo.szPrompt = pszField;
promptInfo.dwPromptFlags = 0;
promptInfo.hwndApp = _pAuto->_GetHWND();
hr = _CreateStore();
if (hr)
goto Cleanup;
hr = _GetPStoreTypes(pszField, &itemType, &itemSubtype, &bstrName);
if (hr)
goto Cleanup;
hr = m_pStore->ReadItem(
s_Key,
&itemType,
&itemSubtype,
bstrName,
&cbData,
&pbData,
&promptInfo,
0);
if (FAILED(hr))
{
*pbstrValue = SysAllocString(L"");
hr = S_OK;
goto Cleanup;
}
*pbstrValue = SysAllocString((OLECHAR *) pbData);
Cleanup:
_ReleaseStore();
CoTaskMemFree(pbData);
SysFreeString(bstrName);
return hr;
}
HRESULT CIEFrameAuto::COpsProfile::_SetFieldValue(const OLECHAR *pszField, BSTR bstrValue)
{
HRESULT hr;
PST_TYPEINFO typeInfo;
PST_PROMPTINFO promptInfo;
WCHAR * szValue = bstrValue ? bstrValue : L"";
TCHAR szDisplayName[MAX_PATH];
WCHAR wzDisplayName[MAX_PATH];
if (pszField==NULL)
return E_POINTER;
MLLoadString(IDS_PROFILE_ASSISTANT, szDisplayName, ARRAYSIZE(szDisplayName));
typeInfo.cbSize = sizeof(typeInfo);
int cch = MultiByteToWideChar( CP_ACP, 0, szDisplayName, -1,
wzDisplayName, ARRAYSIZE(wzDisplayName));
ASSERT(cch != 0);
typeInfo.szDisplayName = wzDisplayName;
promptInfo.cbSize = sizeof(promptInfo);
promptInfo.dwPromptFlags = 0;
promptInfo.hwndApp = _pAuto->_GetHWND();
promptInfo.szPrompt = pszField;
hr = _CreateStore();
if (hr)
goto Cleanup;
hr = m_pStore->CreateType(s_Key, &GUID_PStoreType, &typeInfo, 0);
if (hr && (hr != PST_E_TYPE_EXISTS))
goto Cleanup;
hr = m_pStore->CreateSubtype(
s_Key,
&GUID_PStoreType,
&GUID_NULL,
&typeInfo,
NULL,
0);
if (hr && (hr != PST_E_TYPE_EXISTS))
goto Cleanup;
hr = m_pStore->WriteItem(
s_Key,
&GUID_PStoreType,
&GUID_NULL,
pszField,
(lstrlenW(szValue) + 1) * sizeof(WCHAR),
(BYTE *) szValue,
&promptInfo,
PST_CF_NONE,
0);
Cleanup:
_ReleaseStore();
return hr;
}
#else // _USE_PSTORE_
HRESULT CIEFrameAuto::COpsProfile::_GetFieldValue(const OLECHAR *pszField, BSTR * pbstrValue)
{
LPMAILUSER lpMailUser = NULL;
ULONG ulPropTag;
ULONG ulObjType = 0;
WCHAR * pwzValue = NULL;
BOOL bStoreCreated = FALSE;
HRESULT hr;
if (pszField==NULL || pbstrValue==NULL)
return E_POINTER;
hr = _CreateStore();
if (hr)
goto Cleanup;
else
bStoreCreated = TRUE;
INT index;
index = INVALID_ATTRIBUTE_INDEX;
if (!_ValidateElemName(pszField, &index))
{
hr = E_INVALIDARG;
goto Cleanup;
}
// Open the entry in the address book.
hr = m_lpAdrBook->OpenEntry(m_SBMe.cb,
(LPENTRYID) m_SBMe.lpb,
NULL,
0,
&ulObjType,
(LPUNKNOWN *)&lpMailUser);
if (hr)
goto Cleanup;
if (lpMailUser)
{
ulPropTag = _GetPropTagFromAttrIndex(index);
SPropTagArray SPTA;
SPTA.cValues = 1;
SPTA.aulPropTag[0] = ulPropTag;
if (PROP_TYPE(ulPropTag) == PT_TSTRING || ulPropTag == PR_GENDER)
{
DWORD cValues = 0;
LPSPropValue lpSPropValue = NULL;
hr = lpMailUser->GetProps(&SPTA, 0, &cValues, &lpSPropValue);
if (!hr)
{
ASSERT(1 == cValues);
ASSERT(NULL != lpSPropValue);
int cch = 0;
LPCTSTR pszPropStr = NULL;
if (ulPropTag == PR_GENDER)
{
switch (lpSPropValue->Value.i)
{
case 1:
pszPropStr = GENDER_FEMALE;
break;
case 2:
pszPropStr = GENDER_MALE;
break;
default:
pszPropStr = GENDER_UNSPECIFIED;
break;
}
}
else
{
ASSERT(PROP_TYPE(lpSPropValue->ulPropTag) == PT_TSTRING);
pszPropStr = lpSPropValue->Value.LPSZ;
}
if (pszPropStr)
{
#ifdef _UNICODE
cch = lstrlen(pszPropStr) + 1;
#else
// We get the string back in ANSI convert to Unicode.
cch = MultiByteToWideChar(CP_ACP, 0, pszPropStr, -1, NULL, 0);
#endif
pwzValue = new WCHAR [cch];
if (NULL == pwzValue)
{
hr = E_OUTOFMEMORY;
}
else
{
#ifdef _UNICODE
StrCpyN(pwzValue, pszPropStr, cch);
#else
cch = MultiByteToWideChar(CP_ACP, 0, pszPropStr, -1, pwzValue, cch);
ASSERT(0 != cch);
#endif
}
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); // This will cause us to just return the NULL string.
}
}
m_lpWABObject->FreeBuffer(lpSPropValue);
}
else
{
// If this assert fires you are probably adding a new PR_* mapping to the OPS code.
// You will need to write code to convert the returned value to a string meaningfully.
// See the example for GENDER above.
ASSERT(FALSE);
hr = E_NOTIMPL ;
}
}
else
{
hr = E_UNEXPECTED;
}
if (hr)
{
*pbstrValue = SysAllocString(L"");
hr = (NULL != pbstrValue) ? S_OK : E_OUTOFMEMORY;
goto Cleanup;
}
*pbstrValue = SysAllocString((OLECHAR *) pwzValue);
Cleanup:
if (bStoreCreated)
_ReleaseStore();
if (lpMailUser)
lpMailUser->Release();
delete [] pwzValue;
return hr;
}
HRESULT CIEFrameAuto::COpsProfile::_SetFieldValue(const OLECHAR *pszField, BSTR bstrValue)
{
HRESULT hr;
LPMAILUSER lpMailUser = NULL;
ULONG ulPropTag;
ULONG ulObjType = 0;
BOOL bStoreCreated = FALSE;
if (pszField==NULL)
return E_POINTER;
hr = _CreateStore();
if (hr)
goto Cleanup;
else
bStoreCreated = TRUE;
INT index;
index = INVALID_ATTRIBUTE_INDEX;
if (!_ValidateElemName(pszField, &index))
{
hr = E_INVALIDARG;
goto Cleanup;
}
// Open the entry in the address book.
hr = m_lpAdrBook->OpenEntry(m_SBMe.cb,
(LPENTRYID) m_SBMe.lpb,
NULL,
MAPI_MODIFY,
&ulObjType,
(LPUNKNOWN *)&lpMailUser);
if (hr)
goto Cleanup;
if (lpMailUser)
{
ulPropTag = _GetPropTagFromAttrIndex(index);
if (PROP_TYPE(ulPropTag) == PT_TSTRING || ulPropTag == PR_GENDER)
{
// First remove the existing entry
SPropTagArray SPTA;
SPTA.cValues = 1;
SPTA.aulPropTag[0] = ulPropTag;
lpMailUser->DeleteProps(&SPTA, NULL);
SPropValue prop;
prop.ulPropTag = ulPropTag;
CHAR *pszValue = NULL;
if (ulPropTag == PR_GENDER)
{
short int i = 0; // unspecified.
if (0 == StrCmpIW(bstrValue, GENDER_FEMALE_W))
i = 1;
else if (0 == StrCmpIW(bstrValue, GENDER_MALE_W))
i = 2;
prop.Value.i = i;
}
else
{
prop.Value.LPSZ = bstrValue;
}
if (!hr)
{
hr = lpMailUser->SetProps(1, &prop, NULL);
lpMailUser->SaveChanges(0);
}
delete [] pszValue;
}
else
{
hr = E_NOTIMPL ; // FIX THIS BEFORE CHECKING IN.
}
}
else
{
hr = E_UNEXPECTED;
}
Cleanup:
if (bStoreCreated)
_ReleaseStore();
if (lpMailUser)
lpMailUser->Release();
return hr;
}
#endif // ! _USE_PSTORE_
HRESULT CIEFrameAuto::COpsProfile::_GetIDispatchExDelegate(IDispatchEx ** const delegate)
{
if( !delegate )
return E_POINTER;
*delegate = NULL; // We do not handle expandos yet
return DISP_E_MEMBERNOTFOUND;
}
HRESULT CIEFrameAuto::COpsProfile::_InternalQueryInterface(REFIID riid, void ** const ppvObjOut)
{
ASSERT( this );
ASSERT( !IsEqualIID(riid, IID_IUnknown) );
if (IsEqualIID(riid, IID_IHTMLOpsProfile))
{
*ppvObjOut = SAFECAST(this,IHTMLOpsProfile*);
}
else if (IsEqualIID(riid, IID_IOpsProfileSimple))
{
*ppvObjOut = SAFECAST(this,IOpsProfileSimple*);
}
else
{
*ppvObjOut = NULL;
return E_NOINTERFACE;
}
AddRef( );
return S_OK;
}
#ifdef _USE_PSTORE_
HRESULT
CIEFrameAuto::COpsProfile::_GetPStoreTypes(
BSTR bstrField,
GUID * pguidType,
GUID * pguidSub,
BSTR * pbstrName)
{
*pguidType = GUID_PStoreType;
*pguidSub = GUID_NULL;
*pbstrName = SysAllocString(bstrField);
return S_OK;
}
#endif // _USE_PSTORE_
// Functions to display the consent dialog.
BOOL CIEFrameAuto::COpsProfile::_OPSConsent_OnInitDlg(HWND hDlg)
{
const int cbMaxStringDisplay = 24;
LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO) GetWindowLongPtr(hDlg, DWLP_USER);
COpsProfile *pProfile = lpOpsDlgInfo->m_pOpsProfile;
if (!lpOpsDlgInfo || !lpOpsDlgInfo->m_hdpa)
return FALSE;
// Get the hostname
TCHAR rgSiteName[MAX_URL_STRING];
DWORD dwchOut = ARRAYSIZE(rgSiteName);
HRESULT hr;
hr = UrlGetPart(lpOpsDlgInfo->m_rgchURL, rgSiteName, &dwchOut, URL_PART_HOSTNAME, 0);
if (FAILED(hr) || dwchOut == 0 )
StrCpyN(rgSiteName, lpOpsDlgInfo->m_rgchURL, ARRAYSIZE(rgSiteName));
// Display site identity information
HWND hwndReq = GetDlgItem(hDlg, IDC_SITE_IDENTITY);
TCHAR rgRequestInfo[MAX_URL_STRING];
TCHAR rgFormat[MAX_URL_STRING];
BSTR bstrFName = lpOpsDlgInfo->m_bstrFName;
TCHAR rgFName[MAX_URL_STRING];
MLLoadString(IDS_DEFAULT_FNAME, rgFName, ARRAYSIZE(rgFName));
MLLoadString(IDS_OPS_REQUEST, rgFormat, ARRAYSIZE(rgFormat));
wnsprintf(rgRequestInfo, ARRAYSIZE(rgRequestInfo), rgFormat, rgFName);
SetWindowText(hwndReq, rgRequestInfo);
// Display the access settings
TCHAR rgchAccessPath[MAX_URL_STRING];
HWND hwndURL = GetDlgItem(hDlg, IDC_OPS_URL);
_FormatSiteSettings(lpOpsDlgInfo->m_pacSettings, rgchAccessPath, ARRAYSIZE(rgchAccessPath));
SetWindowText(hwndURL, rgchAccessPath);
// Display the usage information
HWND hwndUsage = GetDlgItem(hDlg, IDC_USAGE_STRING);
SetWindowText(hwndUsage, lpOpsDlgInfo->m_rgchUsage);
// Detect SSL and inform user in the lower pane
BOOL fUsingSSL = pProfile->_IsUsingSSL();
if (fUsingSSL)
{
// If the connection is SSL, the default is to remember the settings
lpOpsDlgInfo->m_fRemember = TRUE;
// Hide the unsecure connection text.
HWND hwndStatic = GetDlgItem(hDlg, IDC_UNSECURE_CONNECTION);
ASSERT(hwndStatic != NULL);
ShowWindow(hwndStatic, SW_HIDE);
HICON hicon = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_LOCK));
if (hicon != NULL)
{
HICON hiconOld = (HICON)SendDlgItemMessage(hDlg, IDC_SECURITY_ICON, STM_SETICON,
(WPARAM)hicon, 0);
if (hiconOld)
{
DestroyIcon(hiconOld);
}
}
}
else
{
// Hide the view certificate button and the secure connection text.
HWND hwndViewCert = GetDlgItem(hDlg, IDC_VIEW_CERT);
ASSERT(hwndViewCert != NULL);
ShowWindow(hwndViewCert, SW_HIDE);
HWND hwndStatic = GetDlgItem(hDlg, IDC_SECURE_CONNECTION);
ASSERT(hwndStatic != NULL);
ShowWindow(hwndStatic, SW_HIDE);
}
// Hide the Edit Profile button if we are using the PStore.
#ifdef _USE_PSTORE
HWND hwndEditProf = GetDlgItem(hDlg, IDC_EDIT_PROFILE);
ASSERT(hwndEditProf != NULL);
ShowWindow(hwndEditProf, SW_HIDE);
#endif
Button_SetCheck(GetDlgItem(hDlg, IDC_KEEP_SETTINGS), lpOpsDlgInfo->m_fRemember);
HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
ASSERT(hwndLV);
// Initialize the list view control
ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_CHECKBOXES);
// Setup the columns for the list view control.
LV_COLUMN lvc = { LVCF_FMT , LVCFMT_LEFT };
ListView_InsertColumn(hwndLV, 0, &lvc);
ListView_InsertColumn(hwndLV, 1, &lvc);
// Add elements to the list view.
_OPSConsent_ShowRequestedItems(hDlg);
// show the items.
ListView_RedrawItems(hwndLV, 0, ListView_GetItemCount(hwndLV));
UpdateWindow(hwndLV);
return TRUE;
}
BOOL
CIEFrameAuto::COpsProfile::_OPSConsent_ShowRequestedItems(HWND hDlg)
{
LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO) GetWindowLongPtr(hDlg, DWLP_USER);
COpsProfile *pProfile = lpOpsDlgInfo->m_pOpsProfile;
HDPA hdpaList = lpOpsDlgInfo->m_hdpa;
HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
ASSERT(hwndLV);
BOOL fAllBlank = TRUE;
TCHAR szName[MAX_PROFILE_NAME];
// Initialize the common parts of the LVI
LV_ITEM lvi = { 0 };
for (int i=DPA_GetPtrCount(hdpaList)-1; i>=0; i--)
{
OPSRequestEntry * pOpsEntry = (OPSRequestEntry*) DPA_FastGetPtr(hdpaList,i);
MLLoadString(_GetResourceIdFromAttrName(pOpsEntry->m_bstrName), szName, MAX_PATH);
BSTR bstrValue = NULL;
TCHAR rgchValue[1024];
pProfile->_GetFieldValue(pOpsEntry->m_bstrName, &bstrValue);
_StringFromBSTR(bstrValue, rgchValue, ARRAYSIZE(rgchValue));
fAllBlank = fAllBlank && EMPTY_STRING(rgchValue);
TCHAR *pchNewLine = StrPBrk(rgchValue, TEXT("\r\n"));
if (pchNewLine)
*pchNewLine = '\0';
if (lstrlen(rgchValue)==0)
{
MLLoadString(IDS_OPS_BLANK, rgchValue, ARRAYSIZE(rgchValue));
}
SysFreeString(bstrValue);
lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
lvi.iItem = 0;
lvi.iSubItem = 0;
lvi.pszText = szName;
lvi.cchTextMax = MAX_PROFILE_NAME;
lvi.stateMask = LVIS_STATEIMAGEMASK;
lvi.state = pOpsEntry->m_fAnswer ? 0x00002000 : 0x00001000;
lvi.lParam = (LPARAM)pOpsEntry;
int iItem = ListView_InsertItem(hwndLV, &lvi);
lvi.mask = LVIF_TEXT;
lvi.iItem = iItem;
lvi.iSubItem = 1;
lvi.pszText = rgchValue;
ListView_SetItem(hwndLV, &lvi);
// APPCOMPAT: There is a problem with the listview implementation because of which
// the check box is not displayed even though lvi.state is set correctly.
// We have to find the item and set it again.
ListView_SetItemState(hwndLV, iItem, pOpsEntry->m_fAnswer ? 0x00002000 : 0x00001000, LVIS_STATEIMAGEMASK);
}
lpOpsDlgInfo->m_fAllBlank = fAllBlank;
// Autosize the columns
ListView_SetColumnWidth(hwndLV, 0, LVSCW_AUTOSIZE);
ListView_SetColumnWidth(hwndLV, 1, LVSCW_AUTOSIZE);
return TRUE;
}
BOOL CIEFrameAuto::COpsProfile::_OPSDlg_OnClose(HWND hDlg)
{
LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
int nItems = ListView_GetItemCount(hwndLV);
LV_ITEM lvi = {0};
lvi.mask = LVIF_PARAM ;
for (int i = 0; i < nItems ; i++ )
{
lvi.iItem = i;
lvi.lParam = 0;
ListView_GetItem(hwndLV, &lvi);
ASSERT(lvi.lParam != NULL)
if (lvi.lParam)
{
OPSRequestEntry * pOpsEntry = (OPSRequestEntry *)lvi.lParam;
pOpsEntry->m_fAnswer = ListView_GetCheckState(hwndLV, i);
}
}
lpOpsDlgInfo->m_fRemember = Button_GetCheck(GetDlgItem(hDlg, IDC_KEEP_SETTINGS));
return TRUE;
}
BOOL CIEFrameAuto::COpsProfile::_OPSConsent_EditProfile(HWND hDlg)
{
#ifdef _USE_PSTORE
return FALSE;
#else
HRESULT hr;
LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
if (!lpOpsDlgInfo || !lpOpsDlgInfo->m_hdpa)
return FALSE;
CIEFrameAuto::COpsProfile * pOpsProfile = lpOpsDlgInfo->m_pOpsProfile;
if (pOpsProfile == NULL || pOpsProfile->m_lpAdrBook == NULL)
{
ASSERT(FALSE);
return FALSE;
}
if (pOpsProfile->m_SBMe.cb == 0)
return FALSE;
LPSBinary lpSB = &(pOpsProfile->m_SBMe);
// Display the WAB dialog for the me entry.
hr = pOpsProfile->m_lpAdrBook->Details( (LPULONG) &hDlg,
NULL,
NULL,
lpSB->cb,
(LPENTRYID)lpSB->lpb,
NULL,
NULL,
NULL,
0);
return (hr) ? FALSE : TRUE;
#endif
}
BOOL CIEFrameAuto::COpsProfile::_OPSConsent_OnCommand(HWND hDlg, UINT id, UINT nCmd)
{
LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
switch (id)
{
case IDOK:
if (lpOpsDlgInfo->m_fAllBlank)
{
// The user has agreed to share information but all the entries in the
// profile are blank. This is probably due to user oversight, since the
// easier way to achieve the same effect would be to select "DENY"
TCHAR rgchHeading[256];
MLLoadShellLangString(IDS_PROFILE_ASSISTANT, rgchHeading, ARRAYSIZE(rgchHeading));
TCHAR rgchConfirm[1024];
MLLoadShellLangString(IDS_OPS_NO_INFORMATION, rgchConfirm, ARRAYSIZE(rgchConfirm));
ULONG_PTR uCookie = 0;
SHActivateContext(&uCookie);
DWORD msgRet = MessageBox(hDlg, rgchConfirm, rgchHeading, MB_YESNO | MB_DEFBUTTON1 | MB_ICONWARNING);
if (uCookie)
{
SHDeactivateContext(uCookie);
}
if (msgRet==IDYES)
goto FallThrough;
}
if (! Button_GetCheck(GetDlgItem(hDlg, IDC_KEEP_SETTINGS)) &&
(_GetCookieSettings()==COOKIES_ALLOW))
{
// The user wants to share information for one time only but cookies
// are enabled, allowing sites to store profile information in a cookie
DWORD dwConfirm = 0;
TCHAR rgchHeading[256];
TCHAR rgchConfirm[1024];
AccessSettings *pac = lpOpsDlgInfo->m_pacSettings;
MLLoadShellLangString(IDS_PROFILE_ASSISTANT, rgchHeading, ARRAYSIZE(rgchHeading));
MLLoadShellLangString(IDS_OPS_CONFIRM, rgchConfirm, ARRAYSIZE(rgchConfirm));
ULONG_PTR uCookie = 0;
SHActivateContext(&uCookie);
dwConfirm = MessageBox(hDlg, rgchConfirm, rgchHeading, MB_ICONINFORMATION | MB_OKCANCEL | MB_DEFBUTTON2);
if (uCookie)
{
SHDeactivateContext(uCookie);
}
if (dwConfirm!=IDOK)
break;
}
_OPSDlg_OnClose(hDlg);
EndDialog(hDlg, TRUE);
break;
FallThrough:
case IDC_EDIT_PROFILE:
{
HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
ListView_DeleteAllItems(hwndLV);
_OPSConsent_EditProfile(hDlg);
_OPSConsent_ShowRequestedItems(hDlg);
ListView_RedrawItems(hwndLV, 0, ListView_GetItemCount(hwndLV));
UpdateWindow(hwndLV);
break;
}
case IDCANCEL:
EndDialog(hDlg, FALSE);
break;
case IDC_VIEW_CERT:
_OPSConsent_ViewCertificate(hDlg);
break;
default:
return FALSE;
}
return TRUE;
}
BOOL
CIEFrameAuto::COpsProfile::_OPSConsent_ViewCertificate(HWND hDlg)
{
OPSDlgInfo *pDlgInfo = (OPSDlgInfo*) GetWindowLongPtr(hDlg, DWLP_USER);
InternetShowSecurityInfoByURL(pDlgInfo->m_rgchURL, hDlg);
return TRUE;
}
INT_PTR CIEFrameAuto::COpsProfile::_OPSConsent_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
ASSERT(NULL != lParam);
SetWindowLongPtr(hDlg, DWLP_USER, lParam); // save the list.
return _OPSConsent_OnInitDlg(hDlg);
case WM_COMMAND:
return _OPSConsent_OnCommand(hDlg, LOWORD(wParam), HIWORD(wParam));
case WM_HELP:
SHWinHelpOnDemandWrap((HWND) ((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
HELP_WM_HELP, (DWORD_PTR)(LPTSTR) aHelpIDs);
break;
case WM_CONTEXTMENU:
SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile, HELP_CONTEXTMENU,
(DWORD_PTR)(LPTSTR) aHelpIDs);
break;
case WM_DESTROY:
break;
}
return FALSE;
}
// Update dialog functions.
BOOL CIEFrameAuto::COpsProfile::_OPSUpdate_OnInitDlg(HWND hDlg)
{
LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
if (!lpOpsDlgInfo || !lpOpsDlgInfo->m_hdpa)
return FALSE;
HDPA hdpaList = lpOpsDlgInfo->m_hdpa;
HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
ASSERT(hwndLV);
// Add elements to the list view.
ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_CHECKBOXES);
// Initialize the common parts of the LVI
TCHAR szName[MAX_PROFILE_NAME];
LV_ITEM lvi = { 0 };
lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
lvi.iItem = 0;
lvi.pszText = szName;
lvi.cchTextMax = MAX_PROFILE_NAME;
lvi.stateMask = LVIS_STATEIMAGEMASK;
LV_FINDINFO lvfi = { 0 };
lvfi.flags = LVFI_STRING;
lvfi.psz = szName;
for (int i=0; i<DPA_GetPtrCount(hdpaList); i++)
{
OPSRequestEntry * pOpsEntry = (OPSRequestEntry*) DPA_FastGetPtr(hdpaList,i);
MLLoadString(_GetResourceIdFromAttrName(pOpsEntry->m_bstrName), szName, MAX_PATH);
pOpsEntry->m_fAnswer = TRUE;
lvi.state = 0x00002000;
lvi.lParam = (LPARAM)pOpsEntry;
ListView_InsertItem(hwndLV, &lvi);
// APPCOMPAT: There is a problem with the listview implementation because of which
// the check box is not displayed even though lvi.state is set correctly.
// We have to find the item and set it again.
ListView_SetItemState(hwndLV, ListView_FindItem(hwndLV, -1, &lvfi), 0x00002000, LVIS_STATEIMAGEMASK);
}
// show the items.
ListView_RedrawItems(hwndLV, 0, ListView_GetItemCount(hwndLV));
UpdateWindow(hwndLV);
return TRUE;
}
BOOL CIEFrameAuto::COpsProfile::_OPSUpdate_OnCommand(HWND hDlg, UINT id, UINT nCmd)
{
switch (id)
{
case IDOK:
_OPSDlg_OnClose(hDlg);
EndDialog(hDlg, TRUE);
break;
case IDCANCEL:
EndDialog(hDlg, FALSE);
break;
default:
return FALSE;
}
return TRUE;
}
INT_PTR CIEFrameAuto::COpsProfile::_OPSUpdate_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
ASSERT(NULL != lParam);
SetWindowLongPtr(hDlg, DWLP_USER, lParam); // save the list.
return _OPSUpdate_OnInitDlg(hDlg);
case WM_COMMAND:
return _OPSUpdate_OnCommand(hDlg, LOWORD(wParam), HIWORD(wParam));
case WM_HELP:
break;
case WM_CONTEXTMENU:
break;
case WM_DESTROY:
break;
}
return FALSE;
}
BOOL
CIEFrameAuto::COpsProfile ::_ValidateElemName(LPCWSTR szIn, INT *pIndex /* = NULL */)
{
int index = _GetAttrIndexFromName(szIn);
if ( INVALID_ATTRIBUTE_INDEX != index )
{
if (pIndex)
*pIndex = index;
return TRUE;
}
return FALSE;
}
INT CIEFrameAuto::COpsProfile::_GetAttrIndexFromName (LPCWSTR pwzName )
{
INT index = INVALID_ATTRIBUTE_INDEX;
if ( pwzName != NULL )
{
for ( int i = 0 ; i < ARRAYSIZE(rgProfAttr) ; i++ )
{
if (0 == StrCmpIW(rgProfAttr[i].pwzName, pwzName ))
{
index = i;
break;
}
}
}
return index;
}
INT CIEFrameAuto::COpsProfile::_GetResourceIdFromAttrName( WCHAR * pwzName)
{
return _GetResourceIdFromAttrIndex(_GetAttrIndexFromName(pwzName));
}
BOOL
CIEFrameAuto::COpsProfile::_IsLocalMachine() {
IInternetSecurityManager *pIScManager = NULL;
BSTR bstrURL;
HRESULT hr;
BOOL fLocal = FALSE;
DWORD dwZone;
hr = _pAuto->get_LocationURL(&bstrURL);
if ( FAILED(hr) )
goto Cleanup;
hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_IInternetSecurityManager, (void **)&pIScManager);
if ( FAILED(hr) )
goto Cleanup;
hr = pIScManager->MapUrlToZone(bstrURL, &dwZone, 0);
if ( FAILED(hr) )
goto Cleanup;
fLocal = (dwZone == URLZONE_LOCAL_MACHINE);
Cleanup:
SAFERELEASE(pIScManager);
SysFreeString(bstrURL);
return fLocal;
}
HRESULT
CIEFrameAuto::COpsProfile::_GetUserPreference(BSTR bstrName, P3UserPref *pUsrPref) {
TCHAR rgszName[MAX_PROFILE_NAME];
DWORD dwType;
DWORD dwPrefSize;
DWORD dwError;
_StringFromBSTR(bstrName, rgszName, ARRAYSIZE(rgszName));
dwPrefSize = sizeof(struct P3UserPref);
dwError = RegQueryValueEx(m_hP3Global, rgszName, 0, &dwType,
(LPBYTE) pUsrPref, &dwPrefSize);
if (dwError == ERROR_MORE_DATA)
{
BYTE *pBuffer;
pBuffer = new BYTE [dwPrefSize];
if (pBuffer == NULL)
{
return E_OUTOFMEMORY;
}
dwError = RegQueryValueEx(m_hP3Global, rgszName, 0, &dwType, pBuffer, &dwPrefSize);
memcpy(pUsrPref, pBuffer, sizeof(struct P3UserPref));
delete [] pBuffer;
}
// If a preference for this attribute is not found, create a default one and
// write it back to persistent storage
if (dwError != ERROR_SUCCESS)
{
P3UserPref defPrefs;
defPrefs.m_access = P3_QUERY;
defPrefs.m_lastRequest = P3_ACCEPT;
_PutUserPreference(bstrName, defPrefs);
*pUsrPref = defPrefs;
}
return S_OK;
}
HRESULT
CIEFrameAuto::COpsProfile::_PutUserPreference(BSTR bstrName, P3UserPref usrPref) {
TCHAR rgszName[MAX_PROFILE_NAME];
DWORD dwError;
_StringFromBSTR(bstrName, rgszName, ARRAYSIZE(rgszName));
dwError = RegSetValueEx(m_hP3Global, rgszName, 0, REG_BINARY,
(LPBYTE) &usrPref,
sizeof(struct P3UserPref));
return HRESULT_FROM_WIN32(dwError);
}
BOOL
CIEFrameAuto::COpsProfile::_IsUsingSSL()
{
BOOL fSecure = FALSE;
BSTR bstrUrl;
TCHAR rgchUrl[MAX_URL_STRING+1];
_pAuto->get_LocationURL(&bstrUrl);
_StringFromBSTR(bstrUrl, rgchUrl, ARRAYSIZE(rgchUrl));
SysFreeString(bstrUrl);
fSecure = GetUrlScheme(rgchUrl)==URL_SCHEME_HTTPS;
return fSecure;
}
HRESULT
CIEFrameAuto::COpsProfile::_ApplyPreferences(URL_COMPONENTS *pucURL, HDPA hdpaReqList)
{
for (int k=0; k<DPA_GetPtrCount(hdpaReqList); k++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(hdpaReqList,k);
pCurrent->m_fQuery = TRUE;
pCurrent->m_fAnswer = FALSE;
pCurrent->m_dwDecision = P3_NONE;
}
_ApplySiteSettings(pucURL, hdpaReqList);
_ApplyGlobalSettings(hdpaReqList);
return S_OK;
}
HRESULT
CIEFrameAuto::COpsProfile::_ApplyGlobalSettings(HDPA hdpaReqList)
{
for (int k=0; k<DPA_GetPtrCount(hdpaReqList); k++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(hdpaReqList,k);
P3UserPref userInfo;
_GetUserPreference(pCurrent->m_bstrName, &userInfo);
switch (userInfo.m_access)
{
case P3_GRANT: if (pCurrent->m_fQuery)
{
pCurrent->grantRequest();
pCurrent->m_dwDecision = P3_GLOBAL;
}
break;
case P3_DENY: pCurrent->denyRequest();
pCurrent->m_dwDecision = P3_GLOBAL;
break;
case P3_REQSSL: // This resolves to P3_QUERY at the moment
case P3_QUERY: if (pCurrent->m_fQuery)
pCurrent->m_fAnswer = (userInfo.m_lastRequest == P3_ACCEPT);
break;
default: ;
}
}
return S_OK;
}
HRESULT
CIEFrameAuto::COpsProfile::_ApplySiteSettings(URL_COMPONENTS *pucURL, HDPA hdpaReqList)
{
if (pucURL->nScheme!=INTERNET_SCHEME_HTTP && pucURL->nScheme!=INTERNET_SCHEME_HTTPS)
return S_OK;
TCHAR *pszSubDomain = pucURL->lpszHostName;
// For a given hostname such as "www.foo.bar.com", this loop will iterate over all possible
// domains such as "www.foo.bar.com", ".foo.bar.com" and ".bar.com" but NOT ".com"
while (pszSubDomain!=NULL && _LegalDomain(pucURL->lpszHostName, pszSubDomain))
{
HKEY hkey = NULL;
if (ERROR_SUCCESS == RegOpenKeyEx(m_hP3Sites, pszSubDomain, 0, KEY_ALL_ACCESS, &hkey))
{
_ApplyDomainSettings(pucURL, hkey, hdpaReqList);
RegCloseKey(hkey);
}
pszSubDomain = StrChr(pszSubDomain+1, TEXT('.')); // Find the next embedded dot
}
return S_OK;
}
HRESULT
CIEFrameAuto::COpsProfile::_ApplyDomainSettings(URL_COMPONENTS *pucComp, HKEY hkey, HDPA hdpaReqList)
{
DWORD dwError;
DWORD dwIndex = 0;
TCHAR rgchName[MAX_PATH];
int iReqCount = DPA_GetPtrCount(hdpaReqList);
DWORD *pdwLastApplied = new DWORD[iReqCount];
if (pdwLastApplied == NULL)
{
return E_OUTOFMEMORY;
}
for (int i=0; i<iReqCount; i++)
pdwLastApplied[i] = 0;
do
{
DWORD dwcbVal = ARRAYSIZE(rgchName);
dwError = RegEnumKeyEx(hkey, dwIndex, rgchName, &dwcbVal, NULL, NULL, NULL, NULL);
if (dwError==ERROR_SUCCESS)
{
HKEY hPathKey;
AccessSettings ac;
dwError = RegOpenKeyEx(hkey, rgchName, 0, KEY_READ, &hPathKey);
_ReadSettingsFromRegistry(hPathKey, &ac);
_ApplySettings(&ac, pucComp, hdpaReqList, pdwLastApplied);
RegCloseKey(hPathKey);
}
dwIndex++;
}
while (dwError==ERROR_SUCCESS);
delete [] pdwLastApplied;
return S_OK;
}
HRESULT
CIEFrameAuto::COpsProfile::_UpdateSiteSettings(AccessSettings *pSettings, HDPA hdpaReqList)
{
DWORD dwError;
DWORD dwAction;
HKEY hDomainKey = NULL;
HKEY hPathKey = NULL;
// Clear the allow and deny vectors
ZeroMemory(pSettings->m_rgbStdAllow, sizeof(pSettings->m_rgbStdAllow));
ZeroMemory(pSettings->m_rgbStdDeny, sizeof(pSettings->m_rgbStdDeny));
// Fill out the vectors based on the user responses on the request list
for (int i=0; i<DPA_GetPtrCount(hdpaReqList); i++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(hdpaReqList,i);
int iVcardIndex = _GetAttrIndexFromName(pCurrent->m_bstrName);
// At the moment we do not handle custom attributes
if (iVcardIndex!=INVALID_ATTRIBUTE_INDEX)
_WriteBitVector(pCurrent->m_fAnswer ? pSettings->m_rgbStdAllow : pSettings->m_rgbStdDeny, iVcardIndex);
}
// Create a key for the given domain or open it if one already exists
dwError = RegCreateKeyEx(m_hP3Sites, pSettings->m_rgchDomain,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&hDomainKey, &dwAction);
if (dwError!=ERROR_SUCCESS)
return E_FAIL;
TCHAR rgchName[16];
DWORD dwcbName = 0;
DWORD dwIndex = 0;
do
{
AccessSettings ac;
dwcbName = ARRAYSIZE(rgchName);
if (ERROR_SUCCESS != RegEnumKeyEx(hDomainKey, dwIndex, rgchName, &dwcbName, NULL, NULL, NULL, NULL))
break;
if (ERROR_SUCCESS != RegOpenKeyEx(hDomainKey, rgchName, 0, KEY_READ, &hPathKey))
break;
_ReadSettingsFromRegistry(hPathKey, &ac);
// If there are existing settings for this domain and path, merge the permissions
if (StrCmp(ac.m_rgchPath, pSettings->m_rgchPath) == 0)
{
// An attribute is allowed if it has been allowed explicitly by the user from
// the current UI or it was previously allowed and it has not been denied
// in the current UI. Similarly, an attribute is denied if it is denied in the
// current UI or it was denied previously and it has not been granted this time.
for (int i=0; i<ARRAYSIZE(pSettings->m_rgbStdAllow); i++)
{
pSettings->m_rgbStdAllow[i] |= ac.m_rgbStdAllow[i] & ~(pSettings->m_rgbStdDeny[i]);
pSettings->m_rgbStdDeny[i] |= ac.m_rgbStdDeny[i] & ~(pSettings->m_rgbStdAllow[i]);
}
break;
}
RegCloseKey(hPathKey);
dwIndex++;
}
while (dwError==ERROR_SUCCESS);
wnsprintf(rgchName, ARRAYSIZE(rgchName), TEXT("%03d"), dwIndex);
if (ERROR_SUCCESS == RegCreateKeyEx(hDomainKey, rgchName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hPathKey, &dwAction))
_WriteSettingsToRegistry(hPathKey, pSettings);
RegCloseKey(hPathKey);
RegCloseKey(hDomainKey);
return S_OK;
}
BOOL
CIEFrameAuto::COpsProfile::_ReadBitVector(LPCBYTE ucBitVector, DWORD dwIndex)
{
DWORD dwByte = dwIndex/8;
DWORD dwMask = 0x80 >> (dwIndex & 0x07);
return (ucBitVector[dwByte]&dwMask) != 0;
}
VOID
CIEFrameAuto::COpsProfile::_WriteBitVector(LPBYTE ucBitVector, DWORD dwIndex)
{
DWORD dwByte = dwIndex/8;
DWORD dwMask = 0x80 >> (dwIndex & 0x07);
ucBitVector[dwByte] |= dwMask;
}
// The path matching is done on a character-level, which is the way cookies are
// implemented in IE4 and in Navigator
// Note that this is different from the RFC-2109
BOOL
CIEFrameAuto::COpsProfile::_PathMatch(TCHAR *pszDocumentPath, TCHAR *pszAccessPath)
{
return StrStr(pszDocumentPath,pszAccessPath) == pszDocumentPath;
}
// Domain name matching is done on the character level except that a leading
// period is added to the access domain if necessary
// Refer to "cookie.cxx" in MSHTML for details
BOOL
CIEFrameAuto::COpsProfile::_DomainMatch(TCHAR *pszHostName, TCHAR *pszDomain)
{
// If domain is the same as hostname, matching is successful
if (StrCmp(pszHostName, pszDomain) == 0)
return TRUE;
// Fail if the domain is not a legal subdomain of the hostname
// This prevents matching against invaid domains such as ".com" or ".edu"
if (! _LegalDomain(pszHostName, pszDomain))
return FALSE;
// Find the matching part of the domain on the access path
TCHAR *pszMatchingPart = StrStr(pszHostName, pszDomain);
// If the domain is not a substring of the hostname, it does not match
if (pszMatchingPart==NULL)
return FALSE;
// Otherwise the domain must be a suffix and it should either contain a period
// at the beginning or should match following a period
if (StrCmp(pszMatchingPart, pszDomain) != 0)
return FALSE;
if (*pszMatchingPart!='.' && pszMatchingPart[-1]!='.')
return FALSE;
return TRUE;
}
BOOL
CIEFrameAuto::COpsProfile::_LegalDomain(TCHAR *pszHostName, TCHAR *pszDomain)
{
// Fail if either of the strings are invalid
if (pszHostName==NULL || pszDomain==NULL ||
EMPTY_STRING(pszHostName) || EMPTY_STRING(pszDomain))
return FALSE;
// If domain is the same as hostname, it is always valid
if (!StrCmpI(pszHostName, pszDomain))
return TRUE;
int iEmbeddedPeriods = 0;
// Count the number of embedded periods, defined as the number of dots after
// the first character of the domain
for(int i=1; pszDomain[i]!=0; i++)
if (pszDomain[i]=='.')
iEmbeddedPeriods++;
// Require that the domain name has at least one embedded period
if (iEmbeddedPeriods==0)
return FALSE;
// Find the requested domain name in the host name
TCHAR *pszMatchingPart = StrStr(pszHostName, pszDomain);
// Require that this search succeed
if (pszMatchingPart==NULL)
return FALSE;
// Require furthermore that the domain name be a suffix of the hostname
if (StrCmp(pszMatchingPart, pszDomain) != 0)
return FALSE;
// If all the above criteria has been satisfied, then the domain is valid
return TRUE;
}
// Path matching is done at a character-level; this is to be compliant with Netscape
// Navigator and the original cookie specification.
// This has the surprising result that "/foo" matches "/foo/doc" as well as "/foobar/doc"
BOOL
CIEFrameAuto::COpsProfile::_LegalPath(TCHAR *pszActualPath, TCHAR *pszAccessPath)
{
return StrStr(pszActualPath, pszAccessPath) == pszActualPath;
}
// For the ANSI<-->UNICODE transition
HRESULT
CIEFrameAuto::COpsProfile::_StringFromBSTR(BSTR bstrSource, TCHAR *pszDest, DWORD dwDestSize)
{
StrCpyNW(pszDest, bstrSource, dwDestSize-1);
return S_OK;
}
HRESULT
CIEFrameAuto::COpsProfile::_StringFromVariant(VARIANT *vaSource, TCHAR *pszDest, DWORD dwDestSize)
{
VARIANT vaTemp;
HRESULT hr;
VariantInit(&vaTemp);
hr = VariantChangeType(&vaTemp, vaSource, 0, VT_BSTR);
if (SUCCEEDED(hr))
_StringFromBSTR(vaTemp.bstrVal, pszDest, dwDestSize);
else
ZeroMemory(pszDest, dwDestSize);
VariantClear(&vaTemp);
return hr;
}
INT
CIEFrameAuto::COpsProfile::_GetCookieSettings()
{
HKEY hInetKey = NULL;
DWORD dwCookiePref;
DWORD dwDataRead = sizeof(dwCookiePref);
DWORD dwError = RegOpenKeyEx(HKEY_CURRENT_USER, rgszInetKey, 0, KEY_READ, &hInetKey);
if (dwError !=ERROR_SUCCESS)
return COOKIES_DENY;
dwError = RegQueryValueEx(hInetKey, rgszCookieTxt, NULL, NULL, (LPBYTE) &dwCookiePref, &dwDataRead);
RegCloseKey(hInetKey);
if (dwError==ERROR_SUCCESS)
return dwCookiePref;
else
return COOKIES_ALLOW;
}
HRESULT
CIEFrameAuto::COpsProfile::_GetUsageCode(VARIANT vaUsage, LPTSTR rgchUsage, int cLen)
{
LONG lUsage;
VARIANT varDest;
VariantInit(&varDest);
HRESULT hr = VariantChangeType(&varDest, &vaUsage, 0, VT_I4);
if (SUCCEEDED(hr))
{
lUsage = varDest.lVal;
// If lUsage is not within range just display unknown usage.
if (lUsage < 0 || lUsage > (IDS_OPS_USAGEMAX - IDS_OPS_USAGE0))
lUsage = -1;
}
else
lUsage = -1;
VariantClear(&varDest);
MLLoadString(lUsage + IDS_OPS_USAGE0, rgchUsage, cLen);
return S_OK;
}
BOOL
CIEFrameAuto::COpsProfile::_IsP3Enabled()
{
DWORD dwEnabled;
DWORD dwDataOut = sizeof(dwEnabled);
DWORD dwError = RegQueryValueEx(m_hP3Global, rgszEnabled,
NULL, NULL,
(LPBYTE) &dwEnabled, &dwDataOut);
if (dwError!=ERROR_SUCCESS)
{
dwEnabled = TRUE;
RegSetValueEx( m_hP3Global, rgszEnabled, 0, REG_DWORD,
(LPBYTE) &dwEnabled, sizeof(dwEnabled));
return TRUE;
}
else
return dwEnabled;
}
// The script can specify domain, path and expiration date for the settings.
// If these are not provided, the domain defaults to the hostname, the path to the current
// document and the expiration to a specified number of days in the future
HRESULT
CIEFrameAuto::COpsProfile::_GetSiteSettings(URL_COMPONENTS *pucComp,
VARIANT vaDomain, VARIANT vaPath, VARIANT vaExpire,
AccessSettings *pSettings)
{
SYSTEMTIME st;
TCHAR rgchExpire[32];
HRESULT hr;
BOOL bRet;
// Note: For IE4, the domain name has to be hostname.
StrCpyN(pSettings->m_rgchDomain, pucComp->lpszHostName, ARRAYSIZE(pSettings->m_rgchDomain));
hr = _StringFromVariant(&vaPath, pSettings->m_rgchPath, ARRAYSIZE(pSettings->m_rgchPath));
if (FAILED(hr))
StrCpyN(pSettings->m_rgchPath, pucComp->lpszUrlPath, ARRAYSIZE(pSettings->m_rgchPath));
// If the path is different from the page, add a "/" if necessary at the end
DWORD dwPathLen = lstrlen(pSettings->m_rgchPath);
if (StrCmp(pSettings->m_rgchPath, pucComp->lpszUrlPath) &&
pSettings->m_rgchPath[dwPathLen-1] != TEXT('/'))
{
StrCatBuff(pSettings->m_rgchPath, TEXT("/"), ARRAYSIZE(pSettings->m_rgchPath));
}
FILETIME ftNow;
LARGE_INTEGER *pqwNow = (LARGE_INTEGER*) & ftNow;
LARGE_INTEGER *pftime = (LARGE_INTEGER*) & pSettings->m_ftExpire;
GetSystemTimeAsFileTime(&ftNow);
hr = _StringFromVariant(&vaExpire, rgchExpire, ARRAYSIZE(rgchExpire));
if (SUCCEEDED(hr))
{
bRet = InternetTimeToSystemTime(rgchExpire, &st, 0);
SystemTimeToFileTime(&st, & pSettings->m_ftExpire);
}
if (FAILED(hr) || !bRet)
{
QUAD_PART(*pftime) = QUAD_PART(*pqwNow) + defExpiration;
}
// Enforce the limit on expiration time
__int64 qwDelta = (QUAD_PART(*pftime)) - (QUAD_PART(*pqwNow));
if (qwDelta<0 || qwDelta>maxExpiration)
QUAD_PART(*pftime) = QUAD_PART(*pqwNow) + maxExpiration;
// Make sure that the domain and path are valid
// The criteria is a mix of the cookie semantics as defined by RFC-2109 and Navigator
// compliant behaviour as implemented elsewhere in IE4
if (! _LegalPath(pucComp->lpszUrlPath, pSettings->m_rgchPath) )
StrCpyN(pSettings->m_rgchPath, pucComp->lpszUrlPath, ARRAYSIZE(pSettings->m_rgchPath));
if (! _LegalDomain(pucComp->lpszHostName, pSettings->m_rgchDomain) )
StrCpyN(pSettings->m_rgchDomain, pucComp->lpszHostName, ARRAYSIZE(pSettings->m_rgchDomain));
// Add a period at the beginning of the domain name if it is not equal to
// the host name
if (StrCmpI(pucComp->lpszHostName, pSettings->m_rgchDomain) &&
pSettings->m_rgchDomain[0] != '.')
{
StrCpyN(1+pSettings->m_rgchDomain, pSettings->m_rgchDomain, lstrlen(pSettings->m_rgchDomain));
pSettings->m_rgchDomain[0] = '.';
}
pSettings->m_fExactDomain = ! StrCmpI(pSettings->m_rgchDomain, pucComp->lpszHostName);
if (StrCmp(pSettings->m_rgchPath, pucComp->lpszUrlPath))
{
pSettings->m_fExactPath = FALSE;
}
else
{
pSettings->m_fExactPath = pSettings->m_rgchPath[dwPathLen-1]!=TEXT('/');
}
return S_OK;
}
HRESULT
CIEFrameAuto::COpsProfile::_FormatSiteSettings(AccessSettings *pSettings, LPTSTR rgchOut, int cLimit)
{
TCHAR rgchFullName[MAX_URL_STRING];
TCHAR rgchTemp[MAX_URL_STRING];
wnsprintf(rgchFullName,
ARRAYSIZE(rgchFullName),
TEXT("http://%s%s"),
pSettings->m_rgchDomain,
pSettings->m_rgchPath);
FormatUrlForDisplay(rgchFullName, rgchTemp, cLimit, NULL, 0, FALSE, CP_ACP, NULL);
TCHAR *pchSiteName = StrStr(rgchTemp, TEXT("//"));
if (pchSiteName==NULL)
pchSiteName = rgchTemp;
else
pchSiteName += 2;
StrCpyN(rgchOut, pchSiteName, cLimit);
return S_OK;
}
// Attempts to use the given settings to determine the user response to the requests
// in the given list. If the domain and path for the settings is not applicable to
// for the given URL, returns FALSE.
BOOL
CIEFrameAuto::COpsProfile::_ApplySettings(AccessSettings *pac, URL_COMPONENTS *puc, HDPA hdpaReqList, DWORD *pdwLast)
{
if (!_DomainMatch(puc->lpszHostName, pac->m_rgchDomain) ||
!_PathMatch(puc->lpszUrlPath, pac->m_rgchPath))
return FALSE;
DWORD dwPathLen = lstrlen(pac->m_rgchPath);
for (int i=0; i<DPA_GetPtrCount(hdpaReqList); i++)
{
OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(hdpaReqList,i);
int iVcIndex = _GetAttrIndexFromName(pCurrent->m_bstrName);
if (iVcIndex==INVALID_ATTRIBUTE_INDEX)
continue;
if (pdwLast[i]>=dwPathLen)
continue;
else
pdwLast[i] = dwPathLen;
BOOL fAllow = _ReadBitVector(pac->m_rgbStdAllow, iVcIndex);
BOOL fDeny = _ReadBitVector(pac->m_rgbStdDeny, iVcIndex);
if (fDeny)
{
pCurrent->denyRequest();
pCurrent->m_dwDecision = P3_SITELEVEL;
}
else if (fAllow)
{
pCurrent->grantRequest();
pCurrent->m_dwDecision = P3_SITELEVEL;
}
}
return TRUE;
}
BOOL
CIEFrameAuto::COpsProfile::_ReadSettingsFromRegistry(HKEY hkey, AccessSettings *pac)
{
DWORD dwError;
DWORD dwcb;
ZeroMemory(pac, sizeof(struct AccessSettings));
dwcb = sizeof(pac->m_rgbStdAllow);
dwError = RegQueryValueEx(hkey, rgszAllowTxt, NULL, NULL, (LPBYTE) pac->m_rgbStdAllow, &dwcb);
dwcb = sizeof(pac->m_rgbStdDeny);
dwError = RegQueryValueEx(hkey, rgszDenyTxt, NULL, NULL, (LPBYTE) pac->m_rgbStdDeny, &dwcb);
dwcb = sizeof(pac->m_rgchPath);
dwError = RegQueryValueEx(hkey, rgszPathTxt, NULL, NULL, (LPBYTE) pac->m_rgchPath, &dwcb);
dwcb = sizeof(pac->m_rgchDomain);
dwError = RegQueryValueEx(hkey, rgszDomainTxt, NULL, NULL, (LPBYTE) pac->m_rgchDomain, &dwcb);
return (dwError==ERROR_SUCCESS);
}
BOOL
CIEFrameAuto::COpsProfile::_WriteSettingsToRegistry(HKEY hkey, AccessSettings *pac)
{
RegSetValueEx(hkey, rgszAllowTxt, 0, REG_BINARY, pac->m_rgbStdAllow, sizeof(pac->m_rgbStdAllow));
RegSetValueEx(hkey, rgszDenyTxt, 0, REG_BINARY, pac->m_rgbStdDeny, sizeof(pac->m_rgbStdDeny));
RegSetValueEx(hkey, rgszPathTxt, 0, REG_SZ, (LPBYTE) pac->m_rgchPath, sizeof(pac->m_rgchPath));
RegSetValueEx(hkey, rgszDomainTxt, 0, REG_SZ, (LPBYTE) pac->m_rgchDomain, sizeof(pac->m_rgchDomain));
return TRUE;
}
// This function revokes all site permission given previously by deleting
// the registry entries for all the domains under the "P3Sites" key
// It is not a good idea to invoke recursive delete on the P3Sites key because
// the running instance of the navigator will end up with an invalid handle
HRESULT
CIEFrameAuto::COpsProfile::_ClearAllSettings(HWND hwnd)
{
DWORD dwAction;
DWORD dwError;
HKEY hP3Sites;
dwError = RegCreateKeyEx(HKEY_CURRENT_USER, rgszP3Sites, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &hP3Sites, &dwAction);
DWORD dwIndex = 0;
DWORD dwcbVal;
TCHAR rgchName[MAX_PATH];
HDPA hdpaKeys = DPA_Create(0);
do
{
dwcbVal = ARRAYSIZE(rgchName);
dwError = RegEnumKeyEx(hP3Sites, dwIndex, rgchName, &dwcbVal, NULL, NULL, NULL, NULL);
if (dwError==ERROR_SUCCESS)
{
LPTSTR pszSiteName = new TCHAR[MAX_PATH];
if (pszSiteName)
{
StrCpyN(pszSiteName, rgchName, MAX_PATH);
DPA_AppendPtr(hdpaKeys, pszSiteName);
}
}
dwIndex++;
}
while (dwError==ERROR_SUCCESS);
for (int i=0; i<DPA_GetPtrCount(hdpaKeys); i++)
{
LPTSTR pszSiteName = (LPTSTR) DPA_FastGetPtr(hdpaKeys, i);
SHDeleteKey(hP3Sites, pszSiteName);
delete pszSiteName;
}
DPA_Destroy(hdpaKeys);
hdpaKeys = NULL;
return S_OK;
}
BOOL
CIEFrameAuto::COpsProfile::_DifferentURL()
{
BSTR bstrCurrentURL = NULL;
HRESULT hr = _pAuto->get_LocationURL(&bstrCurrentURL);
BOOL fDifferent = (m_bstrLastURL!=NULL) && StrCmpW(bstrCurrentURL, m_bstrLastURL);
SysFreeString(bstrCurrentURL);
return fDifferent;
}
STDAPI ResetProfileSharing(HWND hwin)
{
return CIEFrameAuto::COpsProfile::_ClearAllSettings(hwin);
}