/*
 * 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", 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 *) &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;
}
