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.
147 lines
3.7 KiB
147 lines
3.7 KiB
//
|
|
// event.cxx - simple eventing mechanism for ras/offline/logon events
|
|
//
|
|
#include "wininetp.h"
|
|
#include <docobj.h>
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
static const TCHAR szEventKey[] = REGSTR_PATH_INETEVENTS;
|
|
|
|
CLSID clsidEventGroup = { /* ab8ed004-b86a-11d1-b1f8-00c04fa357fa */
|
|
0xab8ed004,
|
|
0xb86a,
|
|
0x11d1,
|
|
{0xb1, 0xf8, 0x00, 0xc0, 0x4f, 0xa3, 0x57, 0xfa}
|
|
};
|
|
|
|
//
|
|
// remember events so we don't repeat them
|
|
//
|
|
static DWORD g_dwOffline = 0;
|
|
|
|
//
|
|
// SendEvent - deliver an event to a single client
|
|
//
|
|
BOOL SendEvent(DWORD dwEvent, VARIANTARG *pva, LPTSTR pszValue)
|
|
{
|
|
CLSID clsid;
|
|
IOleCommandTarget *poct;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
#ifdef UNICODE
|
|
if(FAILED(CLSIDFromString(pszValue, &clsid)))
|
|
return FALSE;
|
|
#else
|
|
WCHAR wszCLSID[80];
|
|
MultiByteToWideChar(CP_ACP, 0, pszValue, -1, wszCLSID, sizeof(wszCLSID) / sizeof(WCHAR));
|
|
if(FAILED(CLSIDFromString(wszCLSID, &clsid)))
|
|
return FALSE;
|
|
#endif
|
|
|
|
|
|
hr = (CoCreateInstance(clsid, NULL, CLSCTX_ALL,
|
|
IID_IOleCommandTarget, (void **)&poct));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// ensure client likes our group
|
|
hr = poct->Exec(&clsidEventGroup, dwEvent, 0, pva, NULL);
|
|
poct->Release();
|
|
}
|
|
|
|
return SUCCEEDED(hr);
|
|
}
|
|
|
|
|
|
//
|
|
// EnumClients - send all events to clients in a reg key
|
|
//
|
|
DWORD EnumClients(HKEY hkey, DWORD dwEvent, LPWSTR pwsEventDesc, DWORD dwEventData)
|
|
{
|
|
DWORD cbData, cbValue, dwType, i, dwMask;
|
|
TCHAR szValueName[80];
|
|
VARIANTARG va;
|
|
|
|
va.vt = VT_EMPTY;
|
|
|
|
//
|
|
// Enumerate everyone
|
|
//
|
|
for (i = 0; ; i++)
|
|
{
|
|
LONG lEnum;
|
|
|
|
cbValue = sizeof(szValueName) / sizeof(TCHAR);
|
|
cbData = sizeof(DWORD);
|
|
|
|
// BUGBUG (Unicode, Davepl) I'm assuming that the data is UNICODE,
|
|
// but I'm not sure who put it there yet... double check.
|
|
|
|
if( ( lEnum = RegEnumValue( hkey, i, szValueName, &cbValue, NULL,
|
|
&dwType, (LPBYTE)&dwMask, &cbData ) ) == ERROR_MORE_DATA )
|
|
{
|
|
// ERROR_MORE_DATA means the value name or data was too large
|
|
// skip to the next item
|
|
continue;
|
|
}
|
|
else if( lEnum != ERROR_SUCCESS )
|
|
{
|
|
// could be ERROR_NO_MORE_ENTRIES, or some kind of failure
|
|
// we can't recover from any other registry problem, anyway
|
|
break;
|
|
}
|
|
|
|
if(0 != (dwMask & dwEvent)) {
|
|
// this guy wants this event
|
|
SendEvent(dwEvent, &va, szValueName);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// DispatchEvent - enumerate all clients and deliver the event to them
|
|
//
|
|
|
|
DWORD InternetDispatchEvent(DWORD dwEvent, LPWSTR pwsEventDesc, DWORD dwEventData)
|
|
{
|
|
HKEY hkey;
|
|
|
|
// get rid of repeated events here
|
|
switch(dwEvent) {
|
|
case INETEVT_OFFLINE:
|
|
if(g_dwOffline == dwEvent)
|
|
return 0;
|
|
g_dwOffline = dwEvent;
|
|
break;
|
|
case INETEVT_ONLINE:
|
|
if(g_dwOffline == dwEvent)
|
|
return 0;
|
|
g_dwOffline = dwEvent;
|
|
break;
|
|
default:
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// fire up com
|
|
if(SUCCEEDED(CoInitialize(NULL))) {
|
|
|
|
if (REGOPENKEY(HKEY_CURRENT_USER, szEventKey, &hkey) == ERROR_SUCCESS) {
|
|
EnumClients(hkey, dwEvent, pwsEventDesc, dwEventData);
|
|
REGCLOSEKEY(hkey);
|
|
}
|
|
|
|
if (REGOPENKEY(HKEY_LOCAL_MACHINE, szEventKey, &hkey) == ERROR_SUCCESS) {
|
|
EnumClients(hkey, dwEvent, pwsEventDesc, dwEventData);
|
|
REGCLOSEKEY(hkey);
|
|
}
|
|
|
|
CoUninitialize();
|
|
}
|
|
|
|
return 0;
|
|
}
|