1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/*
2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * ndis_events - Receive NdisMIndicateStatus() events using WMI
3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify
6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as
7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation.
8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license.
11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *
12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details.
13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */
14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define _WIN32_WINNT    0x0400
16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h"
18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifndef COBJMACROS
20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define COBJMACROS
21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* COBJMACROS */
22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <wbemidl.h>
23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h"
25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wmi_refcnt = 0;
28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wmi_first = 1;
29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ndis_events_data {
31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemObjectSink sink;
32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemObjectSinkVtbl sink_vtbl;
33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemServices *pSvc;
35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemLocator *pLoc;
36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HANDLE read_pipe, write_pipe, event_avail;
38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	UINT ref;
39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int terminating;
40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *ifname; /* {GUID..} */
41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	WCHAR *adapter_desc;
42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt};
43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define BstrAlloc(x) (x) ? SysAllocString(x) : NULL
45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define BstrFree(x) if (x) SysFreeString(x)
46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* WBEM / WMI wrapper functions, to perform in-place conversion of WCHARs to
48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * BSTRs */
49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtHRESULT STDMETHODCALLTYPE call_IWbemServices_ExecQuery(
50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery,
51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum)
52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BSTR bsQueryLanguage, bsQuery;
54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HRESULT hr;
55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bsQueryLanguage = BstrAlloc(strQueryLanguage);
57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bsQuery = BstrAlloc(strQuery);
58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IWbemServices_ExecQuery(pSvc, bsQueryLanguage, bsQuery, lFlags,
60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				     pCtx, ppEnum);
61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BstrFree(bsQueryLanguage);
63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BstrFree(bsQuery);
64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return hr;
66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtHRESULT STDMETHODCALLTYPE call_IWbemServices_ExecNotificationQueryAsync(
70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery,
71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler)
72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BSTR bsQueryLanguage, bsQuery;
74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HRESULT hr;
75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bsQueryLanguage = BstrAlloc(strQueryLanguage);
77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bsQuery = BstrAlloc(strQuery);
78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IWbemServices_ExecNotificationQueryAsync(pSvc, bsQueryLanguage,
80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						      bsQuery, lFlags, pCtx,
81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt						      pResponseHandler);
82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BstrFree(bsQueryLanguage);
84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BstrFree(bsQuery);
85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return hr;
87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry ShmidtHRESULT STDMETHODCALLTYPE call_IWbemLocator_ConnectServer(
91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemLocator *pLoc, LPCWSTR strNetworkResource, LPCWSTR strUser,
92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LPCWSTR strPassword, LPCWSTR strLocale, long lSecurityFlags,
93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LPCWSTR strAuthority, IWbemContext *pCtx, IWbemServices **ppNamespace)
94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BSTR bsNetworkResource, bsUser, bsPassword, bsLocale, bsAuthority;
96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HRESULT hr;
97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bsNetworkResource = BstrAlloc(strNetworkResource);
99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bsUser = BstrAlloc(strUser);
100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bsPassword = BstrAlloc(strPassword);
101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bsLocale = BstrAlloc(strLocale);
102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	bsAuthority = BstrAlloc(strAuthority);
103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IWbemLocator_ConnectServer(pLoc, bsNetworkResource, bsUser,
105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					bsPassword, bsLocale, lSecurityFlags,
106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					bsAuthority, pCtx, ppNamespace);
107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BstrFree(bsNetworkResource);
109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BstrFree(bsUser);
110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BstrFree(bsPassword);
111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BstrFree(bsLocale);
112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	BstrFree(bsAuthority);
113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return hr;
115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtenum event_types { EVENT_CONNECT, EVENT_DISCONNECT, EVENT_MEDIA_SPECIFIC,
119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   EVENT_ADAPTER_ARRIVAL, EVENT_ADAPTER_REMOVAL };
120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ndis_events_get_adapter(struct ndis_events_data *events,
122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   const char *ifname, const char *desc);
123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ndis_events_constructor(struct ndis_events_data *events)
126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->ref = 1;
128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!CreatePipe(&events->read_pipe, &events->write_pipe, NULL, 512)) {
130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CreatePipe() failed: %d",
131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->event_avail = CreateEvent(NULL, TRUE, FALSE, NULL);
135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (events->event_avail == NULL) {
136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CreateEvent() failed: %d",
137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) GetLastError());
138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(events->read_pipe);
139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CloseHandle(events->write_pipe);
140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ndis_events_destructor(struct ndis_events_data *events)
148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	CloseHandle(events->read_pipe);
150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	CloseHandle(events->write_pipe);
151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	CloseHandle(events->event_avail);
152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemServices_Release(events->pSvc);
153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemLocator_Release(events->pLoc);
154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (--wmi_refcnt == 0)
155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CoUninitialize();
156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic HRESULT STDMETHODCALLTYPE
160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtndis_events_query_interface(IWbemObjectSink *this, REFIID riid, void **obj)
161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*obj = NULL;
163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (IsEqualIID(riid, &IID_IUnknown) ||
165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	    IsEqualIID(riid, &IID_IWbemObjectSink)) {
166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*obj = this;
167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemObjectSink_AddRef(this);
168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NOERROR;
169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return E_NOINTERFACE;
172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic ULONG STDMETHODCALLTYPE ndis_events_add_ref(IWbemObjectSink *this)
176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ndis_events_data *events = (struct ndis_events_data *) this;
178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return ++events->ref;
179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic ULONG STDMETHODCALLTYPE ndis_events_release(IWbemObjectSink *this)
183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ndis_events_data *events = (struct ndis_events_data *) this;
185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (--events->ref != 0)
187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return events->ref;
188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ndis_events_destructor(events);
190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: terminated");
191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(events->adapter_desc);
192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(events->ifname);
193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(events);
194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ndis_events_send_event(struct ndis_events_data *events,
199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  enum event_types type,
200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  char *data, size_t data_len)
201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char buf[512], *pos, *end;
203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int _type;
204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	DWORD written;
205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	end = buf + sizeof(buf);
207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_type = (int) type;
208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_memcpy(buf, &_type, sizeof(_type));
209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = buf + sizeof(_type);
210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data) {
212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (2 + data_len > (size_t) (end - pos)) {
213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "Not enough room for send_event "
214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "data (%d)", data_len);
215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos++ = data_len >> 8;
218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos++ = data_len & 0xff;
219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_memcpy(pos, data, data_len);
220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pos += data_len;
221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (WriteFile(events->write_pipe, buf, pos - buf, &written, NULL)) {
224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SetEvent(events->event_avail);
225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_INFO, "WriteFile() failed: %d", (int) GetLastError());
228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return -1;
229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ndis_events_media_connect(struct ndis_events_data *events)
233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaConnect");
235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ndis_events_send_event(events, EVENT_CONNECT, NULL, 0);
236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ndis_events_media_disconnect(struct ndis_events_data *events)
240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaDisconnect");
242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ndis_events_send_event(events, EVENT_DISCONNECT, NULL, 0);
243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ndis_events_media_specific(struct ndis_events_data *events,
247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       IWbemClassObject *pObj)
248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	VARIANT vt;
250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HRESULT hr;
251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	LONG lower, upper, k;
252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	UCHAR ch;
253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *data, *pos;
254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t data_len;
255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaSpecificIndication");
257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* This is the StatusBuffer from NdisMIndicateStatus() call */
259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IWbemClassObject_Get(pObj, L"NdisStatusMediaSpecificIndication",
260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  0, &vt, NULL, NULL);
261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (FAILED(hr)) {
262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Could not get "
263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "NdisStatusMediaSpecificIndication from "
264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "the object?!");
265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SafeArrayGetLBound(V_ARRAY(&vt), 1, &lower);
269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	SafeArrayGetUBound(V_ARRAY(&vt), 1, &upper);
270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data_len = upper - lower + 1;
271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	data = os_malloc(data_len);
272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (data == NULL) {
273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Failed to allocate buffer for event "
274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "data");
275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		VariantClear(&vt);
276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return;
277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = data;
280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (k = lower; k <= upper; k++) {
281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		SafeArrayGetElement(V_ARRAY(&vt), &k, &ch);
282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos++ = ch;
283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_hexdump(MSG_DEBUG, "MediaSpecificEvent", (u8 *) data, data_len);
285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	VariantClear(&vt);
287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ndis_events_send_event(events, EVENT_MEDIA_SPECIFIC, data, data_len);
289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(data);
291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ndis_events_adapter_arrival(struct ndis_events_data *events)
295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterArrival");
297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ndis_events_send_event(events, EVENT_ADAPTER_ARRIVAL, NULL, 0);
298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void ndis_events_adapter_removal(struct ndis_events_data *events)
302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterRemoval");
304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ndis_events_send_event(events, EVENT_ADAPTER_REMOVAL, NULL, 0);
305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic HRESULT STDMETHODCALLTYPE
309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtndis_events_indicate(IWbemObjectSink *this, long lObjectCount,
310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		     IWbemClassObject __RPC_FAR *__RPC_FAR *ppObjArray)
311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ndis_events_data *events = (struct ndis_events_data *) this;
313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	long i;
314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (events->terminating) {
316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore "
317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "indication - terminating");
318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return WBEM_NO_ERROR;
319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* wpa_printf(MSG_DEBUG, "Notification received - %d object(s)",
321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	   lObjectCount); */
322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; i < lObjectCount; i++) {
324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemClassObject *pObj = ppObjArray[i];
325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		HRESULT hr;
326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		VARIANT vtClass, vt;
327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hr = IWbemClassObject_Get(pObj, L"__CLASS", 0, &vtClass, NULL,
329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  NULL);
330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (FAILED(hr)) {
331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to get __CLASS from "
332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "event.");
333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* wpa_printf(MSG_DEBUG, "CLASS: '%S'", vtClass.bstrVal); */
336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL,
338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  NULL);
339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (FAILED(hr)) {
340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "Failed to get InstanceName "
341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "from event.");
342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			VariantClear(&vtClass);
343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			break;
344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (wcscmp(vtClass.bstrVal,
347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   L"MSNdis_NotifyAdapterArrival") == 0) {
348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "ndis_events_indicate: Try to "
349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "update adapter description since it may "
350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "have changed with new adapter instance");
351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ndis_events_get_adapter(events, events->ifname, NULL);
352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (wcscmp(events->adapter_desc, vt.bstrVal) != 0) {
355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore "
356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "indication for foreign adapter: "
357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "InstanceName: '%S' __CLASS: '%S'",
358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   vt.bstrVal, vtClass.bstrVal);
359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			VariantClear(&vtClass);
360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			VariantClear(&vt);
361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			continue;
362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		VariantClear(&vt);
364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (wcscmp(vtClass.bstrVal,
366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   L"MSNdis_StatusMediaSpecificIndication") == 0) {
367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ndis_events_media_specific(events, pObj);
368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else if (wcscmp(vtClass.bstrVal,
369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  L"MSNdis_StatusMediaConnect") == 0) {
370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ndis_events_media_connect(events);
371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else if (wcscmp(vtClass.bstrVal,
372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  L"MSNdis_StatusMediaDisconnect") == 0) {
373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ndis_events_media_disconnect(events);
374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else if (wcscmp(vtClass.bstrVal,
375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  L"MSNdis_NotifyAdapterArrival") == 0) {
376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ndis_events_adapter_arrival(events);
377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else if (wcscmp(vtClass.bstrVal,
378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				  L"MSNdis_NotifyAdapterRemoval") == 0) {
379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			ndis_events_adapter_removal(events);
380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		} else {
381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_DEBUG, "Unepected event - __CLASS: "
382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "'%S'", vtClass.bstrVal);
383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		VariantClear(&vtClass);
386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return WBEM_NO_ERROR;
389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic HRESULT STDMETHODCALLTYPE
393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtndis_events_set_status(IWbemObjectSink *this, long lFlags, HRESULT hResult,
394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		       BSTR strParam, IWbemClassObject __RPC_FAR *pObjParam)
395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return WBEM_NO_ERROR;
397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int notification_query(IWbemObjectSink *pDestSink,
401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      IWbemServices *pSvc, const char *class_name)
402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HRESULT hr;
404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	WCHAR query[256];
405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_snwprintf(query, 256,
407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		  L"SELECT * FROM %S", class_name);
408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = call_IWbemServices_ExecNotificationQueryAsync(
410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pSvc, L"WQL", query, 0, 0, pDestSink);
411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (FAILED(hr)) {
412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for %s "
413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "failed with hresult of 0x%x",
414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   class_name, (int) hr);
415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int register_async_notification(IWbemObjectSink *pDestSink,
423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       IWbemServices *pSvc)
424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int i;
426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	const char *class_list[] = {
427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		"MSNdis_StatusMediaConnect",
428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		"MSNdis_StatusMediaDisconnect",
429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		"MSNdis_StatusMediaSpecificIndication",
430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		"MSNdis_NotifyAdapterArrival",
431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		"MSNdis_NotifyAdapterRemoval",
432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		NULL
433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	};
434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (i = 0; class_list[i]; i++) {
436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (notification_query(pDestSink, pSvc, class_list[i]) < 0)
437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtvoid ndis_events_deinit(struct ndis_events_data *events)
445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->terminating = 1;
447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemServices_CancelAsyncCall(events->pSvc, &events->sink);
448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemObjectSink_Release(&events->sink);
449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * Rest of deinitialization is done in ndis_events_destructor() once
451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * all reference count drops to zero.
452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ndis_events_use_desc(struct ndis_events_data *events,
457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				const char *desc)
458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	char *tmp, *pos;
460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	size_t len;
461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (desc == NULL) {
463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (events->adapter_desc == NULL)
464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return -1;
465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* Continue using old description */
466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0;
467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	tmp = os_strdup(desc);
470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (tmp == NULL)
471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pos = os_strstr(tmp, " (Microsoft's Packet Scheduler)");
474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (pos)
475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		*pos = '\0';
476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	len = os_strlen(tmp);
478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->adapter_desc = os_malloc((len + 1) * sizeof(WCHAR));
479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (events->adapter_desc == NULL) {
480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(tmp);
481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return -1;
482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_snwprintf(events->adapter_desc, len + 1, L"%S", tmp);
484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(tmp);
485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int ndis_events_get_adapter(struct ndis_events_data *events,
490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   const char *ifname, const char *desc)
491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HRESULT hr;
493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemServices *pSvc;
494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define MAX_QUERY_LEN 256
495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	WCHAR query[MAX_QUERY_LEN];
496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IEnumWbemClassObject *pEnumerator;
497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemClassObject *pObj;
498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ULONG uReturned;
499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	VARIANT vt;
500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	int len, pos;
501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * Try to get adapter descriptor through WMI CIMv2 Win32_NetworkAdapter
504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * to have better probability of matching with InstanceName from
505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * MSNdis events. If this fails, use the provided description.
506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(events->adapter_desc);
509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->adapter_desc = NULL;
510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = call_IWbemLocator_ConnectServer(
512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		events->pLoc, L"ROOT\\CIMV2", NULL, NULL, 0, 0, 0, 0, &pSvc);
513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (FAILED(hr)) {
514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "ndis_events: Could not connect to WMI "
515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "server (ROOT\\CIMV2) - error 0x%x", (int) hr);
516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return ndis_events_use_desc(events, desc);
517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: Connected to ROOT\\CIMV2.");
519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_snwprintf(query, MAX_QUERY_LEN,
521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		  L"SELECT Index FROM Win32_NetworkAdapterConfiguration "
522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		  L"WHERE SettingID='%S'", ifname);
523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = call_IWbemServices_ExecQuery(
526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pSvc, L"WQL", query,
527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		NULL, &pEnumerator);
529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr)) {
530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "GUID from Win32_NetworkAdapterConfiguration: "
532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "0x%x", (int) hr);
533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return ndis_events_use_desc(events, desc);
535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	uReturned = 0;
538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       &pObj, &uReturned);
540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr) || uReturned == 0) {
541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "GUID from Win32_NetworkAdapterConfiguration: "
543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "0x%x", (int) hr);
544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IEnumWbemClassObject_Release(pEnumerator);
545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return ndis_events_use_desc(events, desc);
547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IEnumWbemClassObject_Release(pEnumerator);
549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	VariantInit(&vt);
551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IWbemClassObject_Get(pObj, L"Index", 0, &vt, NULL, NULL);
552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr)) {
553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Index from "
554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "Win32_NetworkAdapterConfiguration: 0x%x",
555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   (int) hr);
556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return ndis_events_use_desc(events, desc);
558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	_snwprintf(query, MAX_QUERY_LEN,
561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		  L"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE "
562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		  L"Index=%d",
563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		  vt.uintVal);
564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	VariantClear(&vt);
566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemClassObject_Release(pObj);
567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = call_IWbemServices_ExecQuery(
569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pSvc, L"WQL", query,
570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		NULL, &pEnumerator);
572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr)) {
573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "from Win32_NetworkAdapter: 0x%x", (int) hr);
575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return ndis_events_use_desc(events, desc);
577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	uReturned = 0;
580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       &pObj, &uReturned);
582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr) || uReturned == 0) {
583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "from Win32_NetworkAdapter: 0x%x", (int) hr);
585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IEnumWbemClassObject_Release(pEnumerator);
586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return ndis_events_use_desc(events, desc);
588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IEnumWbemClassObject_Release(pEnumerator);
590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL);
592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr)) {
593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from "
594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "Win32_NetworkAdapter: 0x%x", (int) hr);
595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemClassObject_Release(pObj);
596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return ndis_events_use_desc(events, desc);
598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::Name='%S'",
601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   vt.bstrVal);
602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->adapter_desc = _wcsdup(vt.bstrVal);
603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	VariantClear(&vt);
604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/*
606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * Try to get even better candidate for matching with InstanceName
607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * from Win32_PnPEntity. This is needed at least for some USB cards
608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * that can change the InstanceName whenever being unplugged and
609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 * plugged again.
610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	 */
611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IWbemClassObject_Get(pObj, L"PNPDeviceID", 0, &vt, NULL, NULL);
613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr)) {
614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to get PNPDeviceID "
615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "from Win32_NetworkAdapter: 0x%x", (int) hr);
616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemClassObject_Release(pObj);
617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (events->adapter_desc == NULL)
619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return ndis_events_use_desc(events, desc);
620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0; /* use Win32_NetworkAdapter::Name */
621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::PNPDeviceID="
624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   "'%S'", vt.bstrVal);
625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	len = _snwprintf(query, MAX_QUERY_LEN,
627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			L"SELECT Name FROM Win32_PnPEntity WHERE DeviceID='");
628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (len < 0 || len >= MAX_QUERY_LEN - 1) {
629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		VariantClear(&vt);
630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemClassObject_Release(pObj);
631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (events->adapter_desc == NULL)
633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return ndis_events_use_desc(events, desc);
634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0; /* use Win32_NetworkAdapter::Name */
635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	/* Escape \ as \\ */
638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	for (pos = 0; vt.bstrVal[pos] && len < MAX_QUERY_LEN - 2; pos++) {
639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (vt.bstrVal[pos] == '\\') {
640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			if (len >= MAX_QUERY_LEN - 3)
641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				break;
642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			query[len++] = '\\';
643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		query[len++] = vt.bstrVal[pos];
645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	query[len++] = L'\'';
647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	query[len] = L'\0';
648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	VariantClear(&vt);
649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemClassObject_Release(pObj);
650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = call_IWbemServices_ExecQuery(
653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		pSvc, L"WQL", query,
654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		NULL, &pEnumerator);
656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr)) {
657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "Name from Win32_PnPEntity: 0x%x", (int) hr);
659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (events->adapter_desc == NULL)
661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return ndis_events_use_desc(events, desc);
662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0; /* use Win32_NetworkAdapter::Name */
663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	uReturned = 0;
666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				       &pObj, &uReturned);
668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr) || uReturned == 0) {
669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "from Win32_PnPEntity: 0x%x", (int) hr);
671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IEnumWbemClassObject_Release(pEnumerator);
672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (events->adapter_desc == NULL)
674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return ndis_events_use_desc(events, desc);
675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0; /* use Win32_NetworkAdapter::Name */
676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IEnumWbemClassObject_Release(pEnumerator);
678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL);
680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (!SUCCEEDED(hr)) {
681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from "
682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "Win32_PnPEntity: 0x%x", (int) hr);
683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemClassObject_Release(pObj);
684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		IWbemServices_Release(pSvc);
685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (events->adapter_desc == NULL)
686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return ndis_events_use_desc(events, desc);
687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return 0; /* use Win32_NetworkAdapter::Name */
688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: Win32_PnPEntity::Name='%S'",
691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   vt.bstrVal);
692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	os_free(events->adapter_desc);
693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->adapter_desc = _wcsdup(vt.bstrVal);
694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	VariantClear(&vt);
695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemClassObject_Release(pObj);
697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemServices_Release(pSvc);
699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (events->adapter_desc == NULL)
701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return ndis_events_use_desc(events, desc);
702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return 0;
704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ndis_events_data *
708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtndis_events_init(HANDLE *read_pipe, HANDLE *event_avail,
709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 const char *ifname, const char *desc)
710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{
711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	HRESULT hr;
712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	IWbemObjectSink *pSink;
713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	struct ndis_events_data *events;
714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events = os_zalloc(sizeof(*events));
716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (events == NULL) {
717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Could not allocate sink for events.");
718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->ifname = os_strdup(ifname);
721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (events->ifname == NULL) {
722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(events);
723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wmi_refcnt++ == 0) {
727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hr = CoInitializeEx(0, COINIT_MULTITHREADED);
728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (FAILED(hr)) {
729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "CoInitializeEx() failed - "
730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "returned 0x%x", (int) hr);
731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(events);
732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (wmi_first) {
737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		/* CoInitializeSecurity() must be called once and only once
738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * per process, so let's use wmi_first flag to protect against
739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		 * multiple calls. */
740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wmi_first = 0;
741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  RPC_C_IMP_LEVEL_IMPERSONATE,
745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt					  NULL, EOAC_SECURE_REFS, NULL);
746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		if (FAILED(hr)) {
747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			wpa_printf(MSG_ERROR, "CoInitializeSecurity() failed "
748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt				   "- returned 0x%x", (int) hr);
749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			os_free(events);
750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			return NULL;
751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		}
752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      &IID_IWbemLocator,
756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			      (LPVOID *) (void *) &events->pLoc);
757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (FAILED(hr)) {
758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "CoCreateInstance() failed - returned "
759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "0x%x", (int) hr);
760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CoUninitialize();
761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(events);
762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (ndis_events_get_adapter(events, ifname, desc) < 0) {
766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CoUninitialize();
767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(events);
768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "ndis_events: use adapter descriptor '%S'",
771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		   events->adapter_desc);
772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	hr = call_IWbemLocator_ConnectServer(
774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		events->pLoc, L"ROOT\\WMI", NULL, NULL,
775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		0, 0, 0, 0, &events->pSvc);
776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (FAILED(hr)) {
777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_ERROR, "Could not connect to server - error "
778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "0x%x", (int) hr);
779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		CoUninitialize();
780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(events->adapter_desc);
781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(events);
782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	wpa_printf(MSG_DEBUG, "Connected to ROOT\\WMI.");
785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	ndis_events_constructor(events);
787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pSink = &events->sink;
788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	pSink->lpVtbl = &events->sink_vtbl;
789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->sink_vtbl.QueryInterface = ndis_events_query_interface;
790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->sink_vtbl.AddRef = ndis_events_add_ref;
791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->sink_vtbl.Release = ndis_events_release;
792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->sink_vtbl.Indicate = ndis_events_indicate;
793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	events->sink_vtbl.SetStatus = ndis_events_set_status;
794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	if (register_async_notification(pSink, events->pSvc) < 0) {
796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		wpa_printf(MSG_DEBUG, "Failed to register async "
797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt			   "notifications");
798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		ndis_events_destructor(events);
799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(events->adapter_desc);
800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		os_free(events);
801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt		return NULL;
802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	}
803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*read_pipe = events->read_pipe;
805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	*event_avail = events->event_avail;
806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt
807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt	return events;
808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}
809