// // 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 // 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=0 && index=0 && indexgrantRequest(); 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; im_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; kclearValue(); } 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; km_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; km_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; im_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; im_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; im_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; im_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; im_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; im_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_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; im_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; km_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; km_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; im_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; im_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; im_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; im_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; iget_LocationURL(&bstrCurrentURL); BOOL fDifferent = (m_bstrLastURL!=NULL) && StrCmpW(bstrCurrentURL, m_bstrLastURL); SysFreeString(bstrCurrentURL); return fDifferent; } STDAPI ResetProfileSharing(HWND hwin) { return CIEFrameAuto::COpsProfile::_ClearAllSettings(hwin); }