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