http://www.newsmth.net/nForum/#!article/DotNET/1472

 
拜康神教教主
身份
用户
文章
59325
积分
48578
等级
楠木(12)

发信人: RoachCock (奉旨挖坑陈三疯), 信区: MSDN
标  题: 用WMI获取网卡连接通知信息
发信站: 水木社区 (Fri Jun 10 18:15:21 2005), 站内
  
wpa_supplicant里的代码,略微改了一下,可以用来获得网卡的插拔,连接及断开等通知

/* 
  * 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; 
}