http://www.newsmth.net/nForum/#!article/DotNET/1472
拜康神教教主
|
发信人: RoachCock (奉旨挖坑陈三疯), 信区: MSDN |
/* * ndis_events - test program for receiving NdisMIndicateStatus() * events * Copyright (c) 2004, Jouni Malinen <jkmaline@cc.hut.fi> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms * of BSD license. * * See README and COPYING for more details. */ #define _WIN32_WINNT 0x0400 #include <windows.h> #include <stdio.h> #include <wbemidl.h> #include <winsock.h> class CNdisSink; struct EVENT_HANDLER_MAP { const wchar_t* EventName; void (CNdisSink::*Handler)(IWbemClassObject *pObj); }; class CNdisSink : public IWbemObjectSink { public: CNdisSink(); ~CNdisSink(); // IUnknown members STDMETHOD(QueryInterface)(REFIID, LPVOID *); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // IWbemObjectSink members STDMETHOD(Indicate)( long lObjectCount, IWbemClassObject **ppObjArray); STDMETHOD(SetStatus)( long lFlags, HRESULT hResult, BSTR strParam, IWbemClassObject *pObjParam); public: int RegisterAsyncNotification(IWbemServices *pSvc); private: void AdapterArrival(IWbemClassObject *pObj){} void AdapterRemoval(IWbemClassObject *pObj){} void ResetStart(IWbemClassObject *pObj){} void ResetEnd(IWbemClassObject *pObj){} void LinkSpeedChange(IWbemClassObject *pObj){} void MediaConnect(IWbemClassObject *pObj); void MediaDisconnect(IWbemClassObject *pObj); void MediaSpecific(IWbemClassObject *pObj); void ProtocolBind(IWbemClassObject *pObj){} void ProtocolUnbind(IWbemClassObject *pObj){} void DevicePowerOn(IWbemClassObject *pObj){} void DevicePowerOff(IWbemClassObject *pObj){} private: static EVENT_HANDLER_MAP s_EventHandlerMap[]; UINT m_cRef; }; EVENT_HANDLER_MAP CNdisSink::s_EventHandlerMap[] = { { L"MSNdis_NotifyAdapterArrival", &CNdisSink::AdapterArrival }, { L"MSNdis_NotifyAdapterRemoval", &CNdisSink::AdapterRemoval }, { L"MSNdis_StatusResetStart", &CNdisSink::ResetStart }, { L"MSNdis_StatusResetEnd", &CNdisSink::ResetEnd }, { L"MSNdis_StatusLinkSpeedChange", &CNdisSink::LinkSpeedChange }, { L"MSNdis_StatusMediaConnect", &CNdisSink::MediaConnect }, { L"MSNdis_StatusMediaDisconnect", &CNdisSink::MediaDisconnect }, { L"MSNdis_StatusProtocolBind", &CNdisSink::ProtocolBind }, { L"MSNdis_StatusProtocolUnbind", &CNdisSink::ProtocolUnbind }, { L"MSNdis_StatusDevicePowerOn", &CNdisSink::DevicePowerOn }, { L"MSNdis_StatusDevicePowerOff", &CNdisSink::DevicePowerOff }, }; CNdisSink::CNdisSink() { m_cRef = 1; } CNdisSink::~CNdisSink() { } STDMETHODIMP CNdisSink::QueryInterface(REFIID riid, LPVOID *ppv) { *ppv = 0; if (riid == IID_IUnknown || riid == IID_IWbemObjectSink) { *ppv = (IWbemObjectSink *) this; AddRef(); return NOERROR; } return E_NOINTERFACE; } ULONG CNdisSink::AddRef() { return ++m_cRef; } ULONG CNdisSink::Release() { if (--m_cRef == 0) { delete this; return 0; } return m_cRef; } void CNdisSink::MediaConnect(IWbemClassObject *pObj) { } void CNdisSink::MediaDisconnect(IWbemClassObject *pObj) { } void CNdisSink::MediaSpecific(IWbemClassObject *pObj) { VARIANT vt; HRESULT hr; LONG lower, upper, k; UCHAR ch; char *data, *pos; size_t data_len; printf("MSNdis_StatusMediaSpecificIndication\n"); /* This is the StatusBuffer from NdisMIndicateStatus() call */ hr = pObj->Get(L"NdisStatusMediaSpecificIndication", 0, &vt, NULL, NULL); if (FAILED(hr)) { printf("Could not get NdisStatusMediaSpecificIndication from " "the object?!\n"); return; } SafeArrayGetLBound(V_ARRAY(&vt), 1, &lower); SafeArrayGetUBound(V_ARRAY(&vt), 1, &upper); data_len = upper - lower + 1; data = (char *) malloc(data_len); if (data == NULL) { printf("Failed to allocate buffer for event data\n"); VariantClear(&vt); return; } printf(" Data(len=%d):", data_len); pos = data; for (k = lower; k <= upper; k++) { SafeArrayGetElement(V_ARRAY(&vt), &k, &ch); *pos++ = ch; printf(" %02x", ch); } printf("\n"); VariantClear(&vt); hr = pObj->Get(L"InstanceName", 0, &vt, NULL, NULL); if (SUCCEEDED(hr)) { printf(" InstanceName: '%S'\n", vt.bstrVal); VariantClear(&vt); } free(data); } HRESULT CNdisSink::Indicate(long lObjectCount, IWbemClassObject __RPC_FAR *__RPC_FAR *ppObjArray) { //printf("Notification received - %d object(s)\n", lObjectCount); for (long i = 0; i < lObjectCount; i++) { IWbemClassObject *pObj = ppObjArray[i]; HRESULT hr; VARIANT vtClass; hr = pObj->Get(L"__CLASS", 0, &vtClass, NULL, NULL); if (FAILED(hr)) { printf("Failed to get __CLASS from event.\n"); break; } VARIANT vtInstanceName; hr = pObj->Get(L"InstanceName", 0, &vtInstanceName, NULL, NULL); if (FAILED(hr)) { printf("Failed to get __CLASS from event.\n"); continue; } for( size_t j = 0; j<sizeof(s_EventHandlerMap)/sizeof(s_EventHandlerMap[0]); ++j) { if(wcscmp( vtClass.bstrVal, s_EventHandlerMap[j].EventName) ==0) { if(s_EventHandlerMap[j].Handler) (this->*s_EventHandlerMap[j].Handler)(pObj); break; } } printf( "%S:\t'%S'\n", vtClass.bstrVal, vtInstanceName.bstrVal); VariantClear(&vtInstanceName); VariantClear(&vtClass); } return WBEM_NO_ERROR; } HRESULT CNdisSink::SetStatus( long lFlags, HRESULT hResult, BSTR strParam, IWbemClassObject *pObjParam) { printf("%s\n", "SetStatus"); return WBEM_NO_ERROR; } int CNdisSink::RegisterAsyncNotification(IWbemServices *pSvc) { wchar_t Sql[128]; for( size_t i=0; i<sizeof(s_EventHandlerMap)/sizeof(s_EventHandlerMap[0]); ++i) { wcsncpy(Sql, L"SELECT * FROM ", 128); wcsncat(Sql, s_EventHandlerMap[i].EventName, 128); if (pSvc->ExecNotificationQueryAsync( L"WQL", Sql, 0, 0, this) != 0) return -1; } return 0; } int main(int argc, char *argv[]) { HRESULT hr; hr = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hr)) { printf("CoInitializeEx() failed - returned 0x%x", hr); return -1; } hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_SECURE_REFS, NULL); if (FAILED(hr)) { printf("CoInitializeSecurity() failed - returned 0x%x", hr); return -1; } IWbemLocator *pLoc = NULL; hr = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hr)) { printf("CoCreateInstance() failed - returned 0x%x\n", hr); CoUninitialize(); return -1; } IWbemServices *pSvc = 0; hr = pLoc->ConnectServer( L"ROOT\\WMI", NULL, NULL, 0, 0, 0, 0, &pSvc); if (hr) { printf("Could not connect to server - error 0x%x\n", hr); CoUninitialize(); return -1; } printf("Connected to ROOT\\WMI.\n"); CNdisSink *pSink = new CNdisSink; if (pSink == NULL) { printf("Could not allocate sink for events.\n"); CoUninitialize(); return -1; } if (pSink->RegisterAsyncNotification(pSvc) < 0) { printf("Failed to register async notifications\n"); CoUninitialize(); return -1; } /* Just wait.. sink will be called with events.. */ while (getchar() != '\n'); pSvc->CancelAsyncCall(pSink); pSink->Release(); pSvc->Release(); pLoc->Release(); CoUninitialize(); return 0; }