📄 ndis_events.c
字号:
/* * ndis_events - Receive NdisMIndicateStatus() events using WMI * Copyright (c) 2004-2006, Jouni Malinen <j@w1.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 "includes.h"#ifndef COBJMACROS#define COBJMACROS#endif /* COBJMACROS */#include <wbemidl.h>#include "common.h"static int wmi_refcnt = 0;static int wmi_first = 1;struct ndis_events_data { IWbemObjectSink sink; IWbemObjectSinkVtbl sink_vtbl; IWbemServices *pSvc; IWbemLocator *pLoc; HANDLE read_pipe, write_pipe, event_avail; UINT ref; int terminating; char *ifname; /* {GUID..} */ WCHAR *adapter_desc;};#define BstrAlloc(x) (x) ? SysAllocString(x) : NULL#define BstrFree(x) if (x) SysFreeString(x)/* WBEM / WMI wrapper functions, to perform in-place conversion of WCHARs to * BSTRs */HRESULT STDMETHODCALLTYPE call_IWbemServices_ExecQuery( IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery, long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum){ BSTR bsQueryLanguage, bsQuery; HRESULT hr; bsQueryLanguage = BstrAlloc(strQueryLanguage); bsQuery = BstrAlloc(strQuery); hr = IWbemServices_ExecQuery(pSvc, bsQueryLanguage, bsQuery, lFlags, pCtx, ppEnum); BstrFree(bsQueryLanguage); BstrFree(bsQuery); return hr;}HRESULT STDMETHODCALLTYPE call_IWbemServices_ExecNotificationQueryAsync( IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery, long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler){ BSTR bsQueryLanguage, bsQuery; HRESULT hr; bsQueryLanguage = BstrAlloc(strQueryLanguage); bsQuery = BstrAlloc(strQuery); hr = IWbemServices_ExecNotificationQueryAsync(pSvc, bsQueryLanguage, bsQuery, lFlags, pCtx, pResponseHandler); BstrFree(bsQueryLanguage); BstrFree(bsQuery); return hr;}HRESULT STDMETHODCALLTYPE call_IWbemLocator_ConnectServer( IWbemLocator *pLoc, LPCWSTR strNetworkResource, LPCWSTR strUser, LPCWSTR strPassword, LPCWSTR strLocale, long lSecurityFlags, LPCWSTR strAuthority, IWbemContext *pCtx, IWbemServices **ppNamespace){ BSTR bsNetworkResource, bsUser, bsPassword, bsLocale, bsAuthority; HRESULT hr; bsNetworkResource = BstrAlloc(strNetworkResource); bsUser = BstrAlloc(strUser); bsPassword = BstrAlloc(strPassword); bsLocale = BstrAlloc(strLocale); bsAuthority = BstrAlloc(strAuthority); hr = IWbemLocator_ConnectServer(pLoc, bsNetworkResource, bsUser, bsPassword, bsLocale, lSecurityFlags, bsAuthority, pCtx, ppNamespace); BstrFree(bsNetworkResource); BstrFree(bsUser); BstrFree(bsPassword); BstrFree(bsLocale); BstrFree(bsAuthority); return hr;}enum event_types { EVENT_CONNECT, EVENT_DISCONNECT, EVENT_MEDIA_SPECIFIC, EVENT_ADAPTER_ARRIVAL, EVENT_ADAPTER_REMOVAL };static int ndis_events_get_adapter(struct ndis_events_data *events, const char *ifname, const char *desc);static int ndis_events_constructor(struct ndis_events_data *events){ events->ref = 1; if (!CreatePipe(&events->read_pipe, &events->write_pipe, NULL, 512)) { wpa_printf(MSG_ERROR, "CreatePipe() failed: %d", (int) GetLastError()); return -1; } events->event_avail = CreateEvent(NULL, TRUE, FALSE, NULL); if (events->event_avail == NULL) { wpa_printf(MSG_ERROR, "CreateEvent() failed: %d", (int) GetLastError()); CloseHandle(events->read_pipe); CloseHandle(events->write_pipe); return -1; } return 0;}static void ndis_events_destructor(struct ndis_events_data *events){ CloseHandle(events->read_pipe); CloseHandle(events->write_pipe); CloseHandle(events->event_avail); IWbemServices_Release(events->pSvc); IWbemLocator_Release(events->pLoc); if (--wmi_refcnt == 0) CoUninitialize();}static HRESULT STDMETHODCALLTYPEndis_events_query_interface(IWbemObjectSink *this, REFIID riid, void **obj){ *obj = NULL; if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IWbemObjectSink)) { *obj = this; IWbemObjectSink_AddRef(this); return NOERROR; } return E_NOINTERFACE;}static ULONG STDMETHODCALLTYPE ndis_events_add_ref(IWbemObjectSink *this){ struct ndis_events_data *events = (struct ndis_events_data *) this; return ++events->ref;}static ULONG STDMETHODCALLTYPE ndis_events_release(IWbemObjectSink *this){ struct ndis_events_data *events = (struct ndis_events_data *) this; if (--events->ref != 0) return events->ref; ndis_events_destructor(events); wpa_printf(MSG_DEBUG, "ndis_events: terminated"); os_free(events->adapter_desc); os_free(events->ifname); os_free(events); return 0;}static int ndis_events_send_event(struct ndis_events_data *events, enum event_types type, char *data, size_t data_len){ char buf[512], *pos, *end; int _type; DWORD written; end = buf + sizeof(buf); _type = (int) type; os_memcpy(buf, &_type, sizeof(_type)); pos = buf + sizeof(_type); if (data) { if (2 + data_len > (size_t) (end - pos)) { wpa_printf(MSG_DEBUG, "Not enough room for send_event " "data (%d)", data_len); return -1; } *pos++ = data_len >> 8; *pos++ = data_len & 0xff; os_memcpy(pos, data, data_len); pos += data_len; } if (WriteFile(events->write_pipe, buf, pos - buf, &written, NULL)) { SetEvent(events->event_avail); return 0; } wpa_printf(MSG_INFO, "WriteFile() failed: %d", (int) GetLastError()); return -1;}static void ndis_events_media_connect(struct ndis_events_data *events){ wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaConnect"); ndis_events_send_event(events, EVENT_CONNECT, NULL, 0);}static void ndis_events_media_disconnect(struct ndis_events_data *events){ wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaDisconnect"); ndis_events_send_event(events, EVENT_DISCONNECT, NULL, 0);}static void ndis_events_media_specific(struct ndis_events_data *events, IWbemClassObject *pObj){ VARIANT vt; HRESULT hr; LONG lower, upper, k; UCHAR ch; char *data, *pos; size_t data_len; wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaSpecificIndication"); /* This is the StatusBuffer from NdisMIndicateStatus() call */ hr = IWbemClassObject_Get(pObj, L"NdisStatusMediaSpecificIndication", 0, &vt, NULL, NULL); if (FAILED(hr)) { wpa_printf(MSG_DEBUG, "Could not get " "NdisStatusMediaSpecificIndication from " "the object?!"); return; } SafeArrayGetLBound(V_ARRAY(&vt), 1, &lower); SafeArrayGetUBound(V_ARRAY(&vt), 1, &upper); data_len = upper - lower + 1; data = os_malloc(data_len); if (data == NULL) { wpa_printf(MSG_DEBUG, "Failed to allocate buffer for event " "data"); VariantClear(&vt); return; } pos = data; for (k = lower; k <= upper; k++) { SafeArrayGetElement(V_ARRAY(&vt), &k, &ch); *pos++ = ch; } wpa_hexdump(MSG_DEBUG, "MediaSpecificEvent", data, data_len); VariantClear(&vt); ndis_events_send_event(events, EVENT_MEDIA_SPECIFIC, data, data_len); os_free(data);}static void ndis_events_adapter_arrival(struct ndis_events_data *events){ wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterArrival"); ndis_events_send_event(events, EVENT_ADAPTER_ARRIVAL, NULL, 0);}static void ndis_events_adapter_removal(struct ndis_events_data *events){ wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterRemoval"); ndis_events_send_event(events, EVENT_ADAPTER_REMOVAL, NULL, 0);}static HRESULT STDMETHODCALLTYPEndis_events_indicate(IWbemObjectSink *this, long lObjectCount, IWbemClassObject __RPC_FAR *__RPC_FAR *ppObjArray){ struct ndis_events_data *events = (struct ndis_events_data *) this; long i; if (events->terminating) { wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore " "indication - terminating"); return WBEM_NO_ERROR; } /* wpa_printf(MSG_DEBUG, "Notification received - %d object(s)", lObjectCount); */ for (i = 0; i < lObjectCount; i++) { IWbemClassObject *pObj = ppObjArray[i]; HRESULT hr; VARIANT vtClass, vt; hr = IWbemClassObject_Get(pObj, L"__CLASS", 0, &vtClass, NULL, NULL); if (FAILED(hr)) { wpa_printf(MSG_DEBUG, "Failed to get __CLASS from " "event."); break; } /* wpa_printf(MSG_DEBUG, "CLASS: '%S'", vtClass.bstrVal); */ hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, NULL); if (FAILED(hr)) { wpa_printf(MSG_DEBUG, "Failed to get InstanceName " "from event."); VariantClear(&vtClass); break; } if (wcscmp(vtClass.bstrVal, L"MSNdis_NotifyAdapterArrival") == 0) { wpa_printf(MSG_DEBUG, "ndis_events_indicate: Try to " "update adapter description since it may " "have changed with new adapter instance"); ndis_events_get_adapter(events, events->ifname, NULL); } if (wcscmp(events->adapter_desc, vt.bstrVal) != 0) { wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore " "indication for foreign adapter: " "InstanceName: '%S' __CLASS: '%S'", vt.bstrVal, vtClass.bstrVal); VariantClear(&vtClass); VariantClear(&vt); continue; } VariantClear(&vt); if (wcscmp(vtClass.bstrVal, L"MSNdis_StatusMediaSpecificIndication") == 0) { ndis_events_media_specific(events, pObj); } else if (wcscmp(vtClass.bstrVal, L"MSNdis_StatusMediaConnect") == 0) { ndis_events_media_connect(events); } else if (wcscmp(vtClass.bstrVal, L"MSNdis_StatusMediaDisconnect") == 0) { ndis_events_media_disconnect(events); } else if (wcscmp(vtClass.bstrVal, L"MSNdis_NotifyAdapterArrival") == 0) { ndis_events_adapter_arrival(events); } else if (wcscmp(vtClass.bstrVal, L"MSNdis_NotifyAdapterRemoval") == 0) { ndis_events_adapter_removal(events); } else { wpa_printf(MSG_DEBUG, "Unepected event - __CLASS: " "'%S'", vtClass.bstrVal); } VariantClear(&vtClass); } return WBEM_NO_ERROR;}static HRESULT STDMETHODCALLTYPEndis_events_set_status(IWbemObjectSink *this, long lFlags, HRESULT hResult, BSTR strParam, IWbemClassObject __RPC_FAR *pObjParam){ return WBEM_NO_ERROR;}static int notification_query(IWbemObjectSink *pDestSink, IWbemServices *pSvc, const char *class_name){ HRESULT hr; WCHAR query[256];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -