Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2604 lines
73 KiB

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