757 lines
22 KiB
C++
757 lines
22 KiB
C++
|
#include <windows.h>
|
||
|
#include <windowsx.h>
|
||
|
#include <stdio.h>
|
||
|
#include <urlmon.h>
|
||
|
#include <msnotify.h>
|
||
|
#include <webcheck.h>
|
||
|
#include <wininet.h>
|
||
|
#include <mstask.h>
|
||
|
#include <inetreg.h>
|
||
|
#include "schedcdf.h"
|
||
|
|
||
|
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||
|
// This is where we do most of the actual work
|
||
|
void StartOperation(LPSTR lpCDFName);
|
||
|
// Our Dialog Proc function for the Use Other CDF dialog
|
||
|
BOOL CALLBACK UseOtherCDFDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
// Helper Functions
|
||
|
HRESULT WriteDWORD(IPropertyMap *pPropertyMap, LPWSTR szName, DWORD dwVal);
|
||
|
HRESULT WriteBSTR(IPropertyMap *pPropertyMap, LPWSTR szName, LPWSTR szVal);
|
||
|
HRESULT WriteLONGLONG(IPropertyMap *pPropertyMap, LPCWSTR szName, LONGLONG llVal);
|
||
|
HRESULT ReadBSTR(IPropertyMap *pPropertyMap, LPWSTR szName, BSTR *bstrRet);
|
||
|
void WriteToScreen(LPSTR lpText, HRESULT hr);
|
||
|
void DBGOut(LPSTR psz);
|
||
|
|
||
|
// Functions called by NotificationSink Object
|
||
|
HRESULT OnBeginReport(INotification *pNotification, INotificationReport *pNotificationReport);
|
||
|
HRESULT OnEndReport(INotification *pNotification);
|
||
|
|
||
|
HANDLE g_hHeap = NULL;
|
||
|
int g_iActive=0;
|
||
|
int g_BufSize=0;
|
||
|
LPSTR lpEditBuffer;
|
||
|
HINSTANCE hInstance;
|
||
|
HWND hwndEdit;
|
||
|
|
||
|
void DBGOut(LPSTR psz)
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
OutputDebugString("SchedCDF: ");
|
||
|
OutputDebugString(psz);
|
||
|
OutputDebugString("\n");
|
||
|
#endif //DEBUG
|
||
|
}
|
||
|
|
||
|
class MySink : public INotificationSink
|
||
|
{
|
||
|
long m_cRef;
|
||
|
public:
|
||
|
MySink() { m_cRef = 1; }
|
||
|
~MySink() {}
|
||
|
|
||
|
// IUnknown members
|
||
|
STDMETHODIMP QueryInterface(REFIID riid, void **punk);
|
||
|
STDMETHODIMP_(ULONG) AddRef(void);
|
||
|
STDMETHODIMP_(ULONG) Release(void);
|
||
|
|
||
|
// INotificationSink members
|
||
|
STDMETHODIMP OnNotification(
|
||
|
INotification *pNotification,
|
||
|
INotificationReport *pNotificationReport,
|
||
|
DWORD dwReserved);
|
||
|
};
|
||
|
|
||
|
STDMETHODIMP_(ULONG) MySink::AddRef(void)
|
||
|
{
|
||
|
return ++m_cRef;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) MySink::Release(void)
|
||
|
{
|
||
|
if( 0L != --m_cRef )
|
||
|
return m_cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0L;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP MySink::QueryInterface(REFIID riid, void ** ppv)
|
||
|
{
|
||
|
*ppv=NULL;
|
||
|
|
||
|
// Validate requested interface
|
||
|
if ((IID_IUnknown == riid) ||
|
||
|
(IID_INotificationSink == riid))
|
||
|
*ppv=(INotificationSink *)this;
|
||
|
|
||
|
// Addref through the interface
|
||
|
if( NULL != *ppv ) {
|
||
|
((LPUNKNOWN)*ppv)->AddRef();
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
return E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// INotificationSink members
|
||
|
//
|
||
|
STDMETHODIMP MySink::OnNotification(
|
||
|
INotification *pNotification,
|
||
|
INotificationReport *pNotificationReport,
|
||
|
DWORD dwReserved)
|
||
|
{
|
||
|
NOTIFICATIONTYPE nt;
|
||
|
HRESULT hr=S_OK;
|
||
|
|
||
|
DBGOut("SchedCDF sink receiving OnNotification");
|
||
|
|
||
|
hr = pNotification->GetNotificationInfo(&nt, NULL,NULL,NULL,0);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
DBGOut("Failed to get notification type!");
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
if (IsEqualGUID(nt, NOTIFICATIONTYPE_BEGIN_REPORT))
|
||
|
hr = OnBeginReport(pNotification, pNotificationReport);
|
||
|
else if (IsEqualGUID(nt, NOTIFICATIONTYPE_END_REPORT))
|
||
|
hr = OnEndReport(pNotification);
|
||
|
else DBGOut("NotSend: Unknown notification type received");
|
||
|
|
||
|
// Avoid bogus assert
|
||
|
if (SUCCEEDED(hr)) hr = S_OK;
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
|
||
|
{
|
||
|
static char szAppName[] = "CDF Agent Notification Delivery Tool";
|
||
|
HWND hwnd;
|
||
|
MSG msg;
|
||
|
WNDCLASSEX wndclass;
|
||
|
HACCEL hAccel;
|
||
|
|
||
|
wndclass.cbSize = sizeof(wndclass);
|
||
|
wndclass.style = CS_HREDRAW | CS_VREDRAW;
|
||
|
wndclass.lpfnWndProc = WndProc;
|
||
|
wndclass.cbClsExtra = 0;
|
||
|
wndclass.cbWndExtra = 0;
|
||
|
wndclass.hInstance = hInstance;
|
||
|
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||
|
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||
|
wndclass.hbrBackground = (HBRUSH) GetStockObject (GRAY_BRUSH);
|
||
|
wndclass.lpszMenuName = MAKEINTRESOURCE(SCHEDCDF);
|
||
|
wndclass.lpszClassName = szAppName;
|
||
|
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
||
|
|
||
|
RegisterClassEx(&wndclass);
|
||
|
|
||
|
hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||
|
CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
|
||
|
|
||
|
ShowWindow(hwnd, iCmdShow);
|
||
|
UpdateWindow(hwnd);
|
||
|
|
||
|
while(GetMessage(&msg, NULL, 0, 0))
|
||
|
{
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
return msg.wParam;
|
||
|
}
|
||
|
|
||
|
|
||
|
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
MySink *pSink = NULL;
|
||
|
RECT rcClientWnd;
|
||
|
HRESULT hr;
|
||
|
INotificationMgr *pNotificationMgr = NULL;
|
||
|
LPNOTIFICATION pNotification = NULL;
|
||
|
NOTIFICATIONITEM NotItem;
|
||
|
NOTIFICATIONCOOKIE ncCookie;
|
||
|
TASK_TRIGGER tt;
|
||
|
TASK_DATA td;
|
||
|
LPSTR lpBuffer = NULL;
|
||
|
DWORD dwStartTime = 0;
|
||
|
MSG msg;
|
||
|
SYSTEMTIME st;
|
||
|
ZeroMemory(&tt, sizeof(TASK_TRIGGER));
|
||
|
ZeroMemory(&td, sizeof(TASK_DATA));
|
||
|
ZeroMemory(&st, sizeof(SYSTEMTIME));
|
||
|
|
||
|
switch(iMsg)
|
||
|
{
|
||
|
case WM_CREATE:
|
||
|
{
|
||
|
OleInitialize(NULL);
|
||
|
hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
|
||
|
|
||
|
GetClientRect(hwnd, &rcClientWnd);
|
||
|
|
||
|
hwndEdit = CreateWindow("EDIT", NULL, WS_BORDER | WS_VISIBLE | WS_CHILD
|
||
|
| WS_HSCROLL | ES_MULTILINE, 0, 0, rcClientWnd.right, rcClientWnd.bottom,
|
||
|
hwnd, (HMENU) 1, hInstance, NULL);
|
||
|
|
||
|
ShowWindow(hwndEdit, SW_SHOW);
|
||
|
|
||
|
lpEditBuffer = NULL;
|
||
|
// Alloc a 4k buffer for the edit window
|
||
|
lpEditBuffer = (LPSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, 4096);
|
||
|
if (lpEditBuffer)
|
||
|
g_BufSize = 4096;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
case WM_SIZE:
|
||
|
{
|
||
|
GetClientRect(hwnd, &rcClientWnd);
|
||
|
SetWindowPos(hwndEdit, HWND_TOP, 0, 0, rcClientWnd.right, rcClientWnd.bottom,
|
||
|
SWP_SHOWWINDOW);
|
||
|
break;
|
||
|
}
|
||
|
case WM_COMMAND:
|
||
|
{
|
||
|
switch(LOWORD(wParam))
|
||
|
{
|
||
|
case ID_EXIT:
|
||
|
{
|
||
|
SendMessage(hwnd, WM_CLOSE, 0, 0L);
|
||
|
return 0;
|
||
|
}
|
||
|
case ID_UPDATESCOPEALL:
|
||
|
{
|
||
|
StartOperation("all.cdf");
|
||
|
return 0;
|
||
|
}
|
||
|
case ID_UPDATESCOPEOFFLINE:
|
||
|
{
|
||
|
StartOperation("offline.cdf");
|
||
|
return 0;
|
||
|
}
|
||
|
case ID_UPDATESCOPEONLINE:
|
||
|
{
|
||
|
StartOperation("online.cdf");
|
||
|
return 0;
|
||
|
}
|
||
|
case ID_UPDATEFRAMESCDF:
|
||
|
{
|
||
|
StartOperation("frames.cdf");
|
||
|
return 0;
|
||
|
}
|
||
|
case ID_USEOTHERCDF:
|
||
|
{
|
||
|
DialogBox(hInstance, MAKEINTRESOURCE(IDD_OTHER), hwnd, UseOtherCDFDialogProc);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
{
|
||
|
if (lpEditBuffer)
|
||
|
{
|
||
|
GlobalFree(lpEditBuffer);
|
||
|
lpEditBuffer = NULL;
|
||
|
}
|
||
|
PostQuitMessage(0);
|
||
|
return 0;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
return DefWindowProc(hwnd, iMsg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
void StartOperation(LPSTR lpszCDFName)
|
||
|
{
|
||
|
LONG lret = NULL;
|
||
|
DWORD cbSize = NULL;
|
||
|
LPSTR lpszTemp = NULL;
|
||
|
LPSTR lpszCDFUrlPath = NULL;
|
||
|
LPSTR lpszCookie = NULL;
|
||
|
HKEY hKey = NULL;
|
||
|
MySink *pSink = NULL;
|
||
|
INotificationMgr *pNotificationMgr = NULL;
|
||
|
LPNOTIFICATION pNotification = NULL;
|
||
|
NOTIFICATIONITEM NotItem;
|
||
|
NotItem.pNotification = NULL;
|
||
|
NOTIFICATIONCOOKIE ncCookie;
|
||
|
TASK_TRIGGER tt;
|
||
|
TASK_DATA td;
|
||
|
MSG msg;
|
||
|
SYSTEMTIME st;
|
||
|
HRESULT hr;
|
||
|
ZeroMemory(&tt, sizeof(TASK_TRIGGER));
|
||
|
ZeroMemory(&td, sizeof(TASK_DATA));
|
||
|
ZeroMemory(&st, sizeof(SYSTEMTIME));
|
||
|
// Hack: To workaround fault that happens when urlmon calls InternetCloseHandle after wininet
|
||
|
// has been unloaded we'll call into wininet first which will hopefully cause it to stay
|
||
|
// around until urlmon is gone.
|
||
|
DWORD cbPfx = 0;
|
||
|
HANDLE hCacheEntry = NULL;
|
||
|
LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL;
|
||
|
LPSTR lpPfx = NULL;
|
||
|
lpPfx = (LPSTR)GlobalAlloc(GPTR, lstrlen("Log:")+1);
|
||
|
lstrcpy(lpPfx, "Log:");
|
||
|
lpCE = (LPINTERNET_CACHE_ENTRY_INFO)GlobalAlloc(GPTR, 2048);
|
||
|
ASSERT(lpCE);
|
||
|
cbSize = 2048;
|
||
|
hCacheEntry = FindFirstUrlCacheEntry("Log:", lpCE, &cbSize);
|
||
|
if (lpCE)
|
||
|
{
|
||
|
GlobalFree(lpCE);
|
||
|
lpCE = NULL;
|
||
|
}
|
||
|
if (lpPfx)
|
||
|
{
|
||
|
GlobalFree(lpPfx);
|
||
|
lpPfx = NULL;
|
||
|
}
|
||
|
cbSize = 0;
|
||
|
// End Hack
|
||
|
lret = RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_SCHEDCDF, 0,
|
||
|
KEY_READ | KEY_WRITE, &hKey);
|
||
|
|
||
|
if (ERROR_SUCCESS != lret)
|
||
|
{
|
||
|
lret = RegCreateKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_SCHEDCDF, 0, NULL,
|
||
|
REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, NULL);
|
||
|
}
|
||
|
|
||
|
if (ERROR_SUCCESS == lret)
|
||
|
{
|
||
|
lret = RegQueryValueEx(hKey, REGSTR_VAL_CDFURLPATH, 0, NULL, NULL, &cbSize);
|
||
|
|
||
|
if (ERROR_SUCCESS == lret)
|
||
|
{
|
||
|
lpszTemp = (LPSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, cbSize+1);
|
||
|
if (lpszTemp)
|
||
|
{
|
||
|
lret = RegQueryValueEx(hKey, REGSTR_VAL_CDFURLPATH, 0, NULL,
|
||
|
(LPBYTE)lpszTemp, &cbSize);
|
||
|
}
|
||
|
}
|
||
|
else // No URL Path to the CDF Found.. use default
|
||
|
{
|
||
|
lpszTemp = (LPSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
|
||
|
lstrlen("http://ohserv/users/davidhen/")+1);
|
||
|
if (lpszTemp)
|
||
|
{
|
||
|
lstrcpy(lpszTemp, "http://ohserv/users/davidhen/");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add the CDFName to the Path for the final URL
|
||
|
lpszCDFUrlPath = (LPSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
|
||
|
(lstrlen(lpszTemp) + lstrlen(lpszCDFName) + 1));
|
||
|
|
||
|
lstrcpy(lpszCDFUrlPath, lpszTemp);
|
||
|
lstrcat(lpszCDFUrlPath, lpszCDFName);
|
||
|
|
||
|
if (lpszTemp)
|
||
|
{
|
||
|
GlobalFree(lpszTemp);
|
||
|
lpszTemp = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (hKey)
|
||
|
{
|
||
|
lret = RegQueryValueEx(hKey, lpszCDFName, 0, NULL, NULL, &cbSize);
|
||
|
|
||
|
if (ERROR_SUCCESS == lret)
|
||
|
{
|
||
|
lpszCookie = (LPSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, cbSize+1);
|
||
|
if (lpszCookie)
|
||
|
{
|
||
|
lret = RegQueryValueEx(hKey, lpszCDFName, 0, NULL, (LPBYTE)lpszCookie,
|
||
|
&cbSize);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
do
|
||
|
{
|
||
|
hr = CoInitialize(NULL);
|
||
|
ASSERT(SUCCEEDED(hr));
|
||
|
|
||
|
hr = CoCreateInstance(CLSID_StdNotificationMgr, NULL, CLSCTX_INPROC,
|
||
|
IID_INotificationMgr, (void**)&pNotificationMgr);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
WriteToScreen("Error: Unable to CoCreateInstance NotificationMgr", NULL);
|
||
|
WriteToScreen(" CoCreateInstance returned:", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ASSERT(pNotificationMgr);
|
||
|
|
||
|
pSink = new MySink;
|
||
|
|
||
|
if (lpszCookie)
|
||
|
{
|
||
|
// MAKE_WIDEPTR_FROMANSI is a macro which will create a wide string from an ansi string.
|
||
|
// The first parameter isn't defined before calling and it doesn't need to be freed.
|
||
|
// (handled by the temp buffer class destructor)
|
||
|
MAKE_WIDEPTR_FROMANSI(lpwszCookie, lpszCookie);
|
||
|
// Make a valid cookie from the wide string.
|
||
|
CLSIDFromString(lpwszCookie, &ncCookie);
|
||
|
|
||
|
NotItem.cbSize = sizeof(NOTIFICATIONITEM);
|
||
|
hr = pNotificationMgr->FindNotification(&ncCookie, &NotItem, 0);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
WriteToScreen("Found Scheduled Notification, Delivering Existing Notification", NULL);
|
||
|
WriteToScreen(" and waiting for End Report...", NULL);
|
||
|
hr = pNotificationMgr->DeliverNotification(NotItem.pNotification, CLSID_ChannelAgent,
|
||
|
(DELIVERMODE)DM_NEED_COMPLETIONREPORT, pSink, NULL, 0);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
WriteToScreen("Error 1: Unable to Deliver First Notification", NULL);
|
||
|
WriteToScreen(" DeliverNotification returned:", hr);
|
||
|
break;
|
||
|
}
|
||
|
WriteToScreen("First Notification Delivered. Waiting for End Report...", NULL);
|
||
|
|
||
|
// Delay until End Report recieved
|
||
|
g_iActive = 1;
|
||
|
while (g_iActive && GetMessage(&msg, NULL, 0, 0))
|
||
|
{
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
SAFERELEASE(NotItem.pNotification);
|
||
|
// For Debugging purposes we'll find the notification again to verify Task Trigger
|
||
|
// information for Auto Scheduling
|
||
|
NotItem.cbSize = sizeof (NOTIFICATIONITEM);
|
||
|
hr = pNotificationMgr->FindNotification(&ncCookie, &NotItem, 0);
|
||
|
SAFERELEASE(NotItem.pNotification);
|
||
|
WriteToScreen("Finished Successfully", NULL);
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
WriteToScreen("Warning, Cookie string found in registry but we were unable to find the", NULL);
|
||
|
WriteToScreen(" scheduled Notification. Creating a new notification instead", NULL);
|
||
|
// Because the notification couldn't be found we'll go through the same path as creating
|
||
|
// a new notification.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GetSystemTime(&st);
|
||
|
|
||
|
tt.cbTriggerSize = sizeof(TASK_TRIGGER);
|
||
|
tt.wBeginYear = st.wYear;
|
||
|
tt.wBeginMonth = st.wMonth;
|
||
|
tt.wBeginDay = st.wDay;
|
||
|
tt.wStartHour = st.wHour;
|
||
|
tt.wStartMinute = st.wMinute;
|
||
|
|
||
|
tt.MinutesInterval = 10;
|
||
|
tt.MinutesDuration = 60;
|
||
|
tt.Type.Daily.DaysInterval = 1;
|
||
|
tt.TriggerType = TASK_TIME_TRIGGER_DAILY;
|
||
|
tt.rgFlags = TASK_FLAG_DISABLED;
|
||
|
|
||
|
td.cbSize = sizeof(TASK_DATA);
|
||
|
td.dwTaskFlags = TASK_FLAG_START_ONLY_IF_IDLE;
|
||
|
|
||
|
|
||
|
hr = pNotificationMgr->CreateNotification(NOTIFICATIONTYPE_AGENT_START,
|
||
|
(NOTIFICATIONFLAGS) 0, NULL, &pNotification, 0);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
WriteToScreen("Error: Unable to CreateNotification", NULL);
|
||
|
WriteToScreen(" CreateNotification returned:", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ASSERT(pNotification);
|
||
|
|
||
|
MAKE_WIDEPTR_FROMANSI(lpwszCDFUrl, lpszCDFUrlPath);
|
||
|
|
||
|
WriteBSTR(pNotification, L"URL", lpwszCDFUrl);
|
||
|
WriteDWORD(pNotification, L"Priority", 0);
|
||
|
WriteDWORD(pNotification, L"RecurseLevels", 2);
|
||
|
WriteDWORD(pNotification, L"RecurseFlags", (DWORD)WEBCRAWL_LINKS_ELSEWHERE);
|
||
|
WriteDWORD(pNotification, L"ChannelFlags", (DWORD)CHANNEL_AGENT_DYNAMIC_SCHEDULE);
|
||
|
|
||
|
// WriteBSTR(pNotification, L"PostURL", L"http://ohserv/scripts/davidhen/davidhen.pl");
|
||
|
// WriteLONGLONG(pNotification, L"LogGroupID", (LONGLONG)0);
|
||
|
// WriteDWORD(pNotification, L"PostFailureRetry", 0);
|
||
|
|
||
|
hr = pNotificationMgr->ScheduleNotification(pNotification, CLSID_ChannelAgent,
|
||
|
&tt, &td, (DELIVERMODE)0, NULL, NULL, NULL, &ncCookie, 0);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
WriteToScreen("Error: ScheduleNotification Failed", NULL);
|
||
|
WriteToScreen(" ScheduleNotification returned:", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Save the cookie to the registry for future updates to this channel
|
||
|
if (hKey)
|
||
|
{
|
||
|
WCHAR wszCookie[GUIDSTR_MAX];
|
||
|
StringFromGUID2(ncCookie, wszCookie, sizeof(wszCookie));
|
||
|
|
||
|
MAKE_ANSIPTR_FROMWIDE(szCookie, wszCookie);
|
||
|
|
||
|
cbSize = lstrlen(szCookie)+1;
|
||
|
RegSetValueEx(hKey, lpszCDFName, 0, REG_SZ, (LPBYTE)szCookie, cbSize);
|
||
|
}
|
||
|
|
||
|
SAFERELEASE(pNotification);
|
||
|
|
||
|
NotItem.cbSize = sizeof (NOTIFICATIONITEM);
|
||
|
hr = pNotificationMgr->FindNotification(&ncCookie, &NotItem, 0);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
WriteToScreen("Error 1: Unable to Find Scheduled Notification", NULL);
|
||
|
WriteToScreen(" FindNotification returned:", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = pNotificationMgr->DeliverNotification(NotItem.pNotification, CLSID_ChannelAgent,
|
||
|
(DELIVERMODE)DM_NEED_COMPLETIONREPORT, pSink, NULL, 0);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
WriteToScreen("Error 1: Unable to Deliver First Notification", NULL);
|
||
|
WriteToScreen(" DeliverNotification returned:", hr);
|
||
|
break;
|
||
|
}
|
||
|
WriteToScreen("First Notification Delivered. Waiting for End Report...", NULL);
|
||
|
|
||
|
// Delay until End Report recieved
|
||
|
g_iActive = 1;
|
||
|
while (g_iActive && GetMessage(&msg, NULL, 0, 0))
|
||
|
{
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
SAFERELEASE(NotItem.pNotification);
|
||
|
NotItem.cbSize = sizeof (NOTIFICATIONITEM);
|
||
|
hr = pNotificationMgr->FindNotification(&ncCookie, &NotItem, 0);
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
WriteToScreen("Error 2: Unable to Find Scheduled Notification", NULL);
|
||
|
WriteToScreen(" FindNotification returned:", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = pNotificationMgr->DeliverNotification(NotItem.pNotification, CLSID_ChannelAgent,
|
||
|
(DELIVERMODE)DM_NEED_COMPLETIONREPORT, pSink, NULL, 0);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
WriteToScreen("Error 2: Unable to Deliver First Notification", NULL);
|
||
|
WriteToScreen(" DeliverNotification returned:", hr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
WriteToScreen("Second Notification Delivered. Waiting for End Report ...", NULL);
|
||
|
|
||
|
// Delay until End Report recieved
|
||
|
g_iActive = 1;
|
||
|
while (g_iActive && GetMessage(&msg, NULL, 0, 0))
|
||
|
{
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
WriteToScreen("Finished Successfully", NULL);
|
||
|
break;
|
||
|
}
|
||
|
while (TRUE);
|
||
|
|
||
|
SAFERELEASE(NotItem.pNotification);
|
||
|
SAFERELEASE(pNotification);
|
||
|
SAFERELEASE(pSink);
|
||
|
SAFERELEASE(pNotificationMgr);
|
||
|
|
||
|
if (hKey)
|
||
|
{
|
||
|
RegCloseKey(hKey);
|
||
|
hKey = NULL;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
BOOL CALLBACK UseOtherCDFDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
switch (iMsg)
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
{
|
||
|
HWND hwndEditBox = GetDlgItem(hDlg, IDC_CDFNAME);
|
||
|
SetFocus(hwndEditBox);
|
||
|
return TRUE;
|
||
|
}
|
||
|
case WM_COMMAND:
|
||
|
{
|
||
|
switch (LOWORD(wParam))
|
||
|
{
|
||
|
case IDOK:
|
||
|
{
|
||
|
int iLength = 0;
|
||
|
LPSTR lpszCDFName = NULL;
|
||
|
HWND hwndEditBox = GetDlgItem(hDlg, IDC_CDFNAME);
|
||
|
iLength = GetWindowTextLength(hwndEditBox);
|
||
|
|
||
|
if (0 == iLength)
|
||
|
{
|
||
|
MessageBox(NULL, "No CDF filename Specified.. Enter CDF filename before selecting OK", "Error", MB_OK);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
EndDialog(hDlg, 0);
|
||
|
lpszCDFName = (LPSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, iLength+1);
|
||
|
|
||
|
if (lpszCDFName)
|
||
|
{
|
||
|
GetWindowText(hwndEditBox, lpszCDFName, iLength+1);
|
||
|
|
||
|
StartOperation(lpszCDFName);
|
||
|
|
||
|
GlobalFree(lpszCDFName);
|
||
|
lpszCDFName = NULL;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
case IDCANCEL:
|
||
|
{
|
||
|
EndDialog(hDlg, 0);
|
||
|
return TRUE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Helper Functions
|
||
|
//
|
||
|
|
||
|
HRESULT WriteDWORD(IPropertyMap *pPropertyMap, LPWSTR szName, DWORD dwVal)
|
||
|
{
|
||
|
VARIANT Val;
|
||
|
|
||
|
Val.vt = VT_I4;
|
||
|
Val.lVal = dwVal;
|
||
|
|
||
|
return pPropertyMap->Write(szName, Val, 0);
|
||
|
}
|
||
|
|
||
|
HRESULT WriteBSTR(IPropertyMap *pPropertyMap, LPWSTR szName, LPWSTR szVal)
|
||
|
{
|
||
|
VARIANT Val;
|
||
|
|
||
|
Val.vt = VT_BSTR;
|
||
|
Val.bstrVal = SysAllocString(szVal);
|
||
|
|
||
|
HRESULT hr = pPropertyMap->Write(szName, Val, 0);
|
||
|
|
||
|
SysFreeString(Val.bstrVal);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT WriteLONGLONG(IPropertyMap *pPropertyMap, LPCWSTR szName, LONGLONG llVal)
|
||
|
{
|
||
|
VARIANT Val;
|
||
|
|
||
|
Val.vt = VT_CY;
|
||
|
Val.cyVal = *(CY *)&llVal;
|
||
|
|
||
|
return pPropertyMap->Write(szName, Val, 0);
|
||
|
}
|
||
|
|
||
|
HRESULT ReadBSTR(IPropertyMap *pPropertyMap, LPWSTR szName, BSTR *bstrRet)
|
||
|
{
|
||
|
VARIANT Val;
|
||
|
|
||
|
Val.vt = VT_EMPTY;
|
||
|
|
||
|
if (SUCCEEDED(pPropertyMap->Read(szName, &Val)) &&
|
||
|
(Val.vt==VT_BSTR))
|
||
|
{
|
||
|
*bstrRet = Val.bstrVal;
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
VariantClear(&Val); // free any return value of wrong type
|
||
|
*bstrRet = NULL;
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void WriteToScreen(LPSTR lpText, HRESULT hr)
|
||
|
{
|
||
|
char tmp[150];
|
||
|
int BufStrLength = 0;
|
||
|
int NewStrLength = 0;
|
||
|
LPSTR lpTempBuf = NULL;
|
||
|
|
||
|
if (!lpEditBuffer)
|
||
|
return;
|
||
|
|
||
|
if (hr)
|
||
|
{
|
||
|
wsprintf(tmp, "%s %x\r\n", lpText, hr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wsprintf(tmp, "%s\r\n", lpText);
|
||
|
}
|
||
|
|
||
|
BufStrLength = lstrlen(lpEditBuffer);
|
||
|
NewStrLength = lstrlen(tmp);
|
||
|
|
||
|
if ((BufStrLength + NewStrLength) >= g_BufSize)
|
||
|
{
|
||
|
lpEditBuffer = (LPSTR)GlobalReAlloc((HGLOBAL)lpEditBuffer, g_BufSize+4096, GMEM_FIXED | GMEM_ZEROINIT);
|
||
|
g_BufSize += 4096;
|
||
|
}
|
||
|
lstrcat(lpEditBuffer, tmp);
|
||
|
|
||
|
Edit_SetText(hwndEdit, lpEditBuffer);
|
||
|
|
||
|
}
|
||
|
|
||
|
HRESULT OnBeginReport(INotification *pNotification, INotificationReport *pNotificationReport)
|
||
|
{
|
||
|
DBGOut("BeginReport received");
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT OnEndReport(INotification *pNotification)
|
||
|
{
|
||
|
DBGOut("EndReport received");
|
||
|
|
||
|
BSTR bstrEndStatus=NULL;
|
||
|
|
||
|
ReadBSTR(pNotification, L"StatusString", &bstrEndStatus);
|
||
|
|
||
|
g_iActive = 0;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|