helper.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 75k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "private.h"
  2. #include "offl_cpp.h"
  3. #include "subsmgrp.h"
  4. #include "helper.h"
  5. #include <mluisupp.h>
  6. #ifdef DEBUG
  7. void    DumpTaskTrigger(TASK_TRIGGER * pTaskTrigger);
  8. #endif  // DEBUG
  9. // {D994B6F0-DA3C-11d1-857D-00C04FA35C89}
  10. const GUID NOOP_SCHEDULE_COOKIE = 
  11. { 0xd994b6f0, 0xda3c, 0x11d1, { 0x85, 0x7d, 0x0, 0xc0, 0x4f, 0xa3, 0x5c, 0x89 
  12. } };
  13. #ifndef TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
  14. #define TASK_FLAG_RUN_ONLY_IF_LOGGED_ON        (0x2000)
  15. #endif
  16. const PROPSPEC c_rgPropRead[] = {
  17.     { PRSPEC_PROPID, PID_INTSITE_SUBSCRIPTION},
  18.     { PRSPEC_PROPID, PID_INTSITE_FLAGS},
  19.     { PRSPEC_PROPID, PID_INTSITE_TRACKING},
  20.     { PRSPEC_PROPID, PID_INTSITE_CODEPAGE},
  21. };
  22. void UpdateTimeFormat(LPTSTR tszTimeFormat, ULONG cchTimeFormat);
  23. HRESULT WriteProperties(POOEntry pooe);
  24. HRESULT ReadProperties(POOEBuf pBuf);
  25. const TCHAR c_szLoadWC[] = TEXT("LoadWC");
  26. void FixupRandomTrigger(TASK_TRIGGER *pTrigger)
  27. {
  28.     if (pTrigger->wRandomMinutesInterval > 0)
  29.     {
  30.         //  We have a random interval so we need to add a random number of minutes to it.
  31.         //  Given the fact that all of the fields need to carry over to the next, the
  32.         //  simplest way to do this is to flatten the start time into FILETIME, add the
  33.         //  random minutes, and then convert back to a TASK_TRIGGER.  This let's us use
  34.         //  Win32 APIs instead of doing all of the calendar and carry over stuff ourselves.
  35.         SYSTEMTIME st;
  36.         CFileTime ft;
  37.         memset(&st, 0, sizeof(SYSTEMTIME));
  38.         st.wYear = pTrigger->wBeginYear;
  39.         st.wMonth = pTrigger->wBeginMonth;
  40.         st.wDay = pTrigger->wBeginDay;
  41.         st.wHour = pTrigger->wStartHour;
  42.         st.wMinute = pTrigger->wStartMinute;
  43.         SystemTimeToFileTime(&st, &ft);
  44.         ft += ONE_MINUTE_IN_FILETIME * (__int64)Random(pTrigger->wRandomMinutesInterval);
  45.         FileTimeToSystemTime(&ft, &st);
  46.         pTrigger->wBeginYear = st.wYear;
  47.         pTrigger->wBeginMonth = st.wMonth;
  48.         pTrigger->wBeginDay = st.wDay;
  49.         pTrigger->wStartHour = st.wHour;
  50.         pTrigger->wStartMinute = st.wMinute;
  51.         pTrigger->wRandomMinutesInterval = 0;
  52.     }
  53. }
  54. //  Come up with a name like "MSN Recommended Schedule"
  55. void CreatePublisherScheduleNameW(WCHAR *pwszSchedName, int cchSchedName, 
  56.                                   const TCHAR *pszName, const WCHAR *pwszName)
  57. {
  58.     WCHAR wszFormat[MAX_PATH];
  59.     WCHAR wszPubName[MAX_PATH];
  60.     const WCHAR *pwszPubName;
  61.     ASSERT((NULL != pszName) || (NULL != pwszName));
  62.     ASSERT((NULL != pwszSchedName) && (cchSchedName > 0));
  63.     if (NULL == pwszName)
  64.     {
  65.         ASSERT(NULL != pszName);
  66.         MyStrToOleStrN(wszPubName, ARRAYSIZE(wszPubName), pszName);
  67.         pwszPubName = wszPubName;
  68.     }
  69.     else
  70.     {
  71.         pwszPubName = pwszName;
  72.     }
  73. #ifdef UNICODE
  74.     MLLoadStringW(IDS_RECOMMENDED_SCHEDULE_FORMAT, wszFormat, ARRAYSIZE(wszFormat));
  75. #else
  76.     CHAR szFormat[MAX_PATH];
  77.     MLLoadStringA(IDS_RECOMMENDED_SCHEDULE_FORMAT, szFormat, ARRAYSIZE(szFormat));
  78.     MultiByteToWideChar(CP_ACP, 0, szFormat, -1, wszFormat, ARRAYSIZE(wszFormat));
  79. #endif
  80.     wnsprintfW(pwszSchedName, cchSchedName, wszFormat, pwszPubName);
  81. }
  82. void CreatePublisherScheduleName(TCHAR *pszSchedName, int cchSchedName, 
  83.                                  const TCHAR *pszName, const WCHAR *pwszName)
  84. {
  85.     WCHAR wszSchedName[MAX_PATH];
  86.     CreatePublisherScheduleNameW(wszSchedName, ARRAYSIZE(wszSchedName),
  87.                                  pszName, pwszName);
  88.     MyOleStrToStrN(pszSchedName, cchSchedName, wszSchedName);
  89. }
  90. HICON LoadItemIcon(ISubscriptionItem *psi, BOOL bLarge)
  91. {
  92.     HICON hIcon = NULL;
  93.     SUBSCRIPTIONITEMINFO sii;
  94.     SUBSCRIPTIONCOOKIE cookie;
  95.     HRESULT hr;
  96.     sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
  97.     psi->GetCookie(&cookie);
  98.     
  99.     hr = psi->GetSubscriptionItemInfo(&sii);
  100.     if (SUCCEEDED(hr))
  101.     {
  102.         ISubscriptionAgentShellExt *pSubscriptionAgentShellExt;
  103.         
  104.         hr = CoCreateInstance(sii.clsidAgent, NULL, CLSCTX_INPROC_SERVER, 
  105.                               IID_ISubscriptionAgentShellExt, 
  106.                               (void **)&pSubscriptionAgentShellExt);
  107.         if (SUCCEEDED(hr))
  108.         {
  109.             hr = pSubscriptionAgentShellExt->Initialize(&cookie, L"", L"", (SUBSCRIPTIONTYPE)-1);
  110.             if (SUCCEEDED(hr))
  111.             {
  112.                 IExtractIcon *pExtractIcon;
  113.                 hr = pSubscriptionAgentShellExt->QueryInterface(IID_IExtractIcon, 
  114.                                                                 (void **)&pExtractIcon);
  115.                 if (SUCCEEDED(hr))
  116.                 {
  117.                     TCHAR szIconFile[INTERNET_MAX_URL_LENGTH];
  118.                     int iIndex;
  119.                     UINT wFlags;
  120.                     HICON hIconScrap = NULL;
  121.                     HICON *phIconLarge = bLarge ? &hIcon : &hIconScrap;
  122.                     HICON *phIconSmall = bLarge ? &hIconScrap : &hIcon;
  123.                     
  124.                     hr = pExtractIcon->GetIconLocation(0, szIconFile, ARRAYSIZE(szIconFile), &iIndex, &wFlags);
  125.                     if (SUCCEEDED(hr))
  126.                     {
  127.                         hr = pExtractIcon->Extract(szIconFile, iIndex, phIconLarge, phIconSmall, 
  128.                                                    MAKELONG(GetSystemMetrics(SM_CXICON), 
  129.                                                             GetSystemMetrics(SM_CXSMICON)));
  130.                         if (S_FALSE == hr)
  131.                         {
  132.                             hIcon = ExtractIcon(g_hInst, szIconFile, iIndex);
  133.                             if (NULL == hIcon)
  134.                             {
  135.                                 hr = E_FAIL;
  136.                             }
  137.                         }
  138.                         else if ((NULL != hIconScrap) && (hIcon != hIconScrap))
  139.                         {
  140.                             DestroyIcon(hIconScrap);
  141.                         }
  142.                     }
  143.                     pExtractIcon->Release();
  144.                 }
  145.             }
  146.             
  147.             pSubscriptionAgentShellExt->Release();
  148.         }
  149.     }
  150.     if (FAILED(hr))
  151.     {
  152.         DWORD dwChannel = 0;
  153.         DWORD dwDesktop = 0;
  154.         int iSize = bLarge ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXSMICON);
  155.         int id;
  156.         HINSTANCE   hinstSrc;
  157.         ReadDWORD(psi, c_szPropChannel, &dwChannel);
  158.         ReadDWORD(psi, c_szPropDesktopComponent, &dwDesktop);
  159.         if (dwDesktop == 1)
  160.         {
  161.             id = IDI_DESKTOPITEM;
  162.             hinstSrc = MLGetHinst();
  163.         }
  164.         else if (dwChannel == 1)
  165.         {
  166.             id = IDI_CHANNEL;
  167.             hinstSrc = g_hInst;
  168.         }
  169.         else
  170.         {
  171.             id = IDI_WEBDOC;
  172.             hinstSrc = g_hInst;
  173.         }
  174.         hIcon = (HICON)LoadImage(hinstSrc, MAKEINTRESOURCE(id), IMAGE_ICON, 
  175.                                  iSize, iSize, LR_DEFAULTCOLOR);
  176.     
  177.     }
  178.     return hIcon;
  179. }
  180. BOOL ScheduleCookieExists(SYNCSCHEDULECOOKIE *pSchedCookie)
  181. {
  182.     HRESULT hr;
  183.     ISyncScheduleMgr *pSyncScheduleMgr;
  184.     hr = CoInitialize(NULL);
  185.     if (SUCCEEDED(hr))
  186.     {
  187.         hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  188.                               IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  189.         if (SUCCEEDED(hr))
  190.         {
  191.             ISyncSchedule *pSyncSchedule = NULL;
  192.             hr = pSyncScheduleMgr->OpenSchedule(pSchedCookie, 0, &pSyncSchedule);
  193.             if (SUCCEEDED(hr))
  194.             {
  195.                 pSyncSchedule->Release();
  196.             }
  197.             pSyncScheduleMgr->Release();
  198.         }
  199.         CoUninitialize();
  200.     }
  201.     return hr == S_OK;
  202. }
  203. BOOL IsScheduleNameInUse(TCHAR *pszSchedName)
  204. {
  205.     HRESULT hr;
  206.     ISyncScheduleMgr *pSyncScheduleMgr;
  207.     hr = CoInitialize(NULL);
  208.     if (SUCCEEDED(hr))
  209.     {
  210.         hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  211.                               IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  212.         if (SUCCEEDED(hr))
  213.         {
  214.             CWaitCursor waitCursor;
  215.             ISyncSchedule *pSyncSchedule = NULL;
  216.             SYNCSCHEDULECOOKIE schedCookie = GUID_NULL;
  217.             WCHAR wszSchedName[MAX_PATH];
  218.             MyStrToOleStrN(wszSchedName, ARRAYSIZE(wszSchedName), pszSchedName);
  219.             hr = pSyncScheduleMgr->CreateSchedule(wszSchedName, 0, 
  220.                                                   &schedCookie, &pSyncSchedule);
  221.             if (SUCCEEDED(hr))
  222.             {
  223.                 pSyncSchedule->Release();
  224.             }
  225.             pSyncScheduleMgr->Release();
  226.         }
  227.         CoUninitialize();
  228.     }
  229.     return hr == SYNCMGR_E_NAME_IN_USE;
  230. }
  231. struct CONFLICT_DATA
  232. {
  233.     TCHAR szSchedName[MAX_PATH];
  234.     TCHAR szFriendlyTrigger[MAX_PATH];
  235. };
  236. INT_PTR CALLBACK SchedConflictDlgProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
  237. {
  238.     BOOL bResult = FALSE;
  239.     switch (message)
  240.     {
  241.         case WM_INITDIALOG:
  242.         {
  243.             TCHAR szConflictFormat[MAX_PATH];
  244.             TCHAR szConflictMsg[MAX_PATH * 2];
  245.             CONFLICT_DATA *pcd = (CONFLICT_DATA *)lParam;
  246.             ASSERT(NULL != pcd);
  247.             MLLoadString(IDS_SCHED_CONFLICT_FORMAT, 
  248.                        szConflictFormat, ARRAYSIZE(szConflictFormat));
  249.             wnsprintf(szConflictMsg, ARRAYSIZE(szConflictMsg),
  250.                       szConflictFormat, pcd->szSchedName);
  251.             SetDlgItemText(hdlg, IDC_SCHEDULE_MESSAGE, szConflictMsg);
  252.             SetDlgItemText(hdlg, IDC_FRIENDLY_SCHEDULE_TEXT, pcd->szFriendlyTrigger);
  253.             
  254.             bResult = TRUE;
  255.             break;
  256.         }
  257.         case WM_COMMAND:
  258.             if (HIWORD(wParam) == BN_CLICKED)
  259.             {
  260.                 EndDialog(hdlg, LOWORD(wParam));
  261.                 bResult = TRUE;
  262.             }
  263.             break;
  264.     }
  265.     
  266.     return bResult;
  267. }
  268. BOOL CompareTaskTrigger(TASK_TRIGGER *pTrigA, TASK_TRIGGER *pTrigB)
  269. {
  270.     BOOL bDontMatch;    //  TRUE if any elements don't match
  271.     //  Simple memcmp won't work since the start date will be different
  272.     //  when in fact they are effectively the same schedule - at least
  273.     //  from a user perspective.
  274.     //  BUGBUG - this is far from complete - we only check for values
  275.     //  which can be set by our wizard.
  276.     bDontMatch  = pTrigA->wStartHour != pTrigB->wStartHour;
  277.     bDontMatch |= pTrigA->wStartMinute != pTrigB->wStartMinute;
  278.     bDontMatch |= pTrigA->TriggerType != pTrigB->TriggerType;
  279.     bDontMatch |= pTrigA->Type.Daily.DaysInterval != pTrigB->Type.Daily.DaysInterval;
  280.     bDontMatch |= pTrigA->MinutesDuration != pTrigB->MinutesDuration;
  281.     bDontMatch |= pTrigA->MinutesInterval != pTrigB->MinutesInterval;
  282.     bDontMatch |= pTrigA->wRandomMinutesInterval != pTrigB->wRandomMinutesInterval;
  283.     return !bDontMatch;
  284. }
  285. //  HandleScheduleNameConflict
  286. //
  287. //  Return values:
  288. //  CONFLICT_NONE               - pSchedCookie will be GUID_NULL and the caller is 
  289. //                                free to create a new schedule
  290. //  CONFLICT_RESOLVED_USE_NEW   - pSchedCookie will be the cookie of an existing
  291. //                                schedule which the caller should update with
  292. //                                it's new TASK_TRIGGER
  293. //  CONFLICT_RESOLVED_USE_OLD   - pSchedCookie will be the cookie of an existing
  294. //                                schedule which the caller should use without
  295. //                                modifying anything
  296. //  CONFLICT_UNRESOLVED         - pSchedCookie will be GUID_NULL and the caller
  297. //                                shouldn't do anything until the user has made
  298. //                                up his/her mind
  299. //
  300. int HandleScheduleNameConflict(/* in  */ TCHAR *pszSchedName, 
  301.                                /* in  */ TASK_TRIGGER *pTrigger,
  302.                                /* in  */ HWND hwndParent,
  303.                                /* out */ SYNCSCHEDULECOOKIE *pSchedCookie)
  304. {
  305.     HRESULT hr;
  306.     ISyncScheduleMgr *pSyncScheduleMgr;
  307.     int iResult = CONFLICT_NONE;
  308.     *pSchedCookie = GUID_NULL;
  309.     hr = CoInitialize(NULL);
  310.     if (SUCCEEDED(hr))
  311.     {
  312.         hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  313.                               IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  314.         if (SUCCEEDED(hr))
  315.         {
  316.             ISyncSchedule *pSyncSchedule = NULL;
  317.             SYNCSCHEDULECOOKIE schedCookie = GUID_NULL;
  318.             WCHAR wszSchedName[MAX_PATH];
  319.             MyStrToOleStrN(wszSchedName, ARRAYSIZE(wszSchedName), pszSchedName);
  320.             {
  321.                 CWaitCursor waitCursor;
  322.                 hr = pSyncScheduleMgr->CreateSchedule(wszSchedName, 0, 
  323.                                                       &schedCookie, &pSyncSchedule);
  324.             }
  325.             if (SUCCEEDED(hr))
  326.             {
  327.                 pSyncSchedule->Release();
  328.             }
  329.             else if (SYNCMGR_E_NAME_IN_USE == hr)
  330.             {
  331.                 //  schedCookie will have the cookie of the conflicting schedule
  332.                 hr = pSyncScheduleMgr->OpenSchedule(&schedCookie, 0, &pSyncSchedule);
  333.                 if (SUCCEEDED(hr))
  334.                 {
  335.                     ITaskTrigger *pITaskTrigger;
  336.                     
  337.                     hr = pSyncSchedule->GetTrigger(&pITaskTrigger);
  338.                     if (SUCCEEDED(hr))
  339.                     {
  340.                         TASK_TRIGGER existTrigger = { sizeof(TASK_TRIGGER) };
  341.                         hr = pITaskTrigger->GetTrigger(&existTrigger);
  342.                         if (SUCCEEDED(hr))
  343.                         {
  344.                             if (!CompareTaskTrigger(&existTrigger, pTrigger))
  345.                             {
  346.                                 CONFLICT_DATA cd;
  347.                                 LPWSTR pwszFriendlyTrigger;
  348.                                 StrCpyN(cd.szSchedName, pszSchedName, ARRAYSIZE(cd.szSchedName));
  349.                                 if (SUCCEEDED(pITaskTrigger->GetTriggerString(&pwszFriendlyTrigger)))
  350.                                 {
  351.                                     MyOleStrToStrN(cd.szFriendlyTrigger,
  352.                                                    ARRAYSIZE(cd.szFriendlyTrigger),
  353.                                                    pwszFriendlyTrigger);
  354.                                     CoTaskMemFree(pwszFriendlyTrigger);
  355.                                 }
  356.                                 else
  357.                                 {
  358.                                     cd.szFriendlyTrigger[0] = TEXT('');
  359.                                 }
  360.                                 INT_PTR iRet = DialogBoxParam(MLGetHinst(),
  361.                                                               MAKEINTRESOURCE(IDD_DUPLICATE_SCHEDULE),
  362.                                                               hwndParent,
  363.                                                               SchedConflictDlgProc,
  364.                                                               (LPARAM)&cd);
  365.                                 switch (iRet)
  366.                                 {
  367.                                     case IDC_NEW_SETTINGS:
  368.                                         iResult = CONFLICT_RESOLVED_USE_NEW;
  369.                                         *pSchedCookie = schedCookie;
  370.                                         break;
  371.                                         
  372.                                     case IDC_OLD_SETTINGS:
  373.                                         iResult = CONFLICT_RESOLVED_USE_OLD;
  374.                                         *pSchedCookie = schedCookie;
  375.                                         break;
  376.                                     default:
  377.                                         iResult = CONFLICT_UNRESOLVED;
  378.                                         break;
  379.                                 }
  380.                             }
  381.                         }
  382.                         pITaskTrigger->Release();
  383.                     }
  384.                     pSyncSchedule->Release();
  385.                 }
  386.             }
  387.             pSyncScheduleMgr->Release();
  388.         }
  389.         CoUninitialize();
  390.     }
  391.     return iResult;
  392. }
  393. HRESULT UpdateScheduleTrigger(SYNCSCHEDULECOOKIE *pSchedCookie, TASK_TRIGGER *pTrigger)
  394. {
  395.     HRESULT hr;
  396.     ISyncScheduleMgr *pSyncScheduleMgr;
  397.     hr = CoInitialize(NULL);
  398.     if (SUCCEEDED(hr))
  399.     {
  400.         CWaitCursor waitCursor;
  401.         hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  402.                               IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  403.         if (SUCCEEDED(hr))
  404.         {
  405.             ISyncSchedule *pSyncSchedule;
  406.             hr = pSyncScheduleMgr->OpenSchedule(pSchedCookie, 0, &pSyncSchedule);
  407.             if (SUCCEEDED(hr))
  408.             {
  409.                 ITaskTrigger *pITaskTrigger;
  410.                 
  411.                 hr = pSyncSchedule->GetTrigger(&pITaskTrigger);
  412.                 if (SUCCEEDED(hr))
  413.                 {
  414.                     FixupRandomTrigger(pTrigger);
  415.                     hr = pITaskTrigger->SetTrigger(pTrigger);
  416.                     if (SUCCEEDED(hr))
  417.                     {
  418.                         hr = pSyncSchedule->Save();
  419.                     }
  420.                     pITaskTrigger->Release();
  421.                 }
  422.                 pSyncSchedule->Release();
  423.             }
  424.             pSyncScheduleMgr->Release();
  425.         }
  426.         CoUninitialize();
  427.     }
  428.     return hr;
  429. }
  430. HRESULT RemoveItemFromAllSchedules(SUBSCRIPTIONCOOKIE *pCookie)
  431. {
  432.     HRESULT hr;
  433.     ISyncScheduleMgr *pSyncScheduleMgr;
  434.     hr = CoInitialize(NULL);
  435.     if (SUCCEEDED(hr))
  436.     {
  437.         CWaitCursor waitCursor;
  438.         hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  439.                               IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  440.         if (SUCCEEDED(hr))
  441.         {
  442.             IEnumSyncSchedules *pEnumSyncSchedules;
  443.             
  444.             hr = pSyncScheduleMgr->EnumSyncSchedules(&pEnumSyncSchedules);
  445.             if (SUCCEEDED(hr))
  446.             {
  447.                 SYNCSCHEDULECOOKIE schedCookie;
  448.                 ULONG ulFetched;
  449.                 while (S_OK == pEnumSyncSchedules->Next(1, &schedCookie, &ulFetched) &&
  450.                        (0 != ulFetched))    //  BUGBUG - this shouldn't be necessary
  451.                 {
  452.                     ISyncSchedule *pSyncSchedule;
  453.                     //  If this fails, there ain't much we can do about
  454.                     //  it so just plod along anyhow
  455.                     if (SUCCEEDED(pSyncScheduleMgr->OpenSchedule(&schedCookie, 0, &pSyncSchedule)))
  456.                     {
  457.                         //  Don't care about the return value, it's cheaper
  458.                         //  for us to just delete than to ask if it's there
  459.                         //  and then delete.
  460.                         pSyncSchedule->SetItemCheck(CLSID_WebCheckOfflineSync,
  461.                                                     pCookie,
  462.                                                     SYNCMGRITEMSTATE_UNCHECKED);
  463.                         pSyncSchedule->Save();
  464.                         pSyncSchedule->Release();
  465.                     }
  466.                 }
  467.                 pEnumSyncSchedules->Release();
  468.             }
  469.             pSyncScheduleMgr->Release();
  470.         }
  471.         CoUninitialize();
  472.     }
  473.     return hr;
  474. }
  475. HRESULT AddRemoveScheduledItem(SYNC_HANDLER_ITEM_INFO *pSyncHandlerItemInfo, // For Add
  476.                                SUBSCRIPTIONCOOKIE *pCookie,                  // For Remove
  477.                                SYNCSCHEDULECOOKIE *pSchedCookie, BOOL bAdd)
  478. {
  479.     HRESULT hr;
  480.     ISyncScheduleMgr *pSyncScheduleMgr;
  481.     ASSERT((bAdd && (NULL != pSyncHandlerItemInfo)) || 
  482.             (!bAdd && (NULL != pCookie)));
  483.     hr = CoInitialize(NULL);
  484.     if (SUCCEEDED(hr))
  485.     {
  486.         hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  487.                               IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  488.         if (SUCCEEDED(hr))
  489.         {
  490.             ISyncSchedule *pSyncSchedule;
  491.             hr = pSyncScheduleMgr->OpenSchedule(pSchedCookie, 0, &pSyncSchedule);
  492.             if (SUCCEEDED(hr))
  493.             {
  494.                 if (bAdd)
  495.                 {
  496.                     hr = pSyncSchedule->AddItem(pSyncHandlerItemInfo);
  497.                     hr = pSyncSchedule->SetItemCheck(CLSID_WebCheckOfflineSync,
  498.                                                      &pSyncHandlerItemInfo->itemID,
  499.                                                      SYNCMGRITEMSTATE_CHECKED);
  500.                 }
  501.                 else
  502.                 {
  503.                     hr = pSyncSchedule->SetItemCheck(CLSID_WebCheckOfflineSync,
  504.                                                      pCookie,
  505.                                                      SYNCMGRITEMSTATE_UNCHECKED);
  506.                 }
  507.                 hr = pSyncSchedule->Save();
  508.                 pSyncSchedule->Release();
  509.             }
  510.             pSyncScheduleMgr->Release();
  511.         }
  512.         CoUninitialize();
  513.     }
  514.     return hr;
  515. }
  516. HRESULT SetScheduleValues(ISyncSchedule *pSyncSchedule, 
  517.                           TASK_TRIGGER *pTrigger,
  518.                           DWORD dwSyncScheduleFlags)
  519. {
  520.     HRESULT hr;
  521.     ITaskTrigger *pITaskTrigger;
  522.     ASSERT(NULL != pSyncSchedule);
  523.     ASSERT(NULL != pTrigger);
  524.     hr = pSyncSchedule->GetTrigger(&pITaskTrigger);
  525.     ASSERT(SUCCEEDED(hr));
  526.     if (SUCCEEDED(hr))
  527.     {
  528.         FixupRandomTrigger(pTrigger);
  529.         hr = pITaskTrigger->SetTrigger(pTrigger);
  530.         pITaskTrigger->Release();
  531.         ASSERT(SUCCEEDED(hr));
  532.         if (SUCCEEDED(hr))
  533.         {
  534.             DWORD dwFlags;
  535.             DWORD dwConnectionType = SYNCSCHEDINFO_FLAGS_CONNECTION_LAN;
  536.             WCHAR wszConnectionName[MAX_PATH];
  537.             //  Return code doesn't help us.  This returns the best guess
  538.             //  at connection:
  539.             //      1) LAN
  540.             //      2) currently connected connectoid
  541.             //      3) auto-dial connectoid
  542.             //  This is according to darrenmi, if this changes - kill him.
  543.             InternetGetConnectedStateExW(&dwFlags, wszConnectionName,
  544.                                          ARRAYSIZE(wszConnectionName), 0);
  545.             if (dwFlags & INTERNET_CONNECTION_MODEM)
  546.             {
  547.                 dwConnectionType = SYNCSCHEDINFO_FLAGS_CONNECTION_WAN;
  548.             }
  549.             hr = pSyncSchedule->SetConnection(
  550.                 (dwConnectionType == SYNCSCHEDINFO_FLAGS_CONNECTION_WAN) ?
  551.                     wszConnectionName : NULL, 
  552.                 dwConnectionType);
  553.             ASSERT(SUCCEEDED(hr));
  554.             if (SUCCEEDED(hr))
  555.             {
  556.                 hr = pSyncSchedule->SetFlags(dwSyncScheduleFlags);
  557.                 ASSERT(SUCCEEDED(hr));
  558.                 if (SUCCEEDED(hr))
  559.                 {
  560.                     hr = pSyncSchedule->Save();
  561.                     ASSERT(SUCCEEDED(hr));
  562.                 }
  563.             }
  564.         }
  565.     }
  566.     return hr;
  567. }
  568. HRESULT CreateSchedule(LPWSTR pwszScheduleName, DWORD dwSyncScheduleFlags, 
  569.                        SYNCSCHEDULECOOKIE *pSchedCookie, TASK_TRIGGER *pTrigger,
  570.                        BOOL fDupCookieOK)
  571. {
  572.     HRESULT hr;
  573.     ISyncScheduleMgr *pSyncScheduleMgr;
  574.     ISyncSchedule *pSyncSchedule = NULL;
  575.     hr = CoInitialize(NULL);
  576.     if (SUCCEEDED(hr))
  577.     {
  578.         CWaitCursor waitCursor;
  579.         hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  580.                               IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  581.         if (SUCCEEDED(hr))
  582.         {
  583.             hr = pSyncScheduleMgr->CreateSchedule(pwszScheduleName, 0, 
  584.                                       pSchedCookie, &pSyncSchedule);
  585.             ASSERT((FAILED(hr) && (NULL == pSyncSchedule)) ||
  586.                    (SUCCEEDED(hr) && (NULL != pSyncSchedule)));
  587.             switch (hr)
  588.             {
  589.                 case S_OK:
  590.                     hr = SetScheduleValues(pSyncSchedule, pTrigger, dwSyncScheduleFlags);
  591.                 #ifdef DEBUG
  592.                     if (FAILED(hr))
  593.                     {
  594.                         TraceMsg(TF_ALWAYS, "SetScheduleValues failed - hr=0x%08x", hr);
  595.                     }
  596.                 #endif
  597.                 
  598.                     break;
  599.                 case HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS):
  600.                     if (fDupCookieOK)
  601.                     {
  602.                         hr = S_OK;
  603.                     }
  604.                     break;
  605.             }
  606.             SAFERELEASE(pSyncSchedule);
  607.             pSyncScheduleMgr->Release();
  608.         }
  609.         CoUninitialize();
  610.     }
  611.     return hr;
  612. }
  613. BOOL IsCookieOnSchedule(ISyncSchedule *pSyncSchedule, SUBSCRIPTIONCOOKIE *pCookie)
  614. {
  615.     HRESULT hr;
  616.     DWORD dwCheckState = SYNCMGRITEMSTATE_UNCHECKED;
  617.     hr = pSyncSchedule->GetItemCheck(CLSID_WebCheckOfflineSync,
  618.                                      pCookie,
  619.                                      &dwCheckState);
  620.     return SUCCEEDED(hr) && (SYNCMGRITEMSTATE_CHECKED & dwCheckState);
  621. }
  622. struct GIS_DATA
  623. {
  624.     SUBSCRIPTIONCOOKIE *pSubsCookie;
  625.     SYNCSCHEDULECOOKIE *pSchedCookie;
  626. };
  627. BOOL GetItemScheduleCallback(ISyncSchedule *pSyncSchedule, 
  628.                              SYNCSCHEDULECOOKIE *pSchedCookie, 
  629.                              LPARAM lParam)
  630. {
  631.     BOOL bContinue = TRUE;
  632.     GIS_DATA *pgd = (GIS_DATA *)lParam;
  633.     
  634.     if (IsCookieOnSchedule(pSyncSchedule, pgd->pSubsCookie))
  635.     {
  636.         *pgd->pSchedCookie = *pSchedCookie;
  637.         bContinue = FALSE;
  638.     }
  639.     return bContinue;
  640. }
  641. HRESULT GetItemSchedule(SUBSCRIPTIONCOOKIE *pSubsCookie, SYNCSCHEDULECOOKIE *pSchedCookie)
  642. {
  643.     HRESULT hr;
  644.     ISyncScheduleMgr *pSyncScheduleMgr;
  645.     *pSchedCookie = GUID_NULL;
  646.     
  647.     hr = CoInitialize(NULL);
  648.     if (SUCCEEDED(hr))
  649.     {
  650.         hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  651.                               IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  652.         if (SUCCEEDED(hr))
  653.         {
  654.             ISubscriptionItem *psi;
  655.             //  First let's chech to see if it has a custom schedule
  656.             hr = SubscriptionItemFromCookie(FALSE, pSubsCookie, &psi);
  657.             if (SUCCEEDED(hr))
  658.             {
  659.                 SUBSCRIPTIONITEMINFO sii;
  660.                 sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
  661.                 
  662.                 hr = psi->GetSubscriptionItemInfo(&sii);
  663.                 psi->Release();
  664.                 if (SUCCEEDED(hr) && (sii.ScheduleGroup != GUID_NULL))
  665.                 {
  666.                     *pSchedCookie = sii.ScheduleGroup;
  667.                 }
  668.                 else
  669.                 {
  670.                     GIS_DATA gd;
  671.                     gd.pSubsCookie = pSubsCookie;
  672.                     gd.pSchedCookie = pSchedCookie;
  673.                     EnumSchedules(GetItemScheduleCallback, (LPARAM)&gd);
  674.                 }
  675.             }
  676.             pSyncScheduleMgr->Release();
  677.         }
  678.         CoUninitialize();
  679.     }
  680.     return hr;
  681. }
  682. HRESULT EnumSchedules(SCHEDULEENUMCALLBACK pCallback, LPARAM lParam)
  683. {
  684.     HRESULT hr;
  685.     ISyncScheduleMgr *pSyncScheduleMgr;
  686.     hr = CoInitialize(NULL);
  687.     if (SUCCEEDED(hr))
  688.     {
  689.         CWaitCursor waitCursor;
  690.         hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  691.                               IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  692.         if (SUCCEEDED(hr))
  693.         {
  694.             IEnumSyncSchedules *pEnumSyncSchedules;
  695.             
  696.             hr = pSyncScheduleMgr->EnumSyncSchedules(&pEnumSyncSchedules);
  697.             if (SUCCEEDED(hr))
  698.             {
  699.                 SYNCSCHEDULECOOKIE schedCookie;
  700.                 ULONG ulFetched;
  701.                 while (S_OK == pEnumSyncSchedules->Next(1, &schedCookie, &ulFetched)&&
  702.                        (0 != ulFetched))    //  BUGBUG - this shouldn't be necessary
  703.                 {
  704.                     ISyncSchedule *pSyncSchedule;
  705.                     HRESULT hrTemp = pSyncScheduleMgr->OpenSchedule(&schedCookie, 0, &pSyncSchedule);
  706.                     if (SUCCEEDED(hrTemp) && pSyncSchedule)
  707.                     {
  708.                         BOOL bContinue = pCallback(pSyncSchedule, &schedCookie, lParam);
  709.                         pSyncSchedule->Release();
  710.                         if (!bContinue)
  711.                         {
  712.                             hr = S_FALSE;
  713.                             break;
  714.                         }
  715.                     }
  716.                 }
  717.                 pEnumSyncSchedules->Release();
  718.             }
  719.             pSyncScheduleMgr->Release();
  720.         }
  721.         CoUninitialize();
  722.     }
  723.     return hr;
  724. }
  725. SUBSCRIPTIONTYPE GetItemCategory(BOOL bDesktop, const CLSID& clsidDest)
  726. {
  727.     SUBSCRIPTIONTYPE st;
  728.     
  729.     if (clsidDest == CLSID_WebCrawlerAgent)
  730.     {
  731.         st = (!bDesktop) ? SUBSTYPE_URL : SUBSTYPE_DESKTOPURL;
  732.     }
  733.     else if (clsidDest == CLSID_ChannelAgent)
  734.     {
  735.         st = (!bDesktop) ? SUBSTYPE_CHANNEL : SUBSTYPE_DESKTOPCHANNEL;
  736.     }
  737.     else
  738.     {
  739.         st = SUBSTYPE_EXTERNAL;
  740.     }
  741.     return st;
  742. }
  743. SUBSCRIPTIONSCHEDULE GetGroup(BOOL bDesktop, const CLSID& clsidDest, 
  744.                               DWORD fChannelFlags, const NOTIFICATIONCOOKIE& groupCookie)
  745. {
  746.     SUBSCRIPTIONTYPE category = GetItemCategory(bDesktop, clsidDest);
  747.     if (category == SUBSTYPE_CHANNEL || category == SUBSTYPE_DESKTOPCHANNEL) {
  748.         if ((fChannelFlags & CHANNEL_AGENT_DYNAMIC_SCHEDULE) && 
  749.             (GUID_NULL == groupCookie))
  750.             return SUBSSCHED_AUTO;
  751.     }
  752.     //  We have no idea about the AUTO schedule stuff of unknown types.
  753.     if (groupCookie == NOTFCOOKIE_SCHEDULE_GROUP_DAILY)
  754.             return SUBSSCHED_DAILY;
  755.     else if (groupCookie == NOTFCOOKIE_SCHEDULE_GROUP_WEEKLY)
  756.         return SUBSSCHED_WEEKLY;
  757.     else if (groupCookie == NOTFCOOKIE_SCHEDULE_GROUP_MANUAL)
  758.         return SUBSSCHED_MANUAL;
  759.     else
  760.         return SUBSSCHED_CUSTOM;
  761. }
  762. HRESULT LoadGroupCookie(NOTIFICATIONCOOKIE * pCookie, SUBSCRIPTIONSCHEDULE subGroup)
  763. {
  764.     if (pCookie)    {
  765.         switch (subGroup)   {
  766.         case SUBSSCHED_DAILY:
  767.             *pCookie = NOTFCOOKIE_SCHEDULE_GROUP_DAILY;
  768.             break;
  769.         case SUBSSCHED_WEEKLY:
  770.             *pCookie = NOTFCOOKIE_SCHEDULE_GROUP_WEEKLY;
  771.             break;
  772.         case SUBSSCHED_MANUAL:
  773.             *pCookie = NOTFCOOKIE_SCHEDULE_GROUP_MANUAL;
  774.             break;
  775.         default:
  776.             *pCookie = CLSID_NULL;
  777.             ASSERT(0);
  778.             break;
  779.         }
  780.         return S_OK;
  781.     }
  782.     return E_INVALIDARG;
  783. }
  784. /////////////////////////////////////////////////////////////////////
  785. //  Subscription helper functions.
  786. HRESULT TSTR2BSTR(VARIANT * pvarBSTR, LPCTSTR srcTSTR)
  787. {
  788.     ASSERT(pvarBSTR);
  789.     ASSERT(srcTSTR);
  790.     BSTR    bstrBuf = NULL;
  791.     LONG    lTSTRLen = 0;
  792.     lTSTRLen = lstrlen(srcTSTR) + 1;
  793.     bstrBuf = SysAllocStringLen(NULL, lTSTRLen);
  794.     if (!bstrBuf)
  795.         return E_OUTOFMEMORY;
  796.     MyStrToOleStrN(bstrBuf, lTSTRLen, srcTSTR);
  797.     pvarBSTR->vt = VT_BSTR;
  798.     pvarBSTR->bstrVal = bstrBuf;
  799.     return S_OK; 
  800. }
  801. HRESULT WriteCookieToInetDB(LPCTSTR pszURL, SUBSCRIPTIONCOOKIE *pCookie, BOOL bRemove)
  802. {
  803.     PROPVARIANT propCookie;
  804.     LPOLESTR pclsid = NULL; // init to keep compiler happy
  805.     ASSERT(pszURL);
  806.     if (bRemove)
  807.     {
  808.         propCookie.vt = VT_EMPTY;
  809.     } 
  810.     else 
  811.     {
  812.         ASSERT(pCookie);
  813.         if (FAILED(StringFromCLSID(*pCookie, &pclsid)))
  814.             return E_FAIL;
  815.         propCookie.vt = VT_LPWSTR;
  816.         propCookie.pwszVal = pclsid;
  817.     }
  818.     HRESULT hr = IntSiteHelper(pszURL, &c_rgPropRead[PROP_SUBSCRIPTION], &propCookie, 1, TRUE);
  819.     if (!bRemove)
  820.         CoTaskMemFree(pclsid);
  821.     return hr;
  822. }
  823. HRESULT WritePropertiesToItem(POOEntry pooe, ISubscriptionItem *psi)
  824. {
  825.     HRESULT hr = S_OK;
  826.     VARIANT var;
  827.     BOOL bHasUNAME = TRUE;
  828.     ASSERT(NULL != psi);
  829.     
  830.     VariantInit(&var);
  831.     if (pooe->dwFlags & PROP_WEBCRAWL_URL)
  832.     {
  833.         if (FAILED(TSTR2BSTR(&var, URL(pooe))))
  834.             return E_FAIL;
  835.         WriteVariant(psi, c_szPropURL, &var);
  836.         VariantClear(&var);
  837.     }
  838.     if (pooe->dwFlags & PROP_WEBCRAWL_NAME)
  839.     {
  840.         if (FAILED(TSTR2BSTR(&var, NAME(pooe))))
  841.             return E_FAIL;
  842.         WriteVariant(psi, c_szPropName, &var);
  843.         VariantClear(&var);
  844.     }
  845.     if (pooe->dwFlags & PROP_WEBCRAWL_UNAME)
  846.     {
  847.         if(*(UNAME(pooe)))
  848.         {
  849.             if (FAILED(TSTR2BSTR(&var, UNAME(pooe))))
  850.                 return E_FAIL;
  851.             WriteVariant(psi, c_szPropCrawlUsername, &var);
  852.             VariantClear(&var);
  853.         }
  854.         else
  855.         {
  856.             WriteEMPTY(psi, c_szPropCrawlUsername);
  857.             bHasUNAME = FALSE;
  858.         }
  859.     }
  860.     if (pooe->dwFlags & PROP_WEBCRAWL_DESKTOP)
  861.     {
  862.         if (pooe->bDesktop)
  863.         {
  864.             WriteDWORD(psi, c_szPropDesktopComponent, 1);
  865.         }
  866.         else
  867.         {
  868.             WriteEMPTY(psi, c_szPropDesktopComponent);
  869.         }
  870.     }
  871.     if (pooe->dwFlags & PROP_WEBCRAWL_CHANNEL)
  872.     {
  873.         if (pooe->bChannel)
  874.         {
  875.             WriteDWORD(psi, c_szPropChannel, 1);
  876.         }
  877.         else
  878.         {
  879.             WriteEMPTY(psi, c_szPropChannel);
  880.         }
  881.     }
  882.     if (pooe->dwFlags & PROP_WEBCRAWL_GLEAM)
  883.     {
  884.         if (pooe->bGleam)
  885.         {
  886.             WriteDWORD(psi, c_szPropEnableShortcutGleam, 1);
  887.         }
  888.         else
  889.         {
  890.             WriteEMPTY(psi, c_szPropEnableShortcutGleam);
  891.         }
  892.     }
  893.     if (pooe->dwFlags & PROP_WEBCRAWL_CHANGESONLY)
  894.     {
  895.         if (pooe->bChangesOnly)
  896.         {
  897.             WriteDWORD(psi, c_szPropCrawlChangesOnly, 1);
  898.         }
  899.         else
  900.         {
  901.             WriteEMPTY(psi, c_szPropCrawlChangesOnly);
  902.         }
  903.     }
  904.     if (pooe->dwFlags & PROP_WEBCRAWL_CHANNELFLAGS)
  905.     {
  906.         if (pooe->fChannelFlags)
  907.         {
  908.             WriteDWORD(psi, c_szPropChannelFlags, pooe->fChannelFlags);
  909.         }
  910.         else
  911.         {
  912.             WriteEMPTY(psi, c_szPropChannelFlags);
  913.         }
  914.     }
  915.     if (pooe->dwFlags & PROP_WEBCRAWL_EMAILNOTF)
  916.     {
  917.         if (pooe->bMail)
  918.         {
  919.             WriteDWORD(psi, c_szPropEmailNotf, 1);
  920.         }
  921.         else
  922.         {
  923.             WriteEMPTY(psi, c_szPropEmailNotf);
  924.         }
  925.     }
  926.     if (pooe->dwFlags & PROP_WEBCRAWL_PSWD)
  927.     {
  928.         if (*(PASSWD(pooe)) && bHasUNAME)
  929.         {
  930.             if (FAILED(TSTR2BSTR(&var, PASSWD(pooe))))
  931.                 return E_FAIL;
  932.             WritePassword(psi, var.bstrVal);
  933.             VariantClear(&var);
  934.         }
  935.         else
  936.         {
  937.             WritePassword(psi, NULL);
  938.         }
  939.     }
  940.     if (pooe->dwFlags & PROP_WEBCRAWL_LEVEL)
  941.     {
  942.         if(pooe->m_RecurseLevels)
  943.         {
  944.             WriteDWORD(psi, c_szPropCrawlLevels, pooe->m_RecurseLevels);
  945.         }
  946.         else
  947.         {
  948.             // top page only was specified, empty out levels
  949.             WriteEMPTY(psi, c_szPropCrawlLevels);
  950.         }
  951.     }
  952.     if (pooe->dwFlags & PROP_WEBCRAWL_FLAGS)
  953.     {
  954.         WriteDWORD(psi, c_szPropCrawlFlags, pooe->m_RecurseFlags);
  955.     }
  956.     if (pooe->dwFlags & PROP_WEBCRAWL_ACTUALSIZE)
  957.     {
  958.         WriteDWORD(psi, c_szPropCrawlActualSize, pooe->m_ActualSize);
  959.     }
  960.     if (pooe->dwFlags & PROP_WEBCRAWL_SIZE)
  961.     {
  962.         if(pooe->m_SizeLimit)
  963.         {
  964.             // limit was specified
  965.             WriteDWORD(psi, c_szPropCrawlMaxSize, pooe->m_SizeLimit);
  966.         }
  967.         else
  968.         {
  969.             // no limit was specified, empty out limit prop
  970.             WriteEMPTY(psi, c_szPropCrawlMaxSize);
  971.         }
  972.     }
  973.     SUBSCRIPTIONITEMINFO sii;
  974.     sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
  975.     if (SUCCEEDED(psi->GetSubscriptionItemInfo(&sii)))
  976.     {
  977.         sii.dwFlags = pooe->grfTaskTrigger;
  978.         psi->SetSubscriptionItemInfo(&sii);
  979.     }
  980.     //  We don't write Status/Last update.
  981.     // BUGBUG: We should fail the subscription if we were unable to write
  982.     // any of the properties into the notification for some reason.
  983.     return hr;
  984. }
  985. HRESULT WriteProperties(POOEntry pooe)
  986. {
  987.     HRESULT hr;
  988.     ISubscriptionItem *psi = NULL;
  989.     ASSERT(NULL != pooe);
  990.     hr = SubscriptionItemFromCookie(FALSE, &pooe->m_Cookie, &psi);
  991.     if (SUCCEEDED(hr))
  992.     {
  993.         hr = WritePropertiesToItem(pooe, psi);
  994.         psi->Release();
  995.     }
  996.     return hr;
  997. }
  998. HRESULT CreatePublisherSchedule()
  999. {
  1000.     return S_OK;
  1001. }
  1002. #define RANDOM_TIME_START       0       // 12am (in minutes)
  1003. #define RANDOM_TIME_END         300     // 5am (in minutes)
  1004. #define RANDOM_TIME_INC         30      // 30min increment
  1005. DWORD GetRandomTime(DWORD StartMins, DWORD EndMins, DWORD Inc)
  1006. {
  1007.     DWORD Range;
  1008.     DWORD nIncrements;
  1009.     if (StartMins > EndMins)
  1010.     {
  1011.         Range = ((1440 - StartMins) + EndMins);
  1012.     }
  1013.     else
  1014.     {
  1015.         Range = (EndMins - StartMins);
  1016.     }
  1017.     nIncrements = ((Range / Inc) + 1);
  1018.     return (StartMins + (Random(nIncrements) * Inc));
  1019. }
  1020. HRESULT CreateDefaultSchedule(SUBSCRIPTIONSCHEDULE subsSchedule,
  1021.                               SYNCSCHEDULECOOKIE *pSchedCookie)
  1022. {
  1023.     HRESULT hr = S_OK;
  1024.     TASK_TRIGGER trig;
  1025.     int resID;
  1026.     *pSchedCookie = GUID_NULL;
  1027.     
  1028.     switch (subsSchedule)
  1029.     {
  1030.         case SUBSSCHED_DAILY:
  1031.             trig.TriggerType = TASK_TIME_TRIGGER_DAILY;
  1032.             trig.Type.Daily.DaysInterval = 1;
  1033.             resID = IDS_DAILY_GRO;
  1034.             *pSchedCookie = NOTFCOOKIE_SCHEDULE_GROUP_DAILY;
  1035.             break;
  1036.         case SUBSSCHED_WEEKLY:
  1037.             trig.TriggerType = TASK_TIME_TRIGGER_WEEKLY;
  1038.             trig.Type.Weekly.WeeksInterval = 1;
  1039.             trig.Type.Weekly.rgfDaysOfTheWeek = TASK_MONDAY;
  1040.             resID = IDS_WEEKLY_GRO;
  1041.             *pSchedCookie = NOTFCOOKIE_SCHEDULE_GROUP_WEEKLY;
  1042.             break;
  1043.         case SUBSSCHED_AUTO:
  1044.         case SUBSSCHED_CUSTOM:
  1045.         case SUBSSCHED_MANUAL:
  1046.         default:
  1047.             resID = 0;
  1048.             hr = E_FAIL;
  1049.             break;
  1050.     }
  1051.     if (SUCCEEDED(hr))
  1052.     {
  1053.         if (!ScheduleCookieExists(pSchedCookie))
  1054.         {
  1055.             WCHAR wszSchedName[MAX_PATH];
  1056.             DWORD dwRandTime = GetRandomTime(RANDOM_TIME_START, 
  1057.                                              RANDOM_TIME_END, 
  1058.                                              RANDOM_TIME_INC);
  1059.             trig.cbTriggerSize = sizeof(TASK_TRIGGER);
  1060.             trig.wRandomMinutesInterval = RANDOM_TIME_INC;
  1061.             trig.wStartHour = (UINT)(dwRandTime / 60);
  1062.             trig.wStartMinute = (UINT)(dwRandTime % 60);
  1063.             trig.rgFlags = 0;
  1064.             MLLoadStringW(resID, wszSchedName, ARRAYSIZE(wszSchedName));
  1065.             hr = CreateSchedule(wszSchedName, 0, pSchedCookie, &trig, TRUE);
  1066.             if (hr == SYNCMGR_E_NAME_IN_USE)
  1067.             {
  1068.                 hr = S_OK;
  1069.             }
  1070.         }
  1071.     }
  1072.     return hr;
  1073. }
  1074. HRESULT AddIt(ISubscriptionItem *psi, POOEntry pooe, SUBSCRIPTIONSCHEDULE subGroup)
  1075. {
  1076.     SYNCSCHEDULECOOKIE schedCookie = GUID_NULL;
  1077.     HRESULT hr = E_FAIL;
  1078.     switch (subGroup)
  1079.     {
  1080.         case SUBSSCHED_DAILY:
  1081.         case SUBSSCHED_WEEKLY:
  1082.             hr = CreateDefaultSchedule(subGroup, &schedCookie);
  1083.             break;
  1084.             
  1085.         case SUBSSCHED_CUSTOM:
  1086.             schedCookie = pooe->groupCookie;
  1087.             hr = S_OK;
  1088.             break;
  1089.         
  1090.         case SUBSSCHED_MANUAL:
  1091.             RemoveItemFromAllSchedules(&pooe->m_Cookie);
  1092.             hr = S_FALSE;
  1093.             break;
  1094.         case SUBSSCHED_AUTO:
  1095.             //  BUGBUG - for now, until pub schedules are wired in
  1096.             hr = CreateDefaultSchedule(SUBSSCHED_DAILY, &schedCookie);
  1097.             break;
  1098.     }
  1099.     if (hr == S_OK)
  1100.     {
  1101.         ASSERT(GUID_NULL != schedCookie);
  1102.         if (NOOP_SCHEDULE_COOKIE == schedCookie)
  1103.         {
  1104.             hr = S_FALSE;
  1105.         }
  1106.         if (GUID_NULL != schedCookie)
  1107.         {
  1108.             SYNC_HANDLER_ITEM_INFO shii;
  1109.             shii.handlerID = CLSID_WebCheckOfflineSync;
  1110.             shii.itemID = pooe->m_Cookie;
  1111.             shii.hIcon = NULL;
  1112.             MyStrToOleStrN(shii.wszItemName, ARRAYSIZE(shii.wszItemName), NAME(pooe));
  1113.             shii.dwCheckState = SYNCMGRITEMSTATE_CHECKED;
  1114.             hr = AddScheduledItem(&shii, &schedCookie);
  1115.         }
  1116.         else
  1117.         {
  1118.             hr = E_FAIL;
  1119.         }
  1120.     }
  1121.     return S_OK;
  1122. //  return hr;
  1123. }
  1124. HRESULT ScheduleIt(ISubscriptionItem *psi, TCHAR *pszName, TASK_TRIGGER *pTrigger)
  1125. {
  1126.     HRESULT hr;
  1127.     SUBSCRIPTIONITEMINFO subscriptionItemInfo;
  1128.     ASSERT(pTrigger->cbTriggerSize == sizeof(TASK_TRIGGER));
  1129.     subscriptionItemInfo.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
  1130. #ifdef DEBUG
  1131.     DumpTaskTrigger(pTrigger);
  1132. #endif
  1133.     hr = psi->GetSubscriptionItemInfo(&subscriptionItemInfo);
  1134.     if (SUCCEEDED(hr))
  1135.     {
  1136.         if (GUID_NULL != subscriptionItemInfo.ScheduleGroup)
  1137.         {
  1138.             hr = UpdateScheduleTrigger(&subscriptionItemInfo.ScheduleGroup, pTrigger);
  1139.         }
  1140.         else
  1141.         {
  1142.             hr = E_FAIL;
  1143.         }
  1144.     }
  1145.     if (FAILED(hr))
  1146.     {
  1147.         WCHAR wszSchedName[MAX_PATH];
  1148.         CreatePublisherScheduleNameW(wszSchedName, ARRAYSIZE(wszSchedName),
  1149.                                      pszName, NULL);
  1150.         hr = CreateSchedule(wszSchedName, SYNCSCHEDINFO_FLAGS_READONLY,
  1151.                             &subscriptionItemInfo.ScheduleGroup, pTrigger, TRUE);
  1152.         if (SUCCEEDED(hr) || (hr == SYNCMGR_E_NAME_IN_USE))
  1153.         {
  1154.             psi->SetSubscriptionItemInfo(&subscriptionItemInfo);
  1155.             hr = S_OK;
  1156.         }
  1157.         else
  1158.         {
  1159.             TraceMsg(TF_ALWAYS, "Error creating schedule - hr=0x%08x", hr);
  1160.         }
  1161.     }
  1162.     if (SUCCEEDED(hr))
  1163.     {
  1164.         SYNC_HANDLER_ITEM_INFO shii;
  1165.         shii.handlerID = CLSID_WebCheckOfflineSync;
  1166.         psi->GetCookie(&shii.itemID);
  1167.         shii.hIcon = NULL;
  1168.         MyStrToOleStrN(shii.wszItemName, ARRAYSIZE(shii.wszItemName), pszName);
  1169.         
  1170.         hr = AddScheduledItem(&shii, &subscriptionItemInfo.ScheduleGroup); 
  1171.     }
  1172.     return S_OK;
  1173. //    return hr;
  1174. }
  1175. HRESULT ReadProperties(POOEBuf pBuf)
  1176. {
  1177.     VARIANT var;
  1178.     HRESULT hr;
  1179.     ASSERT(pBuf);
  1180.     BOOL    bHasUNAME = TRUE;
  1181.     ISubscriptionItem *psi = NULL;
  1182.     ASSERT(NULL != pBuf);
  1183.     hr = SubscriptionItemFromCookie(FALSE, &pBuf->m_Cookie, &psi);
  1184.     if (SUCCEEDED(hr))
  1185.     {
  1186.         VariantInit(&var);
  1187.         if (pBuf->dwFlags & PROP_WEBCRAWL_URL)
  1188.         {
  1189.             hr = ReadVariant(psi, c_szPropURL, &var);
  1190.             if (SUCCEEDED(hr) && (var.vt == VT_BSTR))
  1191.             {
  1192.                 MyOleStrToStrN(pBuf->m_URL, MAX_URL, var.bstrVal);
  1193.             }
  1194.             else
  1195.             {
  1196.                 pBuf->m_URL[0] = (TCHAR)0;
  1197.             }
  1198.             VariantClear(&var);
  1199.         }
  1200.         if (pBuf->dwFlags & PROP_WEBCRAWL_NAME) 
  1201.         {
  1202.             hr = ReadVariant(psi, c_szPropName, &var);
  1203.             if (SUCCEEDED(hr) && (var.vt == VT_BSTR)) 
  1204.             {
  1205.                 MyOleStrToStrN(pBuf->m_Name, MAX_NAME, var.bstrVal);
  1206.             }
  1207.             else
  1208.             {
  1209.                 pBuf->m_Name[0] = (TCHAR)0;
  1210.             }
  1211.             VariantClear(&var);
  1212.         }
  1213.         if (pBuf->dwFlags & PROP_WEBCRAWL_UNAME)
  1214.         {
  1215.             hr = ReadVariant(psi, c_szPropCrawlUsername, &var);
  1216.             if (SUCCEEDED(hr) && (var.vt == VT_BSTR))
  1217.             {
  1218.                 MyOleStrToStrN(pBuf->username, MAX_USERNAME, var.bstrVal);
  1219.             }
  1220.             else
  1221.             {
  1222.                 pBuf->username[0] = (TCHAR)0;
  1223.                 bHasUNAME = FALSE;
  1224.             }
  1225.             VariantClear(&var);
  1226.         }
  1227.         if (pBuf->dwFlags & PROP_WEBCRAWL_DESKTOP)
  1228.         {
  1229.             hr = ReadVariant(psi, c_szPropDesktopComponent, &var);
  1230.             if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
  1231.             {
  1232.                 pBuf->bDesktop = TRUE;
  1233.             }
  1234.             else
  1235.             {
  1236.                 pBuf->bDesktop = FALSE;
  1237.             }
  1238.             VariantClear(&var);
  1239.         }
  1240.         if (pBuf->dwFlags & PROP_WEBCRAWL_CHANNEL)
  1241.         {
  1242.             hr = ReadVariant(psi, c_szPropChannel, &var);
  1243.             if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
  1244.             {
  1245.                 pBuf->bChannel = TRUE;
  1246.             }
  1247.             else
  1248.             {
  1249.                 pBuf->bChannel = FALSE;
  1250.             }
  1251.             VariantClear(&var);
  1252.         }
  1253.         if (pBuf->dwFlags & PROP_WEBCRAWL_GLEAM)
  1254.         {
  1255.             hr = ReadVariant(psi, c_szPropEnableShortcutGleam, &var);
  1256.             if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
  1257.             {
  1258.                 pBuf->bGleam = TRUE;
  1259.             }
  1260.             else
  1261.             {
  1262.                 pBuf->bGleam = FALSE;
  1263.             }
  1264.             VariantClear(&var);
  1265.         }
  1266.         if (pBuf->dwFlags & PROP_WEBCRAWL_CHANGESONLY)
  1267.         {
  1268.             hr = ReadVariant(psi, c_szPropCrawlChangesOnly, &var);
  1269.             if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
  1270.             {
  1271.                 pBuf->bChangesOnly = TRUE;
  1272.             }
  1273.             else 
  1274.             {
  1275.                 pBuf->bChangesOnly = FALSE;
  1276.             }
  1277.             VariantClear(&var);
  1278.         }
  1279.         if (pBuf->dwFlags & PROP_WEBCRAWL_CHANNELFLAGS)
  1280.         {
  1281.             hr = ReadVariant(psi, c_szPropChannelFlags, &var);
  1282.             if (SUCCEEDED(hr) && (var.vt == VT_I4))
  1283.             {
  1284.                 pBuf->fChannelFlags = var.lVal;
  1285.             }
  1286.             else 
  1287.             {
  1288.                 pBuf->fChannelFlags = 0;
  1289.             }
  1290.             VariantClear(&var);
  1291.         }
  1292.         if (pBuf->dwFlags & PROP_WEBCRAWL_EMAILNOTF)
  1293.         {
  1294.             hr = ReadVariant(psi, c_szPropEmailNotf, &var);
  1295.             if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
  1296.             {
  1297.                 pBuf->bMail = TRUE;
  1298.             }
  1299.             else
  1300.             {
  1301.                 pBuf->bMail = FALSE;
  1302.             }
  1303.             VariantClear(&var);
  1304.         }
  1305.         if ((pBuf->dwFlags & PROP_WEBCRAWL_PSWD) && bHasUNAME)
  1306.         {
  1307.             BSTR bstrVal = NULL;
  1308.             hr = ReadPassword(psi, &bstrVal);
  1309.             if (SUCCEEDED(hr) && bstrVal)
  1310.             {
  1311.                 MyOleStrToStrN(pBuf->password, MAX_PASSWORD, bstrVal);
  1312.             }
  1313.             else
  1314.             {
  1315.                 pBuf->password[0] = (TCHAR)0;
  1316.             }
  1317.             SAFEFREEBSTR(bstrVal);
  1318.         }
  1319.         if ((pBuf->dwFlags & PROP_WEBCRAWL_PSWD) || (pBuf->dwFlags & PROP_WEBCRAWL_UNAME)) {
  1320.             //bNeedPassword isn't stored in the property map... calculate it from the presence
  1321.             //of username/password.
  1322.             pBuf->bNeedPassword = pBuf->password[0] || pBuf->username[0];
  1323.         }
  1324.         if (pBuf->dwFlags & PROP_WEBCRAWL_STATUS)
  1325.         {
  1326.             hr = ReadVariant(psi, c_szPropStatusString, &var);
  1327.             if (SUCCEEDED(hr) && (var.vt == VT_BSTR))
  1328.             {
  1329.                 MyOleStrToStrN(pBuf->statusStr, MAX_STATUS, var.bstrVal);
  1330.             }
  1331.             else
  1332.             {
  1333.                 pBuf->statusStr[0] = (TCHAR)0;
  1334.             }
  1335.             VariantClear(&var);
  1336.             hr = ReadSCODE(psi, c_szPropStatusCode, &(pBuf->status));
  1337.             //  BUGBUG! What should we put here if we don't have last status?
  1338.             if (FAILED(hr))
  1339.             {
  1340.                 pBuf->status = S_OK;
  1341.             }
  1342.             VariantClear(&var);
  1343.         }
  1344.         //
  1345.         // Use the CompletionTime property if present and it is greater than
  1346.         // value in the NOTIFICATIONITEM structure.
  1347.         //
  1348.         if (pBuf->dwFlags & PROP_WEBCRAWL_LAST) 
  1349.         {
  1350.             CFileTime ft;
  1351.             hr = ReadVariant(psi, c_szPropCompletionTime, &var);
  1352.             if (SUCCEEDED(hr) && (var.vt == VT_DATE))
  1353.             {
  1354.                 VariantTimeToFileTime(var.date, ft);
  1355.                 if (ft > pBuf->m_LastUpdated)
  1356.                 {
  1357.                     pBuf->m_LastUpdated = ft;
  1358.                 }
  1359.             }
  1360.         }
  1361.         if (pBuf->dwFlags & PROP_WEBCRAWL_LEVEL)
  1362.         {
  1363.             hr = ReadDWORD(psi, c_szPropCrawlLevels, (DWORD *)&(pBuf->m_RecurseLevels));
  1364.             if (FAILED(hr))
  1365.             {
  1366.                 pBuf->m_RecurseLevels = 0;
  1367.             }
  1368.         }
  1369.         if (pBuf->dwFlags & PROP_WEBCRAWL_FLAGS)
  1370.         {
  1371.             hr = ReadDWORD(psi, c_szPropCrawlFlags, (DWORD *)&(pBuf->m_RecurseFlags));
  1372.             if (FAILED(hr))
  1373.             {
  1374.                 pBuf->m_RecurseFlags = 0;   //  Minimal memory usage.
  1375.             }
  1376.         }
  1377.         if (pBuf->dwFlags & PROP_WEBCRAWL_SIZE)
  1378.         {
  1379.             hr = ReadDWORD(psi, c_szPropCrawlMaxSize, (DWORD *)&(pBuf->m_SizeLimit));
  1380.             if (FAILED(hr))
  1381.             {
  1382.                 pBuf->m_SizeLimit = 0;
  1383.             }
  1384.         }
  1385.         if (pBuf->dwFlags & PROP_WEBCRAWL_ACTUALSIZE)
  1386.         {
  1387.             hr = ReadDWORD(psi, c_szPropCrawlActualSize, (DWORD *)&(pBuf->m_ActualSize));
  1388.             if (FAILED(hr))
  1389.             {
  1390.                 pBuf->m_ActualSize = 0;
  1391.             }
  1392.         }
  1393.         SUBSCRIPTIONITEMINFO sii;
  1394.         sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
  1395.         if (SUCCEEDED(psi->GetSubscriptionItemInfo(&sii)))
  1396.         {
  1397.             pBuf->grfTaskTrigger = sii.dwFlags;
  1398.         }
  1399.         psi->Release();
  1400.     }
  1401.     // BUGBUG: Need to support c_szPropEnableShortcutGleam here.
  1402.     // BUGBUG: Need to support c_szPropEnableShortcutGleam here.
  1403.     
  1404.     return S_OK;
  1405. }
  1406. // If url is NULL, no need to compare.
  1407. HRESULT LoadWithCookie(LPCTSTR pszURL, POOEBuf pBuf, DWORD *pdwBufferSize, SUBSCRIPTIONCOOKIE *pCookie)
  1408. {
  1409.     HRESULT hr = LoadOOEntryInfo(pBuf, pCookie, pdwBufferSize);
  1410.     if (SUCCEEDED(hr) && pszURL)
  1411.     {
  1412.         if (UrlCompare(pBuf->m_URL, pszURL, TRUE))
  1413.         {
  1414.             TraceMsg(TF_ALWAYS, "Mismatched cookie/URL in LoadWithCookie");
  1415.             hr = E_FAIL;      //  Mismatched cookie!
  1416.         }
  1417.     }
  1418.     return hr;
  1419. }
  1420. HRESULT ReadCookieFromInetDB(LPCTSTR pszURL, SUBSCRIPTIONCOOKIE *pCookie)
  1421. {
  1422.     ASSERT(pszURL && pCookie);
  1423.     PROPVARIANT propCookie;
  1424.     PropVariantInit(&propCookie);
  1425.     HRESULT hr = FindURLProps(pszURL, &propCookie);
  1426.     if (SUCCEEDED(hr) && (propCookie.vt == VT_LPWSTR))
  1427.     {
  1428.         hr = CLSIDFromString(propCookie.pwszVal, pCookie);
  1429.     }
  1430.     PropVariantClear(&propCookie);
  1431.     //  If we couldn't find it, use a brute force approach
  1432.     if (S_OK != hr)
  1433.     {
  1434.         CEnumSubscription *pes = new CEnumSubscription;
  1435.         if (NULL != pes)
  1436.         {
  1437.             if (SUCCEEDED(pes->Initialize(0)))
  1438.             {
  1439.                 SUBSCRIPTIONCOOKIE cookie;
  1440.                 BOOL bFound = FALSE;
  1441.                 
  1442.                 while (!bFound && (S_OK == pes->Next(1, &cookie, NULL)))
  1443.                 {
  1444.                     ISubscriptionItem *psi;
  1445.                     
  1446.                     if (SUCCEEDED(SubscriptionItemFromCookie(FALSE, &cookie, &psi)))
  1447.                     {
  1448.                         LPTSTR pszCurURL;
  1449.                         if (SUCCEEDED(ReadTSTR(psi, c_szPropURL, &pszCurURL)))
  1450.                         {
  1451.                             bFound = (StrCmpI(pszCurURL, pszURL) == 0);
  1452.                             CoTaskMemFree(pszCurURL);
  1453.                         }
  1454.                         psi->Release();
  1455.                     }
  1456.                 }
  1457.                 if (bFound)
  1458.                 {
  1459.                     WriteCookieToInetDB(pszURL, &cookie, FALSE);
  1460.                     *pCookie = cookie;
  1461.                     hr = S_OK;
  1462.                 }
  1463.             }
  1464.             pes->Release();
  1465.         }
  1466.     }
  1467.     return hr;
  1468. }
  1469. HRESULT LoadSubscription(LPCTSTR url, LPMYPIDL *ppidl)
  1470. {
  1471.     HRESULT hr;
  1472.     POOEntry pooe = NULL;
  1473.     OOEBuf  ooeBuf;
  1474.     DWORD   dwBufferSize;
  1475.     SUBSCRIPTIONCOOKIE cookie;
  1476.     hr = ReadCookieFromInetDB(url, &cookie);
  1477.     if (S_OK == hr)
  1478.     {
  1479.         hr = LoadWithCookie(url, &ooeBuf, &dwBufferSize, &cookie);
  1480.         if (hr == S_OK)
  1481.         {
  1482.             *ppidl = COfflineFolderEnum::NewPidl(dwBufferSize);
  1483.             if (!(*ppidl))
  1484.             {
  1485.                 return E_OUTOFMEMORY;
  1486.             }
  1487.             pooe = &((*ppidl)->ooe);
  1488.             CopyToMyPooe(&ooeBuf, pooe);
  1489.         }
  1490.         else 
  1491.         {
  1492.             WriteCookieToInetDB(url, NULL, TRUE);
  1493.             hr = E_FAIL;
  1494.         }
  1495.     }
  1496.     else
  1497.     {
  1498.         hr = E_FAIL;
  1499.     }
  1500.     return hr;
  1501. }
  1502.  
  1503. // KENSY: This needs to work like GetDefaultInfo
  1504. HRESULT GetDefaultOOEBuf(OOEBuf * pBuf, SUBSCRIPTIONTYPE subType)
  1505. {
  1506.     ASSERT(pBuf);
  1507.     ASSERT(IS_VALID_SUBSCRIPTIONTYPE(subType));
  1508.     memset((void *)pBuf, 0, sizeof(OOEBuf));
  1509.     pBuf->dwFlags = PROP_WEBCRAWL_ALL;
  1510.     pBuf->m_RecurseLevels = DEFAULTLEVEL;
  1511.     pBuf->m_RecurseFlags = DEFAULTFLAGS;
  1512.     pBuf->m_Priority = AGENT_PRIORITY_NORMAL;
  1513.     if (subType == SUBSTYPE_CHANNEL || subType == SUBSTYPE_DESKTOPCHANNEL)    
  1514.     {
  1515.         pBuf->clsidDest = CLSID_ChannelAgent;
  1516.         pBuf->fChannelFlags = CHANNEL_AGENT_PRECACHE_ALL | CHANNEL_AGENT_DYNAMIC_SCHEDULE;
  1517.     } 
  1518.     else
  1519.     {
  1520.         pBuf->clsidDest = CLSID_WebCrawlerAgent;
  1521.     }
  1522.     pBuf->bDesktop = (subType == SUBSTYPE_DESKTOPCHANNEL || subType == SUBSTYPE_DESKTOPURL);
  1523.     pBuf->bChannel = (subType == SUBSTYPE_CHANNEL || subType == SUBSTYPE_DESKTOPCHANNEL);
  1524.     pBuf->bGleam = !(pBuf->bDesktop);
  1525.     pBuf->m_LastUpdated = 0;
  1526.     pBuf->m_NextUpdate = 0;
  1527.     //  BUGBUG: Is this what we want?  IE 4 was DAILY.
  1528.     //  Default to not changing the schedule settings -- if it's already subscribed
  1529.     //  we won't blast anything and if it's not already subscribed then it will
  1530.     //  just be manual.
  1531.     pBuf->groupCookie = NOOP_SCHEDULE_COOKIE;       
  1532.     pBuf->grfTaskTrigger = TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET |     // Default to not autodial
  1533.                            TASK_FLAG_START_ONLY_IF_IDLE;               // and to idle time
  1534.     return S_OK;
  1535. }
  1536. HRESULT CreateSubscriptionFromOOEBuf(OOEBuf *pBuf, LPMYPIDL *ppidl)
  1537. {
  1538.     HRESULT hr;
  1539.     DWORD dwBufferSize = BufferSize(pBuf);
  1540.     *ppidl = COfflineFolderEnum::NewPidl(dwBufferSize);
  1541.     if (!(*ppidl))
  1542.     {
  1543.         return E_OUTOFMEMORY;
  1544.     }
  1545.     POOEntry pooe = &((*ppidl)->ooe);
  1546.     CopyToMyPooe(pBuf, pooe);
  1547.     //  See if the caller has already given us a cookie
  1548.     if (GUID_NULL == pooe->m_Cookie)
  1549.     {
  1550.         //  Nope, see if we have one already
  1551.         ReadCookieFromInetDB(URL(pooe), &(pooe->m_Cookie));
  1552.         if (GUID_NULL == pooe->m_Cookie)
  1553.         {
  1554.             //  Nope, so create one
  1555.             CreateCookie(&pooe->m_Cookie);
  1556.         }
  1557.     }
  1558.     WriteCookieToInetDB(URL(pooe), &(pooe->m_Cookie), FALSE);
  1559.     WCHAR wszURL[INTERNET_MAX_URL_LENGTH];
  1560.     SUBSCRIPTIONITEMINFO sii;
  1561.     sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
  1562.     sii.dwFlags = 0;
  1563.     sii.dwPriority = 0;
  1564.     sii.ScheduleGroup = CLSID_NULL;
  1565.     sii.clsidAgent = pooe->clsidDest;
  1566.     MyStrToOleStrN(wszURL, ARRAYSIZE(wszURL), URL(pooe));
  1567.     hr = AddUpdateSubscription(&(pooe->m_Cookie), &sii, wszURL, 0, NULL, NULL);
  1568.     if (SUCCEEDED(hr))
  1569.     {
  1570.         hr = WriteProperties(pooe);
  1571.         if (SUCCEEDED(hr))
  1572.         {
  1573.             ISubscriptionItem *psi;
  1574.             hr = SubscriptionItemFromCookie(TRUE, &pooe->m_Cookie, &psi);
  1575.             if (SUCCEEDED(hr))
  1576.             {
  1577.                 SUBSCRIPTIONSCHEDULE subGroup = GetGroup(pooe);
  1578.                 SUBSCRIPTIONTYPE   subType = GetItemCategory(pooe);
  1579.                 if (subGroup == SUBSSCHED_AUTO)
  1580.                 {
  1581.                     if (subType != SUBSTYPE_CHANNEL && subType != SUBSTYPE_DESKTOPCHANNEL)
  1582.                     {
  1583.                         hr = AddIt(psi, pooe, SUBSSCHED_DAILY);
  1584.                     }
  1585.                     else
  1586.                     {
  1587.                         if (pooe->m_Trigger.cbTriggerSize == sizeof(TASK_TRIGGER))
  1588.                         {
  1589.                             hr = ScheduleIt(psi, NAME(pooe), &pooe->m_Trigger);
  1590.                             pooe->groupCookie = CLSID_NULL;
  1591.                         }
  1592.                         else
  1593.                         {
  1594.                             hr = AddIt(psi, pooe, SUBSSCHED_DAILY);
  1595.                         }
  1596.                     }
  1597.                 }
  1598.                 else 
  1599.                 {
  1600.                     hr = AddIt(psi, pooe, subGroup);
  1601.                 }
  1602.                 psi->Release();
  1603.             }
  1604.         }
  1605.     }
  1606.     if (SUCCEEDED(hr))
  1607.     {
  1608.         FireSubscriptionEvent(SUBSNOTF_CREATE, &pooe->m_Cookie);
  1609.     }
  1610.     else 
  1611.     {
  1612.         TraceMsg(TF_ALWAYS, "Failed to add new subscription");
  1613.         TraceMsg(TF_ALWAYS, "thr = 0x%x", hr);
  1614.         COfflineFolderEnum::FreePidl(*ppidl);
  1615.         *ppidl = NULL;
  1616.     }
  1617.     return hr;
  1618. }
  1619. HRESULT SendUpdateRequests(HWND hwnd, CLSID * arrClsid, UINT count)
  1620. {
  1621.     ISubscriptionMgr2 *pSubsMgr2;
  1622.     HRESULT hr;
  1623.     hr = CoInitialize(NULL);
  1624.     if (SUCCEEDED(hr))
  1625.     {
  1626.         hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, 
  1627.                               IID_ISubscriptionMgr2, (void**)&pSubsMgr2);
  1628.         if (SUCCEEDED(hr))
  1629.         {
  1630.             SUBSCRIPTIONCOOKIE *pCookies = NULL;
  1631.             ULONG nItemsToRun = count;
  1632.             if (NULL == arrClsid)
  1633.             {
  1634.                 IEnumSubscription *pes;
  1635.                 hr = pSubsMgr2->EnumSubscriptions(0, &pes);
  1636.                 if (SUCCEEDED(hr))
  1637.                 {
  1638.                     ASSERT(NULL != pes);
  1639.                     pes->GetCount(&nItemsToRun);
  1640.                     if (nItemsToRun > 0)
  1641.                     {
  1642.                         pCookies = new SUBSCRIPTIONCOOKIE[nItemsToRun];
  1643.                         if (NULL != pCookies)
  1644.                         {
  1645.                             hr = pes->Next(nItemsToRun, pCookies, &nItemsToRun);
  1646.                         }
  1647.                         else
  1648.                         {
  1649.                             hr = E_OUTOFMEMORY;
  1650.                         }
  1651.                     }
  1652.                     pes->Release();
  1653.                 }
  1654.             }
  1655.             else
  1656.             {
  1657.                 pCookies = arrClsid;
  1658.             }
  1659.             if (SUCCEEDED(hr))
  1660.             {
  1661.                 hr = pSubsMgr2->UpdateItems(0, nItemsToRun, pCookies);
  1662.             }
  1663.             if ((NULL == arrClsid) && (NULL != pCookies))
  1664.             {
  1665.                 delete [] pCookies;
  1666.             }
  1667.             pSubsMgr2->Release();
  1668.         }
  1669.         CoUninitialize();
  1670.     }
  1671.     return hr;
  1672. }
  1673. HRESULT DoDeleteSubscription(POOEntry pooe)
  1674. {
  1675.     HRESULT hr;
  1676.     ISubscriptionItem *psi;
  1677.     ASSERT(NULL != pooe);
  1678.     hr = SubscriptionItemFromCookie(FALSE, &pooe->m_Cookie, &psi);
  1679.     if (SUCCEEDED(hr))
  1680.     {
  1681.         WritePassword(psi, NULL);
  1682.         hr = DoDeleteSubscriptionItem(&pooe->m_Cookie, TRUE);
  1683.         if (SUCCEEDED(hr) && (GetItemCategory(pooe) != SUBSTYPE_EXTERNAL))
  1684.         {
  1685.             WriteCookieToInetDB(URL(pooe), NULL, TRUE);
  1686.         }
  1687.     }
  1688.     return hr;
  1689. }
  1690. HRESULT PersistUpdate(POOEntry pooe, BOOL bCreate)
  1691. {
  1692.     HRESULT hr;
  1693.     ISubscriptionItem *psi;
  1694.     
  1695.     hr = SubscriptionItemFromCookie(bCreate, &(pooe->m_Cookie), &psi);
  1696.     if (SUCCEEDED(hr))
  1697.     {
  1698.         SUBSCRIPTIONITEMINFO sii = { sizeof(SUBSCRIPTIONITEMINFO) };
  1699.         hr = psi->GetSubscriptionItemInfo(&sii);
  1700.         if (SUCCEEDED(hr) || bCreate)
  1701.         {
  1702.             sii.clsidAgent = pooe->clsidDest;
  1703.             hr = psi->SetSubscriptionItemInfo(&sii);
  1704.             if (SUCCEEDED(hr))
  1705.             {
  1706.                 hr = WritePropertiesToItem(pooe, psi);
  1707.                 
  1708.                 if (SUCCEEDED(hr) && IsNativeAgent(pooe->clsidDest))
  1709.                 {
  1710.                     WriteCookieToInetDB(URL(pooe), &(pooe->m_Cookie), FALSE);
  1711.                 }
  1712.             }
  1713.         }
  1714.         // REVIEW: should we delete on failure here?
  1715.         psi->Release();
  1716.     }
  1717.     return hr;
  1718. }
  1719. #ifdef NEWSCHED_AUTONAME
  1720. void NewSched_AutoNameHelper(HWND hDlg)
  1721. {
  1722.     TCHAR szDays[16];
  1723.     TCHAR szTime[128];
  1724.     TCHAR szFormat[MAX_PATH];
  1725.     TCHAR szSchedName[MAX_PATH];
  1726.     LPTSTR lpArguments[2];
  1727.     BOOL bTranslate;
  1728.     int nDays = GetDlgItemInt(hDlg, IDC_SCHEDULE_DAYS, &bTranslate, FALSE);
  1729.     if (MLLoadString((nDays == 1) ? IDS_SCHED_FORMAT_DAILY : IDS_SCHED_FORMAT, 
  1730.         szFormat, ARRAYSIZE(szFormat)))
  1731.     {
  1732.         TCHAR szTimeFormat[32];
  1733.         SYSTEMTIME st;
  1734.         DateTime_GetSystemtime(GetDlgItem(hDlg, IDC_SCHEDULE_TIME), &st);
  1735.         UpdateTimeFormat(szTimeFormat, ARRAYSIZE(szTimeFormat));
  1736.         GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st,
  1737.                       szTimeFormat, szTime, ARRAYSIZE(szTime));
  1738.         GetDlgItemText(hDlg, IDC_SCHEDULE_DAYS, szDays, ARRAYSIZE(szDays));
  1739.         lpArguments[0] = szDays;
  1740.         lpArguments[1] = szTime;
  1741.         if (FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1742.                           szFormat, 0, 0, szSchedName, ARRAYSIZE(szSchedName),
  1743.                           (va_list *)&lpArguments[0]))
  1744.         {
  1745.             SetDlgItemText(hDlg, IDC_SCHEDULE_NAME, szSchedName);
  1746.         }
  1747.     }
  1748. }
  1749. #endif
  1750. BOOL NewSched_ResolveNameConflictHelper(HWND hDlg, TASK_TRIGGER *pTrig, 
  1751.                                         SYNCSCHEDULECOOKIE *pSchedCookie)
  1752. {
  1753.     BOOL bResult;
  1754.     SYSTEMTIME st;
  1755.     TCHAR szSchedName[MAX_PATH];
  1756.     GetDlgItemText(hDlg, IDC_SCHEDULE_NAME, szSchedName, ARRAYSIZE(szSchedName));
  1757.     TrimWhiteSpace(szSchedName);
  1758.     if (szSchedName[0] != 0)
  1759.     {
  1760.         bResult = TRUE;
  1761.             
  1762.         memset(pTrig, 0, sizeof(TASK_TRIGGER));
  1763.         pTrig->cbTriggerSize = sizeof(TASK_TRIGGER);
  1764.         GetLocalTime(&st);
  1765.         pTrig->wBeginYear = st.wYear;
  1766.         pTrig->wBeginMonth = st.wMonth;
  1767.         pTrig->wBeginDay = st.wDay;
  1768.         DateTime_GetSystemtime(GetDlgItem(hDlg, IDC_SCHEDULE_TIME), &st);
  1769.         pTrig->wStartHour = st.wHour;
  1770.         pTrig->wStartMinute = st.wMinute;
  1771.         pTrig->TriggerType = TASK_TIME_TRIGGER_DAILY;
  1772.         BOOL bTranslated;
  1773.         pTrig->Type.Daily.DaysInterval = (WORD)GetDlgItemInt(hDlg, IDC_SCHEDULE_DAYS, &bTranslated, FALSE);
  1774.         int iConflictResult = HandleScheduleNameConflict(szSchedName, 
  1775.                                                          pTrig,
  1776.                                                          hDlg,
  1777.                                                          pSchedCookie);
  1778.         switch (iConflictResult)
  1779.         {
  1780.             case CONFLICT_NONE:
  1781.                 ASSERT(GUID_NULL == *pSchedCookie);
  1782.                 break;
  1783.             case CONFLICT_RESOLVED_USE_NEW:
  1784.                 ASSERT(GUID_NULL != *pSchedCookie);
  1785.                 break;
  1786.             case CONFLICT_RESOLVED_USE_OLD:
  1787.                 ASSERT(GUID_NULL == *pSchedCookie);
  1788.                 pTrig->cbTriggerSize = 0;
  1789.                 break;
  1790.             case CONFLICT_UNRESOLVED:
  1791.                 bResult = FALSE;
  1792.                 break;
  1793.         }
  1794.     }
  1795.     else
  1796.     {
  1797.         SGMessageBox(hDlg, IDS_EMPTY_SCHEDULE_NAME, MB_OK | MB_ICONWARNING);
  1798.         bResult = FALSE;
  1799.     }
  1800.     return bResult;
  1801. }
  1802. void NewSched_CreateScheduleHelper(HWND hDlg, TASK_TRIGGER *pTrig,
  1803.                                    SYNCSCHEDULECOOKIE *pSchedCookie)
  1804. {
  1805.     HRESULT hr;
  1806.     
  1807.     if (GUID_NULL == *pSchedCookie)
  1808.     {
  1809.         //  Create new schedule
  1810.         TCHAR szSchedName[MAX_PATH];
  1811.         WCHAR wszSchedName[MAX_PATH];
  1812.         DWORD dwSyncScheduleFlags = 
  1813.             (IsDlgButtonChecked(hDlg, IDC_WIZ_SCHEDULE_AUTOCONNECT) == BST_CHECKED) 
  1814.                  ? SYNCSCHEDINFO_FLAGS_AUTOCONNECT : 0;
  1815.         GetDlgItemText(hDlg, IDC_SCHEDULE_NAME, szSchedName, ARRAYSIZE(szSchedName));
  1816.         MyStrToOleStrN(wszSchedName, ARRAYSIZE(wszSchedName), szSchedName);
  1817.         hr = CreateSchedule(wszSchedName, dwSyncScheduleFlags, pSchedCookie, pTrig, FALSE);
  1818.         ASSERT(SUCCEEDED(hr));
  1819.     }
  1820.     else if (sizeof(TASK_TRIGGER) == pTrig->cbTriggerSize)
  1821.     {
  1822.         //  Update existing schedule with new task trigger
  1823.         hr = UpdateScheduleTrigger(pSchedCookie, pTrig);
  1824.         ASSERT(SUCCEEDED(hr));
  1825.     }
  1826.     else
  1827.     {
  1828.         //  Use existing schedule without munging it
  1829.     }
  1830. }
  1831. void NewSched_SetDefaultScheduleName(HWND hDlg)
  1832. {
  1833.     if (SUCCEEDED(CoInitialize(NULL)))
  1834.     {   
  1835.         ISyncScheduleMgr *pSyncScheduleMgr;
  1836.         
  1837.         if (SUCCEEDED(CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL, 
  1838.                                        IID_ISyncScheduleMgr, 
  1839.                                        (void **)&pSyncScheduleMgr)))
  1840.         {
  1841.             SYNCSCHEDULECOOKIE schedCookie;
  1842.             ISyncSchedule *pSyncSchedule;
  1843.             if (SUCCEEDED(pSyncScheduleMgr->CreateSchedule(L"", 0, &schedCookie, &pSyncSchedule)))
  1844.             {
  1845.                 WCHAR wszSchedName[MAX_PATH];
  1846.                 DWORD cchSchedName = ARRAYSIZE(wszSchedName);
  1847.                 if (SUCCEEDED(pSyncSchedule->GetScheduleName(&cchSchedName, wszSchedName)))
  1848.                 {
  1849.                     TCHAR szSchedName[MAX_PATH];
  1850.                     MyOleStrToStrN(szSchedName, ARRAYSIZE(szSchedName), wszSchedName);
  1851.                     SetDlgItemText(hDlg, IDC_SCHEDULE_NAME, szSchedName);
  1852.                 }
  1853.                 pSyncSchedule->Release();
  1854.             }
  1855.             pSyncScheduleMgr->Release();
  1856.         }
  1857.         CoUninitialize();
  1858.     }
  1859. }
  1860. void NewSched_OnInitDialogHelper(HWND hDlg)
  1861. {
  1862.     SYSTEMTIME st;
  1863.     GetLocalTime(&st);
  1864.     Edit_LimitText(GetDlgItem(hDlg, IDC_SCHEDULE_NAME), MAX_PATH - 1);
  1865.     Edit_LimitText(GetDlgItem(hDlg, IDC_SCHEDULE_DAYS), 2);
  1866.     SendMessage(GetDlgItem(hDlg, IDC_SCHEDULE_DAYS_SPIN), 
  1867.                 UDM_SETRANGE, 0, MAKELONG(99, 1));
  1868.     SendMessage(GetDlgItem(hDlg, IDC_SCHEDULE_DAYS_SPIN), UDM_SETPOS, 0, 1);
  1869.     HWND hwndTimePicker = GetDlgItem(hDlg, IDC_SCHEDULE_TIME);
  1870.     TCHAR szTimeFormat[32];
  1871.     UpdateTimeFormat(szTimeFormat, ARRAYSIZE(szTimeFormat));
  1872.     DateTime_SetSystemtime(hwndTimePicker, GDT_VALID, &st);
  1873.     DateTime_SetFormat(hwndTimePicker, szTimeFormat);
  1874.     NewSched_SetDefaultScheduleName(hDlg);
  1875. }
  1876. int KeepSpinNumberInRange(HWND hdlg, int idEdit, int idSpin, int minVal, int maxVal)
  1877. {
  1878.     BOOL bTranslate;
  1879.     int val = GetDlgItemInt(hdlg, idEdit, &bTranslate, FALSE);
  1880.     if (!bTranslate || (val  < minVal) || (val > maxVal))
  1881.     {   
  1882.         //  We have a problem, query the spin control
  1883.         val = LOWORD(SendDlgItemMessage(hdlg, idSpin, UDM_GETPOS, 0, 0));
  1884.         val = max(minVal, min(maxVal, val));
  1885.         SetDlgItemInt(hdlg, idEdit, val, FALSE);
  1886.     }
  1887.     return val;
  1888. }
  1889. void SetPropSheetFlags(POOEBuf pBuf, BOOL bSet, DWORD dwPropSheetFlags)
  1890. {
  1891.     if (bSet)
  1892.     {
  1893.         pBuf->m_dwPropSheetFlags |= dwPropSheetFlags;
  1894.     }
  1895.     else
  1896.     {
  1897.         pBuf->m_dwPropSheetFlags &= ~dwPropSheetFlags;
  1898.     }
  1899. }
  1900. HRESULT FindURLProps(LPCTSTR m_URL, PROPVARIANT * pVarInfo)
  1901. {
  1902.     HRESULT hr; 
  1903.     hr = IntSiteHelper(m_URL, &c_rgPropRead[PROP_SUBSCRIPTION], pVarInfo, 1, FALSE);
  1904.     return hr;
  1905. }
  1906. HRESULT LoadOOEntryInfo(POOEBuf pBuf, SUBSCRIPTIONCOOKIE *pCookie, DWORD *pdwSize)
  1907. {
  1908.     HRESULT hr;
  1909.     if (!pBuf || !pCookie || !pdwSize)
  1910.     {
  1911.         TraceMsg(TF_ALWAYS, "Invalid ARG (1/2/3) %x %x", pBuf, pCookie, pdwSize);
  1912.         return E_INVALIDARG;
  1913.     }
  1914.     ISubscriptionItem *psi;
  1915.     hr = SubscriptionItemFromCookie(FALSE, pCookie, &psi);
  1916.     if (SUCCEEDED(hr))
  1917.     {
  1918.         SUBSCRIPTIONITEMINFO sii;
  1919.         
  1920.         sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
  1921.         hr = psi->GetSubscriptionItemInfo(&sii);
  1922.         if (SUCCEEDED(hr))
  1923.         {       
  1924.             ZeroMemory((void *)pBuf, sizeof(OOEBuf));
  1925.             pBuf->m_Cookie = *pCookie;
  1926.         //  TODO: resolve scheduling goo!
  1927.         //    pBuf->groupCookie = pItem->groupCookie;
  1928.         //    pBuf->grfTaskTrigger = pItem->TaskData.dwTaskFlags;
  1929.         /*    if (pItem->groupCookie == CLSID_NULL)   {
  1930.                 pBuf->m_Trigger = pItem->TaskTrigger;
  1931.                 if (pBuf->m_Trigger.cbTriggerSize != sizeof(TASK_TRIGGER))  {
  1932.                     ASSERT(0);
  1933.                     return E_INVALIDARG;
  1934.                 }
  1935.             } else  {
  1936.                 pBuf->m_Trigger.cbTriggerSize = 0;  //  Invalid
  1937.             }
  1938.         */
  1939.             pBuf->clsidDest = sii.clsidAgent;
  1940.             if (!IsNativeAgent(sii.clsidAgent))
  1941.             {
  1942.                 pBuf->dwFlags = PROP_WEBCRAWL_EXTERNAL;
  1943.             }
  1944.             else
  1945.             {
  1946.                 pBuf->dwFlags = PROP_WEBCRAWL_ALL; 
  1947.             }
  1948.             hr = ReadProperties(pBuf);
  1949.             *pdwSize = BufferSize(pBuf);
  1950.         }
  1951.         psi->Release();
  1952.     }
  1953.     return hr;
  1954. }
  1955. /////////////////////////////////////////////////
  1956. //
  1957. //  SaveBufferChange
  1958. //      newBuf: [in/out]
  1959. /////////////////////////////////////////////////
  1960. HRESULT SaveBufferChange(POOEBuf newBuf, BOOL bCreate)
  1961. {
  1962.     HRESULT hr;
  1963.     DWORD   dwSize;
  1964.     POOEntry pooe;
  1965.     LPMYPIDL newPidl;
  1966.     ASSERT (newBuf);
  1967.     if (newBuf->dwFlags == 0)
  1968.         return S_OK;
  1969.     dwSize = BufferSize(newBuf);
  1970.     newPidl = COfflineFolderEnum::NewPidl(dwSize);
  1971.     if (!newPidl)
  1972.         return E_OUTOFMEMORY;
  1973.     pooe = &(newPidl->ooe);                
  1974.     CopyToMyPooe(newBuf, pooe);
  1975.     newBuf->dwFlags = 0;
  1976.     hr = PersistUpdate(pooe, bCreate);
  1977.     if (SUCCEEDED(hr))  {
  1978.         DWORD dwPropSheetFlags = newBuf->m_dwPropSheetFlags; //  Preserve prop sheet flags
  1979.         
  1980.         hr = LoadWithCookie(URL(pooe), newBuf, &dwSize, &(pooe->m_Cookie));
  1981.         newBuf->m_dwPropSheetFlags = dwPropSheetFlags;  //  restore 
  1982.         newBuf->dwFlags = 0;
  1983.         if (hr == S_OK)  {
  1984.             COfflineFolderEnum::FreePidl(newPidl);
  1985.             newPidl = COfflineFolderEnum::NewPidl(dwSize);
  1986.             if (!(newPidl))  {
  1987.                 return E_OUTOFMEMORY;
  1988.             }
  1989.             pooe = &(newPidl->ooe);
  1990.             CopyToMyPooe(newBuf, pooe);
  1991.         }
  1992.         _GenerateEvent(SHCNE_UPDATEITEM, (LPITEMIDLIST)newPidl, NULL);
  1993.     }
  1994.     COfflineFolderEnum::FreePidl(newPidl);
  1995.     return hr;
  1996. }
  1997. //////////////////////////////////////////////////////////////////////////
  1998. //////////////////////////////////////////////////////////////////////////
  1999. //
  2000. // IntSiteHelper
  2001. //
  2002. // pszURL               url to read/write props for
  2003. // pPropspec            properties to read or write
  2004. // pReadPropvar         where to store or get properties
  2005. // uPropVarArraySize    number of properties
  2006. // fWrite               read/write flag
  2007. //
  2008. HRESULT IntSiteHelper(LPCTSTR pszURL, const PROPSPEC *pPropspec,
  2009.         PROPVARIANT *pPropvar, UINT uPropVarArraySize, BOOL fWrite)
  2010. {
  2011.     HRESULT                     hr;
  2012.     IUniformResourceLocator *   purl = NULL;
  2013.     IPropertySetStorage *       ppropsetstg = NULL; // init to keep compiler happy
  2014.     IPropertyStorage *          ppropstg = NULL; // init to keep compiler happy
  2015.     hr = SHCoCreateInstance(NULL, &CLSID_InternetShortcut, NULL, 
  2016.             IID_IUniformResourceLocator, (LPVOID*)&purl);
  2017.     if(SUCCEEDED(hr)) {
  2018.         hr = purl->SetURL(pszURL, 0);
  2019.     }
  2020.     if(SUCCEEDED(hr)) {
  2021.         hr = purl->QueryInterface(IID_IPropertySetStorage,
  2022.                 (LPVOID *)&ppropsetstg);
  2023.     }
  2024.     if(SUCCEEDED(hr)) {
  2025.         hr = ppropsetstg->Open(FMTID_InternetSite, STGM_READWRITE, &ppropstg);
  2026.         ppropsetstg->Release();
  2027.     }
  2028.     if(SUCCEEDED(hr)) {
  2029.         if(fWrite) {
  2030.             hr = ppropstg->WriteMultiple(uPropVarArraySize, pPropspec,
  2031.                             pPropvar, 0);
  2032.             ppropstg->Commit(STGC_DEFAULT);
  2033.         } else {
  2034.             hr = ppropstg->ReadMultiple(uPropVarArraySize, pPropspec,
  2035.                             pPropvar);
  2036.         }
  2037.         ppropstg->Release();
  2038.     }
  2039.     if(purl)
  2040.         purl->Release();
  2041.     return hr;
  2042. }
  2043. // CODE FROM SYNCMGR SOURCES.
  2044. //
  2045. // Local constants
  2046. // 
  2047. // DEFAULT_TIME_FORMAT - what to use if there's a problem getting format
  2048. //                       from system.
  2049. //
  2050. #define ARRAYLEN(a) (sizeof(a) / sizeof((a)[0]))
  2051. #define DEFAULT_TIME_FORMAT         TEXT("hh:mm tt")
  2052. #define GET_LOCALE_INFO(lcid)                           
  2053.         {                                               
  2054.             cch = GetLocaleInfo(LOCALE_USER_DEFAULT,    
  2055.                                 (lcid),                 
  2056.                                 tszScratch,             
  2057.                                 ARRAYLEN(tszScratch));  
  2058.             if (!cch)                                   
  2059.             {                                           
  2060.                 break;                                  
  2061.             }                                           
  2062.         }
  2063. //+--------------------------------------------------------------------------
  2064. //
  2065. //  Function:   UpdateTimeFormat
  2066. //
  2067. //  Synopsis:   Construct a time format containing hour and minute for use
  2068. //              with the date picker control.
  2069. //
  2070. //  Arguments:  [tszTimeFormat] - buffer to fill with time format
  2071. //              [cchTimeFormat] - size in chars of buffer
  2072. //
  2073. //  Modifies:   *[tszTimeFormat]
  2074. //
  2075. //  History:    11-18-1996   DavidMun   Created
  2076. //
  2077. //  Notes:      This is called on initialization and for wininichange
  2078. //              processing.
  2079. //
  2080. //---------------------------------------------------------------------------
  2081. void 
  2082. UpdateTimeFormat(
  2083.         LPTSTR tszTimeFormat, 
  2084.         ULONG  cchTimeFormat)
  2085. {
  2086.     ULONG cch;
  2087.     TCHAR tszScratch[80];
  2088.     BOOL  fAmPm = FALSE;
  2089.     BOOL  fAmPmPrefixes = FALSE;
  2090.     BOOL  fLeadingZero = FALSE;
  2091.     do
  2092.     {
  2093.         GET_LOCALE_INFO(LOCALE_ITIME);
  2094.         fAmPm = (*tszScratch == TEXT('0'));
  2095.         if (fAmPm)
  2096.         {
  2097.             GET_LOCALE_INFO(LOCALE_ITIMEMARKPOSN);
  2098.             fAmPmPrefixes = (*tszScratch == TEXT('1'));
  2099.         }
  2100.         GET_LOCALE_INFO(LOCALE_ITLZERO);
  2101.         fLeadingZero = (*tszScratch == TEXT('1'));
  2102.         GET_LOCALE_INFO(LOCALE_STIME);
  2103.         //
  2104.         // See if there's enough room in destination string
  2105.         //
  2106.         cch = 1                     +  // terminating nul
  2107.               1                     +  // first hour digit specifier "h"
  2108.               2                     +  // minutes specifier "mm"
  2109.               (fLeadingZero != 0)   +  // leading hour digit specifier "h"
  2110.               lstrlen(tszScratch)   +  // separator string
  2111.               (fAmPm ? 3 : 0);         // space and "tt" for AM/PM
  2112.         if (cch > cchTimeFormat)
  2113.         {
  2114.             cch = 0; // signal error
  2115.         }
  2116.     } while (0);
  2117.     //
  2118.     // If there was a problem in getting locale info for building time string
  2119.     // just use the default and bail.
  2120.     //
  2121.     if (!cch)
  2122.     {
  2123.         StrCpy(tszTimeFormat, DEFAULT_TIME_FORMAT);
  2124.         return;
  2125.     }
  2126.     //
  2127.     // Build a time string that has hours and minutes but no seconds.
  2128.     //
  2129.     tszTimeFormat[0] = TEXT('');
  2130.     if (fAmPm)
  2131.     {
  2132.         if (fAmPmPrefixes)
  2133.         {
  2134.             StrCpy(tszTimeFormat, TEXT("tt "));
  2135.         }
  2136.         StrCat(tszTimeFormat, TEXT("h"));
  2137.  
  2138.         if (fLeadingZero)
  2139.         {
  2140.             StrCat(tszTimeFormat, TEXT("h"));
  2141.         }
  2142.     }
  2143.     else 
  2144.     {
  2145.         StrCat(tszTimeFormat, TEXT("H"));
  2146.  
  2147.         if (fLeadingZero)
  2148.         {
  2149.             StrCat(tszTimeFormat, TEXT("H"));
  2150.         }
  2151.     }
  2152.     StrCat(tszTimeFormat, tszScratch); // separator
  2153.     StrCat(tszTimeFormat, TEXT("mm"));
  2154.     if (fAmPm && !fAmPmPrefixes)
  2155.     {
  2156.         StrCat(tszTimeFormat, TEXT(" tt"));
  2157.     }
  2158. }