Leaked source code of windows server 2003
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.

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