Import moonshot-gss-eap_0.9.2.orig.tar.gz
[mech_eap.git] / libeap / src / drivers / ndis_events.c
diff --git a/libeap/src/drivers/ndis_events.c b/libeap/src/drivers/ndis_events.c
deleted file mode 100644 (file)
index f6eaa7c..0000000
+++ /dev/null
@@ -1,808 +0,0 @@
-/*
- * 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 STDMETHODCALLTYPE
-ndis_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", (u8 *) 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 STDMETHODCALLTYPE
-ndis_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 STDMETHODCALLTYPE
-ndis_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];
-
-       _snwprintf(query, 256,
-                 L"SELECT * FROM %S", class_name);
-       wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
-       hr = call_IWbemServices_ExecNotificationQueryAsync(
-               pSvc, L"WQL", query, 0, 0, pDestSink);
-       if (FAILED(hr)) {
-               wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for %s "
-                          "failed with hresult of 0x%x",
-                          class_name, (int) hr);
-               return -1;
-       }
-
-       return 0;
-}
-
-
-static int register_async_notification(IWbemObjectSink *pDestSink,
-                                      IWbemServices *pSvc)
-{
-       int i;
-       const char *class_list[] = {
-               "MSNdis_StatusMediaConnect",
-               "MSNdis_StatusMediaDisconnect",
-               "MSNdis_StatusMediaSpecificIndication",
-               "MSNdis_NotifyAdapterArrival",
-               "MSNdis_NotifyAdapterRemoval",
-               NULL
-       };
-
-       for (i = 0; class_list[i]; i++) {
-               if (notification_query(pDestSink, pSvc, class_list[i]) < 0)
-                       return -1;
-       }
-
-       return 0;
-}
-
-
-void ndis_events_deinit(struct ndis_events_data *events)
-{
-       events->terminating = 1;
-       IWbemServices_CancelAsyncCall(events->pSvc, &events->sink);
-       IWbemObjectSink_Release(&events->sink);
-       /*
-        * Rest of deinitialization is done in ndis_events_destructor() once
-        * all reference count drops to zero.
-        */
-}
-
-
-static int ndis_events_use_desc(struct ndis_events_data *events,
-                               const char *desc)
-{
-       char *tmp, *pos;
-       size_t len;
-
-       if (desc == NULL) {
-               if (events->adapter_desc == NULL)
-                       return -1;
-               /* Continue using old description */
-               return 0;
-       }
-
-       tmp = os_strdup(desc);
-       if (tmp == NULL)
-               return -1;
-
-       pos = os_strstr(tmp, " (Microsoft's Packet Scheduler)");
-       if (pos)
-               *pos = '\0';
-
-       len = os_strlen(tmp);
-       events->adapter_desc = os_malloc((len + 1) * sizeof(WCHAR));
-       if (events->adapter_desc == NULL) {
-               os_free(tmp);
-               return -1;
-       }
-       _snwprintf(events->adapter_desc, len + 1, L"%S", tmp);
-       os_free(tmp);
-       return 0;
-}
-
-
-static int ndis_events_get_adapter(struct ndis_events_data *events,
-                                  const char *ifname, const char *desc)
-{
-       HRESULT hr;
-       IWbemServices *pSvc;
-#define MAX_QUERY_LEN 256
-       WCHAR query[MAX_QUERY_LEN];
-       IEnumWbemClassObject *pEnumerator;
-       IWbemClassObject *pObj;
-       ULONG uReturned;
-       VARIANT vt;
-       int len, pos;
-
-       /*
-        * Try to get adapter descriptor through WMI CIMv2 Win32_NetworkAdapter
-        * to have better probability of matching with InstanceName from
-        * MSNdis events. If this fails, use the provided description.
-        */
-
-       os_free(events->adapter_desc);
-       events->adapter_desc = NULL;
-
-       hr = call_IWbemLocator_ConnectServer(
-               events->pLoc, L"ROOT\\CIMV2", NULL, NULL, 0, 0, 0, 0, &pSvc);
-       if (FAILED(hr)) {
-               wpa_printf(MSG_ERROR, "ndis_events: Could not connect to WMI "
-                          "server (ROOT\\CIMV2) - error 0x%x", (int) hr);
-               return ndis_events_use_desc(events, desc);
-       }
-       wpa_printf(MSG_DEBUG, "ndis_events: Connected to ROOT\\CIMV2.");
-
-       _snwprintf(query, MAX_QUERY_LEN,
-                 L"SELECT Index FROM Win32_NetworkAdapterConfiguration "
-                 L"WHERE SettingID='%S'", ifname);
-       wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
-
-       hr = call_IWbemServices_ExecQuery(
-               pSvc, L"WQL", query,
-               WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
-               NULL, &pEnumerator);
-       if (!SUCCEEDED(hr)) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
-                          "GUID from Win32_NetworkAdapterConfiguration: "
-                          "0x%x", (int) hr);
-               IWbemServices_Release(pSvc);
-               return ndis_events_use_desc(events, desc);
-       }
-
-       uReturned = 0;
-       hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
-                                      &pObj, &uReturned);
-       if (!SUCCEEDED(hr) || uReturned == 0) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
-                          "GUID from Win32_NetworkAdapterConfiguration: "
-                          "0x%x", (int) hr);
-               IEnumWbemClassObject_Release(pEnumerator);
-               IWbemServices_Release(pSvc);
-               return ndis_events_use_desc(events, desc);
-       }
-       IEnumWbemClassObject_Release(pEnumerator);
-
-       VariantInit(&vt);
-       hr = IWbemClassObject_Get(pObj, L"Index", 0, &vt, NULL, NULL);
-       if (!SUCCEEDED(hr)) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Index from "
-                          "Win32_NetworkAdapterConfiguration: 0x%x",
-                          (int) hr);
-               IWbemServices_Release(pSvc);
-               return ndis_events_use_desc(events, desc);
-       }
-
-       _snwprintf(query, MAX_QUERY_LEN,
-                 L"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE "
-                 L"Index=%d",
-                 vt.uintVal);
-       wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
-       VariantClear(&vt);
-       IWbemClassObject_Release(pObj);
-
-       hr = call_IWbemServices_ExecQuery(
-               pSvc, L"WQL", query,
-               WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
-               NULL, &pEnumerator);
-       if (!SUCCEEDED(hr)) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
-                          "from Win32_NetworkAdapter: 0x%x", (int) hr);
-               IWbemServices_Release(pSvc);
-               return ndis_events_use_desc(events, desc);
-       }
-
-       uReturned = 0;
-       hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
-                                      &pObj, &uReturned);
-       if (!SUCCEEDED(hr) || uReturned == 0) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
-                          "from Win32_NetworkAdapter: 0x%x", (int) hr);
-               IEnumWbemClassObject_Release(pEnumerator);
-               IWbemServices_Release(pSvc);
-               return ndis_events_use_desc(events, desc);
-       }
-       IEnumWbemClassObject_Release(pEnumerator);
-
-       hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL);
-       if (!SUCCEEDED(hr)) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from "
-                          "Win32_NetworkAdapter: 0x%x", (int) hr);
-               IWbemClassObject_Release(pObj);
-               IWbemServices_Release(pSvc);
-               return ndis_events_use_desc(events, desc);
-       }
-
-       wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::Name='%S'",
-                  vt.bstrVal);
-       events->adapter_desc = _wcsdup(vt.bstrVal);
-       VariantClear(&vt);
-
-       /*
-        * Try to get even better candidate for matching with InstanceName
-        * from Win32_PnPEntity. This is needed at least for some USB cards
-        * that can change the InstanceName whenever being unplugged and
-        * plugged again.
-        */
-
-       hr = IWbemClassObject_Get(pObj, L"PNPDeviceID", 0, &vt, NULL, NULL);
-       if (!SUCCEEDED(hr)) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to get PNPDeviceID "
-                          "from Win32_NetworkAdapter: 0x%x", (int) hr);
-               IWbemClassObject_Release(pObj);
-               IWbemServices_Release(pSvc);
-               if (events->adapter_desc == NULL)
-                       return ndis_events_use_desc(events, desc);
-               return 0; /* use Win32_NetworkAdapter::Name */
-       }
-
-       wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::PNPDeviceID="
-                  "'%S'", vt.bstrVal);
-
-       len = _snwprintf(query, MAX_QUERY_LEN,
-                       L"SELECT Name FROM Win32_PnPEntity WHERE DeviceID='");
-       if (len < 0 || len >= MAX_QUERY_LEN - 1) {
-               VariantClear(&vt);
-               IWbemClassObject_Release(pObj);
-               IWbemServices_Release(pSvc);
-               if (events->adapter_desc == NULL)
-                       return ndis_events_use_desc(events, desc);
-               return 0; /* use Win32_NetworkAdapter::Name */
-       }
-
-       /* Escape \ as \\ */
-       for (pos = 0; vt.bstrVal[pos] && len < MAX_QUERY_LEN - 2; pos++) {
-               if (vt.bstrVal[pos] == '\\') {
-                       if (len >= MAX_QUERY_LEN - 3)
-                               break;
-                       query[len++] = '\\';
-               }
-               query[len++] = vt.bstrVal[pos];
-       }
-       query[len++] = L'\'';
-       query[len] = L'\0';
-       VariantClear(&vt);
-       IWbemClassObject_Release(pObj);
-       wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
-
-       hr = call_IWbemServices_ExecQuery(
-               pSvc, L"WQL", query,
-               WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
-               NULL, &pEnumerator);
-       if (!SUCCEEDED(hr)) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
-                          "Name from Win32_PnPEntity: 0x%x", (int) hr);
-               IWbemServices_Release(pSvc);
-               if (events->adapter_desc == NULL)
-                       return ndis_events_use_desc(events, desc);
-               return 0; /* use Win32_NetworkAdapter::Name */
-       }
-
-       uReturned = 0;
-       hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
-                                      &pObj, &uReturned);
-       if (!SUCCEEDED(hr) || uReturned == 0) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
-                          "from Win32_PnPEntity: 0x%x", (int) hr);
-               IEnumWbemClassObject_Release(pEnumerator);
-               IWbemServices_Release(pSvc);
-               if (events->adapter_desc == NULL)
-                       return ndis_events_use_desc(events, desc);
-               return 0; /* use Win32_NetworkAdapter::Name */
-       }
-       IEnumWbemClassObject_Release(pEnumerator);
-
-       hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL);
-       if (!SUCCEEDED(hr)) {
-               wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from "
-                          "Win32_PnPEntity: 0x%x", (int) hr);
-               IWbemClassObject_Release(pObj);
-               IWbemServices_Release(pSvc);
-               if (events->adapter_desc == NULL)
-                       return ndis_events_use_desc(events, desc);
-               return 0; /* use Win32_NetworkAdapter::Name */
-       }
-
-       wpa_printf(MSG_DEBUG, "ndis_events: Win32_PnPEntity::Name='%S'",
-                  vt.bstrVal);
-       os_free(events->adapter_desc);
-       events->adapter_desc = _wcsdup(vt.bstrVal);
-       VariantClear(&vt);
-
-       IWbemClassObject_Release(pObj);
-
-       IWbemServices_Release(pSvc);
-
-       if (events->adapter_desc == NULL)
-               return ndis_events_use_desc(events, desc);
-
-       return 0;
-}
-
-
-struct ndis_events_data *
-ndis_events_init(HANDLE *read_pipe, HANDLE *event_avail,
-                const char *ifname, const char *desc)
-{
-       HRESULT hr;
-       IWbemObjectSink *pSink;
-       struct ndis_events_data *events;
-
-       events = os_zalloc(sizeof(*events));
-       if (events == NULL) {
-               wpa_printf(MSG_ERROR, "Could not allocate sink for events.");
-               return NULL;
-       }
-       events->ifname = os_strdup(ifname);
-       if (events->ifname == NULL) {
-               os_free(events);
-               return NULL;
-       }
-
-       if (wmi_refcnt++ == 0) {
-               hr = CoInitializeEx(0, COINIT_MULTITHREADED);
-               if (FAILED(hr)) {
-                       wpa_printf(MSG_ERROR, "CoInitializeEx() failed - "
-                                  "returned 0x%x", (int) hr);
-                       os_free(events);
-                       return NULL;
-               }
-       }
-
-       if (wmi_first) {
-               /* CoInitializeSecurity() must be called once and only once
-                * per process, so let's use wmi_first flag to protect against
-                * multiple calls. */
-               wmi_first = 0;
-
-               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)) {
-                       wpa_printf(MSG_ERROR, "CoInitializeSecurity() failed "
-                                  "- returned 0x%x", (int) hr);
-                       os_free(events);
-                       return NULL;
-               }
-       }
-
-       hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
-                             &IID_IWbemLocator,
-                             (LPVOID *) (void *) &events->pLoc);
-       if (FAILED(hr)) {
-               wpa_printf(MSG_ERROR, "CoCreateInstance() failed - returned "
-                          "0x%x", (int) hr);
-               CoUninitialize();
-               os_free(events);
-               return NULL;
-       }
-
-       if (ndis_events_get_adapter(events, ifname, desc) < 0) {
-               CoUninitialize();
-               os_free(events);
-               return NULL;
-       }
-       wpa_printf(MSG_DEBUG, "ndis_events: use adapter descriptor '%S'",
-                  events->adapter_desc);
-
-       hr = call_IWbemLocator_ConnectServer(
-               events->pLoc, L"ROOT\\WMI", NULL, NULL,
-               0, 0, 0, 0, &events->pSvc);
-       if (FAILED(hr)) {
-               wpa_printf(MSG_ERROR, "Could not connect to server - error "
-                          "0x%x", (int) hr);
-               CoUninitialize();
-               os_free(events->adapter_desc);
-               os_free(events);
-               return NULL;
-       }
-       wpa_printf(MSG_DEBUG, "Connected to ROOT\\WMI.");
-
-       ndis_events_constructor(events);
-       pSink = &events->sink;
-       pSink->lpVtbl = &events->sink_vtbl;
-       events->sink_vtbl.QueryInterface = ndis_events_query_interface;
-       events->sink_vtbl.AddRef = ndis_events_add_ref;
-       events->sink_vtbl.Release = ndis_events_release;
-       events->sink_vtbl.Indicate = ndis_events_indicate;
-       events->sink_vtbl.SetStatus = ndis_events_set_status;
-
-       if (register_async_notification(pSink, events->pSvc) < 0) {
-               wpa_printf(MSG_DEBUG, "Failed to register async "
-                          "notifications");
-               ndis_events_destructor(events);
-               os_free(events->adapter_desc);
-               os_free(events);
-               return NULL;
-       }
-
-       *read_pipe = events->read_pipe;
-       *event_avail = events->event_avail;
-
-       return events;
-}