// // privacyui.cpp - Implements the UI for IE's privacy features // // The privacy dialog is managed from this sourcefile. // The privacy view dialog is also managed from this sourcefile. #include "priv.h" #include "resource.h" #include "privacyui.hpp" #include #include "richedit.h" #include "SmallUtil.hpp" #define REGSTR_PRIVACYPS_PATHEDIT TEXT("Software\\Policies\\Microsoft\\Internet Explorer") #define REGSTR_PRIVACYPS_VALUEDIT TEXT("PrivacyAddRemoveSites") // this key is duplicated in cpls\inetcpl\privacyui.cpp #define REGSTR_PRIVACYPS_PATHPANE TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\Control Panel") #define REGSTR_PRIVACYPS_VALUPANE TEXT("Privacy Settings") // this key is duplicated in cpls\inetcpl\privacyui.cpp #define REGSTR_PRIVACYPS_PATHTAB TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\Control Panel") #define REGSTR_PRIVACYPS_VALUTAB TEXT("PrivacyTab") // this key is duplicated somewhere else BOOL allowPerSiteModify() { DWORD dwSize, dwRet, dwType, dwValue; dwSize = sizeof(dwValue); dwRet = SHGetValue(HKEY_CURRENT_USER, REGSTR_PRIVACYPS_PATHEDIT, REGSTR_PRIVACYPS_VALUEDIT, &dwType, &dwValue, &dwSize); if (ERROR_SUCCESS == dwRet && dwValue && REG_DWORD == dwType) { return FALSE; } dwSize = sizeof(dwValue); dwRet = SHGetValue(HKEY_CURRENT_USER, REGSTR_PRIVACYPS_PATHPANE, REGSTR_PRIVACYPS_VALUPANE, &dwType, &dwValue, &dwSize); if (ERROR_SUCCESS == dwRet && dwValue && REG_DWORD == dwType) { return FALSE; } dwSize = sizeof(dwValue); dwRet = SHGetValue(HKEY_CURRENT_USER, REGSTR_PRIVACYPS_PATHTAB, REGSTR_PRIVACYPS_VALUTAB, &dwType, &dwValue, &dwSize); if (ERROR_SUCCESS == dwRet && dwValue && REG_DWORD == dwType) { return FALSE; } return TRUE; } struct SPerSiteData; typedef SPerSiteData* PSPerSiteData; class CPolicyHunt; struct SPrivacyDialogData; typedef SPrivacyDialogData* PSPrivacyDialogData; //+--------------------------------------------------------------------------- // // Function: HyperlinkSubclass // // Synopsis: subclass for the makeshift hyperlink control // // Arguments: [hwnd] -- window handle // [uMsg] -- message id // [wParam] -- parameter 1 // [lParam] -- parameter 2 // // Returns: TRUE if message handled, FALSE otherwise // // Notes: // //---------------------------------------------------------------------------- LRESULT CALLBACK HyperlinkSubclass ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { WNDPROC wndproc; static BOOL fMouseCaptured; wndproc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA); switch ( uMsg ) { case WM_SETCURSOR: if (!fMouseCaptured) { SetCapture(hwnd); fMouseCaptured = TRUE; } SetCursor(LoadHandCursor(0)); return( TRUE ); case WM_GETDLGCODE: { MSG* pmsg; LRESULT lRet = DLGC_STATIC; if (((pmsg = (MSG*)lParam)) && ((WM_KEYDOWN == pmsg->message || WM_KEYUP == pmsg->message))) { switch(pmsg->wParam) { case VK_RETURN: case VK_SPACE: lRet |= DLGC_WANTALLKEYS; break; default: break; } } return lRet; } case WM_KEYDOWN: if ((wParam!=VK_SPACE)&&(wParam!=VK_RETURN)) { break; } case WM_LBUTTONUP: SetFocus(hwnd); PostMessage( GetParent(hwnd), WM_APP, (WPARAM)GetDlgCtrlID( hwnd), (LPARAM)hwnd); return( TRUE ); case WM_LBUTTONDBLCLK: case WM_MBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: return( TRUE ); case EM_SETSEL: return( TRUE ); case WM_SETFOCUS: if ( hwnd == GetFocus() ) { InvalidateRect(hwnd, NULL, FALSE); UpdateWindow(hwnd); SetCursor(LoadHandCursor(0)); return( TRUE ); } break; case WM_KILLFOCUS: InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); SetCursor(LoadCursor(NULL, IDC_ARROW)); return( TRUE ); case WM_PAINT: CallWindowProc(wndproc, hwnd, uMsg, wParam, lParam); if ( hwnd == GetFocus() ) { DrawFocusRectangle(hwnd, NULL); } return( TRUE ); case WM_MOUSEMOVE: RECT rect; int xPos, yPos; // check to see if the mouse is in this windows rect, if not, then reset // the cursor to an arrow and release the mouse GetClientRect(hwnd, &rect); xPos = LOWORD(lParam); yPos = HIWORD(lParam); if ((xPos < 0) || (yPos < 0) || (xPos > (rect.right - rect.left)) || (yPos > (rect.bottom - rect.top))) { SetCursor(LoadCursor(NULL, IDC_ARROW)); ReleaseCapture(); fMouseCaptured = FALSE; } } return(CallWindowProc(wndproc, hwnd, uMsg, wParam, lParam)); } // Data structure associated with each site the privacy dialog may show struct SPerSiteData : public IDispatch { BSTR bstrUrl; BSTR bstrCookieDomain; BSTR bstrHeaderPolicyRef; BSTR bstrLinkTagPolicyRef; DWORD dwFlags; int iPrivacyImpactResource; CPolicyHunt* pPolicyHunt; SPerSiteData(); ~SPerSiteData(); BOOL ReadyForPolicyHunt(); // here is overhead for IDispatch: virtual ULONG __stdcall AddRef( void ); virtual ULONG __stdcall Release( void ); virtual HRESULT __stdcall QueryInterface( REFIID iid, void ** ppv); virtual HRESULT __stdcall GetTypeInfoCount( unsigned int FAR* pctinfo); virtual HRESULT __stdcall GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo); virtual HRESULT __stdcall GetIDsOfNames( REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId); virtual HRESULT __stdcall Invoke( DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr); }; enum enumPolicyHuntResult { POLICYHUNT_INPROGRESS, POLICYHUNT_NOTFOUND, POLICYHUNT_FOUND, POLICYHUNT_ERROR, POLICYHUNT_FORMATERROR, POLICYHUNT_CANCELLED, }; class CPolicyHunt : public CCancellableThread { public: CPolicyHunt(); ~CPolicyHunt(); BOOL Initialize( PSPerSiteData pSite); //BOOL Run(); defined in CCancelableThread //BOOL IsFinished(); defined in CCancelableThread //BOOL WaitForNotRunning( DWORD dwMilliseconds, PBOOL pfFinished); defined in CCancelableThread BOOL GetResult( PDWORD pdwResult); // special handling wraps CCancelableThread::GetResult LPCWSTR GetResultFilename(); private: virtual DWORD run(); P3PSignal _p3pSignal; P3PResource _resourceSite; CHAR _szPolicy[MAX_URL_STRING]; WCHAR _wszPolicy[MAX_URL_STRING]; WCHAR _wszResultsFile[ MAX_PATH]; HANDLE _hPolicyFile; PCHAR allocCharFromWChar( LPCWSTR pOriginal); static BSTR s_pwszPrivacyPolicyTransform; // the transform is loaded from a resource and does not need //to be deallocated.. public: LPCWSTR GetPolicyUrl() { return _wszPolicy;}; static void FreePrivacyPolicyTransform() { if( s_pwszPrivacyPolicyTransform != NULL) { SysFreeString( s_pwszPrivacyPolicyTransform); s_pwszPrivacyPolicyTransform = NULL; } } }; BSTR CPolicyHunt::s_pwszPrivacyPolicyTransform = NULL; // // data used by privacy dialog // struct SPrivacyDialogData { // parameters set when initiating the privacy dialog.. IEnumPrivacyRecords *pEnumPrivacyRecords; // enumerator from Trident LPOLESTR pszName; // site name BOOL fReportAllSites; // flag: Report all sites? Otherwise, only report impacted // and their parent sites. // parameters set within the privacy dialog code. // listAllSites lists pointers to SPerSiteData for sites //return from IEnumPrivacyRecords::enum CQueueSortOf listAllSites; ULONG countRecordsEnumerated; SPrivacyDialogData() { countRecordsEnumerated = 0; } }; SPerSiteData::SPerSiteData() { bstrUrl = NULL; bstrCookieDomain = NULL; bstrHeaderPolicyRef = NULL; bstrLinkTagPolicyRef = NULL; dwFlags = 0; iPrivacyImpactResource = 0; pPolicyHunt = NULL; } SPerSiteData::~SPerSiteData() { if( bstrUrl != NULL) SysFreeString( bstrUrl); if( bstrCookieDomain != NULL) SysFreeString( bstrCookieDomain); if( bstrHeaderPolicyRef != NULL) SysFreeString( bstrHeaderPolicyRef); if( bstrLinkTagPolicyRef != NULL) SysFreeString( bstrLinkTagPolicyRef); if( pPolicyHunt != NULL) delete pPolicyHunt; } CPolicyHunt::CPolicyHunt() { memset( &_p3pSignal, 0, sizeof(P3PSignal)); memset( &_resourceSite, 0, sizeof(P3PResource)); _szPolicy[0] = '\0'; _wszPolicy[0] = L'\0'; _wszResultsFile[0] = L'\0'; _hPolicyFile = INVALID_HANDLE_VALUE; } CPolicyHunt::~CPolicyHunt() { if( _hPolicyFile != INVALID_HANDLE_VALUE) CloseHandle( _hPolicyFile); if( _wszResultsFile[0] != L'\0') { DeleteFile( _wszResultsFile); } if( _p3pSignal.hEvent != NULL) CloseHandle( _p3pSignal.hEvent); if( _resourceSite.pszLocation != NULL) delete [] _resourceSite.pszLocation; if( _resourceSite.pszVerb != NULL) delete [] _resourceSite.pszVerb; if( _resourceSite.pszP3PHeaderRef != NULL) delete [] _resourceSite.pszP3PHeaderRef; if( _resourceSite.pszLinkTagRef != NULL) delete [] _resourceSite.pszLinkTagRef; } PCHAR CPolicyHunt::allocCharFromWChar( LPCWSTR pOriginal) { PCHAR pResult; if( pOriginal == NULL) return NULL; int iSize = 1 + lstrlen( pOriginal); pResult = new CHAR[ iSize]; if( pResult == NULL) return NULL; SHTCharToAnsi( pOriginal, pResult, iSize); return pResult; } BOOL CPolicyHunt::Initialize( PSPerSiteData pSite) { if( TRUE != CCancellableThread::Initialize()) return FALSE; _resourceSite.pszLocation = allocCharFromWChar( pSite->bstrUrl); _resourceSite.pszVerb = allocCharFromWChar( (pSite->dwFlags & PRIVACY_URLHASPOSTDATA) ? L"POST" : L"GET"); _resourceSite.pszP3PHeaderRef = allocCharFromWChar( pSite->bstrHeaderPolicyRef); _resourceSite.pszLinkTagRef = allocCharFromWChar( pSite->bstrLinkTagPolicyRef); _resourceSite.pContainer = NULL; return TRUE; } BOOL CPolicyHunt::GetResult( PDWORD pdwResult) { if( IsFinished()) { return CCancellableThread::GetResult( pdwResult); } *pdwResult = POLICYHUNT_INPROGRESS; return TRUE; } LPCWSTR CPolicyHunt::GetResultFilename() { return _wszResultsFile; } // used only in CPolicyHunt::run.. // This the fetched transform need never be deallocated, //and need only be allocated once. BSTR LoadPrivacyPolicyTransform() { BSTR returnValue = NULL; DWORD dwByteSizeOfResource; HRSRC hrsrc = FindResource( MLGetHinst(), TEXT("privacypolicytransform.xsl"), MAKEINTRESOURCE(RT_HTML)); if( hrsrc == NULL) goto doneLoadPrivacyPolicyTransform; dwByteSizeOfResource = SizeofResource( MLGetHinst(), hrsrc); if( dwByteSizeOfResource == 0) goto doneLoadPrivacyPolicyTransform; HGLOBAL hGlobal = LoadResource( MLGetHinst(), hrsrc); // Loaded resources do not need to be unloaded if( hGlobal == NULL) goto doneLoadPrivacyPolicyTransform; LPVOID pLockedResource = LockResource( hGlobal); // Locked resources do not need to be unlocked if( pLockedResource == NULL) goto doneLoadPrivacyPolicyTransform; // Skip first WCHAR when allocating BSTR copy of the transform, // since unicode resource starts with an extra 0xFF 0xFE int cwCount = (dwByteSizeOfResource/sizeof(WCHAR)) - 1; returnValue = SysAllocStringLen( 1+(LPCWSTR)pLockedResource, cwCount); doneLoadPrivacyPolicyTransform: return returnValue; } DWORD CPolicyHunt::run() { DWORD retVal = POLICYHUNT_ERROR; int iTemp; DWORD dw; if( IsFinished()) goto doneCPolicyHuntRun; // MapResourceToPolicy phase // ... need an event.. _p3pSignal.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL); if( _p3pSignal.hEvent == NULL) goto doneCPolicyHuntRun; // ... now call MapResourceToPolicy iTemp = MapResourceToPolicy(&(_resourceSite), _szPolicy, ARRAYSIZE(_szPolicy), &(_p3pSignal)); if( iTemp != P3P_InProgress) goto doneCPolicyHuntRun; // ... now wait for MapResourceToPolicy to finish do { if( IsCancelled()) { retVal = POLICYHUNT_CANCELLED; goto doneCPolicyHuntRun; } } while ( WAIT_TIMEOUT == (dw = WaitForSingleObject( _p3pSignal.hEvent, 100))); if( WAIT_OBJECT_0 != dw) goto doneCPolicyHuntRun; FreeP3PObject( _p3pSignal.hRequest); _p3pSignal.hRequest = NULL; // ... check if MapResourceToPolicy found anything.. if( _szPolicy[0] == '\0') { retVal = POLICYHUNT_NOTFOUND; goto doneCPolicyHuntRun; } // prepare a WCHAR copy of the policy SHAnsiToUnicode( _szPolicy, _wszPolicy, ARRAYSIZE( _wszPolicy)); // Now we need to prepare a temp file for our result. // ... get the path for the result file WCHAR szPathBuffer[ MAX_PATH]; dw = GetTempPath( ARRAYSIZE( szPathBuffer), szPathBuffer); if( dw == 0 || dw+1 > MAX_PATH) goto doneCPolicyHuntRun; // ... get a .tmp filename for the result file dw = GetTempFileName( szPathBuffer, L"IE", 0, _wszResultsFile); if( dw == 0) goto doneCPolicyHuntRun; DeleteFile( _wszResultsFile); // ... make the .tmp filename a .htm filename dw = lstrlen( _wszResultsFile); while( dw > 0 && _wszResultsFile[dw] != L'.') { dw--; } StrCpyNW( _wszResultsFile + dw, L".htm", ARRAYSIZE(L".htm")); // ... open the file _hPolicyFile = CreateFile( _wszResultsFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if( _hPolicyFile == INVALID_HANDLE_VALUE) goto doneCPolicyHuntRun; if( s_pwszPrivacyPolicyTransform == NULL) s_pwszPrivacyPolicyTransform = LoadPrivacyPolicyTransform(); if( s_pwszPrivacyPolicyTransform == NULL) goto doneCPolicyHuntRun; ResetEvent( _p3pSignal.hEvent); iTemp = GetP3PPolicy( _szPolicy, _hPolicyFile, s_pwszPrivacyPolicyTransform, &_p3pSignal); if( iTemp != P3P_InProgress) goto doneCPolicyHuntRun; // ... now wait for GetP3PPolicy to finish do { if( IsCancelled()) { retVal = POLICYHUNT_CANCELLED; goto doneCPolicyHuntRun; } } while ( WAIT_TIMEOUT == (dw = WaitForSingleObject( _p3pSignal.hEvent, 100))); if( WAIT_OBJECT_0 != dw) goto doneCPolicyHuntRun; int iGetP3PPolicyResult; iGetP3PPolicyResult = GetP3PRequestStatus( _p3pSignal.hRequest); switch( iGetP3PPolicyResult) { case P3P_Done: retVal = POLICYHUNT_FOUND; break; case P3P_NoPolicy: case P3P_NotFound: retVal = POLICYHUNT_NOTFOUND; break; case P3P_Failed: retVal = POLICYHUNT_ERROR; break; case P3P_FormatErr: retVal = POLICYHUNT_FORMATERROR; break; case P3P_Cancelled: retVal = POLICYHUNT_CANCELLED; break; default: retVal = POLICYHUNT_ERROR; break; } doneCPolicyHuntRun: if( _hPolicyFile != INVALID_HANDLE_VALUE) { CloseHandle( _hPolicyFile); _hPolicyFile = INVALID_HANDLE_VALUE; } if( _p3pSignal.hRequest != NULL) { FreeP3PObject( _p3pSignal.hRequest); _p3pSignal.hRequest = NULL; } if( _p3pSignal.hEvent != NULL) { CloseHandle( _p3pSignal.hEvent); _p3pSignal.hEvent = NULL; } memset( &_p3pSignal, 0, sizeof(P3PSignal)); return retVal; } // be warned: a NULL BSTR is equivalent to a "" BSTR.. // This function returns the cookie domain from an http:// or https:// style Url. BSTR GetCookieDomainFromUrl( LPCWSTR bstrFullUrl) { BSTR returnValue = NULL; if( bstrFullUrl == NULL) goto doneGetMinimizedCookieDomain; WCHAR wszUrl[MAX_URL_STRING], *pMinimizedDomain; wszUrl[0] = L'\0'; StrCpyNW( wszUrl, bstrFullUrl, lstrlen( bstrFullUrl)+1); if( wszUrl[0] == '\0') goto doneGetMinimizedCookieDomain; WCHAR *pBeginUrl = wszUrl; // pBeginUrl will be 'http://full.domain.com/path/path...' while( *pBeginUrl != L'\0' && *pBeginUrl != L'/') pBeginUrl++; if( *pBeginUrl == L'/') pBeginUrl++; while( *pBeginUrl != L'\0' && *pBeginUrl != L'/') pBeginUrl++; if( *pBeginUrl == L'/') pBeginUrl++; // now pBeginUrl is 'full.domain.com/path/path'.. WCHAR *pEndUrl = pBeginUrl; // pEndUrl will find the '/path/path..' and clip it from pBeginUrl while( *pEndUrl != L'\0' && *pEndUrl != L'/') pEndUrl++; *pEndUrl = L'\0'; pMinimizedDomain = pEndUrl; // pBeginUrl is now like 'full.domain.com' // pMinimizedDomain will reduce pBeginUrl to a domain minimized to still allow cookies.. do { pMinimizedDomain--; while( pBeginUrl < pMinimizedDomain && *(pMinimizedDomain-1) != L'.') { pMinimizedDomain--; } } while( !IsDomainLegalCookieDomain( pMinimizedDomain, pBeginUrl) && pBeginUrl < pMinimizedDomain); returnValue = SysAllocString( pMinimizedDomain); doneGetMinimizedCookieDomain: return returnValue; } void PrivacyDlgDeallocSiteList( PSPrivacyDialogData pData) { void* iterator = NULL; while( NULL != (iterator = pData->listAllSites.StepEnumerate(iterator))) { PSPerSiteData pCurrent = (PSPerSiteData)(pData->listAllSites.Get( iterator)); delete pCurrent; } CPolicyHunt::FreePrivacyPolicyTransform(); } BOOL PrivacyDialogExtendSiteList( PSPrivacyDialogData pData) { BOOL returnValue = FALSE; BSTR bstrUrl = NULL, bstrPolicyRef = NULL; DWORD dwFlags; ULONG ulPrivacyRecordsTotal; if( FAILED(pData->pEnumPrivacyRecords->GetSize( &ulPrivacyRecordsTotal))) ulPrivacyRecordsTotal = 0; DWORD dwTemp; // Enumerate the sites in IEnumPrivacyRecords::enum PSPerSiteData pCurrentSite = NULL, pCurrentSiteInList = NULL; while( pData->countRecordsEnumerated < ulPrivacyRecordsTotal && SUCCEEDED( dwTemp = pData->pEnumPrivacyRecords-> Next(&bstrUrl, &bstrPolicyRef, NULL, &dwFlags))) { pData->countRecordsEnumerated++; pCurrentSite = NULL; pCurrentSiteInList = NULL; void* iterator = NULL; if(NULL == bstrUrl || 0 == *bstrUrl) { // every time we pass a blank token, //we begin processing a higher navigation level. SysFreeString( bstrUrl); bstrUrl = NULL; continue; } if( 0 != StrNCmpI( bstrUrl, L"http", ARRAYSIZE(L"http")-1)) { // we ignore non http stuff... like ftp, local files.. continue; } // Test if the current site is already in the list. iterator = NULL; while( pCurrentSiteInList == NULL && NULL != (iterator = pData->listAllSites.StepEnumerate(iterator))) { PSPerSiteData pCurrent = (PSPerSiteData)(pData->listAllSites.Get( iterator)); if( 0 == StrCmp( bstrUrl, pCurrent->bstrUrl)) pCurrentSiteInList = pCurrent; } // If the site is not in the list, add it. // If the site isn't in the list, add the information given by enum. if( pCurrentSiteInList == NULL) { pCurrentSite = new SPerSiteData(); if( pCurrentSite == NULL) goto donePrivacyDialogExtendSiteList; pCurrentSite->bstrUrl = bstrUrl; bstrUrl = NULL; pCurrentSite->dwFlags = dwFlags; // Now find the minimized cookie domain.. pCurrentSite->bstrCookieDomain = GetCookieDomainFromUrl( pCurrentSite->bstrUrl); if( pData->listAllSites.InsertAtEnd( pCurrentSite)) pCurrentSiteInList = pCurrentSite; else goto donePrivacyDialogExtendSiteList; } else // else we have a duplicate list item { pCurrentSite = pCurrentSiteInList; // pCurrentSite->bstrUrl is correct // pCurrentSite->bstrCookieDomain is correct pCurrentSite->dwFlags |= dwFlags; } if( bstrPolicyRef != NULL && dwFlags & PRIVACY_URLHASPOLICYREFHEADER) { // We have the policy ref from the header.. SysFreeString( pCurrentSite->bstrHeaderPolicyRef); // NULLs are ignored.. pCurrentSite->bstrHeaderPolicyRef = bstrPolicyRef; bstrPolicyRef = NULL; } else if ( bstrPolicyRef != NULL && dwFlags & PRIVACY_URLHASPOLICYREFLINK) { // We have the policy ref from the link tag.. SysFreeString( pCurrentSite->bstrLinkTagPolicyRef); // NULLs are ignored.. pCurrentSite->bstrLinkTagPolicyRef = bstrPolicyRef; bstrPolicyRef = NULL; } else if( bstrPolicyRef != NULL) { // We have a policy ref with an unknown source.. bug in IEnumPrivacyRecords ASSERT(0); SysFreeString( pCurrentSite->bstrHeaderPolicyRef); // NULLs are ignored.. pCurrentSite->bstrHeaderPolicyRef = bstrPolicyRef; bstrPolicyRef = NULL; } // now to determine the privacy impact of the site.. // precedence: IDS_PRIVACY_BLOCKED > IDS_PRIVACY_RESTRICTED > IDS_PRIVACY_ACCEPTED > nothing if( dwFlags & (COOKIEACTION_ACCEPT | COOKIEACTION_LEASH)) { pCurrentSite->iPrivacyImpactResource = max( pCurrentSite->iPrivacyImpactResource, IDS_PRIVACY_ACCEPTED); } if( dwFlags & COOKIEACTION_DOWNGRADE) { pCurrentSite->iPrivacyImpactResource = max( pCurrentSite->iPrivacyImpactResource, IDS_PRIVACY_RESTRICTED); } if( dwFlags & (COOKIEACTION_REJECT | COOKIEACTION_SUPPRESS)) { pCurrentSite->iPrivacyImpactResource = max( pCurrentSite->iPrivacyImpactResource, IDS_PRIVACY_BLOCKED); } SysFreeString( bstrUrl); bstrUrl = NULL; SysFreeString( bstrPolicyRef); bstrPolicyRef = NULL; } returnValue = TRUE; donePrivacyDialogExtendSiteList: if( bstrUrl != NULL) SysFreeString( bstrUrl); if( bstrPolicyRef != NULL) SysFreeString( bstrUrl); if( pCurrentSite != NULL && pCurrentSiteInList == NULL) delete pCurrentSite; return returnValue; } BOOL PrivacyDlgBuildSiteList( PSPrivacyDialogData pData) { PrivacyDlgDeallocSiteList( pData); return PrivacyDialogExtendSiteList( pData); } BOOL InitializePrivacyDlg(HWND hDlg, PSPrivacyDialogData pData) { WCHAR szBuffer[256]; HWND hwndListView = GetDlgItem(hDlg, IDC_SITE_LIST); RECT rc; // Set the privacy status caption text BOOL fImpacted; if( SUCCEEDED(pData->pEnumPrivacyRecords->GetPrivacyImpacted(&fImpacted)) && fImpacted) { MLLoadStringW( IDS_PRIVACY_STATUSIMPACTED, szBuffer, ARRAYSIZE( szBuffer)); } else { MLLoadStringW( IDS_PRIVACY_STATUSNOIMPACT, szBuffer, ARRAYSIZE( szBuffer)); } SendMessage( GetDlgItem( hDlg, IDC_PRIVACY_STATUSTEXT), WM_SETTEXT, 0, (LPARAM)szBuffer); //Initialize the list view.. // ..Empty the list in list view. ListView_DeleteAllItems (hwndListView); // ..Initialize the columns in the list view. LV_COLUMN lvColumn; lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; lvColumn.fmt = LVCFMT_LEFT; lvColumn.pszText = szBuffer; lvColumn.cx = 300; if( 0 != GetClientRect( hwndListView, &rc)) lvColumn.cx = rc.right - rc.left - 150 - GetSystemMetrics( SM_CXVSCROLL); // 15 is an arbitrary number to prevent the horizontal scrollbar from appearing MLLoadStringW(IDS_PRIVACY_COLUMN1, szBuffer, ARRAYSIZE(szBuffer)); ListView_InsertColumn(hwndListView, 1, &lvColumn); lvColumn.cx = 150; MLLoadStringW(IDS_PRIVACY_COLUMN2, szBuffer, ARRAYSIZE(szBuffer)); ListView_InsertColumn(hwndListView, 2, &lvColumn); // Initialize the view all/restricted combo box HWND hwndComboBox = GetDlgItem( hDlg, IDC_PRIVACY_VIEWCOMBO); ComboBox_ResetContent( hwndComboBox); int iComboPosition; MLLoadStringW(IDS_PRIVACY_VIEWIMPACTED, szBuffer, ARRAYSIZE(szBuffer)); iComboPosition = ComboBox_AddString(hwndComboBox, szBuffer); ComboBox_SetItemData(hwndComboBox, iComboPosition, 0); MLLoadStringW(IDS_PRIVACY_VIEWALL, szBuffer, ARRAYSIZE(szBuffer)); iComboPosition = ComboBox_AddString(hwndComboBox, szBuffer); ComboBox_SetItemData(hwndComboBox, iComboPosition, 1); ComboBox_SetCurSel( hwndComboBox, pData->fReportAllSites); GetDlgItemText( hDlg, IDC_PRIVACY_HELP, szBuffer, ARRAYSIZE( szBuffer)); MLLoadStringW(IDS_PRIVACY_LEARNMOREABOUTPRIVACY, szBuffer, ARRAYSIZE(szBuffer)); RenderStringToEditControlW(hDlg, szBuffer, (WNDPROC)HyperlinkSubclass, IDC_PRIVACY_HELP); return TRUE; } // add items to the privacy dialog's listview.. BOOL PopulatePrivacyDlgListView(HWND hDlg, PSPrivacyDialogData pData, bool fMaintainSelectedItem) { HWND hwndListView = GetDlgItem( hDlg, IDC_SITE_LIST); void* iterator = NULL; int iCurrentPosition = 0; int iSelectedItem = ListView_GetSelectionMark( hwndListView); PSPerSiteData pSelectedItem = NULL; if( fMaintainSelectedItem && iSelectedItem != -1) { LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iItem = iSelectedItem; if( FALSE != ListView_GetItem( hwndListView, &lvi) && lvi.lParam != (LPARAM)NULL) { pSelectedItem = (PSPerSiteData)lvi.lParam; } } // Empty the list in list view. ListView_DeleteAllItems (hwndListView); iSelectedItem = -1; while( NULL != (iterator = pData->listAllSites.StepEnumerate(iterator))) { PSPerSiteData pCurrent = (PSPerSiteData)(pData->listAllSites.Get(iterator)); BOOL fAddItem = pData->fReportAllSites || pCurrent->iPrivacyImpactResource == IDS_PRIVACY_SUPPRESSED || pCurrent->iPrivacyImpactResource == IDS_PRIVACY_RESTRICTED || pCurrent->iPrivacyImpactResource == IDS_PRIVACY_BLOCKED; if( fAddItem == TRUE) { LVITEM lvitem; lvitem.mask = LVIF_TEXT | LVIF_PARAM; lvitem.pszText = pCurrent->bstrUrl; lvitem.iItem = iCurrentPosition++; lvitem.iSubItem = 0; lvitem.lParam = (LPARAM)pCurrent; ListView_InsertItem(hwndListView, &lvitem); if( pCurrent->iPrivacyImpactResource != 0) { WCHAR wszTemp[128]; // set cookie string lvitem.iSubItem = 1; lvitem.mask = LVIF_TEXT; lvitem.pszText = wszTemp; if( MLLoadString(pCurrent->iPrivacyImpactResource, wszTemp, ARRAYSIZE(wszTemp))) { SendMessage(hwndListView, LVM_SETITEMTEXT, (WPARAM)lvitem.iItem, (LPARAM)&lvitem); } } // We either keep the last item selected as selected, //or select the last top-level item. if( fMaintainSelectedItem) { if( pSelectedItem == pCurrent) iSelectedItem = lvitem.iItem; } } } // if( fMaintainSelectedItem && iSelectedItem != -1) // { // ListView_SetItemState( hwndListView, iSelectedItem, LVIS_SELECTED, LVIS_SELECTED); // ListView_SetSelectionMark( hwndListView, iSelectedItem); // ListView_EnsureVisible( hwndListView, iSelectedItem, FALSE); // } PostMessage( hDlg, WM_APP, IDC_SITE_LIST, 0); // notifies the dialog that a listview item has been selected return TRUE; } typedef BOOL (*PFNPRIVACYSETTINGS)(HWND); void LaunchPrivacySettings(HWND hwndParent) { HMODULE hmodInetcpl; PFNPRIVACYSETTINGS pfnPriv; hmodInetcpl = LoadLibrary(TEXT("inetcpl.cpl")); if(hmodInetcpl) { pfnPriv = (PFNPRIVACYSETTINGS)GetProcAddress(hmodInetcpl, "LaunchPrivacyDialog"); if(pfnPriv) { pfnPriv(hwndParent); } FreeLibrary(hmodInetcpl); } } BOOL PrivacyPolicyHtmlDlg( HWND hDlg, HWND hwndListView, int iItemIndex) { BOOL returnValue = FALSE; HRESULT hr; DWORD dw; PSPerSiteData pListViewData; WCHAR* pwchHtmlDialogInput = NULL; IMoniker * pmk = NULL; VARIANT varArg, varOut; VariantInit( &varArg); VariantInit( &varOut); LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iItem = iItemIndex; if( FALSE == ListView_GetItem( hwndListView, &lvi) || lvi.lParam == (LPARAM)NULL) goto donePrivacyPolicyHtmlDlg; pListViewData = (PSPerSiteData)lvi.lParam; WCHAR szResURL[MAX_URL_STRING]; // fetch the HTML for the dialog box.. hr = MLBuildResURLWrap(TEXT("shdoclc.dll"), HINST_THISDLL, ML_CROSSCODEPAGE, TEXT("privacypolicy.dlg"), szResURL, ARRAYSIZE(szResURL), TEXT("shdocvw.dll")); if( FAILED( hr)) goto donePrivacyPolicyHtmlDlg; hr = CreateURLMoniker(NULL, szResURL, &pmk); if( FAILED( hr)) goto donePrivacyPolicyHtmlDlg; varArg.vt = VT_DISPATCH; varArg.pdispVal = (IDispatch*)pListViewData; // Show the dialog.. hr = ShowHTMLDialog( hDlg, pmk, &varArg, L"help:no; resizable:1", &varOut); if( FAILED( hr)) goto donePrivacyPolicyHtmlDlg; hr = VariantChangeType( &varOut, &varOut, NULL, VT_I4); if( FAILED( hr)) goto donePrivacyPolicyHtmlDlg; if( allowPerSiteModify()) { switch( varOut.lVal) { default: hr = TRUE; break; case 1: hr = InternetSetPerSiteCookieDecision( pListViewData->bstrCookieDomain, COOKIE_STATE_UNKNOWN); break; case 2: hr = InternetSetPerSiteCookieDecision( pListViewData->bstrCookieDomain, COOKIE_STATE_ACCEPT); break; case 3: hr = InternetSetPerSiteCookieDecision( pListViewData->bstrCookieDomain, COOKIE_STATE_REJECT); break; } } if( hr != TRUE) goto donePrivacyPolicyHtmlDlg; returnValue = TRUE; donePrivacyPolicyHtmlDlg: if( pListViewData->pPolicyHunt != NULL) { // no-op if already finished pListViewData->pPolicyHunt->NotifyCancel(); pListViewData->pPolicyHunt->WaitForNotRunning( INFINITE); } if( pListViewData->pPolicyHunt != NULL && pListViewData->pPolicyHunt->GetResult( &dw) == TRUE && dw != POLICYHUNT_FOUND) { delete pListViewData->pPolicyHunt; pListViewData->pPolicyHunt = NULL; } if( pwchHtmlDialogInput != NULL) delete[] pwchHtmlDialogInput; if( pmk != NULL) ATOMICRELEASE( pmk); VariantClear( &varArg); VariantClear( &varOut); return returnValue; } BOOL PrivacyDlgContextMenuHandler( HWND hDlg, HWND hwndListView, int iSelectedListItem, int x, int y) { //user has initiated opening the context menu.. // if the user right-clicked a non-list item, we do nothing if( iSelectedListItem == -1 || !allowPerSiteModify()) return TRUE; SPerSiteData *psSiteData = NULL; LVITEM lvi; lvi.mask = LVIF_PARAM; lvi.iItem = iSelectedListItem; if( FALSE == ListView_GetItem( hwndListView, &lvi) || lvi.lParam == (LPARAM)NULL) return FALSE; psSiteData = (PSPerSiteData)(lvi.lParam); HMENU hmenu0 = LoadMenu( MLGetHinst(), MAKEINTRESOURCE(IDD_PRIVACY_CNTXTMN_PERSITE_ADD_REM)); HMENU hmenu1 = GetSubMenu( hmenu0, 0); if( hmenu0 == NULL || hmenu1 == NULL) { DestroyMenu(hmenu0); return FALSE; } // Check the appropriate option.. unsigned long ulResult; MENUITEMINFO menuiteminfo; menuiteminfo.cbSize = sizeof(menuiteminfo); menuiteminfo.fMask = MIIM_STATE; menuiteminfo.fState = MFS_CHECKED; if( InternetGetPerSiteCookieDecision( psSiteData->bstrCookieDomain, &ulResult) == TRUE) { switch( ulResult) { case COOKIE_STATE_ACCEPT: SetMenuItemInfo( hmenu1, IDM_PRIVACY_PAR_ACCEPT, FALSE, &menuiteminfo); break; case COOKIE_STATE_REJECT: SetMenuItemInfo( hmenu1, IDM_PRIVACY_PAR_REJECT, FALSE, &menuiteminfo); break; } } else { SetMenuItemInfo( hmenu1, IDM_PRIVACY_PAR_DEFAULT, FALSE, &menuiteminfo); } // the target location of the context window depends on whether or not the user //right-clicked the mouse or used the context menu button.. if( x == -1 && y == -1) { // context menu was opened through keyboard, not mouse.. RECT rectListRect; RECT rectSelectionRect; if( 0 != GetWindowRect( hwndListView, &rectListRect) && TRUE == ListView_GetItemRect( hwndListView, iSelectedListItem, &rectSelectionRect, LVIR_LABEL)) { x = rectListRect.left + (rectSelectionRect.left + rectSelectionRect.right) / 2; y = rectListRect.top + (rectSelectionRect.top + rectSelectionRect.bottom) / 2; } } // now we know enough to open the conext menu. BOOL userSelection = TrackPopupMenu( hmenu1, TPM_RETURNCMD, x, y, 0, hDlg, NULL); DestroyMenu( hmenu1); DestroyMenu( hmenu0); switch( userSelection) { case 0: // User cancelled context menu, do nothing. break; case IDM_PRIVACY_PAR_ACCEPT: // User chose to add site to per-site exclusion list. InternetSetPerSiteCookieDecision( psSiteData->bstrCookieDomain, COOKIE_STATE_ACCEPT); break; case IDM_PRIVACY_PAR_REJECT: // User chose to add site per-site inclusion list. InternetSetPerSiteCookieDecision( psSiteData->bstrCookieDomain, COOKIE_STATE_REJECT); break; case IDM_PRIVACY_PAR_DEFAULT: // User chose to have site use default behavior. InternetSetPerSiteCookieDecision( psSiteData->bstrCookieDomain, COOKIE_STATE_UNKNOWN); break; } return TRUE; } INT_PTR CALLBACK PrivacyDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { PSPrivacyDialogData pData = (PSPrivacyDialogData)GetWindowLongPtr(hDlg, GWLP_USERDATA); switch (message) { case WM_INITDIALOG: SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam); pData = (PSPrivacyDialogData)lParam; InitializePrivacyDlg( hDlg, pData); PrivacyDlgBuildSiteList( pData); PopulatePrivacyDlgListView(hDlg, pData, false); if( IsOS(OS_WHISTLERORGREATER)) { HICON hIcon = LoadIcon(MLGetHinst(), MAKEINTRESOURCE(IDI_PRIVACY_XP)); if( hIcon != NULL) SendDlgItemMessage(hDlg, IDC_PRIVACY_ICON, STM_SETICON, (WPARAM)hIcon, 0); // icons loaded with LoadIcon never need to be released } PostMessage( hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem( hDlg, IDC_SITE_LIST), MAKELPARAM( TRUE, 0)); SetTimer( hDlg, NULL, 500, NULL); return TRUE; case WM_DESTROY: PrivacyDlgDeallocSiteList( pData); break; case WM_TIMER: { ULONG oldCount = pData->countRecordsEnumerated; if( pData != NULL && TRUE == PrivacyDialogExtendSiteList( pData) && oldCount < pData->countRecordsEnumerated) { PopulatePrivacyDlgListView( hDlg, pData, true); } } case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: switch( GetDlgCtrlID(GetFocus())) { case IDC_SITE_LIST: { PostMessage( hDlg, WM_COMMAND, (WPARAM)IDC_PRIVACY_SHOWPOLICY, (LPARAM)GetDlgItem(hDlg, IDC_PRIVACY_SHOWPOLICY)); return 0; // return 0 to indicate message was handled } case IDC_PRIVACY_HELP: { PostMessage( hDlg, WM_APP, (WPARAM)IDC_PRIVACY_HELP, (LPARAM)GetDlgItem(hDlg, IDC_PRIVACY_HELP)); return 0; } case IDC_PRIVACY_VIEWCOMBO: { PostMessage( hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem( hDlg, IDC_SITE_LIST), MAKELPARAM( TRUE, 0)); return 0; } } // fall through if IDOK was actually due to hitting IDOK with defaulting on an enter.. case IDCANCEL: EndDialog(hDlg, LOWORD(wParam)); return 0; case IDC_SETTINGS: LaunchPrivacySettings(hDlg); return 0; case IDC_PRIVACY_VIEWCOMBO: if( CBN_SELCHANGE == HIWORD(wParam)) { HWND hwndComboBox = (HWND)lParam; int iIndex = ComboBox_GetCurSel(hwndComboBox); if( iIndex != CB_ERR) { pData->fReportAllSites = (iIndex == 1) ? TRUE : FALSE; PopulatePrivacyDlgListView(hDlg, pData, true); } return 0; } break; case IDC_PRIVACY_SHOWPOLICY: { // Catching the default return and seeing if the site list is //selected was the only way to detect a return on the listview. HWND hwndSiteList = GetDlgItem( hDlg, IDC_SITE_LIST); int iSelectedItem = ListView_GetSelectionMark( hwndSiteList); if( iSelectedItem != -1) { PrivacyPolicyHtmlDlg( hDlg, hwndSiteList, iSelectedItem); } return 0; } } break; case WM_APP: if( LOWORD(wParam) == IDC_PRIVACY_HELP) { SHHtmlHelpOnDemandWrap(hDlg, TEXT("iexplore.chm > iedefault"), HH_DISPLAY_TOPIC, (DWORD_PTR) L"sec_cook.htm", ML_CROSSCODEPAGE); } else if ( LOWORD( wParam) == IDC_SITE_LIST) { // We post an WM_APP to the dialog everytime the selected list view item //is changed.. By handling the change in a posted message, we insure the //list view's selected item is updated. // Whenever the selected privacy report list item is changed, we have to enable/disable //the show site policy button. int iSelectedItem = ListView_GetSelectionMark( GetDlgItem( hDlg, IDC_SITE_LIST)); EnableWindow( GetDlgItem( hDlg, IDC_PRIVACY_SHOWPOLICY), (-1 != iSelectedItem)); } return 0; case WM_CONTEXTMENU: // If the user hits the context menu button on the list view, we handle it here, //because its the only place to check for that keypress. // If the user clicks the right mouse button for the context menu, we handle it in //WM__NOTIFY::NM_RCLICK, because the NM_RCLICK gives the correct seleceted item. if( GET_X_LPARAM(lParam) == -1 && (HWND)wParam == GetDlgItem( hDlg, IDC_SITE_LIST)) { int iSelectedItem = ListView_GetSelectionMark( GetDlgItem( hDlg, IDC_SITE_LIST)); PrivacyDlgContextMenuHandler( hDlg, (HWND)wParam, iSelectedItem, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); } break; case WM_NOTIFY: if( IDC_SITE_LIST == ((LPNMHDR)lParam)->idFrom && NM_DBLCLK == ((LPNMHDR)lParam)->code && ((LPNMITEMACTIVATE)lParam)->iItem != -1) { PrivacyPolicyHtmlDlg( hDlg, ((LPNMHDR)lParam)->hwndFrom, ((LPNMITEMACTIVATE)lParam)->iItem); } else if( IDC_SITE_LIST == ((LPNMHDR)lParam)->idFrom && NM_RCLICK == ((LPNMHDR)lParam)->code) { int iRightClickedItem = ((LPNMITEMACTIVATE)lParam)->iItem; if( iRightClickedItem != -1) { POINT pointClick = ((LPNMITEMACTIVATE)lParam)->ptAction; RECT rc; if( 0 != GetWindowRect( GetDlgItem( hDlg, IDC_SITE_LIST), &rc)) { pointClick.x += rc.left; pointClick.y += rc.top; } else { // Strange error case.. but its alright since we can place the context menu //as if the context-menu button was clicked, instead of the mouse pointClick.x = -1; pointClick.y = -1; } PrivacyDlgContextMenuHandler( hDlg, GetDlgItem( hDlg, IDC_SITE_LIST), iRightClickedItem, pointClick.x, pointClick.y); } } else if( IDC_SITE_LIST == ((LPNMHDR)lParam)->idFrom && LVN_ITEMCHANGED == ((LPNMHDR)lParam)->code) { if( ((LPNMLISTVIEW)lParam)->uChanged & LVIF_STATE) { // For some unknown reason the selection mark does not move with //the selected item.. We have to update it. if( ((LPNMLISTVIEW)lParam)->uNewState & LVIS_SELECTED) { ListView_SetSelectionMark( GetDlgItem( hDlg, IDC_SITE_LIST), ((LPNMLISTVIEW)lParam)->iItem); } else { ListView_SetSelectionMark( GetDlgItem( hDlg, IDC_SITE_LIST), -1); } // Now that the selection mark is in sync, the UI can update //related items PostMessage( hDlg, WM_APP, IDC_SITE_LIST, 0); } } break; } return FALSE; } // // Exported entry point to show privacy dialog // SHDOCAPI DoPrivacyDlg( HWND hwndParent, // parent window LPOLESTR pszUrl, // base URL IEnumPrivacyRecords *pPrivacyEnum, // enum of all affected dependant URLs BOOL fReportAllSites // show all or just show bad ) { HINSTANCE hRichEditDll; SPrivacyDialogData p; // data to send to dialogbox if(NULL == pszUrl || NULL == pPrivacyEnum) { return E_INVALIDARG; } // We need to load richedit hRichEditDll = LoadLibrary(TEXT("RICHED20.DLL")); if (!hRichEditDll) { ASSERT(FALSE); //can't load richedit, complain to akabir return E_UNEXPECTED; } p.pszName = pszUrl; p.pEnumPrivacyRecords = pPrivacyEnum; p.fReportAllSites = fReportAllSites; SHFusionDialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_PRIVACY_DIALOG), hwndParent, PrivacyDlgProc, (LPARAM)&p); FreeLibrary( hRichEditDll); return S_OK; } #define DISPID_URL 10 #define DISPID_COOKIEURL 11 #define DISPID_ARD 12 #define DISPID_ARD_FIXED 13 #define DISPID_POLICYHUNT_DONE 14 #define DISPID_POLICYHUNT_VIEW 15 #define DISPID_CREATEABSOLUTEURL 16 struct SPropertyTable { WCHAR* pName; DISPID dispid; } const g_SPerSiteDataDisptable[] = { L"url", DISPID_URL, L"cookieUrl", DISPID_COOKIEURL, L"acceptRejectOrDefault", DISPID_ARD, L"fixedAcceptRejectOrDefault", DISPID_ARD_FIXED, L"flagPolicyHuntDone", DISPID_POLICYHUNT_DONE, L"urlPolicyHuntView", DISPID_POLICYHUNT_VIEW, L"CreateAbsoluteUrl", DISPID_CREATEABSOLUTEURL }; const DWORD g_cSPerSiteDataDisptableSize = ARRAYSIZE( g_SPerSiteDataDisptable); ULONG SPerSiteData::AddRef( void ) { return 1; } ULONG SPerSiteData::Release( void ) { return 1; } HRESULT SPerSiteData::QueryInterface( REFIID iid, void ** ppv) { if( ppv == NULL) return E_POINTER; if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IDispatch)) { *ppv = (void *)this; return S_OK; } else { *ppv = NULL; return E_NOINTERFACE; } } HRESULT SPerSiteData::GetTypeInfoCount( unsigned int FAR* pctinfo) { if( pctinfo == NULL) return E_POINTER; *pctinfo = 0; return S_OK; } HRESULT SPerSiteData::GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo) { return E_NOTIMPL; } HRESULT SPerSiteData::GetIDsOfNames( REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgDispId) { if( !IsEqualIID(riid, IID_NULL) ) return E_INVALIDARG; if( cNames != 1) return E_INVALIDARG; // none of the objects we ID have arguments.. int i; for( i = 0; i < g_cSPerSiteDataDisptableSize; i++) { if( 0 == StrCmp( rgszNames[0], g_SPerSiteDataDisptable[i].pName)) { rgDispId[0] = g_SPerSiteDataDisptable[i].dispid; return S_OK; } } rgDispId[0] = DISPID_UNKNOWN; return DISP_E_UNKNOWNNAME; } HRESULT SPerSiteData::Invoke( DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr) { HRESULT hr; DWORD dw; if( !IsEqualIID(riid, IID_NULL) ) return E_INVALIDARG; if( pDispParams == NULL || pDispParams->cNamedArgs != 0) return DISP_E_BADPARAMCOUNT; switch( dispIdMember) { case DISPID_CREATEABSOLUTEURL: if( pDispParams->cArgs != 1) return DISP_E_BADPARAMCOUNT; if( pVarResult == NULL) return S_OK; break; case DISPID_COOKIEURL: case DISPID_URL: case DISPID_ARD: case DISPID_ARD_FIXED: case DISPID_POLICYHUNT_DONE: case DISPID_POLICYHUNT_VIEW: if( pDispParams->cArgs != 0) return DISP_E_BADPARAMCOUNT; if( !(wFlags & DISPATCH_PROPERTYGET)) return DISP_E_MEMBERNOTFOUND; if( pVarResult == NULL) return S_OK; break; default: return DISP_E_MEMBERNOTFOUND; } pVarResult->vt = VT_BSTR; switch( dispIdMember) { case DISPID_COOKIEURL: pVarResult->bstrVal = SysAllocString(bstrCookieDomain); return S_OK; case DISPID_URL: { BSTR bstrResult = SysAllocString( bstrUrl); if( bstrResult == NULL) return ERROR_OUTOFMEMORY; // Cut of query info from end of URL.. PWCHAR pCursor = bstrResult; while( pCursor[0] != L'\0' && pCursor[0] != L'?') pCursor++; pCursor[0] = L'\0'; pVarResult->bstrVal = bstrResult; return S_OK; } case DISPID_ARD: { unsigned long ulResult; if( InternetGetPerSiteCookieDecision( bstrCookieDomain, &ulResult) == TRUE) { switch( ulResult) { case COOKIE_STATE_ACCEPT: pVarResult->bstrVal = SysAllocString( L"a"); break; case COOKIE_STATE_REJECT: pVarResult->bstrVal = SysAllocString( L"r"); break; default: pVarResult->bstrVal = SysAllocString( L"d"); break; } } else { pVarResult->bstrVal = SysAllocString( L"d"); } return S_OK; } case DISPID_ARD_FIXED: { pVarResult->vt = VT_BOOL; pVarResult->boolVal = !allowPerSiteModify(); return S_OK; } case DISPID_POLICYHUNT_DONE: { // try to start the policy hunt.. if( pPolicyHunt == NULL) { CPolicyHunt* pNewHunt = new CPolicyHunt(); if( !pNewHunt || TRUE != pNewHunt->Initialize( this) || TRUE != pNewHunt->Run()) { goto doneTryToStartPolicyHunt; } pPolicyHunt = pNewHunt; pNewHunt = NULL; doneTryToStartPolicyHunt: if( pNewHunt != NULL) delete pNewHunt; } pVarResult->vt = VT_BOOL; pVarResult->boolVal = pPolicyHunt != NULL && pPolicyHunt->IsFinished(); return S_OK; } case DISPID_POLICYHUNT_VIEW: { pVarResult->vt = VT_BSTR; LPWSTR szResultHtm = L"policyerror.htm"; if( pPolicyHunt == NULL || FALSE == pPolicyHunt->IsFinished()) { szResultHtm = L"policylooking.htm"; } else if( TRUE == pPolicyHunt->GetResult( &dw)) { switch( dw) { case POLICYHUNT_FOUND: pVarResult->bstrVal = SysAllocString( pPolicyHunt->GetResultFilename()); return pVarResult->bstrVal ? S_OK : E_UNEXPECTED; case POLICYHUNT_NOTFOUND: szResultHtm = L"policynone.htm"; break; case POLICYHUNT_INPROGRESS: szResultHtm = L"policylooking.htm"; break; case POLICYHUNT_FORMATERROR: szResultHtm = L"policysyntaxerror.htm"; break; case POLICYHUNT_ERROR: case POLICYHUNT_CANCELLED: szResultHtm = L"policyerror.htm"; break; } } else { szResultHtm = L"policyerror.htm"; } WCHAR szResURL[MAX_URL_STRING]; hr = MLBuildResURLWrap(L"shdoclc.dll", HINST_THISDLL, ML_CROSSCODEPAGE, szResultHtm, szResURL, ARRAYSIZE(szResURL), L"shdocvw.dll"); if( FAILED(hr)) return E_UNEXPECTED; pVarResult->bstrVal = SysAllocString( szResURL); return S_OK; } case DISPID_CREATEABSOLUTEURL: { WCHAR szBuffer[ MAX_URL_STRING]; DWORD dwBufferSize = ARRAYSIZE( szBuffer); pVarResult->bstrVal = NULL; if( pDispParams == NULL) { return E_UNEXPECTED; } if( pDispParams->rgvarg[0].vt != VT_BSTR || pDispParams->rgvarg[0].bstrVal == NULL) { // when pVarResult->bstrVal == NULL and we return S_OK, // we are returning an empty string. return S_OK; } HRESULT hr = UrlCombine( pPolicyHunt->GetPolicyUrl(), pDispParams->rgvarg[0].bstrVal, szBuffer, &dwBufferSize, URL_ESCAPE_UNSAFE ); if( hr != S_OK) return E_UNEXPECTED; pVarResult->bstrVal = SysAllocString( szBuffer); if( pVarResult->bstrVal == NULL) return E_UNEXPECTED; else return S_OK; } } return S_OK; } // // Privacy record implementation // HRESULT CPrivacyRecord::Init( LPTSTR * ppszUrl, LPTSTR * ppszPolicyRef, LPTSTR * ppszP3PHeader, DWORD dwFlags) { unsigned long len = 0; TCHAR * pUrl = NULL; if (!ppszUrl || !*ppszUrl || !**ppszUrl || !ppszP3PHeader || !ppszPolicyRef ) return E_POINTER; _pszUrl = *ppszUrl; _pszP3PHeader = *ppszP3PHeader; _pszPolicyRefUrl = *ppszPolicyRef; // The record will own the memory from now for these *ppszUrl = NULL; *ppszP3PHeader = NULL; *ppszPolicyRef = NULL; _dwPrivacyFlags = dwFlags; return S_OK; } CPrivacyRecord::~CPrivacyRecord() { delete [] _pszUrl; delete [] _pszPolicyRefUrl; delete [] _pszP3PHeader; } HRESULT CPrivacyRecord::SetNext( CPrivacyRecord * pNextRec ) { if (!pNextRec) return E_POINTER; _pNextNode = pNextRec; return S_OK; } // // Privacy queue implementation // CPrivacyQueue::~CPrivacyQueue() { Reset(); } void CPrivacyQueue::Reset() { while (_pHeadRec) { delete Dequeue(); } } void CPrivacyQueue::Queue(CPrivacyRecord *pRecord) { ASSERT(pRecord); if (!_ulSize) { _pHeadRec = _pTailRec = pRecord; } else { ASSERT(_pTailRec); _pTailRec->SetNext(pRecord); _pTailRec = pRecord; } _ulSize++; } CPrivacyRecord* CPrivacyQueue::Dequeue() { CPrivacyRecord *headRec = NULL; if (_ulSize) { ASSERT(_pHeadRec); headRec = _pHeadRec; _pHeadRec = headRec->GetNext(); --_ulSize; } return headRec; } //////////////////////////////////////////////////////////////////////////////////// // // One time privacy discovery dialog proc // //////////////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK PrivacyDiscoveryDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { BOOL fDontShowNextTime = FALSE; WCHAR szBuffer[256]; switch (message) { case WM_INITDIALOG: { CheckDlgButton( hDlg, IDC_PRIV_DISCOVER_DONTSHOW, BST_CHECKED); MLLoadStringW(IDS_PRIVACY_LEARNMOREABOUTCOOKIES, szBuffer, ARRAYSIZE(szBuffer)); RenderStringToEditControlW(hDlg, szBuffer, (WNDPROC)HyperlinkSubclass, IDC_PRIVACY_HELP); if( IsOS(OS_WHISTLERORGREATER)) { HICON hIcon = LoadIcon(MLGetHinst(), MAKEINTRESOURCE(IDI_PRIVACY_XP)); if( hIcon != NULL) SendDlgItemMessage(hDlg, IDC_PRIVACY_ICON, STM_SETICON, (WPARAM)hIcon, 0); // icons loaded with LoadIcon never need to be released } return TRUE; } case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: if(IsDlgButtonChecked(hDlg, IDC_PRIV_DISCOVER_DONTSHOW)) fDontShowNextTime = TRUE; else fDontShowNextTime = FALSE; // fall through case IDCANCEL: EndDialog(hDlg, fDontShowNextTime); return 0; case IDC_SETTINGS: LaunchPrivacySettings(hDlg); return 0; } break; case WM_APP: switch( LOWORD( wParam)) { case IDC_PRIVACY_HELP: SHHtmlHelpOnDemandWrap(hDlg, TEXT("iexplore.chm > iedefault"), HH_DISPLAY_TOPIC, (DWORD_PTR) L"sec_cook.htm", ML_CROSSCODEPAGE); } } return FALSE; } // returns boolean indicating if dialog should be shown again. BOOL DoPrivacyFirstTimeDialog( HWND hwndParent) { HINSTANCE hRichEditDll; BOOL returnValue; // We need to load richedit hRichEditDll = LoadLibrary(TEXT("RICHED20.DLL")); if (!hRichEditDll) { ASSERT(FALSE); //can't load richedit, complain to akabir return TRUE; } returnValue = (BOOL)SHFusionDialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_PRIV_DISCOVER), hwndParent, PrivacyDiscoveryDlgProc, NULL); FreeLibrary( hRichEditDll); return returnValue; }