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.

249 lines
5.7 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. #include <assert.h>
  12. #include <wininet.h>
  13. #include <winineti.h>
  14. #define DIM(x) (sizeof(x) / sizeof(x[0]))
  15. #define DEFAULT_INTERVAL 15
  16. #define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
  17. EXTERN_C const CLSID CLSID_OfflineTrayAgent;
  18. BOOL g_fComInited = FALSE;
  19. INotificationMgr *g_pNotfMgr = NULL;
  20. int g_Interval = DEFAULT_INTERVAL;
  21. char g_szCachePath[MAX_PATH] = "";
  22. void CleanUp()
  23. {
  24. if (g_pNotfMgr)
  25. {
  26. g_pNotfMgr->Release();
  27. g_pNotfMgr = NULL;
  28. }
  29. if (g_fComInited)
  30. {
  31. CoUninitialize();
  32. }
  33. }
  34. void ErrorExit(char *fmt, ...)
  35. {
  36. va_list va;
  37. va_start(va, fmt);
  38. vprintf(fmt, va);
  39. CleanUp();
  40. exit(1);
  41. }
  42. void UpdateNow()
  43. {
  44. HRESULT hr;
  45. INotification *pNotification;
  46. IEnumNotification *pEnumNotification;
  47. ULONG count;
  48. NOTIFICATIONITEM items[1024];
  49. if (g_szCachePath[0])
  50. {
  51. printf("Emptying cache from %s...\n", g_szCachePath);
  52. FreeUrlCacheSpace(g_szCachePath, 100, 0 /*remove all*/);
  53. }
  54. printf("Updating all subscriptions...\n");
  55. hr = g_pNotfMgr->GetEnumNotification(0/*grfFlags*/, &pEnumNotification);
  56. if (FAILED(hr))
  57. {
  58. ErrorExit("Failed to get notification enumerator - hr = %08x\n", hr);
  59. }
  60. hr = pEnumNotification->Next(DIM(items), items, &count);
  61. if (FAILED(hr))
  62. {
  63. ErrorExit("Failed to enumerate notifications - hr = %08x\n", hr);
  64. }
  65. if (!count)
  66. {
  67. printf("There are no subscriptions to update!\n");
  68. return;
  69. }
  70. printf("There are %ld subscriptions to update...\n", count);
  71. BSTR bstrGuids = SysAllocStringLen(NULL, GUIDSTR_MAX * count);
  72. if (!bstrGuids)
  73. {
  74. ErrorExit("Error allocating bstrGuids\n");
  75. }
  76. bstrGuids[0] = L'\0';
  77. for (ULONG i = 0; i < count; i++)
  78. {
  79. WCHAR wszCookie[GUIDSTR_MAX];
  80. int l = StringFromGUID2(items[i].NotificationCookie, wszCookie, DIM(wszCookie));
  81. assert(l == GUIDSTR_MAX);
  82. StrCatW(bstrGuids, wszCookie);
  83. if (items[i].pNotification)
  84. {
  85. items[i].pNotification->Release();
  86. }
  87. }
  88. hr = g_pNotfMgr->CreateNotification(NOTIFICATIONTYPE_AGENT_START,
  89. 0,
  90. NULL,
  91. &pNotification,
  92. 0);
  93. if (FAILED(hr))
  94. {
  95. ErrorExit("Failed to create notification - hr = %08x\n", hr);
  96. }
  97. VARIANT Val;
  98. Val.vt = VT_BSTR;
  99. Val.bstrVal = bstrGuids;
  100. hr = pNotification->Write(L"Guids Array", Val, 0);
  101. SysFreeString(bstrGuids);
  102. if (FAILED(hr))
  103. {
  104. ErrorExit("Failed to write Guids Array property - hr = %08x\n", hr);
  105. }
  106. hr = g_pNotfMgr->DeliverNotification(pNotification, CLSID_OfflineTrayAgent,
  107. 0, NULL, NULL, 0);
  108. pNotification->Release();
  109. if (FAILED(hr))
  110. {
  111. ErrorExit("Failed to deliver notification - hr = %08x\n", hr);
  112. }
  113. }
  114. void Wait()
  115. {
  116. #define HASH_AT 5000
  117. DWORD dwNow = GetTickCount();
  118. DWORD dwNextHash = dwNow + HASH_AT;
  119. DWORD dwNextMin = dwNow + 1000 * 60;
  120. DWORD dwStopTick = dwNow + (g_Interval * 1000 * 60);
  121. int minToGo = g_Interval;
  122. printf("Waiting %d minutes.", g_Interval);
  123. do
  124. {
  125. // Not exactly fool proof accuracy but it will do
  126. if (dwNow > dwNextHash)
  127. {
  128. printf(".");
  129. dwNextHash += HASH_AT;
  130. }
  131. if (dwNow > dwNextMin)
  132. {
  133. printf("\n%d minutes to go.", --minToGo);
  134. dwNextMin += 1000 * 60;
  135. }
  136. Sleep(1000);
  137. dwNow = GetTickCount();
  138. }
  139. while (dwStopTick > dwNow);
  140. printf("\n");
  141. }
  142. int _cdecl main(int argc, char **argv)
  143. {
  144. if (argc > 1)
  145. {
  146. int interval = atoi(argv[1]);
  147. if (interval)
  148. {
  149. g_Interval = interval;
  150. printf("Interval is set to %d minutes\n", g_Interval);
  151. }
  152. else
  153. {
  154. printf("Invalid interval specified on command line - must be integer > 0\n");
  155. printf("Using default of %d minutes\n", g_Interval);
  156. }
  157. }
  158. else
  159. {
  160. printf("No interval specified on command line\n");
  161. printf("Using default of %d minutes\n", g_Interval);
  162. }
  163. printf("Initializing COM...\n");
  164. HRESULT hr = CoInitialize(NULL);
  165. if (FAILED(hr))
  166. {
  167. ErrorExit("CoInitialize failed with hr = %08x\n", hr);
  168. }
  169. printf("Creating Notification Manager...\n");
  170. hr = CoCreateInstance(CLSID_StdNotificationMgr, NULL, CLSCTX_INPROC_SERVER, IID_INotificationMgr, (void**)&g_pNotfMgr);
  171. if (FAILED(hr))
  172. {
  173. ErrorExit("CoCreate failed on notification manager with hr = %08x\n", hr);
  174. }
  175. g_fComInited = TRUE;
  176. HKEY hkey;
  177. LONG l = RegOpenKeyEx(HKEY_CURRENT_USER,
  178. "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
  179. 0,
  180. KEY_READ,
  181. &hkey);
  182. if (l == ERROR_SUCCESS)
  183. {
  184. DWORD dwSize = DIM(g_szCachePath);
  185. if (RegQueryValueEx(hkey, "Cache", NULL, NULL, (LPBYTE)g_szCachePath, &dwSize) != ERROR_SUCCESS)
  186. {
  187. printf("Uh-oh - couldn't get cache path...\n");
  188. }
  189. RegCloseKey(hkey);
  190. }
  191. while (1)
  192. {
  193. UpdateNow();
  194. Wait();
  195. }
  196. CleanUp();
  197. return 0;
  198. }