2737 lines
81 KiB
C++
2737 lines
81 KiB
C++
//
|
|
// 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_READ | KEY_SET_VALUE,
|
|
NULL,
|
|
&m_hP3Global,
|
|
&dwAction);
|
|
|
|
dwError = RegCreateKeyEx(HKEY_CURRENT_USER,
|
|
rgszP3Sites,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_CREATE_SUB_KEY,
|
|
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];
|
|
|
|
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));
|
|
|
|
URL_COMPONENTS uc = {0};
|
|
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.
|
|
|
|
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(bstrAttribValue);
|
|
|
|
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;
|
|
|
|
HRESULT hr;
|
|
BOOL fOpen = FALSE;
|
|
|
|
if (pszField==NULL || pbstrValue==NULL)
|
|
return E_POINTER;
|
|
|
|
PST_PROMPTINFO promptInfo = {0};
|
|
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)
|
|
{
|
|
cch = lstrlen(pszPropStr) + 1;
|
|
pwzValue = new WCHAR [cch];
|
|
if (NULL == pwzValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
StrCpyN(pwzValue, pszPropStr, cch);
|
|
}
|
|
}
|
|
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));
|
|
StringCchPrintf(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()
|
|
{
|
|
BOOL fLocal = FALSE;
|
|
|
|
BSTR bstrURL;
|
|
HRESULT hr = _pAuto->get_LocationURL(&bstrURL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DWORD dwZone;
|
|
hr = GetZoneFromUrl(bstrURL, _pAuto->_psp, &dwZone);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
fLocal = (dwZone == URLZONE_LOCAL_MACHINE);
|
|
}
|
|
|
|
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_ENUMERATE_SUB_KEYS, &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_QUERY_VALUE, &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;
|
|
|
|
// 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
|
|
HKEY hDomainKey;
|
|
dwError = RegCreateKeyEx(m_hP3Sites, pSettings->m_rgchDomain,
|
|
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ENUMERATE_SUB_KEYS,
|
|
NULL, &hDomainKey, &dwAction);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
return E_FAIL;
|
|
|
|
TCHAR rgchName[16];
|
|
DWORD dwIndex = 0;
|
|
|
|
do
|
|
{
|
|
DWORD dwcbName = ARRAYSIZE(rgchName);
|
|
if (ERROR_SUCCESS == RegEnumKeyEx(hDomainKey, dwIndex, rgchName, &dwcbName, NULL, NULL, NULL, NULL))
|
|
{
|
|
HKEY hPathKey;
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hDomainKey, rgchName, 0, KEY_QUERY_VALUE, &hPathKey))
|
|
{
|
|
AccessSettings ac;
|
|
_ReadSettingsFromRegistry(hPathKey, &ac);
|
|
RegCloseKey(hPathKey); // not needed below
|
|
|
|
// 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;
|
|
}
|
|
dwIndex++;
|
|
}
|
|
}
|
|
}
|
|
while (dwError == ERROR_SUCCESS);
|
|
|
|
StringCchPrintf(rgchName, ARRAYSIZE(rgchName), TEXT("%03d"), dwIndex);
|
|
|
|
HKEY hPathKey;
|
|
if (ERROR_SUCCESS == RegCreateKeyEx(hDomainKey, rgchName, 0, NULL, 0, KEY_SET_VALUE, 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 cchDestSize)
|
|
{
|
|
StrCpyNW(pszDest, bstrSource, cchDestSize);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CIEFrameAuto::COpsProfile::_StringFromVariant(VARIANT *vaSource, TCHAR *pszDest, DWORD cchDestSize)
|
|
{
|
|
VARIANT vaTemp;
|
|
HRESULT hr;
|
|
|
|
VariantInit(&vaTemp);
|
|
hr = VariantChangeType(&vaTemp, vaSource, 0, VT_BSTR);
|
|
|
|
if (SUCCEEDED(hr))
|
|
_StringFromBSTR(vaTemp.bstrVal, pszDest, cchDestSize);
|
|
else
|
|
ZeroMemory(pszDest, cchDestSize*sizeof(TCHAR));
|
|
|
|
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 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, ARRAYSIZE(pSettings->m_rgchDomain)-1);
|
|
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];
|
|
|
|
StringCchPrintf(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_READ | DELETE, 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)
|
|
{
|
|
int cchSiteName = MAX_PATH;
|
|
LPTSTR pszSiteName = new TCHAR[cchSiteName];
|
|
if (pszSiteName)
|
|
{
|
|
StrCpyN(pszSiteName, rgchName, cchSiteName);
|
|
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);
|
|
}
|
|
|