opsprof.cpp
上传用户:xhy777
上传日期:2007-02-14
资源大小:24088k
文件大小:82k
源码类别:

系统编程

开发平台:

Visual C++

  1. //
  2. // COPSProfile implementation
  3. //
  4. #include "priv.h"
  5. #include "sccls.h"
  6. #include "hlframe.h"
  7. #include "mshtmdid.h"
  8. #include "wtypes.h"
  9. #include "shlwapi.h"
  10. #include "resource.h"
  11. #include "iehelpid.h"
  12. #include <mluisupp.h>
  13. // Definitions copied from WININET
  14. #define COOKIES_WARN     0 // warn with a dlg if using cookies
  15. #define COOKIES_ALLOW    1 // allow cookies without any warning
  16. #define COOKIES_DENY     2 // disable cookies completely
  17. #ifndef VARIANT_TRUE
  18. #define VARIANT_TRUE     ((VARIANT_BOOL)-1)           // TRUE for VARIANT_BOOL
  19. #endif
  20. #ifndef VARIANT_FALSE
  21. #define VARIANT_FALSE    ((VARIANT_BOOL)0)            // FALSE for VARIANT_BOOL
  22. #endif
  23. #define EMPTY_STRINGA(s)    ( !s || (s)[0] == ''  )
  24. #define EMPTY_STRINGW(s)    ( !s || (s)[0] == L'' )
  25. #ifdef  UNICODE
  26. #define EMPTY_STRING(s)     EMPTY_STRINGW(s)
  27. #else
  28. #define EMPTY_STRING(s)     EMPTY_STRINGA(s)
  29. #endif
  30. // Max number of characters in a friendly OPS attribute name.        
  31. const   int     MAX_PROFILE_NAME = 128;
  32. // Constant non-localizable string definitions
  33. const   TCHAR   rgszP3Global[]  = TEXT("SOFTWARE\Microsoft\Internet Explorer\Security\P3Global");
  34. const   TCHAR   rgszP3Sites[]   = TEXT("SOFTWARE\Microsoft\Internet Explorer\Security\P3Sites");
  35. const   TCHAR   rgszInetKey[]   = TEXT("SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings");
  36. const   TCHAR   rgszPathTxt[]   = TEXT("Path");
  37. const   TCHAR   rgszDomainTxt[] = TEXT("Domain");
  38. const   TCHAR   rgszAllowTxt[]  = TEXT("Allow");
  39. const   TCHAR   rgszDenyTxt[]   = TEXT("Deny");
  40. const   TCHAR   rgszExpireTxt[] = TEXT("Expiration");
  41. const   TCHAR   rgszCookieTxt[] = TEXT("AllowCookies");
  42. const   TCHAR   rgszEnabled[]   = TEXT("Enabled");
  43. const   TCHAR   rgszRegKey[]    = TEXT("SOFTWARE\Microsoft\Internet Explorer\P3\Write");
  44. const   TCHAR   rgszRegTxt[]    = TEXT("Registration");
  45. const   TCHAR   GENDER_UNSPECIFIED[] = TEXT("U");
  46. const   TCHAR   GENDER_FEMALE[] = TEXT("F");
  47. const   TCHAR   GENDER_MALE[] = TEXT("M");
  48. const   WCHAR   GENDER_FEMALE_W[] = L"F";
  49. const   WCHAR   GENDER_MALE_W[] = L"M";
  50. #ifdef _USE_PSTORE_
  51. // {647EC150-DC4A-11d0-A02C-00C0DFA9C763}
  52. EXTERN_C const GUID GUID_PStoreType = { 0x647ec150, 0xdc4a, 0x11d0, { 0xa0, 0x2c, 0x0, 0xc0, 0xdf, 0xa9, 0xc7, 0x63 } };
  53. PST_KEY s_Key = PST_KEY_CURRENT_USER;
  54. #endif  // _USE_PSTORE_
  55. // Static helper functions
  56. static WCHAR*   _GetNameFromAttrIndex ( int index );
  57. static INT      _GetResourceIdFromAttrIndex( int index );
  58. static ULONG    _GetPropTagFromAttrIndex( int index );
  59. // This table maintains the list of the suffixes for the Standard OPS attributes
  60. // The names are intentionally kept here because these should not be localized.
  61. struct _ProfileAttribute
  62. {
  63.      WCHAR * pwzName;
  64.      int     id;         // resource ID for the friendly name of the attribute.
  65.      ULONG   ulPropTag;
  66. };
  67. const _ProfileAttribute rgProfAttr [] =
  68.         {
  69.             { L"Vcard.DisplayName",             IDS_OPS_COMMONNAME,         PR_DISPLAY_NAME             },
  70.             { L"Vcard.FirstName",               IDS_OPS_GIVENNAME,          PR_GIVEN_NAME               },
  71.             { L"Vcard.LastName",                IDS_OPS_LASTNAME,           PR_SURNAME                  },
  72.             { L"Vcard.MiddleName",              IDS_OPS_MIDDLENAME,         PR_MIDDLE_NAME              },
  73.             // 0, 1, 2 for Unspecified, Female, Male
  74.             { L"Vcard.Gender",                  IDS_OPS_GENDER,             PR_GENDER                   },
  75.             { L"Vcard.Cellular",                IDS_OPS_CELLULAR,           PR_CELLULAR_TELEPHONE_NUMBER},
  76.             { L"Vcard.Email",                   IDS_OPS_EMAIL,              PR_EMAIL_ADDRESS            },
  77.             { L"Vcard.HomePage",                IDS_OPS_URL,                PR_PERSONAL_HOME_PAGE       },
  78.             { L"Vcard.Company",                 IDS_OPS_COMPANY,            PR_COMPANY_NAME             },
  79.             { L"Vcard.Department",              IDS_OPS_DEPARTMENT,         PR_DEPARTMENT_NAME          },
  80.             { L"Vcard.Office",                  IDS_OPS_OFFICE,             PR_OFFICE_LOCATION,         },
  81.             { L"Vcard.JobTitle",                IDS_OPS_JOBTITLE,           PR_TITLE                    },
  82.             { L"Vcard.Pager",                   IDS_OPS_PAGER,              PR_PAGER_TELEPHONE_NUMBER   },
  83.             
  84.             { L"Vcard.Home.StreetAddress",      IDS_OPS_HOME_ADDRESS,       PR_HOME_ADDRESS_STREET      },
  85.             { L"Vcard.Home.City",               IDS_OPS_HOME_CITY,          PR_HOME_ADDRESS_CITY        },
  86.             { L"Vcard.Home.ZipCode",            IDS_OPS_HOME_ZIPCODE,       PR_HOME_ADDRESS_POSTAL_CODE },
  87.             { L"Vcard.Home.State",              IDS_OPS_HOME_STATE,         PR_HOME_ADDRESS_STATE_OR_PROVINCE   },
  88.             { L"Vcard.Home.Country",            IDS_OPS_HOME_COUNTRY,       PR_HOME_ADDRESS_COUNTRY     },
  89.             { L"Vcard.Home.Phone",              IDS_OPS_HOME_PHONE,         PR_HOME_TELEPHONE_NUMBER    },
  90.             { L"Vcard.Home.Fax",                IDS_OPS_HOME_FAX,           PR_HOME_FAX_NUMBER          },
  91.             { L"Vcard.Business.StreetAddress",  IDS_OPS_BUSINESS_ADDRESS,   PR_BUSINESS_ADDRESS_STREET  },
  92.             { L"Vcard.Business.City",           IDS_OPS_BUSINESS_CITY,      PR_BUSINESS_ADDRESS_CITY    },
  93.             { L"Vcard.Business.Zipcode",        IDS_OPS_BUSINESS_ZIPCODE,   PR_BUSINESS_ADDRESS_POSTAL_CODE},
  94.             { L"Vcard.Business.State",          IDS_OPS_BUSINESS_STATE,     PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE},
  95.             { L"Vcard.Business.Country",        IDS_OPS_BUSINESS_COUNTRY,   PR_BUSINESS_ADDRESS_COUNTRY },
  96.             
  97.             { L"Vcard.Business.Phone",          IDS_OPS_BUSINESS_PHONE,     PR_BUSINESS_TELEPHONE_NUMBER},
  98.             { L"Vcard.Business.Fax",            IDS_OPS_BUSINESS_FAX,       PR_BUSINESS_FAX_NUMBER      },
  99.             { L"Vcard.Business.URL",            IDS_OPS_BUSINESS_URL,       PR_BUSINESS_HOME_PAGE       },
  100.         };
  101. // A sentinel value returned for unsuccessful searches
  102. const   int     INVALID_ATTRIBUTE_INDEX = 0xFFFFFFFF;
  103. // Compute the number of bytes necessary to hold a bit-vector for the
  104. // Vcard schema where each attribute is represented by one bit.
  105. const   DWORD   dwVcardCount    = ARRAYSIZE(rgProfAttr);
  106. const   DWORD   dwVcardBytes    = (dwVcardCount+7) / 8;
  107. const   DWORD   defExpireDays   = 7;            // Default expiration time in days
  108. const   DWORD   maxExpireDays   = 30;           // Maximum allowed expiration period
  109. // Number of 100-ns intervals per day
  110. const   __int64 intervalsPerDay = (__int64) 10000000 * 3600 * 24;    
  111. // Default and maximum expiration time in units of 100 nanoseconds
  112. // (This is the format used for the FILETIME structure)
  113. const   __int64 defExpiration = defExpireDays * intervalsPerDay;
  114. const   __int64 maxExpiration = maxExpireDays * intervalsPerDay;
  115. // Context-sensitive help IDS
  116. const   DWORD   aHelpIDs[] =
  117. {
  118.     IDC_OPS_INFO_REQUESTED,     IDH_PA_OPS_REQUEST,
  119.     IDC_OPS_URL,                IDH_PA_OPS_REQUEST,
  120.     IDC_SITE_IDENTITY,          IDH_PA_OPS_REQUEST,
  121.     IDC_OPS_LIST,               IDH_PA_OPS_LIST,
  122.     IDC_USAGE_STRING,           IDH_PA_USAGE_STRING,
  123.     IDC_VIEW_CERT,              IDH_PA_VIEW_CERT,
  124.     IDC_EDIT_PROFILE,           IDH_EDIT_PROFILE_BTN,
  125.     IDC_OPS_PRIVACY,            IDH_PA_CONNECTION_SECURITY,
  126.     IDC_SECURITY_ICON,          IDH_PA_CONNECTION_SECURITY,
  127.     IDC_SECURE_CONNECTION,      IDH_PA_CONNECTION_SECURITY,
  128.     IDC_UNSECURE_CONNECTION,    IDH_PA_CONNECTION_SECURITY,
  129.     IDC_KEEP_SETTINGS,          IDH_PA_ALWAYS_SHARE,
  130.     0,                          0
  131. };
  132. WCHAR* _GetNameFromAttrIndex ( int index ) 
  133. {
  134.     // Assert that the index is valid.
  135.     ASSERT(index>=0 && index<ARRAYSIZE(rgProfAttr));
  136.     return rgProfAttr[index].pwzName;
  137. }
  138. INT _GetResourceIdFromAttrIndex( int index )
  139. {
  140.     // Assert that the index is valid.
  141.     ASSERT(index>=0 && index<ARRAYSIZE(rgProfAttr));
  142.     return rgProfAttr[index].id;
  143. }
  144. ULONG _GetPropTagFromAttrIndex( int index )
  145. {
  146.     // Assert that the index is valid.
  147.     ASSERT(index>=0 && index<ARRAYSIZE(rgProfAttr));
  148.     return rgProfAttr[index].ulPropTag;
  149. }
  150. //================================================
  151. //   Implementation of the OPSRequestEntry object
  152. //------------------------------------------------
  153. int CIEFrameAuto::COpsProfile::OPSRequestEntry::destWrapper(void *pEntry, void *pUnused) 
  154. {
  155.     OPSRequestEntry *pReqEntry = (OPSRequestEntry*) pEntry; 
  156.     delete pReqEntry;
  157.     return TRUE; 
  158. }
  159. int CIEFrameAuto::COpsProfile::OPSRequestEntry::grantRequest(void *pEntry, void *pUnused)
  160. {
  161.     OPSRequestEntry *pReqEntry = (OPSRequestEntry*) pEntry;
  162.     pReqEntry->grantRequest();
  163.     return TRUE;
  164. }
  165. void CIEFrameAuto::COpsProfile::OPSRequestEntry::grantRequest() 
  166. {
  167.     m_fQuery    = FALSE;
  168.     m_fAnswer   = TRUE; 
  169. }
  170. void CIEFrameAuto::COpsProfile::OPSRequestEntry::denyRequest() 
  171. {   
  172.     m_fQuery    = FALSE;
  173.     m_fAnswer   = FALSE;
  174. }
  175. void CIEFrameAuto::COpsProfile::OPSRequestEntry::clearValue()
  176. {   
  177.     SysFreeString(m_bstrValue);
  178.     m_bstrValue = NULL;
  179. }
  180. CIEFrameAuto::COpsProfile::OPSRequestEntry::OPSRequestEntry()
  181. {
  182.     m_fQuery        = TRUE;
  183.     m_fAnswer       = FALSE;
  184.     m_bstrValue     = NULL;
  185.     m_bstrName      = NULL;
  186.     m_bstrOldVal    = NULL;
  187. }
  188.    
  189. CIEFrameAuto::COpsProfile::OPSRequestEntry::~OPSRequestEntry()
  190. {
  191.     SysFreeString(m_bstrName);
  192.     SysFreeString(m_bstrValue);
  193.     SysFreeString(m_bstrOldVal);
  194. }
  195. //================================================
  196. //   Implementation of the COpsProfile object
  197. //------------------------------------------------
  198. CIEFrameAuto::COpsProfile::COpsProfile()
  199. :    CAutomationStub( MIN_BROWSER_DISPID, MAX_BROWSER_DISPID, TRUE ) 
  200. {    
  201. #ifdef NEVER
  202.     m_pCert = NULL;
  203. #endif  // NEVER
  204. #ifdef _USE_PSTORE_   
  205.     m_provID = GUID_NULL;
  206.     m_pStore    = NULL;
  207.     m_iStoreRef = 0;
  208. #else
  209.     m_bWABInit = FALSE;
  210.     m_hInstWAB = NULL;
  211.     m_lpAdrBook = NULL;
  212.     m_lpWABObject = NULL;
  213.     m_hrWAB = E_UNEXPECTED;
  214.     m_SBMe.cb = 0;
  215.     m_SBMe.lpb = NULL;
  216. #endif  // _USE_PSTORE_
  217.     m_fEnabled = FALSE;
  218.         
  219.     m_bstrLastURL = NULL;
  220.     m_hdpaRequests = DPA_Create(0);
  221.     m_hdpaChanges = DPA_Create(0);
  222.     m_hP3Global     = NULL;
  223.     m_hP3Sites      = NULL;
  224. }
  225. CIEFrameAuto::COpsProfile::~COpsProfile() 
  226. {
  227.     clearRequest();
  228. #ifdef NEVER
  229.     if (m_pCert)
  230.         m_pCert->Release();
  231. #endif  // NEVER
  232.     for (unsigned i=m_iStoreRef; i>0; i--)
  233.         _ReleaseStore();
  234. #ifdef _USE_PSTORE_
  235.     if (m_pStore)
  236.         ATOMICRELEASE(m_pStore);
  237. #else
  238.     if (m_SBMe.lpb)
  239.         m_lpWABObject->FreeBuffer(m_SBMe.lpb);
  240.     if (m_lpAdrBook)
  241.         ATOMICRELEASE(m_lpAdrBook);
  242.     if (m_lpWABObject)
  243.         ATOMICRELEASE(m_lpWABObject);
  244.     if (m_hInstWAB)
  245.         FreeLibrary(m_hInstWAB);
  246. #endif  // _USE_PSTORE_
  247.     // Prevent delay-loading of OLEAUT32.DLL if not necessary
  248.     if (m_bstrLastURL)
  249.         SysFreeString(m_bstrLastURL);
  250.     RegCloseKey(m_hP3Global);
  251.     RegCloseKey(m_hP3Sites);
  252.     DPA_DestroyCallback(m_hdpaRequests, OPSRequestEntry::destWrapper, NULL);
  253.     DPA_DestroyCallback(m_hdpaChanges, OPSRequestEntry::destWrapper, NULL);
  254. }
  255. HRESULT     CIEFrameAuto::COpsProfile::_CreateStore()
  256. {
  257. #ifdef _USE_PSTORE_
  258.     if (m_iStoreRef == 0) 
  259.     {
  260.         HRESULT hr = PStoreCreateInstance(  &m_pStore,  
  261.                                             IsEqualGUID(m_provID, GUID_NULL) ? NULL : &m_provID,
  262.                                             NULL,
  263.                                             0);
  264.         if (SUCCEEDED(hr))
  265.             m_iStoreRef++;
  266.         return hr;
  267.     }
  268.     m_iStoreRef++;
  269.     return S_OK;
  270. #else
  271.     if (!m_bWABInit) 
  272.     {
  273.         ASSERT(NULL == m_hInstWAB);
  274.         ASSERT(NULL == m_lpAdrBook && NULL == m_lpWABObject);
  275.         // Don't try initializing the wab again and again 
  276.         m_bWABInit = TRUE;
  277.         
  278.         {
  279.             // Figure out the location of the wab dll and try opening it.
  280.             TCHAR szWABDllPath[MAX_PATH];
  281.             DWORD dwType = 0;
  282.             ULONG cbData = sizeof(szWABDllPath) * sizeof(TCHAR);
  283.             HKEY hKey = NULL;
  284.             *szWABDllPath = '';
  285.             if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, WAB_DLL_PATH_KEY, 0, KEY_READ, &hKey))
  286.                 RegQueryValueEx( hKey, TEXT(""), NULL, &dwType, (LPBYTE) szWABDllPath, &cbData);
  287.             if(hKey) RegCloseKey(hKey);
  288.             if (lstrlen(szWABDllPath) != 0 )
  289.                 m_hInstWAB = LoadLibrary (szWABDllPath);
  290.             else
  291.                 m_hInstWAB = NULL;
  292.         }
  293.         HRESULT hr;
  294.         if (m_hInstWAB)
  295.         {
  296.             LPWABOPEN lpfnWABOpen = (LPWABOPEN) GetProcAddress(m_hInstWAB, "WABOpen");
  297.             
  298.             if (lpfnWABOpen)
  299.             {
  300.                 hr = lpfnWABOpen(&m_lpAdrBook, &m_lpWABObject, NULL, 0);
  301.                 if (NULL == m_lpAdrBook || NULL == m_lpWABObject)
  302.                     hr = E_UNEXPECTED;
  303.             }
  304.             else 
  305.             {
  306.                 hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);  // Not the right dll anyway!!
  307.             }
  308.         }
  309.         else
  310.         {
  311.             hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);
  312.         }
  313.         // Good so far, call GetMe.
  314.         if (!hr)
  315.         {
  316.             m_SBMe.cb = 0;
  317.             m_SBMe.lpb = NULL;
  318.             hr = m_lpWABObject->GetMe(m_lpAdrBook, WABOBJECT_ME_NOCREATE | AB_NO_DIALOG, NULL, &m_SBMe, 0);
  319.             if (0 == m_SBMe.cb || NULL == m_SBMe.lpb)
  320.                 hr = E_UNEXPECTED;
  321.         }     
  322.         // Remember the return code for later.
  323.         m_hrWAB = hr;
  324.     }
  325.         
  326.     if (!m_hrWAB)
  327.         m_iStoreRef++;
  328.     return m_hrWAB;
  329. #endif
  330. }
  331. HRESULT     CIEFrameAuto::COpsProfile::_ReleaseStore()
  332. {
  333.     if (m_iStoreRef > 0) 
  334.         m_iStoreRef--;
  335.     return S_OK;
  336. }
  337. HRESULT     CIEFrameAuto::COpsProfile::Init() 
  338. {
  339.     DWORD   dwError;
  340.     DWORD   dwAction;
  341.     dwError = RegCreateKeyEx(HKEY_CURRENT_USER, 
  342.                             rgszP3Global, 
  343.                             0, 
  344.                             NULL,
  345.                             REG_OPTION_NON_VOLATILE,
  346.                             KEY_ALL_ACCESS, 
  347.                             NULL, 
  348.                             &m_hP3Global, 
  349.                             &dwAction);
  350.     dwError = RegCreateKeyEx(HKEY_CURRENT_USER,
  351.                             rgszP3Sites,
  352.                             0, 
  353.                             NULL,
  354.                             REG_OPTION_NON_VOLATILE,
  355.                             KEY_ALL_ACCESS,
  356.                             NULL,
  357.                             &m_hP3Sites,
  358.                             &dwAction);
  359.     m_fEnabled = _IsP3Enabled();
  360.  
  361.     CIEFrameAuto* pauto = IToClass(CIEFrameAuto, _profile, this);
  362.     return CAutomationStub::Init( SAFECAST(this, IHTMLOpsProfile*), IID_IHTMLOpsProfile,
  363.                         CLSID_COpsProfile, pauto );
  364. }
  365. HRESULT     CIEFrameAuto::COpsProfile::addReadRequest(BSTR bstrName, VARIANT reserved, VARIANT_BOOL *pfSuccess)
  366. {
  367.     if ( pfSuccess )
  368.         *pfSuccess = VARIANT_FALSE;
  369.     if (!m_fEnabled)
  370.         return S_FALSE;
  371.     if (bstrName==NULL)
  372.         return E_POINTER;
  373.     BSTR    bstrURL = NULL;
  374.     HRESULT hr = _pAuto->get_LocationURL(&bstrURL);
  375.     if (_DifferentURL())
  376.         clearRequest();
  377.     SysFreeString(m_bstrLastURL);
  378.     m_bstrLastURL = SysAllocString(bstrURL);
  379.     if (NULL == m_bstrLastURL)
  380.     {
  381.         return E_OUTOFMEMORY;
  382.     }
  383.     int index = _GetAttrIndexFromName(bstrName);
  384.     if (index==INVALID_ATTRIBUTE_INDEX)
  385.         return S_FALSE;
  386.     // If the attribute already exists on the list, return from this function
  387.     for (int i=0; i<DPA_GetPtrCount(m_hdpaRequests); i++)
  388.     {
  389.         OPSRequestEntry *pEntry = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests, i);
  390.         if (StrCmpIW(pEntry->m_bstrName,bstrName)==0)
  391.             return S_OK;
  392.     }
  393.     OPSRequestEntry *pNewEntry = new OPSRequestEntry;
  394.     if (pNewEntry==NULL)
  395.         return E_OUTOFMEMORY;
  396.     pNewEntry->m_bstrName = SysAllocString(_GetNameFromAttrIndex(index));
  397.     if (pNewEntry->m_bstrName==NULL) 
  398.     {
  399.         delete pNewEntry;
  400.         return E_OUTOFMEMORY;
  401.     }
  402.     pNewEntry->m_bstrValue  = NULL;
  403.     int eIns = DPA_AppendPtr(m_hdpaRequests, (void*) pNewEntry);
  404.     if (eIns==-1) 
  405.     {
  406.         delete pNewEntry;
  407.         return E_OUTOFMEMORY;
  408.     }
  409.     if ( pfSuccess )
  410.         *pfSuccess = VARIANT_TRUE;
  411.     return S_OK;
  412. }
  413. HRESULT     CIEFrameAuto::COpsProfile::clearRequest() 
  414. {
  415.     m_fEnabled = _IsP3Enabled();
  416.     if (!m_fEnabled)
  417.         return S_FALSE;
  418.    
  419.     DPA_EnumCallback(m_hdpaRequests, OPSRequestEntry::destWrapper, NULL);
  420.     DPA_DeleteAllPtrs(m_hdpaRequests);
  421.     return S_OK;
  422. }
  423. HRESULT     CIEFrameAuto::COpsProfile::doRequest(VARIANT usage, VARIANT fname, 
  424.                                                  VARIANT vaDomain, VARIANT vaPath, VARIANT vaExpire,
  425.                                                  VARIANT reserved)
  426. {
  427.     m_fEnabled = _IsP3Enabled();
  428.     if (!m_fEnabled)
  429.         return S_FALSE;
  430.     int     i, k;
  431.     HRESULT hr;
  432.     BOOL    fShowUI = FALSE;
  433.     BOOL    fPersistent = FALSE;
  434.     BSTR    bstrURL;
  435.     TCHAR   rgchURL[MAX_URL_STRING];
  436.     TCHAR   rgchDomain[INTERNET_MAX_HOST_NAME_LENGTH+1];
  437.     TCHAR   rgchPath[MAX_PATH+1];
  438.     TCHAR   rgchScheme[16];
  439.     URL_COMPONENTS      uc;
  440.     AccessSettings      acSettings;
  441.     HDPA    hdpaConfirm = DPA_Create(0);
  442.     if (_DifferentURL())
  443.     {
  444.         clearRequest();
  445.         return S_FALSE;
  446.     }
  447.     hr = _pAuto->get_LocationURL(&bstrURL);
  448.     if (FAILED(hr))
  449.         return S_FALSE;
  450.     _StringFromBSTR(bstrURL, rgchURL, ARRAYSIZE(rgchURL));
  451.     ZeroMemory(&uc, sizeof(uc));
  452.     uc.dwStructSize = sizeof(URL_COMPONENTS);
  453.     uc.lpszHostName = rgchDomain;
  454.     uc.dwHostNameLength = ARRAYSIZE(rgchDomain);
  455.     uc.lpszUrlPath = rgchPath;
  456.     uc.dwUrlPathLength = ARRAYSIZE(rgchPath);
  457.     uc.lpszScheme = rgchScheme;
  458.     uc.dwSchemeLength = ARRAYSIZE(rgchScheme);
  459.     InternetCrackUrl(rgchURL, lstrlen(rgchURL), ICU_DECODE, &uc);
  460.     
  461.     _GetSiteSettings(&uc, vaDomain, vaPath, vaExpire, &acSettings);
  462.     hr = _CreateStore();
  463.     if (FAILED(hr))
  464.         return S_FALSE;
  465.     if (DPA_GetPtrCount(m_hdpaRequests)==0)
  466.         return S_OK;
  467.     for (k=0; k<DPA_GetPtrCount(m_hdpaRequests); k++)
  468.     {
  469.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,k);
  470.         pCurrent->clearValue();
  471.     }
  472.     HWND hwnd = _pAuto->_GetHWND();
  473.     INT_PTR nRet = -1;
  474.     // #59340 - don't need special priviliges for local machine zone anymore.
  475.     if (FALSE && _IsLocalMachine())
  476.     {
  477.         // If page is on the local machine, all requested information will be given
  478.         DPA_EnumCallback(m_hdpaRequests, OPSRequestEntry::grantRequest, NULL);
  479.         nRet = TRUE;
  480.     }
  481.     else
  482.     {
  483.         // Process the request list and mark attributes according to the configuration
  484.         _ApplyPreferences(&uc, m_hdpaRequests);
  485.         // Go through the request list and for each attribute that was not marked as
  486.         // grant/deny according to the preferences, add it to the list
  487.         for (k=0; k<DPA_GetPtrCount(m_hdpaRequests); k++)
  488.         {
  489.             OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,k);
  490.             
  491.             if (pCurrent->m_fQuery)
  492.                 DPA_AppendPtr(hdpaConfirm, pCurrent);
  493.         }
  494.         // Determine whether there are any attributes to query
  495.         fShowUI = DPA_GetPtrCount(hdpaConfirm)>0;
  496.         if (!fShowUI)
  497.         {
  498.             nRet = TRUE;
  499.             goto HandleRequest;
  500.         }
  501.         // If a UI is going to be shown, all attributes that were going to be
  502.         // given or denied silently should also be shown
  503.         for (k=0; k<DPA_GetPtrCount(m_hdpaRequests); k++)
  504.         {
  505.             OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,k);
  506.             if (!pCurrent->m_fQuery && 
  507.                 (pCurrent->m_fAnswer || (!pCurrent->m_fAnswer && pCurrent->m_dwDecision==P3_SITELEVEL)))
  508.             {
  509.                 DPA_AppendPtr(hdpaConfirm, pCurrent);
  510.                 pCurrent->m_fQuery = TRUE;
  511.             }
  512.         }
  513.         OPSDlgInfo opsDlgInfo;
  514.         opsDlgInfo.m_hdpa = hdpaConfirm;
  515.         StrCpyN(opsDlgInfo.m_rgchURL, rgchURL, ARRAYSIZE(opsDlgInfo.m_rgchURL));
  516.         opsDlgInfo.m_pOpsProfile = this;
  517.         opsDlgInfo.m_pacSettings = &acSettings;
  518.         opsDlgInfo.m_fRemember = (_GetCookieSettings()==COOKIES_ALLOW);
  519.         if (fname.vt == VT_BSTR && fname.bstrVal && lstrlenW(fname.bstrVal)>0)
  520.             opsDlgInfo.m_bstrFName = SysAllocString(fname.bstrVal);
  521.         else
  522.             opsDlgInfo.m_bstrFName = NULL;
  523.         _GetUsageCode(usage, opsDlgInfo.m_rgchUsage, ARRAYSIZE(opsDlgInfo.m_rgchUsage));
  524.         nRet = DialogBoxParam(MLGetHinst(),
  525.                                 MAKEINTRESOURCE(IDD_OPS_CONSENT),
  526.                                 hwnd,
  527.                                 _OPSConsent_DlgProc,
  528.                                 (LPARAM) &opsDlgInfo);
  529.         fPersistent = opsDlgInfo.m_fRemember;
  530.     }
  531. HandleRequest:
  532.     if (nRet==-1)
  533.         return E_FAIL;
  534.     
  535.     if (!nRet)
  536.     {
  537.         fPersistent = FALSE;
  538.         goto Cleanup;
  539.     }
  540.     for (i=0; i<DPA_GetPtrCount(m_hdpaRequests); i++) 
  541.     {
  542.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,i);
  543.  
  544.         if (pCurrent->m_fQuery)
  545.         {
  546.             pCurrent->m_prefs.m_lastRequest = pCurrent->m_fAnswer ? P3_ACCEPT : P3_REJECT;
  547.             _PutUserPreference(pCurrent->m_bstrName, pCurrent->m_prefs);
  548.         }
  549.         if (pCurrent->m_fAnswer)
  550.         {
  551.             hr = _GetFieldValue(pCurrent->m_bstrName, & (pCurrent->m_bstrValue));
  552.             if (FAILED(hr))
  553.                 pCurrent->clearValue();
  554.         }
  555.     }
  556.     if (fShowUI && fPersistent &&
  557.         (uc.nScheme==INTERNET_SCHEME_HTTP || uc.nScheme==INTERNET_SCHEME_HTTPS))
  558.     {
  559.         _UpdateSiteSettings(&acSettings, m_hdpaRequests);
  560.     }
  561. Cleanup:
  562.     DPA_Destroy(hdpaConfirm);
  563.     _ReleaseStore();
  564.     return S_OK;
  565. }
  566. HRESULT     CIEFrameAuto::COpsProfile::getAttribute(BSTR bstrAttribName, BSTR *pbstrAttribValue) 
  567. {
  568.     if (!m_fEnabled)
  569.         return S_FALSE;
  570.     
  571.     if (pbstrAttribValue==NULL || bstrAttribName==NULL)
  572.         return E_POINTER;
  573.     if (_DifferentURL())
  574.     {
  575.         clearRequest();
  576.         return S_FALSE;
  577.     }
  578.     *pbstrAttribValue = NULL;
  579.     for (int i=0; i<DPA_GetPtrCount(m_hdpaRequests); i++) 
  580.     {
  581.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaRequests,i);
  582.         if (StrCmpIW(bstrAttribName,pCurrent->m_bstrName) == 0) 
  583.         {
  584.             if (pCurrent->m_bstrValue == NULL)
  585.             {
  586.                 *pbstrAttribValue = SysAllocString(L"");
  587.             }
  588.             else
  589.             {
  590.                 *pbstrAttribValue = SysAllocString(pCurrent->m_bstrValue);
  591.             }
  592.             return (*pbstrAttribValue == NULL) ? E_OUTOFMEMORY : S_OK;
  593.         }
  594.     }
  595.     return S_FALSE;
  596. }
  597. HRESULT     CIEFrameAuto::COpsProfile::setAttribute(BSTR bstrAttribName, BSTR bstrAttribValue, VARIANT vaPrefs,
  598.                                                     VARIANT_BOOL *pfSuccess)
  599. {
  600.     BSTR bstrStdName = NULL;
  601.     HRESULT hr = S_FALSE;
  602.     if (pfSuccess)
  603.         *pfSuccess = VARIANT_FALSE;
  604.     if (!m_fEnabled)
  605.         return S_FALSE;
  606.     if (bstrAttribName==NULL)
  607.         return E_POINTER;
  608.     // If this is a new URL, flush the change queue.
  609.     if (_DifferentURL())
  610.     {
  611.         DPA_EnumCallback(m_hdpaChanges,OPSRequestEntry::destWrapper,NULL);
  612.         DPA_DeleteAllPtrs(m_hdpaChanges);
  613.     }
  614.     // Load the name of the current URL into the last visited URL
  615.     SysFreeString(m_bstrLastURL);
  616.     _pAuto->get_LocationURL(&m_bstrLastURL);
  617.     int index = _GetAttrIndexFromName(bstrAttribName);
  618.     if (index==INVALID_ATTRIBUTE_INDEX)
  619.         return S_FALSE;
  620.     OPSRequestEntry *pNewEntry = new OPSRequestEntry;
  621.     if (pNewEntry == NULL)
  622.         return E_OUTOFMEMORY;
  623.     
  624.     pNewEntry->m_bstrName = SysAllocString(_GetNameFromAttrIndex(index));
  625.     if (pNewEntry->m_bstrName==NULL) 
  626.         return E_OUTOFMEMORY;
  627.     if (bstrAttribValue != NULL)
  628.         pNewEntry->m_bstrValue = SysAllocString(bstrAttribValue);
  629.     else
  630.         pNewEntry->m_bstrValue = SysAllocString(L"");
  631.     if (pNewEntry->m_bstrValue==NULL)
  632.         return E_OUTOFMEMORY;
  633.     for (int i=0; i<DPA_GetPtrCount(m_hdpaChanges); i++) 
  634.     {
  635.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaChanges,i);
  636.         if (StrCmpIW(pCurrent->m_bstrName, bstrAttribName) == 0)
  637.         {
  638.             SysFreeString(pCurrent->m_bstrValue);
  639.             pCurrent->m_bstrValue = SysAllocString(bstrAttribName);
  640.             if (*pfSuccess)
  641.                 *pfSuccess = (pCurrent->m_bstrValue!=NULL) ? VARIANT_TRUE : VARIANT_FALSE;
  642.             return S_OK;
  643.         }
  644.     }
  645.     int eIns = DPA_AppendPtr(m_hdpaChanges, pNewEntry);
  646.     if (eIns==-1) 
  647.     {
  648.         delete pNewEntry;
  649.         return E_OUTOFMEMORY;
  650.     }
  651.     if (pfSuccess)
  652.         *pfSuccess = VARIANT_TRUE;
  653.     return S_OK;
  654. }
  655. HRESULT     CIEFrameAuto::COpsProfile::commitChanges(VARIANT_BOOL *pfSuccess) {
  656.     if ( pfSuccess )
  657.         *pfSuccess = VARIANT_FALSE;
  658.     if (!m_fEnabled)
  659.         return S_FALSE;
  660.     HRESULT hr;
  661.     HWND hwnd;
  662.     int i;
  663.     INT_PTR nRet;
  664.     OPSDlgInfo opsDlgInfo;
  665.     BSTR    bstrURL = NULL;
  666.     TCHAR   rgchURL[MAX_URL_STRING];
  667.     _pAuto->get_LocationURL(&bstrURL);
  668.     _StringFromBSTR(bstrURL, rgchURL, ARRAYSIZE(rgchURL));
  669.     SysFreeString(bstrURL);
  670.     // Crack the URL and get the hostname
  671.     TCHAR   rgchHostName[INTERNET_MAX_HOST_NAME_LENGTH] = { TEXT('') };
  672.     DWORD   dwcbHostLen = ARRAYSIZE(rgchHostName);
  673.     UrlGetPart(rgchURL, rgchHostName,  &dwcbHostLen, URL_PART_HOSTNAME, 0);
  674.     // Read the hostname for the registration page from the registry 
  675.     TCHAR   rgchRegDomain[INTERNET_MAX_HOST_NAME_LENGTH];
  676.     DWORD   dwcbReg = sizeof(rgchRegDomain);
  677.     HKEY    hWriteKey = NULL;
  678.     DWORD   dwError;
  679.     dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, rgszRegKey, 0, KEY_READ, &hWriteKey);
  680.     if (dwError==ERROR_SUCCESS)
  681.     {
  682.         dwError = RegQueryValueEx(hWriteKey, rgszRegTxt, NULL, NULL, (LPBYTE) rgchRegDomain, &dwcbReg);
  683.         RegCloseKey(hWriteKey);
  684.     }
  685.     BOOL  fRegDomain = (dwError==ERROR_SUCCESS && _DomainMatch(rgchHostName, rgchRegDomain));
  686.     BOOL  fCanWrite = _IsLocalMachine() || fRegDomain;
  687.     if (!fCanWrite || _DifferentURL())
  688.         goto Cleanup;
  689.     hr = _CreateStore();
  690.     if (hr)
  691.         goto Cleanup;
  692.     // Look up the old values from the store
  693.     for (i=0; i<DPA_GetPtrCount(m_hdpaChanges); i++)
  694.     {
  695.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaChanges, i);
  696.         // Default case: the attribute will be updated
  697.         pCurrent->m_fAnswer = TRUE;
  698.         hr = _GetFieldValue (pCurrent->m_bstrName, &(pCurrent->m_bstrOldVal));
  699.         if (hr)
  700.         {
  701.             SysFreeString(pCurrent->m_bstrOldVal);
  702.             pCurrent->m_bstrOldVal = NULL;
  703.         }
  704.     }
  705.     // Delete nodes in the list if the new value is the same as the old one
  706.     // NOTE: The loop counter will remain stationary or increment depending on whether
  707.     // the current node in the list is deleted
  708.     for (i=0; i<DPA_GetPtrCount(m_hdpaChanges); )
  709.     {
  710.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaChanges, i);
  711.         if (StrCmpW(pCurrent->m_bstrValue, pCurrent->m_bstrOldVal)==0)
  712.             DPA_DeletePtr(m_hdpaChanges, i);
  713.         else
  714.             i++;
  715.     }
  716.     // If nothing has changed, then we do not need to write data back to the storage
  717.     if (DPA_GetPtrCount(m_hdpaChanges)==0)     
  718.         goto Cleanup;  
  719.     // The registration domain can write profile information silently.
  720.     // For all other cases, a UI will be displayed.
  721.     if (!fRegDomain)
  722.     {
  723.         // Pop up a UI to show the items that are being changes and allow the user to 
  724.         // confirm the changes by selecting check-boxes for each attribute
  725.         opsDlgInfo.m_hdpa = m_hdpaChanges;
  726.         opsDlgInfo.m_pOpsProfile = this;
  727.         hwnd = _pAuto->_GetHWND();
  728.         nRet = DialogBoxParam(MLGetHinst(),
  729.                                 MAKEINTRESOURCE(IDD_OPS_UPDATE),
  730.                                 hwnd,
  731.                                 _OPSUpdate_DlgProc,
  732.                                 (LPARAM) &opsDlgInfo
  733.                             );
  734.         // Unrecoverable error: failed to show the dialog box
  735.         if (nRet==-1)
  736.             return S_FALSE;
  737.         // If the user clicked "CANCEL", then no changes will be performed
  738.         if (nRet==0)
  739.             goto Cleanup;
  740.     }
  741.     if ( pfSuccess )
  742.         *pfSuccess = VARIANT_TRUE;
  743.     for (i=0; i<DPA_GetPtrCount(m_hdpaChanges); i++)
  744.     {
  745.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(m_hdpaChanges, i);
  746.         // Registration page should not overwrite existing entries
  747.         if (fRegDomain && ! EMPTY_STRINGW(pCurrent->m_bstrOldVal))
  748.             continue;
  749.         // Update only if the user allowed in the UI
  750.         // For the registration page, this condition will hold for all attributes
  751.         if (pCurrent->m_fAnswer)
  752.         {
  753.             hr = _SetFieldValue(pCurrent->m_bstrName, pCurrent->m_bstrValue);
  754.             if (hr && pfSuccess)
  755.                 *pfSuccess = VARIANT_FALSE;
  756.         }
  757.      }
  758. Cleanup:
  759.     // Clear the queue that holds the changes 
  760.     DPA_EnumCallback(m_hdpaChanges,OPSRequestEntry::destWrapper,NULL);
  761.     DPA_DeleteAllPtrs(m_hdpaChanges);
  762.     return S_OK;
  763. }
  764. // *** IOpsProfileSimple members ***
  765. STDMETHODIMP CIEFrameAuto::COpsProfile::ReadProperties(long lNumProperties, const LPCWSTR szProperties[], LPWSTR szReturnValues[])
  766. {
  767.     HRESULT hr=S_OK;
  768.     for (int i=0; i<lNumProperties; i++)
  769.     {
  770.         BSTR bstrValue=NULL;
  771.         LPWSTR pwszRet=NULL;
  772.         if (szProperties[i])
  773.         {
  774.             _GetFieldValue(szProperties[i], &bstrValue);
  775.             if (bstrValue)
  776.             {
  777.                 // BUGBUG change _GetFieldValue so we don't reallocate twice unnecessarily
  778.                 int cch = (1 + lstrlenW(bstrValue));
  779.                 pwszRet = (LPWSTR) CoTaskMemAlloc(sizeof(WCHAR) * cch);
  780.                 if (pwszRet)
  781.                     StrCpyNW(pwszRet, bstrValue, cch);
  782.                 SysFreeString(bstrValue);
  783.             }
  784.             else
  785.             {
  786.                 hr = S_FALSE;
  787.             }
  788.         }
  789.         szReturnValues[i] = pwszRet;
  790.     }
  791.     return hr;
  792. }
  793. STDMETHODIMP CIEFrameAuto::COpsProfile::WriteProperties(long lNumProperties, const LPCWSTR szProperties[], const LPCWSTR szValues[])
  794. {
  795.     return E_NOTIMPL;
  796. }
  797. #ifdef _USE_PSTORE_
  798. HRESULT     CIEFrameAuto::COpsProfile::_GetFieldValue(const OLECHAR *pszField, BSTR * pbstrValue) 
  799. {
  800.     GUID            itemType = GUID_NULL;
  801.     GUID            itemSubtype = GUID_NULL;
  802.     BSTR            bstrName = NULL;
  803.     DWORD           cbData;
  804.     BYTE *          pbData = NULL;
  805.     PST_PROMPTINFO  promptInfo;
  806.     HRESULT         hr;
  807.     BOOL            fOpen = FALSE;
  808.     if (pszField==NULL || pbstrValue==NULL)
  809.         return E_POINTER;
  810.     ZeroMemory(&promptInfo,sizeof(promptInfo));
  811.     promptInfo.cbSize = sizeof(promptInfo);
  812.     promptInfo.szPrompt = pszField;
  813.     promptInfo.dwPromptFlags = 0;
  814.     promptInfo.hwndApp = _pAuto->_GetHWND();
  815.     hr = _CreateStore();
  816.     if (hr)
  817.         goto Cleanup;
  818.     hr = _GetPStoreTypes(pszField, &itemType, &itemSubtype, &bstrName);
  819.     if (hr)
  820.         goto Cleanup;
  821.     hr =    m_pStore->ReadItem(
  822.                         s_Key,
  823.                         &itemType,
  824.                         &itemSubtype,
  825.                         bstrName,
  826.                         &cbData,
  827.                         &pbData,
  828.                         &promptInfo,
  829.                         0);
  830.     if (FAILED(hr))
  831.     {
  832.         *pbstrValue = SysAllocString(L"");
  833.         hr = S_OK;
  834.         goto Cleanup;
  835.     }
  836.     *pbstrValue = SysAllocString((OLECHAR *) pbData);
  837. Cleanup:
  838.     _ReleaseStore();
  839.     CoTaskMemFree(pbData);
  840.     SysFreeString(bstrName);
  841.     return hr;
  842. }
  843. HRESULT     CIEFrameAuto::COpsProfile::_SetFieldValue(const OLECHAR *pszField, BSTR bstrValue) 
  844. {
  845.     
  846.     HRESULT         hr;
  847.     PST_TYPEINFO    typeInfo;
  848.     PST_PROMPTINFO  promptInfo;
  849.     WCHAR *         szValue = bstrValue ? bstrValue : L"";
  850.     TCHAR           szDisplayName[MAX_PATH];
  851.     WCHAR           wzDisplayName[MAX_PATH];
  852.     if (pszField==NULL)
  853.         return E_POINTER;
  854.     MLLoadString(IDS_PROFILE_ASSISTANT, szDisplayName, ARRAYSIZE(szDisplayName));
  855.     typeInfo.cbSize = sizeof(typeInfo);
  856.     int cch = MultiByteToWideChar(  CP_ACP, 0, szDisplayName, -1, 
  857.                                     wzDisplayName, ARRAYSIZE(wzDisplayName));
  858.     ASSERT(cch != 0); 
  859.     typeInfo.szDisplayName = wzDisplayName;
  860.     promptInfo.cbSize = sizeof(promptInfo);
  861.     promptInfo.dwPromptFlags = 0;
  862.     promptInfo.hwndApp = _pAuto->_GetHWND();  
  863.     promptInfo.szPrompt = pszField;
  864.     hr = _CreateStore();
  865.     if (hr)
  866.         goto Cleanup;
  867.     hr = m_pStore->CreateType(s_Key, &GUID_PStoreType, &typeInfo, 0);
  868.     if (hr && (hr != PST_E_TYPE_EXISTS))
  869.         goto Cleanup;
  870.     hr = m_pStore->CreateSubtype(
  871.                             s_Key,
  872.                             &GUID_PStoreType,
  873.                             &GUID_NULL,
  874.                             &typeInfo,
  875.                             NULL,
  876.                             0);
  877.     if (hr && (hr != PST_E_TYPE_EXISTS))
  878.         goto Cleanup;
  879.     hr = m_pStore->WriteItem(
  880.                         s_Key,
  881.                         &GUID_PStoreType,
  882.                         &GUID_NULL,
  883.                         pszField,
  884.                         (lstrlenW(szValue) + 1) * sizeof(WCHAR),
  885.                         (BYTE *) szValue,
  886.                         &promptInfo,
  887.                         PST_CF_NONE,
  888.                         0);
  889. Cleanup:
  890.     _ReleaseStore();
  891.     return hr;
  892. }
  893. #else       // _USE_PSTORE_
  894. HRESULT     CIEFrameAuto::COpsProfile::_GetFieldValue(const OLECHAR *pszField, BSTR * pbstrValue) 
  895. {
  896.     LPMAILUSER lpMailUser = NULL;
  897.     ULONG ulPropTag; 
  898.     ULONG ulObjType = 0;
  899.     WCHAR * pwzValue = NULL;
  900.     BOOL bStoreCreated = FALSE;
  901.     HRESULT hr;
  902.     if (pszField==NULL || pbstrValue==NULL)
  903.         return E_POINTER;
  904.      
  905.     hr = _CreateStore();
  906.     if (hr)
  907.         goto Cleanup;
  908.     else
  909.         bStoreCreated = TRUE;
  910.     INT index;
  911.     index = INVALID_ATTRIBUTE_INDEX;
  912.     if (!_ValidateElemName(pszField, &index))
  913.     {
  914.         hr = E_INVALIDARG;
  915.         goto Cleanup;
  916.     }
  917.     // Open the entry in the address book. 
  918.     hr = m_lpAdrBook->OpenEntry(m_SBMe.cb, 
  919.                                 (LPENTRYID) m_SBMe.lpb,
  920.                                 NULL,
  921.                                 0,
  922.                                 &ulObjType,
  923.                                 (LPUNKNOWN *)&lpMailUser);
  924.     if (hr)
  925.         goto Cleanup;
  926.     if (lpMailUser)
  927.     {
  928.         ulPropTag = _GetPropTagFromAttrIndex(index);
  929.         SPropTagArray SPTA;
  930.         SPTA.cValues = 1;
  931.         SPTA.aulPropTag[0] = ulPropTag;
  932.         if (PROP_TYPE(ulPropTag) ==  PT_TSTRING || ulPropTag == PR_GENDER)
  933.         {
  934.             DWORD cValues = 0;
  935.             LPSPropValue lpSPropValue = NULL;
  936.             hr = lpMailUser->GetProps(&SPTA, 0, &cValues, &lpSPropValue);
  937.             if (!hr)
  938.             {
  939.                 ASSERT(1 == cValues);
  940.                 ASSERT(NULL != lpSPropValue);
  941.                 int cch = 0;
  942.                 LPCTSTR pszPropStr = NULL; 
  943.                 
  944.                 if (ulPropTag == PR_GENDER)
  945.                 {
  946.                     switch (lpSPropValue->Value.i) 
  947.                     {
  948.                         case 1:
  949.                             pszPropStr = GENDER_FEMALE;
  950.                             break;
  951.                         case 2:
  952.                             pszPropStr = GENDER_MALE;
  953.                             break;
  954.                         default:
  955.                             pszPropStr = GENDER_UNSPECIFIED;
  956.                             break;
  957.                     }
  958.                 }
  959.                 else
  960.                 {
  961.                     ASSERT(PROP_TYPE(lpSPropValue->ulPropTag) == PT_TSTRING);
  962.                     pszPropStr = lpSPropValue->Value.LPSZ;
  963.                 }
  964.                 if (pszPropStr)
  965.                 {
  966. #ifdef _UNICODE
  967.                     cch = lstrlen(pszPropStr) + 1;
  968. #else                    
  969.                     // We get the string back in ANSI convert to Unicode.
  970.                     cch = MultiByteToWideChar(CP_ACP, 0, pszPropStr, -1, NULL, 0);
  971. #endif
  972.                     pwzValue = new WCHAR [cch];
  973.                     if (NULL == pwzValue)
  974.                     {
  975.                         hr = E_OUTOFMEMORY;
  976.                     }
  977.                     else
  978.                     {
  979. #ifdef _UNICODE
  980.                         StrCpyN(pwzValue, pszPropStr, cch);
  981. #else
  982.                         cch = MultiByteToWideChar(CP_ACP, 0, pszPropStr, -1, pwzValue, cch);
  983.                         ASSERT(0 != cch);
  984. #endif
  985.                     }
  986.                 }
  987.                 else
  988.                 {
  989.                     hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);    // This will cause us to just return the NULL string.                                                                                                                                                                                                                                    
  990.                 }
  991.             }
  992.             m_lpWABObject->FreeBuffer(lpSPropValue);
  993.         }
  994.         else 
  995.         {
  996.             // If this assert fires you are probably adding a new PR_* mapping to the OPS code.
  997.             // You will need to write code to convert the returned value to a string meaningfully.
  998.             // See the example for GENDER above.
  999.             ASSERT(FALSE);  
  1000.             hr = E_NOTIMPL ; 
  1001.         }
  1002.     }
  1003.     else 
  1004.     {
  1005.         hr = E_UNEXPECTED;
  1006.     }                
  1007.     if (hr)
  1008.     {
  1009.         *pbstrValue = SysAllocString(L"");
  1010.         hr = (NULL != pbstrValue) ? S_OK : E_OUTOFMEMORY;
  1011.         goto Cleanup;
  1012.     }
  1013.     *pbstrValue = SysAllocString((OLECHAR *) pwzValue);
  1014. Cleanup:
  1015.     if (bStoreCreated)
  1016.         _ReleaseStore();
  1017.     if (lpMailUser)
  1018.         lpMailUser->Release();
  1019.     delete [] pwzValue;
  1020.     return hr;
  1021. }
  1022. HRESULT     CIEFrameAuto::COpsProfile::_SetFieldValue(const OLECHAR *pszField, BSTR bstrValue) 
  1023. {
  1024.     HRESULT         hr;
  1025.     LPMAILUSER lpMailUser = NULL;
  1026.     ULONG ulPropTag; 
  1027.     ULONG ulObjType = 0;
  1028.     BOOL bStoreCreated = FALSE;
  1029.     if (pszField==NULL)
  1030.         return E_POINTER;
  1031.      
  1032.     hr = _CreateStore();
  1033.     if (hr)
  1034.         goto Cleanup;
  1035.     else
  1036.         bStoreCreated = TRUE;
  1037.     INT index;
  1038.     index = INVALID_ATTRIBUTE_INDEX;
  1039.     if (!_ValidateElemName(pszField, &index))
  1040.     {
  1041.         hr = E_INVALIDARG;
  1042.         goto Cleanup;
  1043.     }
  1044.     // Open the entry in the address book. 
  1045.     hr = m_lpAdrBook->OpenEntry(m_SBMe.cb, 
  1046.                                 (LPENTRYID) m_SBMe.lpb,
  1047.                                 NULL,
  1048.                                 MAPI_MODIFY,
  1049.                                 &ulObjType,
  1050.                                 (LPUNKNOWN *)&lpMailUser);
  1051.     if (hr)
  1052.         goto Cleanup;
  1053.     if (lpMailUser)
  1054.     {
  1055.         ulPropTag = _GetPropTagFromAttrIndex(index);
  1056.         if (PROP_TYPE(ulPropTag) ==  PT_TSTRING || ulPropTag == PR_GENDER)
  1057.         {
  1058.             // First remove the existing entry
  1059.             SPropTagArray SPTA;
  1060.             SPTA.cValues = 1;
  1061.             SPTA.aulPropTag[0] = ulPropTag;
  1062.             lpMailUser->DeleteProps(&SPTA, NULL);
  1063.             SPropValue prop;
  1064.             prop.ulPropTag = ulPropTag;
  1065.             CHAR *pszValue = NULL;
  1066.             if (ulPropTag == PR_GENDER)
  1067.             {
  1068.                 short int i = 0;    // unspecified.
  1069.                 if (0 == StrCmpIW(bstrValue, GENDER_FEMALE_W))
  1070.                     i = 1;
  1071.                 else if (0 == StrCmpIW(bstrValue, GENDER_MALE_W))
  1072.                     i = 2;
  1073.                 prop.Value.i = i;
  1074.             }
  1075.             else 
  1076.             {
  1077.                 prop.Value.LPSZ = bstrValue;   
  1078.             }
  1079.             if (!hr)
  1080.             {
  1081.                 hr = lpMailUser->SetProps(1, &prop, NULL);
  1082.                 lpMailUser->SaveChanges(0);
  1083.             }
  1084.             
  1085.             delete [] pszValue;
  1086.         }                                                           
  1087.         else 
  1088.         {
  1089.             hr = E_NOTIMPL ; // FIX THIS BEFORE CHECKING IN. 
  1090.         }
  1091.     }
  1092.     else 
  1093.     {
  1094.         hr = E_UNEXPECTED;
  1095.     }                
  1096. Cleanup:
  1097.     if (bStoreCreated)
  1098.         _ReleaseStore();
  1099.     if (lpMailUser)
  1100.         lpMailUser->Release();
  1101.     return hr;
  1102. }
  1103. #endif      // ! _USE_PSTORE_
  1104. HRESULT     CIEFrameAuto::COpsProfile::_GetIDispatchExDelegate(IDispatchEx ** const delegate) 
  1105. {
  1106.     if( !delegate )
  1107.         return E_POINTER;
  1108.     *delegate = NULL;    // We do not handle expandos yet
  1109.     return DISP_E_MEMBERNOTFOUND;
  1110. }
  1111. HRESULT     CIEFrameAuto::COpsProfile::_InternalQueryInterface(REFIID riid, void ** const ppvObjOut)
  1112. {
  1113.     ASSERT( this );
  1114.     ASSERT( !IsEqualIID(riid, IID_IUnknown) );
  1115.     if (IsEqualIID(riid, IID_IHTMLOpsProfile))
  1116.     {
  1117.         *ppvObjOut = SAFECAST(this,IHTMLOpsProfile*);
  1118.     }
  1119.     else if (IsEqualIID(riid, IID_IOpsProfileSimple))
  1120.     {
  1121.         *ppvObjOut = SAFECAST(this,IOpsProfileSimple*);
  1122.     }
  1123.     else
  1124.     {
  1125.         *ppvObjOut = NULL;
  1126.         return E_NOINTERFACE;
  1127.     }
  1128.     AddRef( );
  1129.     return S_OK;
  1130. }
  1131. #ifdef _USE_PSTORE_
  1132. HRESULT
  1133. CIEFrameAuto::COpsProfile::_GetPStoreTypes(
  1134.         BSTR bstrField,
  1135.         GUID * pguidType,
  1136.         GUID * pguidSub,
  1137.         BSTR * pbstrName)
  1138. {
  1139.     *pguidType = GUID_PStoreType;
  1140.     *pguidSub = GUID_NULL;
  1141.     *pbstrName = SysAllocString(bstrField);
  1142.     return S_OK;
  1143. }
  1144. #endif  // _USE_PSTORE_
  1145. // Functions to display the consent dialog.
  1146. BOOL CIEFrameAuto::COpsProfile::_OPSConsent_OnInitDlg(HWND hDlg)
  1147. {
  1148.     const   int cbMaxStringDisplay  = 24;
  1149.     
  1150.     LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO) GetWindowLongPtr(hDlg, DWLP_USER);
  1151.     COpsProfile *pProfile = lpOpsDlgInfo->m_pOpsProfile;
  1152.     if (!lpOpsDlgInfo || !lpOpsDlgInfo->m_hdpa)
  1153.         return FALSE;
  1154.     // Get the hostname
  1155.     TCHAR   rgSiteName[MAX_URL_STRING];
  1156.     DWORD   dwchOut = ARRAYSIZE(rgSiteName);
  1157.     HRESULT hr;
  1158.     
  1159.     hr = UrlGetPart(lpOpsDlgInfo->m_rgchURL, rgSiteName, &dwchOut, URL_PART_HOSTNAME, 0);
  1160.     if (FAILED(hr) || dwchOut == 0 )
  1161.         StrCpyN(rgSiteName, lpOpsDlgInfo->m_rgchURL, ARRAYSIZE(rgSiteName));
  1162.     // Display site identity information
  1163.     HWND        hwndReq = GetDlgItem(hDlg, IDC_SITE_IDENTITY);
  1164.     TCHAR       rgRequestInfo[MAX_URL_STRING];
  1165.     TCHAR       rgFormat[MAX_URL_STRING];
  1166.     BSTR        bstrFName = lpOpsDlgInfo->m_bstrFName;
  1167.     TCHAR       rgBuffer[MAX_URL_STRING];
  1168.     TCHAR       rgFName[MAX_URL_STRING];
  1169.     if (bstrFName==NULL)
  1170.     {
  1171.         MLLoadString(IDS_DEFAULT_FNAME, rgFName, ARRAYSIZE(rgFName));
  1172.     }
  1173.     else
  1174.     {
  1175.         _StringFromBSTR(bstrFName, rgBuffer, ARRAYSIZE(rgBuffer));
  1176.         wnsprintf(rgFName, ARRAYSIZE(rgFName), TEXT("'%s'"),rgBuffer);
  1177.     }
  1178.     MLLoadString(IDS_OPS_REQUEST, rgFormat, ARRAYSIZE(rgFormat));
  1179.     wnsprintf(rgRequestInfo, ARRAYSIZE(rgRequestInfo), rgFormat, rgFName);
  1180.     SetWindowText(hwndReq, rgRequestInfo);
  1181.     // Display the access settings
  1182.     TCHAR rgchAccessPath[MAX_URL_STRING];
  1183.     HWND hwndURL = GetDlgItem(hDlg, IDC_OPS_URL);
  1184.     _FormatSiteSettings(lpOpsDlgInfo->m_pacSettings, rgchAccessPath, ARRAYSIZE(rgchAccessPath));
  1185.     SetWindowText(hwndURL, rgchAccessPath);
  1186.     // Display the usage information
  1187.     HWND hwndUsage = GetDlgItem(hDlg, IDC_USAGE_STRING);
  1188.     SetWindowText(hwndUsage, lpOpsDlgInfo->m_rgchUsage);
  1189.     // Detect SSL and inform user in the lower pane
  1190.     BOOL fUsingSSL = pProfile->_IsUsingSSL();
  1191.     if (fUsingSSL) 
  1192.     {
  1193.         // If the connection is SSL, the default is to remember the settings
  1194.         lpOpsDlgInfo->m_fRemember = TRUE;          
  1195.         // Hide the unsecure connection text.
  1196.         HWND hwndStatic = GetDlgItem(hDlg, IDC_UNSECURE_CONNECTION);
  1197.         ASSERT(hwndStatic != NULL);
  1198.         ShowWindow(hwndStatic, SW_HIDE);
  1199.         HICON hicon = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_LOCK));
  1200.         if (hicon != NULL)
  1201.         {
  1202.              HICON hiconOld = (HICON)SendDlgItemMessage(hDlg, IDC_SECURITY_ICON, STM_SETICON, 
  1203.                                                                 (WPARAM)hicon, 0);
  1204.             if (hiconOld)
  1205.             {
  1206.                 DestroyIcon(hiconOld);
  1207.             }
  1208.         }
  1209.     }
  1210.     else
  1211.     {
  1212.         // Hide the view certificate button and the secure connection text.
  1213.         HWND hwndViewCert = GetDlgItem(hDlg, IDC_VIEW_CERT);
  1214.         ASSERT(hwndViewCert != NULL);
  1215.         ShowWindow(hwndViewCert, SW_HIDE);
  1216.         HWND hwndStatic = GetDlgItem(hDlg, IDC_SECURE_CONNECTION);
  1217.         ASSERT(hwndStatic != NULL);
  1218.         ShowWindow(hwndStatic, SW_HIDE);
  1219.     }
  1220.     // Hide the Edit Profile button if we are using the PStore.
  1221. #ifdef _USE_PSTORE
  1222.     HWND hwndEditProf = GetDlgItem(hDlg, IDC_EDIT_PROFILE);
  1223.     ASSERT(hwndEditProf != NULL);
  1224.     ShowWindow(hwndEditProf, SW_HIDE);
  1225. #endif
  1226.     Button_SetCheck(GetDlgItem(hDlg, IDC_KEEP_SETTINGS), lpOpsDlgInfo->m_fRemember);    
  1227.     HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
  1228.     ASSERT(hwndLV);
  1229.     // Initialize the list view control
  1230.     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_CHECKBOXES);
  1231.     // Setup the columns for the list view control. 
  1232.     LV_COLUMN lvc = { LVCF_FMT , LVCFMT_LEFT };
  1233.     ListView_InsertColumn(hwndLV, 0, &lvc); 
  1234.     ListView_InsertColumn(hwndLV, 1, &lvc); 
  1235.     // Add elements to the list view. 
  1236.     _OPSConsent_ShowRequestedItems(hDlg);
  1237.     // show the items.
  1238.     ListView_RedrawItems(hwndLV, 0, ListView_GetItemCount(hwndLV));
  1239.     UpdateWindow(hwndLV);
  1240.     return TRUE;
  1241. }
  1242. BOOL
  1243. CIEFrameAuto::COpsProfile::_OPSConsent_ShowRequestedItems(HWND hDlg)
  1244. {
  1245.     LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO) GetWindowLongPtr(hDlg, DWLP_USER);
  1246.     COpsProfile *pProfile = lpOpsDlgInfo->m_pOpsProfile;
  1247.     HDPA hdpaList = lpOpsDlgInfo->m_hdpa;
  1248.     HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
  1249.     ASSERT(hwndLV);
  1250.     BOOL  fAllBlank = TRUE;
  1251.     TCHAR szName[MAX_PROFILE_NAME];
  1252.     // Initialize the common parts of the LVI
  1253.     LV_ITEM lvi = { 0 };
  1254.     for (int i=DPA_GetPtrCount(hdpaList)-1; i>=0; i--)
  1255.     {
  1256.         OPSRequestEntry * pOpsEntry = (OPSRequestEntry*) DPA_FastGetPtr(hdpaList,i);
  1257.         MLLoadString(_GetResourceIdFromAttrName(pOpsEntry->m_bstrName), szName, MAX_PATH);
  1258.         
  1259.         BSTR    bstrValue = NULL;
  1260.         TCHAR   rgchValue[1024];
  1261.         pProfile->_GetFieldValue(pOpsEntry->m_bstrName, &bstrValue);
  1262.         _StringFromBSTR(bstrValue, rgchValue, ARRAYSIZE(rgchValue));
  1263.         fAllBlank = fAllBlank && EMPTY_STRING(rgchValue);
  1264.         TCHAR *pchNewLine = StrPBrk(rgchValue, TEXT("rn"));
  1265.         if (pchNewLine)
  1266.             *pchNewLine = '';
  1267.         if (lstrlen(rgchValue)==0)
  1268.         {
  1269.             MLLoadString(IDS_OPS_BLANK, rgchValue, ARRAYSIZE(rgchValue));
  1270.         }
  1271.         SysFreeString(bstrValue);
  1272.         lvi.mask        = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
  1273.         lvi.iItem       = 0;
  1274.         lvi.iSubItem    = 0;
  1275.         lvi.pszText     = szName;
  1276.         lvi.cchTextMax  = MAX_PROFILE_NAME;
  1277.         lvi.stateMask   = LVIS_STATEIMAGEMASK;
  1278.         lvi.state       = pOpsEntry->m_fAnswer ? 0x00002000 : 0x00001000;
  1279.         lvi.lParam      = (LPARAM)pOpsEntry;
  1280.         int iItem = ListView_InsertItem(hwndLV, &lvi);
  1281.         lvi.mask        = LVIF_TEXT;
  1282.         lvi.iItem       = iItem;
  1283.         lvi.iSubItem    = 1;
  1284.         lvi.pszText     = rgchValue;
  1285.         ListView_SetItem(hwndLV, &lvi);
  1286.         // BUGBUG: There is a problem with the listview implementation because of which
  1287.         // the check box is not displayed even though lvi.state is set correctly.
  1288.         //  We have to find the item and set it again.
  1289.         ListView_SetItemState(hwndLV, iItem, pOpsEntry->m_fAnswer ? 0x00002000 : 0x00001000, LVIS_STATEIMAGEMASK);
  1290.     }
  1291.     lpOpsDlgInfo->m_fAllBlank = fAllBlank;
  1292.     // Autosize the columns
  1293.     ListView_SetColumnWidth(hwndLV, 0, LVSCW_AUTOSIZE);
  1294.     ListView_SetColumnWidth(hwndLV, 1, LVSCW_AUTOSIZE);
  1295.     return TRUE;
  1296. }
  1297. BOOL CIEFrameAuto::COpsProfile::_OPSDlg_OnClose(HWND hDlg)
  1298. {
  1299.     LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1300.     HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
  1301.     int nItems = ListView_GetItemCount(hwndLV);
  1302.     LV_ITEM lvi = {0};
  1303.     lvi.mask    = LVIF_PARAM ;        
  1304.     for (int i = 0; i < nItems ; i++ )
  1305.     {
  1306.         lvi.iItem = i;
  1307.         lvi.lParam = 0;
  1308.         
  1309.         ListView_GetItem(hwndLV, &lvi);
  1310.         ASSERT(lvi.lParam != NULL)
  1311.         if (lvi.lParam)
  1312.         {
  1313.             OPSRequestEntry * pOpsEntry = (OPSRequestEntry *)lvi.lParam;
  1314.             
  1315.             pOpsEntry->m_fAnswer = ListView_GetCheckState(hwndLV, i);
  1316.         }
  1317.     }
  1318.     lpOpsDlgInfo->m_fRemember = Button_GetCheck(GetDlgItem(hDlg, IDC_KEEP_SETTINGS));    
  1319.     
  1320.     return TRUE;
  1321. }                                    
  1322. BOOL CIEFrameAuto::COpsProfile::_OPSConsent_EditProfile(HWND hDlg)
  1323. {
  1324. #ifdef _USE_PSTORE
  1325.     return FALSE;
  1326. #else
  1327.     HRESULT hr;
  1328.     LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1329.     if (!lpOpsDlgInfo || !lpOpsDlgInfo->m_hdpa)
  1330.         return FALSE;   
  1331.     
  1332.     CIEFrameAuto::COpsProfile * pOpsProfile = lpOpsDlgInfo->m_pOpsProfile;
  1333.     if (pOpsProfile == NULL || pOpsProfile->m_lpAdrBook == NULL)
  1334.     {
  1335.         ASSERT(FALSE);
  1336.         return FALSE;
  1337.     }
  1338.         
  1339.     if (pOpsProfile->m_SBMe.cb == 0)
  1340.         return FALSE;
  1341.              
  1342.     LPSBinary lpSB = &(pOpsProfile->m_SBMe);
  1343.     // Display the WAB dialog for the me entry. 
  1344.     hr = pOpsProfile->m_lpAdrBook->Details(  (LPULONG) &hDlg,
  1345.                                         NULL,
  1346.                                         NULL,
  1347.                                         lpSB->cb,
  1348.                                         (LPENTRYID)lpSB->lpb,
  1349.                                         NULL,
  1350.                                         NULL,
  1351.                                         NULL,
  1352.                                         0);
  1353.     return (hr) ? FALSE : TRUE;
  1354. #endif
  1355. }
  1356. BOOL CIEFrameAuto::COpsProfile::_OPSConsent_OnCommand(HWND hDlg, UINT id, UINT nCmd)
  1357. {
  1358.     LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1359.     
  1360.     switch (id)
  1361.     {
  1362.         case IDOK:
  1363.             if (lpOpsDlgInfo->m_fAllBlank)
  1364.             {
  1365.                 // The user has agreed to share information but all the entries in the 
  1366.                 // profile are blank. This is probably due to user oversight, since the
  1367.                 // easier way to achieve the same effect would be to select "DENY"
  1368.                 TCHAR   rgchHeading[256];
  1369.                 MLLoadShellLangString(IDS_PROFILE_ASSISTANT, rgchHeading, ARRAYSIZE(rgchHeading));
  1370.                 TCHAR   rgchConfirm[1024];
  1371.                 MLLoadShellLangString(IDS_OPS_NO_INFORMATION, rgchConfirm, ARRAYSIZE(rgchConfirm));
  1372.                 DWORD msgRet = MessageBox(hDlg, rgchConfirm, rgchHeading, MB_YESNO | MB_DEFBUTTON1 | MB_ICONWARNING);
  1373.                 if (msgRet==IDYES)
  1374.                     goto FallThrough;
  1375.             }
  1376.         
  1377.             if (! Button_GetCheck(GetDlgItem(hDlg, IDC_KEEP_SETTINGS))  &&
  1378.                   (_GetCookieSettings()==COOKIES_ALLOW))
  1379.             {
  1380.                 // The user wants to share information for one time only but cookies
  1381.                 // are enabled, allowing sites to store profile information in a cookie
  1382.                 DWORD   dwConfirm = 0;
  1383.                 TCHAR   rgchHeading[256];
  1384.                 TCHAR   rgchConfirm[1024];
  1385.                 AccessSettings *pac = lpOpsDlgInfo->m_pacSettings;
  1386.                 MLLoadShellLangString(IDS_PROFILE_ASSISTANT, rgchHeading, ARRAYSIZE(rgchHeading));
  1387.                 MLLoadShellLangString(IDS_OPS_CONFIRM, rgchConfirm, ARRAYSIZE(rgchConfirm));
  1388.                 dwConfirm = MessageBox(hDlg, rgchConfirm, rgchHeading, MB_ICONINFORMATION | MB_OKCANCEL | MB_DEFBUTTON2);
  1389.                 if (dwConfirm!=IDOK)
  1390.                     break;
  1391.             }
  1392.             _OPSDlg_OnClose(hDlg);        
  1393.             EndDialog(hDlg, TRUE);
  1394.             break;
  1395. FallThrough:
  1396.         case IDC_EDIT_PROFILE:
  1397.             {
  1398.                 HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
  1399.                 ListView_DeleteAllItems(hwndLV);
  1400.     
  1401.                 _OPSConsent_EditProfile(hDlg);
  1402.             
  1403.                 _OPSConsent_ShowRequestedItems(hDlg);
  1404.                 ListView_RedrawItems(hwndLV, 0, ListView_GetItemCount(hwndLV));
  1405.                 UpdateWindow(hwndLV);
  1406.                 break;
  1407.             }
  1408.         case IDCANCEL:
  1409.             EndDialog(hDlg, FALSE);
  1410.             break;
  1411.         case IDC_VIEW_CERT:
  1412.             _OPSConsent_ViewCertificate(hDlg);
  1413.             break;
  1414.         default:
  1415.             return FALSE;
  1416.     }
  1417.     return TRUE;
  1418. }                    
  1419.               
  1420. BOOL         
  1421. CIEFrameAuto::COpsProfile::_OPSConsent_ViewCertificate(HWND hDlg) 
  1422. {
  1423.     OPSDlgInfo *pDlgInfo = (OPSDlgInfo*) GetWindowLongPtr(hDlg, DWLP_USER);
  1424.     InternetShowSecurityInfoByURL(pDlgInfo->m_rgchURL, hDlg);
  1425.     return TRUE;
  1426. }
  1427. INT_PTR CIEFrameAuto::COpsProfile::_OPSConsent_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1428. {
  1429.     switch (uMsg)  
  1430.     {
  1431.         case WM_INITDIALOG:
  1432.             ASSERT(NULL != lParam);            
  1433.             SetWindowLongPtr(hDlg, DWLP_USER, lParam);  // save the list.
  1434.             return _OPSConsent_OnInitDlg(hDlg);
  1435.         case WM_COMMAND:
  1436.             return _OPSConsent_OnCommand(hDlg, LOWORD(wParam), HIWORD(wParam));
  1437.         case WM_HELP:
  1438.             SHWinHelpOnDemandWrap((HWND) ((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
  1439.                     HELP_WM_HELP, (DWORD_PTR)(LPTSTR) aHelpIDs);
  1440.             break;
  1441.         case WM_CONTEXTMENU:
  1442.             SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile, HELP_CONTEXTMENU,
  1443.                     (DWORD_PTR)(LPTSTR) aHelpIDs);
  1444.             break;
  1445.             
  1446.         case WM_DESTROY:
  1447.             break;
  1448.     }
  1449.     
  1450.     return FALSE;
  1451. }                                        
  1452. // Update dialog functions.
  1453. BOOL CIEFrameAuto::COpsProfile::_OPSUpdate_OnInitDlg(HWND hDlg)
  1454. {
  1455.     LPOPSDLGINFO lpOpsDlgInfo = (LPOPSDLGINFO)GetWindowLongPtr(hDlg, DWLP_USER);
  1456.     if (!lpOpsDlgInfo || !lpOpsDlgInfo->m_hdpa)
  1457.         return FALSE;   
  1458.     HDPA hdpaList = lpOpsDlgInfo->m_hdpa;
  1459.     HWND hwndLV = GetDlgItem(hDlg, IDC_OPS_LIST);
  1460.     ASSERT(hwndLV);
  1461.     // Add elements to the list view. 
  1462.     ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_CHECKBOXES);
  1463.     // Initialize the common parts of the LVI
  1464.     TCHAR szName[MAX_PROFILE_NAME];
  1465.     LV_ITEM lvi = { 0 };
  1466.     lvi.mask        = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
  1467.     lvi.iItem       = 0;
  1468.     lvi.pszText     = szName;
  1469.     lvi.cchTextMax  = MAX_PROFILE_NAME;
  1470.     lvi.stateMask   = LVIS_STATEIMAGEMASK;
  1471.     LV_FINDINFO lvfi = { 0 };
  1472.     lvfi.flags = LVFI_STRING;
  1473.     lvfi.psz   = szName;
  1474.     for (int i=0; i<DPA_GetPtrCount(hdpaList); i++)
  1475.     {
  1476.         OPSRequestEntry * pOpsEntry = (OPSRequestEntry*) DPA_FastGetPtr(hdpaList,i);
  1477.         MLLoadString(_GetResourceIdFromAttrName(pOpsEntry->m_bstrName), szName, MAX_PATH);
  1478.         pOpsEntry->m_fAnswer = TRUE;
  1479.         lvi.state       = 0x00002000;
  1480.         lvi.lParam      = (LPARAM)pOpsEntry;
  1481.         ListView_InsertItem(hwndLV, &lvi);
  1482.         // BUGBUG: There is a problem with the listview implementation because of which
  1483.         // the check box is not displayed even though lvi.state is set correctly.
  1484.         //  We have to find the item and set it again.
  1485.         ListView_SetItemState(hwndLV, ListView_FindItem(hwndLV, -1, &lvfi), 0x00002000, LVIS_STATEIMAGEMASK);
  1486.     }
  1487.     // show the items.
  1488.     ListView_RedrawItems(hwndLV, 0, ListView_GetItemCount(hwndLV));
  1489.     UpdateWindow(hwndLV);
  1490.     return TRUE;
  1491. }
  1492. BOOL CIEFrameAuto::COpsProfile::_OPSUpdate_OnCommand(HWND hDlg, UINT id, UINT nCmd)
  1493. {
  1494.     switch (id)
  1495.     {
  1496.         case IDOK:
  1497.             _OPSDlg_OnClose(hDlg);
  1498.             EndDialog(hDlg, TRUE);
  1499.             break;
  1500.             
  1501.         case IDCANCEL:
  1502.             EndDialog(hDlg, FALSE);
  1503.             break;
  1504.         default:
  1505.             return FALSE;
  1506.     }
  1507.     return TRUE;
  1508. }                    
  1509.     
  1510. INT_PTR CIEFrameAuto::COpsProfile::_OPSUpdate_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1511. {
  1512.     switch (uMsg)  
  1513.     {
  1514.         case WM_INITDIALOG:
  1515.             ASSERT(NULL != lParam);            
  1516.             SetWindowLongPtr(hDlg, DWLP_USER, lParam);  // save the list.
  1517.             return _OPSUpdate_OnInitDlg(hDlg);
  1518.         case WM_COMMAND:
  1519.             return _OPSUpdate_OnCommand(hDlg, LOWORD(wParam), HIWORD(wParam));
  1520.         case WM_HELP:
  1521.             break;
  1522.         case WM_CONTEXTMENU:
  1523.             break;
  1524.             
  1525.         case WM_DESTROY:
  1526.             break;
  1527.     }
  1528.     
  1529.     return FALSE;
  1530. }                                        
  1531.        
  1532. BOOL
  1533. CIEFrameAuto::COpsProfile ::_ValidateElemName(LPCWSTR szIn, INT *pIndex /* = NULL */)
  1534. {
  1535.     int index = _GetAttrIndexFromName(szIn);
  1536.     if ( INVALID_ATTRIBUTE_INDEX != index )
  1537.     {
  1538.         if (pIndex) 
  1539.             *pIndex = index;
  1540.         return TRUE;                    
  1541.     }
  1542.     return FALSE;
  1543. }
  1544. INT CIEFrameAuto::COpsProfile::_GetAttrIndexFromName (LPCWSTR pwzName )
  1545. {
  1546.     INT index = INVALID_ATTRIBUTE_INDEX;
  1547.     if ( pwzName != NULL )
  1548.     {
  1549.         for ( int i = 0 ; i < ARRAYSIZE(rgProfAttr) ; i++ )
  1550.         {
  1551.             if (0 == StrCmpIW(rgProfAttr[i].pwzName, pwzName ))
  1552.             {
  1553.                 index = i;
  1554.                 break;
  1555.             }
  1556.         }
  1557.     }
  1558.     return index;
  1559. }
  1560. INT CIEFrameAuto::COpsProfile::_GetResourceIdFromAttrName( WCHAR * pwzName)
  1561. {
  1562.     return _GetResourceIdFromAttrIndex(_GetAttrIndexFromName(pwzName));
  1563. }
  1564. BOOL                
  1565. CIEFrameAuto::COpsProfile::_IsLocalMachine() {
  1566.     IInternetSecurityManager *pIScManager = NULL;
  1567.     BSTR    bstrURL;
  1568.     HRESULT hr;
  1569.     BOOL    fLocal = FALSE;
  1570.     DWORD   dwZone;
  1571.     hr = _pAuto->get_LocationURL(&bstrURL);
  1572.     if ( FAILED(hr) )
  1573.         goto Cleanup;
  1574.     hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_IInternetSecurityManager, (void **)&pIScManager);
  1575.     if ( FAILED(hr) )
  1576.         goto Cleanup;
  1577.     hr = pIScManager->MapUrlToZone(bstrURL, &dwZone, 0);
  1578.     if ( FAILED(hr) )
  1579.         goto Cleanup;
  1580.     fLocal = (dwZone == URLZONE_LOCAL_MACHINE); 
  1581. Cleanup:
  1582.     SAFERELEASE(pIScManager);
  1583.     SysFreeString(bstrURL);
  1584.     return fLocal;
  1585. }
  1586.     
  1587. HRESULT
  1588. CIEFrameAuto::COpsProfile::_GetUserPreference(BSTR bstrName, P3UserPref *pUsrPref) {
  1589.     TCHAR   rgszName[MAX_PROFILE_NAME];
  1590.     DWORD   dwType;
  1591.     DWORD   dwPrefSize;
  1592.     DWORD   dwError;
  1593.     _StringFromBSTR(bstrName, rgszName, ARRAYSIZE(rgszName));
  1594.     dwPrefSize = sizeof(struct P3UserPref);
  1595.     dwError = RegQueryValueEx(m_hP3Global, rgszName, 0, &dwType, 
  1596.                              (LPBYTE) pUsrPref, &dwPrefSize);
  1597.     if (dwError == ERROR_MORE_DATA) 
  1598.     {
  1599.         BYTE *pBuffer;
  1600.         pBuffer = new BYTE [dwPrefSize];
  1601.         if (pBuffer == NULL)
  1602.         {
  1603.             return E_OUTOFMEMORY;
  1604.         }
  1605.         dwError = RegQueryValueEx(m_hP3Global, rgszName, 0, &dwType, pBuffer, &dwPrefSize);
  1606.         memcpy(pUsrPref, pBuffer, sizeof(struct P3UserPref));
  1607.         delete [] pBuffer;
  1608.     }
  1609.     // If a preference for this attribute is not found, create a default one and 
  1610.     // write it back to persistent storage
  1611.     if (dwError != ERROR_SUCCESS)
  1612.     {
  1613.         P3UserPref  defPrefs;
  1614.         
  1615.         defPrefs.m_access = P3_QUERY;
  1616.         defPrefs.m_lastRequest = P3_ACCEPT;
  1617.         _PutUserPreference(bstrName, defPrefs);
  1618.         *pUsrPref = defPrefs;
  1619.     }
  1620.     return S_OK;
  1621. }
  1622. HRESULT 
  1623. CIEFrameAuto::COpsProfile::_PutUserPreference(BSTR bstrName, P3UserPref usrPref) {
  1624.     TCHAR   rgszName[MAX_PROFILE_NAME];
  1625.     DWORD   dwError;
  1626.     _StringFromBSTR(bstrName, rgszName, ARRAYSIZE(rgszName));
  1627.     dwError = RegSetValueEx(m_hP3Global, rgszName, 0, REG_BINARY,
  1628.                             (LPBYTE) &usrPref,
  1629.                             sizeof(struct P3UserPref));
  1630.     return HRESULT_FROM_WIN32(dwError);
  1631. }
  1632. BOOL
  1633. CIEFrameAuto::COpsProfile::_IsUsingSSL() 
  1634. {
  1635.     BOOL fSecure = FALSE;
  1636.     BSTR    bstrUrl;
  1637.     TCHAR   rgchUrl[MAX_URL_STRING+1];
  1638.     _pAuto->get_LocationURL(&bstrUrl);
  1639.     _StringFromBSTR(bstrUrl, rgchUrl, ARRAYSIZE(rgchUrl));
  1640.     SysFreeString(bstrUrl);
  1641.     fSecure = GetUrlScheme(rgchUrl)==URL_SCHEME_HTTPS;
  1642.     return fSecure;
  1643. }
  1644. HRESULT     
  1645. CIEFrameAuto::COpsProfile::_ApplyPreferences(URL_COMPONENTS *pucURL, HDPA hdpaReqList) 
  1646. {
  1647.     for (int k=0; k<DPA_GetPtrCount(hdpaReqList); k++)
  1648.     {
  1649.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(hdpaReqList,k);
  1650.         pCurrent->m_fQuery  = TRUE;
  1651.         pCurrent->m_fAnswer = FALSE;
  1652.         pCurrent->m_dwDecision = P3_NONE;
  1653.     }
  1654.     _ApplySiteSettings(pucURL, hdpaReqList);
  1655.     _ApplyGlobalSettings(hdpaReqList);
  1656.     return S_OK;
  1657. }
  1658. HRESULT     
  1659. CIEFrameAuto::COpsProfile::_ApplyGlobalSettings(HDPA hdpaReqList) 
  1660. {
  1661.     for (int k=0; k<DPA_GetPtrCount(hdpaReqList); k++)
  1662.     {
  1663.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(hdpaReqList,k);
  1664.         P3UserPref       userInfo;
  1665.     
  1666.         _GetUserPreference(pCurrent->m_bstrName, &userInfo);
  1667.         switch (userInfo.m_access)
  1668.         {
  1669.         case P3_GRANT:      if (pCurrent->m_fQuery)
  1670.                             {
  1671.                                 pCurrent->grantRequest();
  1672.                                 pCurrent->m_dwDecision = P3_GLOBAL;
  1673.                             }
  1674.                             break;
  1675.         case P3_DENY:       pCurrent->denyRequest();
  1676.                             pCurrent->m_dwDecision = P3_GLOBAL;
  1677.                             break;
  1678.         case P3_REQSSL:     // This resolves to P3_QUERY at the moment
  1679.         case P3_QUERY:      if (pCurrent->m_fQuery)
  1680.                                 pCurrent->m_fAnswer = (userInfo.m_lastRequest == P3_ACCEPT);
  1681.                             break;
  1682.         default:            ;
  1683.         }
  1684.     }
  1685.     return S_OK;
  1686. }
  1687. HRESULT
  1688. CIEFrameAuto::COpsProfile::_ApplySiteSettings(URL_COMPONENTS *pucURL, HDPA hdpaReqList)
  1689. {
  1690.     if (pucURL->nScheme!=INTERNET_SCHEME_HTTP && pucURL->nScheme!=INTERNET_SCHEME_HTTPS)
  1691.         return S_OK;
  1692.     TCHAR *pszSubDomain = pucURL->lpszHostName;
  1693.     // For a given hostname such as "www.foo.bar.com", this loop will iterate over all possible
  1694.     // domains such as "www.foo.bar.com", ".foo.bar.com" and ".bar.com" but NOT ".com"
  1695.     while (pszSubDomain!=NULL && _LegalDomain(pucURL->lpszHostName, pszSubDomain))
  1696.     {
  1697.         HKEY    hkey    = NULL;
  1698.         
  1699.         if (ERROR_SUCCESS == RegOpenKeyEx(m_hP3Sites, pszSubDomain, 0, KEY_ALL_ACCESS, &hkey))
  1700.         {
  1701.             _ApplyDomainSettings(pucURL, hkey, hdpaReqList);
  1702.             RegCloseKey(hkey);
  1703.         }
  1704.         pszSubDomain = StrChr(pszSubDomain+1, TEXT('.')); // Find the next embedded dot
  1705.     }
  1706.     return S_OK;
  1707. }
  1708. HRESULT     
  1709. CIEFrameAuto::COpsProfile::_ApplyDomainSettings(URL_COMPONENTS *pucComp, HKEY hkey, HDPA hdpaReqList) 
  1710. {
  1711.     DWORD   dwError;
  1712.     DWORD   dwIndex = 0;
  1713.     TCHAR   rgchName[MAX_PATH];
  1714.     int     iReqCount = DPA_GetPtrCount(hdpaReqList);
  1715.     DWORD  *pdwLastApplied = new DWORD[iReqCount];
  1716.     if (pdwLastApplied == NULL)
  1717.     {
  1718.         return E_OUTOFMEMORY;
  1719.     }
  1720.     for (int i=0; i<iReqCount; i++)
  1721.         pdwLastApplied[i] = 0;
  1722.     do
  1723.     {
  1724.         DWORD dwcbVal = ARRAYSIZE(rgchName);
  1725.         
  1726.         dwError = RegEnumKeyEx(hkey, dwIndex, rgchName, &dwcbVal, NULL, NULL, NULL, NULL);
  1727.         if (dwError==ERROR_SUCCESS)
  1728.         {
  1729.             HKEY hPathKey;
  1730.             AccessSettings ac;
  1731.             dwError = RegOpenKeyEx(hkey, rgchName, 0, KEY_READ, &hPathKey);
  1732.             _ReadSettingsFromRegistry(hPathKey, &ac);
  1733.             _ApplySettings(&ac, pucComp, hdpaReqList, pdwLastApplied);
  1734.             RegCloseKey(hPathKey);
  1735.         }
  1736.         dwIndex++;
  1737.     } 
  1738.     while (dwError==ERROR_SUCCESS);
  1739.     delete [] pdwLastApplied;
  1740.     return S_OK;
  1741. }
  1742. HRESULT
  1743. CIEFrameAuto::COpsProfile::_UpdateSiteSettings(AccessSettings *pSettings, HDPA hdpaReqList)
  1744. {
  1745.     DWORD       dwError;
  1746.     DWORD       dwAction;
  1747.     HKEY        hDomainKey      = NULL;
  1748.     HKEY        hPathKey        = NULL;
  1749.     // Clear the allow and deny vectors
  1750.     ZeroMemory(pSettings->m_rgbStdAllow, sizeof(pSettings->m_rgbStdAllow));
  1751.     ZeroMemory(pSettings->m_rgbStdDeny, sizeof(pSettings->m_rgbStdDeny));
  1752.     // Fill out the vectors based on the user responses on the request list    
  1753.     for (int i=0; i<DPA_GetPtrCount(hdpaReqList); i++)
  1754.     {
  1755.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(hdpaReqList,i);
  1756.         int iVcardIndex = _GetAttrIndexFromName(pCurrent->m_bstrName);
  1757.         // At the moment we do not handle custom attributes
  1758.         if (iVcardIndex!=INVALID_ATTRIBUTE_INDEX)
  1759.             _WriteBitVector(pCurrent->m_fAnswer ? pSettings->m_rgbStdAllow : pSettings->m_rgbStdDeny, iVcardIndex);
  1760.     }
  1761.     // Create a key for the given domain or open it if one already exists
  1762.     dwError = RegCreateKeyEx(m_hP3Sites, pSettings->m_rgchDomain, 
  1763.                             0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
  1764.                             &hDomainKey, &dwAction);
  1765.     if (dwError!=ERROR_SUCCESS)
  1766.         return E_FAIL;
  1767.     TCHAR       rgchName[16];
  1768.     DWORD       dwcbName = 0;
  1769.     DWORD       dwIndex = 0;
  1770.     
  1771.     do
  1772.     {
  1773.         AccessSettings ac;
  1774.         dwcbName = ARRAYSIZE(rgchName);
  1775.         if (ERROR_SUCCESS != RegEnumKeyEx(hDomainKey, dwIndex, rgchName, &dwcbName, NULL, NULL, NULL, NULL))
  1776.             break;
  1777.         if (ERROR_SUCCESS != RegOpenKeyEx(hDomainKey, rgchName, 0, KEY_READ, &hPathKey))
  1778.             break;
  1779.         _ReadSettingsFromRegistry(hPathKey, &ac);        
  1780.         // If there are existing settings for this domain and path, merge the permissions
  1781.         if (StrCmp(ac.m_rgchPath, pSettings->m_rgchPath) == 0)
  1782.         {
  1783.             // An attribute is allowed if it has been allowed explicitly by the user from
  1784.             // the current UI or it was previously allowed and it has not been denied
  1785.             // in the current UI. Similarly, an attribute is denied if it is denied in the
  1786.             // current UI or it was denied previously and it has not been granted this time.
  1787.             for (int i=0; i<ARRAYSIZE(pSettings->m_rgbStdAllow); i++)
  1788.             {
  1789.                 pSettings->m_rgbStdAllow[i] |= ac.m_rgbStdAllow[i] & ~(pSettings->m_rgbStdDeny[i]);
  1790.                 pSettings->m_rgbStdDeny[i]  |= ac.m_rgbStdDeny[i]  & ~(pSettings->m_rgbStdAllow[i]);
  1791.             }
  1792.             break;
  1793.         }
  1794.         RegCloseKey(hPathKey);
  1795.         dwIndex++;
  1796.     }
  1797.     while (dwError==ERROR_SUCCESS);
  1798.     wnsprintf(rgchName, ARRAYSIZE(rgchName), TEXT("%03d"), dwIndex);
  1799.     
  1800.     if (ERROR_SUCCESS == RegCreateKeyEx(hDomainKey, rgchName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hPathKey, &dwAction))
  1801.         _WriteSettingsToRegistry(hPathKey, pSettings);
  1802.     RegCloseKey(hPathKey);
  1803.     RegCloseKey(hDomainKey);
  1804.     return S_OK;
  1805. }
  1806. BOOL
  1807. CIEFrameAuto::COpsProfile::_ReadBitVector(LPCBYTE ucBitVector, DWORD dwIndex)
  1808. {
  1809.     DWORD   dwByte = dwIndex/8;
  1810.     DWORD   dwMask = 0x80 >> (dwIndex & 0x07);
  1811.     return (ucBitVector[dwByte]&dwMask) != 0;
  1812. }
  1813. VOID
  1814. CIEFrameAuto::COpsProfile::_WriteBitVector(LPBYTE ucBitVector, DWORD dwIndex)
  1815. {
  1816.     DWORD   dwByte = dwIndex/8;
  1817.     DWORD   dwMask = 0x80 >> (dwIndex & 0x07);
  1818.     ucBitVector[dwByte] |= dwMask;
  1819. }
  1820. // The path matching is done on a character-level, which is the way cookies are
  1821. // implemented in IE4 and in Navigator
  1822. // Note that this is different from the RFC-2109
  1823. BOOL
  1824. CIEFrameAuto::COpsProfile::_PathMatch(TCHAR *pszDocumentPath, TCHAR *pszAccessPath)
  1825. {
  1826.     return StrStr(pszDocumentPath,pszAccessPath) == pszDocumentPath;
  1827. }
  1828. // Domain name matching is done on the character level except that a leading
  1829. // period is added to the access domain if necessary
  1830. // Refer to "cookie.cxx" in MSHTML for details
  1831. BOOL
  1832. CIEFrameAuto::COpsProfile::_DomainMatch(TCHAR *pszHostName, TCHAR *pszDomain) 
  1833. {
  1834.     // If domain is the same as hostname, matching is successful
  1835.     if (StrCmp(pszHostName, pszDomain) == 0)
  1836.         return TRUE;
  1837.     // Fail if the domain is not a legal subdomain of the hostname
  1838.     // This prevents matching against invaid domains such as ".com" or ".edu"
  1839.     if (! _LegalDomain(pszHostName, pszDomain))
  1840.         return FALSE;
  1841.     // Find the matching part of the domain on the access path
  1842.     TCHAR *pszMatchingPart = StrStr(pszHostName, pszDomain);
  1843.     // If the domain is not a substring of the hostname, it does not match
  1844.     if (pszMatchingPart==NULL)
  1845.         return FALSE;
  1846.     // Otherwise the domain must be a suffix and it should either contain a period
  1847.     // at the beginning or should match following a period
  1848.     if (StrCmp(pszMatchingPart, pszDomain) != 0)
  1849.         return FALSE;
  1850.     if (*pszMatchingPart!='.' && pszMatchingPart[-1]!='.')
  1851.         return FALSE;
  1852.     return TRUE;
  1853. }
  1854. BOOL
  1855. CIEFrameAuto::COpsProfile::_LegalDomain(TCHAR *pszHostName, TCHAR *pszDomain)
  1856. {
  1857.     // Fail if either of the strings are invalid
  1858.     if (pszHostName==NULL || pszDomain==NULL ||
  1859.         EMPTY_STRING(pszHostName) || EMPTY_STRING(pszDomain))
  1860.         return FALSE;
  1861.     // If domain is the same as hostname, it is always valid
  1862.     if (!StrCmpI(pszHostName, pszDomain))
  1863.         return TRUE;
  1864.     
  1865.     int iEmbeddedPeriods = 0;
  1866.     // Count the number of embedded periods, defined as the number of dots after
  1867.     // the first character of the domain
  1868.     for(int i=1; pszDomain[i]!=0; i++)
  1869.         if (pszDomain[i]=='.')
  1870.             iEmbeddedPeriods++;
  1871.     // Require that the domain name has at least one embedded period
  1872.     if (iEmbeddedPeriods==0)
  1873.         return FALSE;
  1874.     // Find the requested domain name in the host name 
  1875.     TCHAR   *pszMatchingPart = StrStr(pszHostName, pszDomain);
  1876.     // Require that this search succeed
  1877.     if (pszMatchingPart==NULL)
  1878.         return FALSE;
  1879.     // Require furthermore that the domain name be a suffix of the hostname 
  1880.     if (StrCmp(pszMatchingPart, pszDomain) != 0)
  1881.         return FALSE;
  1882.     // If all the above criteria has been satisfied, then the domain is valid
  1883.     return TRUE;
  1884. }
  1885. // Path matching is done at a character-level; this is to be compliant with Netscape
  1886. // Navigator and the original cookie specification.
  1887. // This has the surprising result that "/foo" matches "/foo/doc" as well as "/foobar/doc"
  1888. BOOL
  1889. CIEFrameAuto::COpsProfile::_LegalPath(TCHAR *pszActualPath, TCHAR *pszAccessPath)
  1890. {
  1891.     return StrStr(pszActualPath, pszAccessPath) == pszActualPath;
  1892. }
  1893. // For the ANSI<-->UNICODE transition 
  1894. HRESULT
  1895. CIEFrameAuto::COpsProfile::_StringFromBSTR(BSTR bstrSource, TCHAR *pszDest, DWORD dwDestSize) 
  1896. {
  1897.     StrCpyNW(pszDest, bstrSource, dwDestSize-1);
  1898.     return S_OK;
  1899. }
  1900. HRESULT     
  1901. CIEFrameAuto::COpsProfile::_StringFromVariant(VARIANT *vaSource, TCHAR *pszDest, DWORD dwDestSize)
  1902. {
  1903.     VARIANT     vaTemp;
  1904.     HRESULT     hr;
  1905.     VariantInit(&vaTemp);
  1906.     hr = VariantChangeType(&vaTemp, vaSource, 0, VT_BSTR);
  1907.     if (SUCCEEDED(hr))
  1908.         _StringFromBSTR(vaTemp.bstrVal, pszDest, dwDestSize);
  1909.     else
  1910.         ZeroMemory(pszDest, dwDestSize);
  1911.     
  1912.     VariantClear(&vaTemp);
  1913.     return hr;
  1914. }
  1915. INT
  1916. CIEFrameAuto::COpsProfile::_GetCookieSettings()
  1917. {
  1918.     HKEY    hInetKey = NULL;
  1919.     DWORD   dwCookiePref;
  1920.     DWORD   dwDataRead = sizeof(dwCookiePref);
  1921.     DWORD   dwError = RegOpenKeyEx(HKEY_CURRENT_USER, rgszInetKey, 0, KEY_READ, &hInetKey);
  1922.     if (dwError !=ERROR_SUCCESS)
  1923.         return COOKIES_DENY;
  1924.     dwError = RegQueryValueEx(hInetKey, rgszCookieTxt, NULL, NULL, (LPBYTE) &dwCookiePref, &dwDataRead);
  1925.     RegCloseKey(hInetKey);
  1926.     if (dwError==ERROR_SUCCESS)
  1927.         return dwCookiePref;
  1928.     else
  1929.         return COOKIES_ALLOW;
  1930. }
  1931. HRESULT
  1932. CIEFrameAuto::COpsProfile::_GetUsageCode(VARIANT vaUsage, LPTSTR rgchUsage, int cLen)
  1933. {
  1934.     LONG lUsage;
  1935.     VARIANT varDest;
  1936.     VariantInit(&varDest);
  1937.     HRESULT hr = VariantChangeType(&varDest, &vaUsage, 0, VT_I4);
  1938.     if (SUCCEEDED(hr))
  1939.     {
  1940.         lUsage = varDest.lVal;
  1941.         // If lUsage is not within range just display unknown usage.     
  1942.         if (lUsage < 0 || lUsage > (IDS_OPS_USAGEMAX - IDS_OPS_USAGE0))
  1943.             lUsage = -1;
  1944.     }
  1945.     else
  1946.         lUsage = -1;
  1947.     VariantClear(&varDest);
  1948.     MLLoadString(lUsage + IDS_OPS_USAGE0, rgchUsage, cLen);
  1949.     return S_OK;
  1950. }
  1951. BOOL
  1952. CIEFrameAuto::COpsProfile::_IsP3Enabled()
  1953. {
  1954.     DWORD dwEnabled;
  1955.     DWORD dwDataOut = sizeof(dwEnabled);
  1956.     DWORD dwError = RegQueryValueEx(m_hP3Global, rgszEnabled, 
  1957.                                     NULL, NULL, 
  1958.                                     (LPBYTE) &dwEnabled, &dwDataOut);
  1959.     if (dwError!=ERROR_SUCCESS)
  1960.     {
  1961.         dwEnabled = TRUE;
  1962.         RegSetValueEx(  m_hP3Global, rgszEnabled, 0, REG_DWORD, 
  1963.                         (LPBYTE) &dwEnabled, sizeof(dwEnabled));
  1964.         return TRUE;
  1965.     }
  1966.     else
  1967.         return dwEnabled;
  1968. }
  1969. // The script can specify domain, path and expiration date for the settings.
  1970. // If these are not provided, the domain defaults to the hostname, the path to the current 
  1971. // document and the expiration to a specified number of days in the future
  1972. HRESULT 
  1973. CIEFrameAuto::COpsProfile::_GetSiteSettings(URL_COMPONENTS *pucComp, 
  1974.                                             VARIANT vaDomain, VARIANT vaPath, VARIANT vaExpire,
  1975.                                             AccessSettings *pSettings)
  1976. {
  1977.     SYSTEMTIME  st;
  1978.     TCHAR       rgchExpire[32];
  1979.     HRESULT     hr;
  1980.     DWORD       dwError = ERROR_SUCCESS;    
  1981.     // Note: For IE4, the domain name has to be hostname.
  1982.     StrCpyN(pSettings->m_rgchDomain, pucComp->lpszHostName, ARRAYSIZE(pSettings->m_rgchDomain));
  1983.     hr = _StringFromVariant(&vaPath, pSettings->m_rgchPath, ARRAYSIZE(pSettings->m_rgchPath)); 
  1984.     if (FAILED(hr))
  1985.         StrCpyN(pSettings->m_rgchPath, pucComp->lpszUrlPath, ARRAYSIZE(pSettings->m_rgchPath));
  1986.     // If the path is different from the page, add a "/" if necessary at the end
  1987.     DWORD dwPathLen = lstrlen(pSettings->m_rgchPath);
  1988.     
  1989.     if (StrCmp(pSettings->m_rgchPath, pucComp->lpszUrlPath)     &&
  1990.         pSettings->m_rgchPath[dwPathLen-1] != TEXT('/'))
  1991.     {
  1992.         StrCatBuff(pSettings->m_rgchPath, TEXT("/"), ARRAYSIZE(pSettings->m_rgchPath));
  1993.     }
  1994.     FILETIME        ftNow;
  1995.     LARGE_INTEGER  *pqwNow = (LARGE_INTEGER*) & ftNow;
  1996.     LARGE_INTEGER  *pftime = (LARGE_INTEGER*) & pSettings->m_ftExpire;
  1997.     GetSystemTimeAsFileTime(&ftNow);
  1998.     hr = _StringFromVariant(&vaExpire, rgchExpire, ARRAYSIZE(rgchExpire));
  1999.     if (SUCCEEDED(hr))
  2000.     {
  2001.         dwError = InternetTimeToSystemTime(rgchExpire, &st, 0);
  2002.         SystemTimeToFileTime(&st, & pSettings->m_ftExpire);
  2003.     }
  2004.     if (FAILED(hr) || dwError!=ERROR_SUCCESS)
  2005.     {
  2006.         QUAD_PART(*pftime) = QUAD_PART(*pqwNow) + defExpiration;
  2007.     }
  2008.     // Enforce the limit on expiration time
  2009.     __int64 qwDelta = (QUAD_PART(*pftime)) - (QUAD_PART(*pqwNow));
  2010.     if (qwDelta<0 || qwDelta>maxExpiration)
  2011.         QUAD_PART(*pftime) = QUAD_PART(*pqwNow) + maxExpiration;
  2012.     // Make sure that the domain and path are valid
  2013.     // The criteria is a mix of the cookie semantics as defined by RFC-2109 and Navigator 
  2014.     // compliant behaviour as implemented elsewhere in IE4 
  2015.     if (! _LegalPath(pucComp->lpszUrlPath, pSettings->m_rgchPath) )
  2016.         StrCpyN(pSettings->m_rgchPath, pucComp->lpszUrlPath, ARRAYSIZE(pSettings->m_rgchPath));
  2017.     if (! _LegalDomain(pucComp->lpszHostName, pSettings->m_rgchDomain) )
  2018.         StrCpyN(pSettings->m_rgchDomain, pucComp->lpszHostName, ARRAYSIZE(pSettings->m_rgchDomain));
  2019.     // Add a period at the beginning of the domain name if it is not equal to 
  2020.     // the host name
  2021.     if (StrCmpI(pucComp->lpszHostName, pSettings->m_rgchDomain)   &&
  2022.         pSettings->m_rgchDomain[0] != '.')
  2023.     {
  2024.         StrCpyN(1+pSettings->m_rgchDomain, pSettings->m_rgchDomain, lstrlen(pSettings->m_rgchDomain));
  2025.         pSettings->m_rgchDomain[0] = '.';
  2026.     }
  2027.     pSettings->m_fExactDomain   = ! StrCmpI(pSettings->m_rgchDomain, pucComp->lpszHostName);
  2028.     
  2029.     if (StrCmp(pSettings->m_rgchPath, pucComp->lpszUrlPath))
  2030.     {
  2031.         pSettings->m_fExactPath = FALSE;
  2032.     }
  2033.     else
  2034.     {
  2035.         pSettings->m_fExactPath = pSettings->m_rgchPath[dwPathLen-1]!=TEXT('/');
  2036.     }
  2037.     return S_OK;
  2038. }
  2039. HRESULT
  2040. CIEFrameAuto::COpsProfile::_FormatSiteSettings(AccessSettings *pSettings, LPTSTR rgchOut, int cLimit)
  2041. {
  2042.     TCHAR   rgchFullName[MAX_URL_STRING];
  2043.     TCHAR   rgchTemp[MAX_URL_STRING];
  2044.     wnsprintf(rgchFullName,
  2045.              ARRAYSIZE(rgchFullName),
  2046.              TEXT("http://%s%s"),
  2047.              pSettings->m_rgchDomain,
  2048.              pSettings->m_rgchPath);
  2049.     FormatUrlForDisplay(rgchFullName, rgchTemp, cLimit, FALSE, CP_ACP);
  2050.     TCHAR *pchSiteName = StrStr(rgchTemp, TEXT("//"));
  2051.  
  2052.     if (pchSiteName==NULL)
  2053.         pchSiteName = rgchTemp;
  2054.     else
  2055.         pchSiteName += 2;
  2056.     StrCpyN(rgchOut, pchSiteName, cLimit);
  2057.     return S_OK;
  2058. }
  2059. // Attempts to use the given settings to determine the user response to the requests 
  2060. // in the given list. If the domain and path for the settings is not applicable to
  2061. // for the given URL, returns FALSE.
  2062. BOOL
  2063. CIEFrameAuto::COpsProfile::_ApplySettings(AccessSettings *pac, URL_COMPONENTS *puc, HDPA hdpaReqList, DWORD *pdwLast)
  2064. {
  2065.     if (!_DomainMatch(puc->lpszHostName, pac->m_rgchDomain)  ||
  2066.         !_PathMatch(puc->lpszUrlPath, pac->m_rgchPath))
  2067.         return FALSE;
  2068.     DWORD   dwPathLen = lstrlen(pac->m_rgchPath);
  2069.     for (int i=0; i<DPA_GetPtrCount(hdpaReqList); i++)
  2070.     {
  2071.         OPSRequestEntry *pCurrent = (OPSRequestEntry*) DPA_FastGetPtr(hdpaReqList,i);
  2072.         int iVcIndex = _GetAttrIndexFromName(pCurrent->m_bstrName);
  2073.         if (iVcIndex==INVALID_ATTRIBUTE_INDEX)
  2074.             continue;
  2075.         if (pdwLast[i]>=dwPathLen)
  2076.             continue;
  2077.         else
  2078.             pdwLast[i] = dwPathLen;
  2079.         BOOL    fAllow  = _ReadBitVector(pac->m_rgbStdAllow, iVcIndex);
  2080.         BOOL    fDeny   = _ReadBitVector(pac->m_rgbStdDeny, iVcIndex);
  2081.         if (fDeny)
  2082.         {
  2083.             pCurrent->denyRequest();
  2084.             pCurrent->m_dwDecision = P3_SITELEVEL;
  2085.         }
  2086.         else if (fAllow)
  2087.         {
  2088.             pCurrent->grantRequest();
  2089.             pCurrent->m_dwDecision = P3_SITELEVEL;
  2090.         }
  2091.     }    
  2092.     return TRUE;
  2093. }
  2094. BOOL
  2095. CIEFrameAuto::COpsProfile::_ReadSettingsFromRegistry(HKEY hkey, AccessSettings *pac)
  2096. {
  2097.     DWORD  dwError;
  2098.     DWORD  dwcb;
  2099.     ZeroMemory(pac, sizeof(struct AccessSettings));
  2100.     dwcb = sizeof(pac->m_rgbStdAllow);
  2101.     dwError = RegQueryValueEx(hkey, rgszAllowTxt, NULL, NULL, (LPBYTE) pac->m_rgbStdAllow, &dwcb);
  2102.     dwcb = sizeof(pac->m_rgbStdDeny);
  2103.     dwError = RegQueryValueEx(hkey, rgszDenyTxt, NULL, NULL, (LPBYTE) pac->m_rgbStdDeny, &dwcb);
  2104.     dwcb = sizeof(pac->m_rgchPath);
  2105.     dwError = RegQueryValueEx(hkey, rgszPathTxt, NULL, NULL, (LPBYTE) pac->m_rgchPath, &dwcb);
  2106.     dwcb = sizeof(pac->m_rgchDomain);
  2107.     dwError = RegQueryValueEx(hkey, rgszDomainTxt, NULL, NULL, (LPBYTE) pac->m_rgchDomain, &dwcb);
  2108.     return (dwError==ERROR_SUCCESS);
  2109. }
  2110. BOOL
  2111. CIEFrameAuto::COpsProfile::_WriteSettingsToRegistry(HKEY hkey, AccessSettings *pac)
  2112. {
  2113.     RegSetValueEx(hkey, rgszAllowTxt, 0, REG_BINARY, pac->m_rgbStdAllow, sizeof(pac->m_rgbStdAllow));
  2114.     RegSetValueEx(hkey, rgszDenyTxt, 0, REG_BINARY, pac->m_rgbStdDeny, sizeof(pac->m_rgbStdDeny));
  2115.     RegSetValueEx(hkey, rgszPathTxt, 0, REG_SZ, (LPBYTE) pac->m_rgchPath, sizeof(pac->m_rgchPath));
  2116.     RegSetValueEx(hkey, rgszDomainTxt, 0, REG_SZ, (LPBYTE) pac->m_rgchDomain, sizeof(pac->m_rgchDomain));
  2117.     return TRUE;
  2118. }
  2119. // This function revokes all site permission given previously by deleting
  2120. // the registry entries for all the domains under the "P3Sites" key
  2121. // It is not a good idea to invoke recursive delete on the P3Sites key because
  2122. // the running instance of the navigator will end up with an invalid handle
  2123. HRESULT
  2124. CIEFrameAuto::COpsProfile::_ClearAllSettings(HWND hwnd)
  2125. {
  2126.     DWORD   dwAction;
  2127.     DWORD   dwError;
  2128.     HKEY    hP3Sites;
  2129.     dwError = RegCreateKeyEx(HKEY_CURRENT_USER,  rgszP3Sites, 0, NULL, REG_OPTION_NON_VOLATILE,
  2130.                             KEY_ALL_ACCESS, NULL, &hP3Sites, &dwAction);
  2131.     DWORD dwIndex = 0;
  2132.     DWORD dwcbVal;
  2133.     TCHAR rgchName[MAX_PATH];
  2134.     HDPA  hdpaKeys = DPA_Create(0);
  2135.     do
  2136.     {
  2137.         dwcbVal = ARRAYSIZE(rgchName);
  2138.         dwError = RegEnumKeyEx(hP3Sites, dwIndex, rgchName, &dwcbVal, NULL, NULL, NULL, NULL);
  2139.         if (dwError==ERROR_SUCCESS)
  2140.         {
  2141.             LPTSTR  pszSiteName = new TCHAR[MAX_PATH];
  2142.             if (pszSiteName)
  2143.             {
  2144.                 StrCpyN(pszSiteName, rgchName, MAX_PATH);
  2145.                 DPA_AppendPtr(hdpaKeys, pszSiteName);
  2146.             }
  2147.         }
  2148.         dwIndex++;
  2149.     }
  2150.     while (dwError==ERROR_SUCCESS);
  2151.     for (int i=0; i<DPA_GetPtrCount(hdpaKeys); i++)
  2152.     {
  2153.         LPTSTR  pszSiteName = (LPTSTR) DPA_FastGetPtr(hdpaKeys, i);
  2154.         SHDeleteKey(hP3Sites, pszSiteName);
  2155.         delete pszSiteName;
  2156.     }
  2157.     DPA_Destroy(hdpaKeys);
  2158.     return S_OK;
  2159. }
  2160. BOOL
  2161. CIEFrameAuto::COpsProfile::_DifferentURL()
  2162. {
  2163.     BSTR    bstrCurrentURL  = NULL;
  2164.     HRESULT hr = _pAuto->get_LocationURL(&bstrCurrentURL);
  2165.     BOOL    fDifferent = (m_bstrLastURL!=NULL) && StrCmpW(bstrCurrentURL, m_bstrLastURL);
  2166.     SysFreeString(bstrCurrentURL);
  2167.     return fDifferent;
  2168. }
  2169. #ifdef UNIX
  2170. EXTERN_C
  2171. #endif
  2172. HRESULT ResetProfileSharing(HWND hwin)
  2173. {
  2174.     return CIEFrameAuto::COpsProfile::_ClearAllSettings(hwin);
  2175. }