// // event.cxx - simple eventing mechanism for ras/offline/logon events // #include "wininetp.h" #include // // 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; }