250 lines
5.7 KiB
C++
250 lines
5.7 KiB
C++
#include <windows.h>
|
|
#include <shlobj.h>
|
|
#include <shlwapi.h>
|
|
#include <shguidp.h>
|
|
#include <msnotify.h>
|
|
#include <subsmgr.h>
|
|
#include <chanmgr.h>
|
|
#include <chanmgrp.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <assert.h>
|
|
#include <wininet.h>
|
|
#include <winineti.h>
|
|
|
|
#define DIM(x) (sizeof(x) / sizeof(x[0]))
|
|
#define DEFAULT_INTERVAL 15
|
|
#define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
|
|
|
|
EXTERN_C const CLSID CLSID_OfflineTrayAgent;
|
|
|
|
BOOL g_fComInited = FALSE;
|
|
INotificationMgr *g_pNotfMgr = NULL;
|
|
int g_Interval = DEFAULT_INTERVAL;
|
|
char g_szCachePath[MAX_PATH] = "";
|
|
|
|
void CleanUp()
|
|
{
|
|
if (g_pNotfMgr)
|
|
{
|
|
g_pNotfMgr->Release();
|
|
g_pNotfMgr = NULL;
|
|
}
|
|
|
|
if (g_fComInited)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
}
|
|
|
|
void ErrorExit(char *fmt, ...)
|
|
{
|
|
va_list va;
|
|
|
|
va_start(va, fmt);
|
|
vprintf(fmt, va);
|
|
|
|
CleanUp();
|
|
exit(1);
|
|
}
|
|
|
|
|
|
void UpdateNow()
|
|
{
|
|
HRESULT hr;
|
|
INotification *pNotification;
|
|
IEnumNotification *pEnumNotification;
|
|
ULONG count;
|
|
NOTIFICATIONITEM items[1024];
|
|
|
|
if (g_szCachePath[0])
|
|
{
|
|
printf("Emptying cache from %s...\n", g_szCachePath);
|
|
FreeUrlCacheSpace(g_szCachePath, 100, 0 /*remove all*/);
|
|
}
|
|
|
|
printf("Updating all subscriptions...\n");
|
|
|
|
hr = g_pNotfMgr->GetEnumNotification(0/*grfFlags*/, &pEnumNotification);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorExit("Failed to get notification enumerator - hr = %08x\n", hr);
|
|
}
|
|
|
|
hr = pEnumNotification->Next(DIM(items), items, &count);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorExit("Failed to enumerate notifications - hr = %08x\n", hr);
|
|
}
|
|
|
|
if (!count)
|
|
{
|
|
printf("There are no subscriptions to update!\n");
|
|
return;
|
|
}
|
|
|
|
printf("There are %ld subscriptions to update...\n", count);
|
|
|
|
BSTR bstrGuids = SysAllocStringLen(NULL, GUIDSTR_MAX * count);
|
|
if (!bstrGuids)
|
|
{
|
|
ErrorExit("Error allocating bstrGuids\n");
|
|
}
|
|
|
|
bstrGuids[0] = L'\0';
|
|
|
|
for (ULONG i = 0; i < count; i++)
|
|
{
|
|
WCHAR wszCookie[GUIDSTR_MAX];
|
|
int l = StringFromGUID2(items[i].NotificationCookie, wszCookie, DIM(wszCookie));
|
|
|
|
assert(l == GUIDSTR_MAX);
|
|
StrCatW(bstrGuids, wszCookie);
|
|
|
|
if (items[i].pNotification)
|
|
{
|
|
items[i].pNotification->Release();
|
|
}
|
|
}
|
|
|
|
hr = g_pNotfMgr->CreateNotification(NOTIFICATIONTYPE_AGENT_START,
|
|
0,
|
|
NULL,
|
|
&pNotification,
|
|
0);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorExit("Failed to create notification - hr = %08x\n", hr);
|
|
}
|
|
|
|
VARIANT Val;
|
|
|
|
Val.vt = VT_BSTR;
|
|
Val.bstrVal = bstrGuids;
|
|
|
|
hr = pNotification->Write(L"Guids Array", Val, 0);
|
|
|
|
SysFreeString(bstrGuids);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorExit("Failed to write Guids Array property - hr = %08x\n", hr);
|
|
}
|
|
|
|
hr = g_pNotfMgr->DeliverNotification(pNotification, CLSID_OfflineTrayAgent,
|
|
0, NULL, NULL, 0);
|
|
|
|
pNotification->Release();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorExit("Failed to deliver notification - hr = %08x\n", hr);
|
|
}
|
|
}
|
|
|
|
void Wait()
|
|
{
|
|
#define HASH_AT 5000
|
|
|
|
DWORD dwNow = GetTickCount();
|
|
DWORD dwNextHash = dwNow + HASH_AT;
|
|
DWORD dwNextMin = dwNow + 1000 * 60;
|
|
DWORD dwStopTick = dwNow + (g_Interval * 1000 * 60);
|
|
int minToGo = g_Interval;
|
|
|
|
printf("Waiting %d minutes.", g_Interval);
|
|
do
|
|
{
|
|
// Not exactly fool proof accuracy but it will do
|
|
if (dwNow > dwNextHash)
|
|
{
|
|
printf(".");
|
|
dwNextHash += HASH_AT;
|
|
}
|
|
|
|
if (dwNow > dwNextMin)
|
|
{
|
|
printf("\n%d minutes to go.", --minToGo);
|
|
dwNextMin += 1000 * 60;
|
|
}
|
|
|
|
Sleep(1000);
|
|
|
|
dwNow = GetTickCount();
|
|
}
|
|
while (dwStopTick > dwNow);
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
int _cdecl main(int argc, char **argv)
|
|
{
|
|
if (argc > 1)
|
|
{
|
|
int interval = atoi(argv[1]);
|
|
|
|
if (interval)
|
|
{
|
|
g_Interval = interval;
|
|
printf("Interval is set to %d minutes\n", g_Interval);
|
|
}
|
|
else
|
|
{
|
|
printf("Invalid interval specified on command line - must be integer > 0\n");
|
|
printf("Using default of %d minutes\n", g_Interval);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("No interval specified on command line\n");
|
|
printf("Using default of %d minutes\n", g_Interval);
|
|
}
|
|
|
|
printf("Initializing COM...\n");
|
|
HRESULT hr = CoInitialize(NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorExit("CoInitialize failed with hr = %08x\n", hr);
|
|
}
|
|
|
|
printf("Creating Notification Manager...\n");
|
|
hr = CoCreateInstance(CLSID_StdNotificationMgr, NULL, CLSCTX_INPROC_SERVER, IID_INotificationMgr, (void**)&g_pNotfMgr);
|
|
if (FAILED(hr))
|
|
{
|
|
ErrorExit("CoCreate failed on notification manager with hr = %08x\n", hr);
|
|
}
|
|
|
|
g_fComInited = TRUE;
|
|
|
|
HKEY hkey;
|
|
|
|
LONG l = RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
|
|
0,
|
|
KEY_READ,
|
|
&hkey);
|
|
|
|
if (l == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwSize = DIM(g_szCachePath);
|
|
if (RegQueryValueEx(hkey, "Cache", NULL, NULL, (LPBYTE)g_szCachePath, &dwSize) != ERROR_SUCCESS)
|
|
{
|
|
printf("Uh-oh - couldn't get cache path...\n");
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
while (1)
|
|
{
|
|
UpdateNow();
|
|
Wait();
|
|
}
|
|
|
|
CleanUp();
|
|
|
|
return 0;
|
|
}
|