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.

459 lines
13 KiB

  1. #include <windows.h>
  2. #include <shlobj.h>
  3. #include <shlwapi.h>
  4. #include <shguidp.h>
  5. #include <msnotify.h>
  6. #include <subsmgr.h>
  7. #include <chanmgr.h>
  8. #include <chanmgrp.h>
  9. #include <stdio.h>
  10. #include <stdarg.h>
  11. #define DIM(x) (sizeof(x) / sizeof(x[0]))
  12. #define INI_FILE "autosub.ini"
  13. #define KEY_URL "URL"
  14. #define KEY_NAME "Name"
  15. #define KEY_AUTODIAL "AutoDial"
  16. #define KEY_ONLYIFIDLE "OnlyIfIdle"
  17. #define KEY_EMAILNOTIFY "EmailNotify"
  18. #define KEY_CHANGESONLY "ChangesOnly"
  19. #define KEY_DOWNLOADLEVELS "DownloadLevels"
  20. #define KEY_FOLLOWLINKS "FollowLinks"
  21. #define KEY_IMAGES "Images"
  22. #define KEY_SOUNDANDVIDEO "SoundAndVideo"
  23. #define KEY_CRAPLETS "Craplets"
  24. #define KEY_MAXDOWNLOADK "MaxDownloadK"
  25. #define KEY_SCHEDULENAME "ScheduleName"
  26. char g_szIniFile[MAX_PATH];
  27. BOOL g_fComInited = FALSE;
  28. ISubscriptionMgr *g_pSubsMgr = NULL;
  29. IChannelMgr *g_pChanMgr = NULL;
  30. IChannelMgrPriv *g_pChanMgrPriv = NULL;
  31. INotificationMgr *g_pNotfMgr = NULL;
  32. HWND g_hwnd = NULL;
  33. int g_iAutoDial = 0;
  34. int g_iOnlyIfIdle = 1;
  35. int g_iEmailNotify = 0;
  36. int g_iChangesOnly = 0;
  37. int g_iDownloadLevels = 0;
  38. int g_iFollowLinks = 1;
  39. int g_iImages = 1;
  40. int g_iSoundAndVideo = 0;
  41. int g_iCraplets = 1;
  42. int g_iMaxDownloadK = 0;
  43. char g_szScheduleName[MAX_PATH] = "Auto";
  44. BOOL SetCustomSchedule(int mins, SUBSCRIPTIONINFO *psi)
  45. {
  46. BOOL fResult = FALSE;
  47. IEnumScheduleGroup *pEnumScheduleGroup;
  48. HRESULT hr;
  49. //
  50. // This isn't very efficient but it's simple
  51. //
  52. hr = g_pNotfMgr->GetEnumScheduleGroup(0, &pEnumScheduleGroup);
  53. if (FAILED(hr))
  54. {
  55. printf("Couldn't enum schedule groups - hr = %08x\n", hr);
  56. }
  57. else
  58. {
  59. IScheduleGroup *pScheduleGroup = NULL;
  60. char szSchedName[64];
  61. WCHAR wszSchedName[64];
  62. TASK_TRIGGER tt;
  63. NOTIFICATIONCOOKIE cookie;
  64. GROUPINFO gi;
  65. BOOL fFound = FALSE;
  66. wsprintf(szSchedName, "%d minutes", mins);
  67. MultiByteToWideChar(CP_ACP, 0, szSchedName, -1, wszSchedName, DIM(wszSchedName));
  68. while (!fFound && pEnumScheduleGroup->Next(1, &pScheduleGroup, NULL) == S_OK)
  69. {
  70. if (SUCCEEDED(pScheduleGroup->GetAttributes(&tt, NULL, &cookie, &gi, NULL, NULL)))
  71. {
  72. int cmp = StrCmpIW(gi.pwzGroupname, wszSchedName);
  73. CoTaskMemFree(gi.pwzGroupname);
  74. if (cmp == 0)
  75. {
  76. psi->schedule = SUBSSCHED_CUSTOM;
  77. psi->customGroupCookie = cookie;
  78. fResult = TRUE;
  79. fFound = TRUE;
  80. }
  81. }
  82. pScheduleGroup->Release();
  83. pScheduleGroup = NULL;
  84. }
  85. pEnumScheduleGroup->Release();
  86. if (!fFound)
  87. {
  88. hr = g_pNotfMgr->CreateScheduleGroup(0, &pScheduleGroup, &cookie, 0);
  89. if (FAILED(hr))
  90. {
  91. printf("Couldn't create schedule group - hr = %08x\n", hr);
  92. }
  93. tt.cbTriggerSize = sizeof(TASK_TRIGGER);
  94. tt.wBeginYear = 1997;
  95. tt.wBeginMonth = 9;
  96. tt.wBeginDay = 1;
  97. tt.MinutesDuration = 1440; //All day
  98. tt.MinutesInterval = mins;
  99. tt.TriggerType = TASK_TIME_TRIGGER_DAILY;
  100. tt.Type.Daily.DaysInterval = 1;
  101. gi.cbSize = sizeof(GROUPINFO);
  102. gi.pwzGroupname = wszSchedName;
  103. if (SUCCEEDED(pScheduleGroup->SetAttributes(&tt, NULL, &cookie, &gi, 0)))
  104. {
  105. psi->schedule = SUBSSCHED_CUSTOM;
  106. psi->customGroupCookie = cookie;
  107. fResult = TRUE;
  108. }
  109. pScheduleGroup->Release();
  110. }
  111. }
  112. return fResult;
  113. }
  114. void SetScheduleGroup(char *pszScheduleName, SUBSCRIPTIONINFO *psi, BOOL fIsChannel)
  115. {
  116. psi->schedule = SUBSSCHED_AUTO;
  117. if (lstrcmpi(pszScheduleName, "Manual") == 0)
  118. {
  119. psi->schedule = SUBSSCHED_MANUAL;
  120. }
  121. else if (lstrcmpi(pszScheduleName, "Auto") == 0)
  122. {
  123. if (fIsChannel)
  124. {
  125. psi->fChannelFlags |= CHANNEL_AGENT_DYNAMIC_SCHEDULE;
  126. psi->schedule = SUBSSCHED_AUTO;
  127. }
  128. else
  129. {
  130. psi->schedule = SUBSSCHED_DAILY;
  131. }
  132. }
  133. else if (lstrcmpi(pszScheduleName, "Weekly") == 0)
  134. {
  135. psi->schedule = SUBSSCHED_WEEKLY;
  136. }
  137. else
  138. {
  139. int mins = atoi(pszScheduleName);
  140. if (!mins || !SetCustomSchedule(mins, psi))
  141. {
  142. psi->schedule = SUBSSCHED_DAILY;
  143. }
  144. }
  145. if (psi->schedule != SUBSSCHED_AUTO)
  146. {
  147. psi->pTrigger = NULL;
  148. }
  149. }
  150. void CreateSubscription(char *pszSection, BOOL fIsChannel)
  151. {
  152. char szURL[2048];
  153. char szName[MAX_PATH];
  154. WCHAR wszURL[2048];
  155. WCHAR wszName[MAX_PATH];
  156. char szScheduleName[MAX_PATH];
  157. HRESULT hr;
  158. TASK_TRIGGER tt = {0};
  159. SUBSCRIPTIONINFO si = {0};
  160. BOOL fIsSoftware = FALSE;
  161. SUBSCRIPTIONTYPE st;
  162. printf("Processing [%s]...\n", pszSection);
  163. GetPrivateProfileString(pszSection, KEY_URL, "", szURL, DIM(szURL), g_szIniFile);
  164. if (!szURL[0])
  165. {
  166. printf("No URL specified in %s - moving on...\n", pszSection);
  167. return;
  168. }
  169. MultiByteToWideChar(CP_ACP, 0, szURL, -1, wszURL, DIM(wszURL));
  170. tt.cbTriggerSize = sizeof(TASK_TRIGGER);
  171. si.pTrigger = (LPVOID)&tt;
  172. if (fIsChannel)
  173. {
  174. printf("Downloading CDF %s...\n", szURL);
  175. si.cbSize = sizeof(SUBSCRIPTIONINFO);
  176. si.fUpdateFlags = SUBSINFO_SCHEDULE;
  177. si.schedule = SUBSSCHED_AUTO;
  178. hr = g_pChanMgrPriv->DownloadMinCDF(g_hwnd, wszURL, wszName,
  179. DIM(wszName), &si, &fIsSoftware);
  180. if (FAILED(hr))
  181. {
  182. printf("Error downloading %s hr = %08x - moving on...\n", szURL, hr);
  183. return;
  184. }
  185. CHANNELSHORTCUTINFO csci = {0};
  186. csci.cbSize = sizeof(CHANNELSHORTCUTINFO);
  187. csci.pszTitle = wszName;
  188. csci.pszURL = wszURL;
  189. csci.bIsSoftware = fIsSoftware;
  190. hr = g_pChanMgr->AddChannelShortcut(&csci);
  191. if (FAILED(hr))
  192. {
  193. printf("Error adding channel shortcut for %s hr = %08x - moving on...\n", szURL, hr);
  194. return;
  195. }
  196. st = SUBSTYPE_CHANNEL;
  197. }
  198. else
  199. {
  200. si.cbSize = sizeof(SUBSCRIPTIONINFO);
  201. si.fUpdateFlags = SUBSINFO_SCHEDULE;
  202. GetPrivateProfileString(pszSection, KEY_NAME, szURL, szName, DIM(szName), g_szIniFile);
  203. MultiByteToWideChar(CP_ACP, 0, szName, -1, wszName, DIM(wszName));
  204. st = SUBSTYPE_URL;
  205. }
  206. if (!GetPrivateProfileInt(pszSection, KEY_AUTODIAL, g_iAutoDial, g_szIniFile))
  207. {
  208. si.fTaskFlags |= TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET;
  209. }
  210. if (GetPrivateProfileInt(pszSection, KEY_ONLYIFIDLE, g_iOnlyIfIdle, g_szIniFile))
  211. {
  212. si.fTaskFlags |= TASK_FLAG_START_ONLY_IF_IDLE;
  213. }
  214. if (GetPrivateProfileInt(pszSection, KEY_EMAILNOTIFY, g_iEmailNotify, g_szIniFile))
  215. {
  216. si.bMailNotification = TRUE;
  217. }
  218. if (GetPrivateProfileInt(pszSection, KEY_CHANGESONLY, g_iChangesOnly, g_szIniFile))
  219. {
  220. si.bChangesOnly = TRUE;
  221. }
  222. if (!si.bChangesOnly)
  223. {
  224. if (fIsChannel)
  225. {
  226. si.fChannelFlags |= CHANNEL_AGENT_PRECACHE_ALL;
  227. }
  228. else
  229. {
  230. si.dwRecurseLevels =
  231. GetPrivateProfileInt(pszSection, KEY_DOWNLOADLEVELS, g_iDownloadLevels, g_szIniFile);
  232. }
  233. }
  234. if (GetPrivateProfileInt(pszSection, KEY_FOLLOWLINKS, g_iFollowLinks, g_szIniFile))
  235. {
  236. si.fWebcrawlerFlags |= WEBCRAWL_LINKS_ELSEWHERE;
  237. }
  238. if (GetPrivateProfileInt(pszSection, KEY_IMAGES, g_iImages, g_szIniFile))
  239. {
  240. si.fWebcrawlerFlags |= WEBCRAWL_GET_IMAGES;
  241. }
  242. if (GetPrivateProfileInt(pszSection, KEY_SOUNDANDVIDEO, g_iSoundAndVideo, g_szIniFile))
  243. {
  244. si.fWebcrawlerFlags |= WEBCRAWL_GET_VIDEOS | WEBCRAWL_GET_BGSOUNDS;
  245. }
  246. if (GetPrivateProfileInt(pszSection, KEY_CRAPLETS, g_iCraplets, g_szIniFile))
  247. {
  248. si.fWebcrawlerFlags |= WEBCRAWL_GET_CONTROLS;
  249. }
  250. si.dwMaxSizeKB =
  251. GetPrivateProfileInt(pszSection, KEY_MAXDOWNLOADK, g_iMaxDownloadK, g_szIniFile);
  252. GetPrivateProfileString(pszSection, KEY_SCHEDULENAME, g_szScheduleName, szScheduleName, DIM(szScheduleName), g_szIniFile);
  253. si.fUpdateFlags = SUBSINFO_ALLFLAGS;
  254. SetScheduleGroup(szScheduleName, &si, fIsChannel);
  255. BOOL fIsSubscribed = FALSE;
  256. g_pSubsMgr->IsSubscribed(wszURL, &fIsSubscribed);
  257. if (fIsSubscribed)
  258. {
  259. printf("Deleting old subscription to %s...\n", szURL);
  260. g_pSubsMgr->DeleteSubscription(wszURL, NULL);
  261. }
  262. printf("Subscribing to %s...\n", szURL);
  263. hr = g_pSubsMgr->CreateSubscription(g_hwnd, wszURL, wszName,
  264. CREATESUBS_NOUI | CREATESUBS_ADDTOFAVORITES |
  265. (fIsSoftware ? CREATESUBS_SOFTWAREUPDATE : 0),
  266. st, &si);
  267. if (FAILED(hr))
  268. {
  269. printf("Error creating subscription to %s hr = %08x - moving on...\n", szURL, hr);
  270. return;
  271. }
  272. }
  273. void ReadDefaults(char *pszSection)
  274. {
  275. printf("Reading defaults from [%s]...\n", pszSection);
  276. g_iAutoDial = GetPrivateProfileInt(pszSection, KEY_AUTODIAL, g_iAutoDial, g_szIniFile);
  277. g_iOnlyIfIdle = GetPrivateProfileInt(pszSection, KEY_ONLYIFIDLE, g_iOnlyIfIdle, g_szIniFile);
  278. g_iEmailNotify = GetPrivateProfileInt(pszSection, KEY_EMAILNOTIFY, g_iEmailNotify, g_szIniFile);
  279. g_iChangesOnly = GetPrivateProfileInt(pszSection, KEY_CHANGESONLY, g_iChangesOnly, g_szIniFile);
  280. g_iDownloadLevels = GetPrivateProfileInt(pszSection, KEY_DOWNLOADLEVELS, g_iDownloadLevels, g_szIniFile);
  281. g_iFollowLinks = GetPrivateProfileInt(pszSection, KEY_FOLLOWLINKS, g_iFollowLinks, g_szIniFile);
  282. g_iImages = GetPrivateProfileInt(pszSection, KEY_IMAGES, g_iImages, g_szIniFile);
  283. g_iSoundAndVideo = GetPrivateProfileInt(pszSection, KEY_SOUNDANDVIDEO, g_iSoundAndVideo, g_szIniFile);
  284. g_iCraplets = GetPrivateProfileInt(pszSection, KEY_CRAPLETS, g_iCraplets, g_szIniFile);
  285. g_iMaxDownloadK = GetPrivateProfileInt(pszSection, KEY_MAXDOWNLOADK, g_iMaxDownloadK, g_szIniFile);
  286. GetPrivateProfileString(pszSection, KEY_SCHEDULENAME, "Auto", g_szScheduleName, DIM(g_szScheduleName), g_szIniFile);
  287. }
  288. void CleanUp()
  289. {
  290. if (g_pSubsMgr)
  291. {
  292. g_pSubsMgr->Release();
  293. g_pSubsMgr = NULL;
  294. }
  295. if (g_pChanMgrPriv)
  296. {
  297. g_pChanMgrPriv->Release();
  298. g_pChanMgrPriv = NULL;
  299. }
  300. if (g_pChanMgr)
  301. {
  302. g_pChanMgr->Release();
  303. g_pChanMgr = NULL;
  304. }
  305. if (g_pNotfMgr)
  306. {
  307. g_pNotfMgr->Release();
  308. g_pNotfMgr = NULL;
  309. }
  310. if (g_fComInited)
  311. {
  312. CoUninitialize();
  313. }
  314. }
  315. void ErrorExit(char *fmt, ...)
  316. {
  317. va_list va;
  318. va_start(va, fmt);
  319. vprintf(fmt, va);
  320. CleanUp();
  321. exit(1);
  322. }
  323. int _cdecl main(int argc, char **argv)
  324. {
  325. char szSections[8192];
  326. char *pszSection;
  327. if (argc < 2)
  328. {
  329. ErrorExit("Need a file name!\nExample:\nautosub \\\\ohserv\\users\\tnoonan\\autosub.ini\n");
  330. }
  331. lstrcpy(g_szIniFile, argv[1]);
  332. printf("Reading %s...\n", g_szIniFile);
  333. if (!GetPrivateProfileSectionNames(szSections, DIM(szSections), g_szIniFile))
  334. {
  335. ErrorExit("No sections found in %s\n", g_szIniFile);
  336. }
  337. printf("Initializing COM...\n");
  338. HRESULT hr = CoInitialize(NULL);
  339. if (FAILED(hr))
  340. {
  341. ErrorExit("CoInitialize failed with hr = %08x\n", hr);
  342. }
  343. g_fComInited = TRUE;
  344. printf("Creating Channel Manager...\n");
  345. hr = CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER, IID_IChannelMgr,
  346. (void **)&g_pChanMgr);
  347. if (FAILED(hr))
  348. {
  349. ErrorExit("CoCreate failed on channel manager with hr = %08x\n", hr);
  350. }
  351. hr = g_pChanMgr->QueryInterface(IID_IChannelMgrPriv, (void **)&g_pChanMgrPriv);
  352. if (FAILED(hr))
  353. {
  354. ErrorExit("QI failed for IID_IChannelMgrPriv with hr = %08x\n", hr);
  355. }
  356. printf("Creating Subscription Manager...\n");
  357. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr,
  358. (void **)&g_pSubsMgr);
  359. if (FAILED(hr))
  360. {
  361. ErrorExit("CoCreate failed on channel manager with hr = %08x\n", hr);
  362. }
  363. printf("Creating Notification Manager...\n");
  364. hr = CoCreateInstance(CLSID_StdNotificationMgr, NULL, CLSCTX_INPROC_SERVER, IID_INotificationMgr, (void**)&g_pNotfMgr);
  365. if (FAILED(hr))
  366. {
  367. ErrorExit("CoCreate failed on notification manager with hr = %08x\n", hr);
  368. }
  369. g_hwnd = GetDesktopWindow();
  370. pszSection = szSections;
  371. ReadDefaults("Defaults");
  372. while (pszSection && *pszSection)
  373. {
  374. BOOL fIsChannel = FALSE;
  375. switch (toupper(*pszSection))
  376. {
  377. case 'C':
  378. fIsChannel = TRUE;
  379. // Fall through
  380. case 'U':
  381. CreateSubscription(pszSection, fIsChannel);
  382. break;
  383. default:
  384. if (lstrcmpi(pszSection, "Defaults") != 0)
  385. {
  386. printf("Skipping [%s]\n", pszSection);
  387. }
  388. break;
  389. }
  390. pszSection += strlen(pszSection) + 1;
  391. }
  392. CleanUp();
  393. return 0;
  394. }