1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * ndis_events - Receive NdisMIndicateStatus() events using WMI 3e5b75505Sopenharmony_ci * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#define _WIN32_WINNT 0x0400 10e5b75505Sopenharmony_ci 11e5b75505Sopenharmony_ci#include "includes.h" 12e5b75505Sopenharmony_ci 13e5b75505Sopenharmony_ci#ifndef COBJMACROS 14e5b75505Sopenharmony_ci#define COBJMACROS 15e5b75505Sopenharmony_ci#endif /* COBJMACROS */ 16e5b75505Sopenharmony_ci#include <wbemidl.h> 17e5b75505Sopenharmony_ci 18e5b75505Sopenharmony_ci#include "common.h" 19e5b75505Sopenharmony_ci 20e5b75505Sopenharmony_ci 21e5b75505Sopenharmony_cistatic int wmi_refcnt = 0; 22e5b75505Sopenharmony_cistatic int wmi_first = 1; 23e5b75505Sopenharmony_ci 24e5b75505Sopenharmony_cistruct ndis_events_data { 25e5b75505Sopenharmony_ci IWbemObjectSink sink; 26e5b75505Sopenharmony_ci IWbemObjectSinkVtbl sink_vtbl; 27e5b75505Sopenharmony_ci 28e5b75505Sopenharmony_ci IWbemServices *pSvc; 29e5b75505Sopenharmony_ci IWbemLocator *pLoc; 30e5b75505Sopenharmony_ci 31e5b75505Sopenharmony_ci HANDLE read_pipe, write_pipe, event_avail; 32e5b75505Sopenharmony_ci UINT ref; 33e5b75505Sopenharmony_ci int terminating; 34e5b75505Sopenharmony_ci char *ifname; /* {GUID..} */ 35e5b75505Sopenharmony_ci WCHAR *adapter_desc; 36e5b75505Sopenharmony_ci}; 37e5b75505Sopenharmony_ci 38e5b75505Sopenharmony_ci#define BstrAlloc(x) (x) ? SysAllocString(x) : NULL 39e5b75505Sopenharmony_ci#define BstrFree(x) if (x) SysFreeString(x) 40e5b75505Sopenharmony_ci 41e5b75505Sopenharmony_ci/* WBEM / WMI wrapper functions, to perform in-place conversion of WCHARs to 42e5b75505Sopenharmony_ci * BSTRs */ 43e5b75505Sopenharmony_ciHRESULT STDMETHODCALLTYPE call_IWbemServices_ExecQuery( 44e5b75505Sopenharmony_ci IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery, 45e5b75505Sopenharmony_ci long lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum) 46e5b75505Sopenharmony_ci{ 47e5b75505Sopenharmony_ci BSTR bsQueryLanguage, bsQuery; 48e5b75505Sopenharmony_ci HRESULT hr; 49e5b75505Sopenharmony_ci 50e5b75505Sopenharmony_ci bsQueryLanguage = BstrAlloc(strQueryLanguage); 51e5b75505Sopenharmony_ci bsQuery = BstrAlloc(strQuery); 52e5b75505Sopenharmony_ci 53e5b75505Sopenharmony_ci hr = IWbemServices_ExecQuery(pSvc, bsQueryLanguage, bsQuery, lFlags, 54e5b75505Sopenharmony_ci pCtx, ppEnum); 55e5b75505Sopenharmony_ci 56e5b75505Sopenharmony_ci BstrFree(bsQueryLanguage); 57e5b75505Sopenharmony_ci BstrFree(bsQuery); 58e5b75505Sopenharmony_ci 59e5b75505Sopenharmony_ci return hr; 60e5b75505Sopenharmony_ci} 61e5b75505Sopenharmony_ci 62e5b75505Sopenharmony_ci 63e5b75505Sopenharmony_ciHRESULT STDMETHODCALLTYPE call_IWbemServices_ExecNotificationQueryAsync( 64e5b75505Sopenharmony_ci IWbemServices *pSvc, LPCWSTR strQueryLanguage, LPCWSTR strQuery, 65e5b75505Sopenharmony_ci long lFlags, IWbemContext *pCtx, IWbemObjectSink *pResponseHandler) 66e5b75505Sopenharmony_ci{ 67e5b75505Sopenharmony_ci BSTR bsQueryLanguage, bsQuery; 68e5b75505Sopenharmony_ci HRESULT hr; 69e5b75505Sopenharmony_ci 70e5b75505Sopenharmony_ci bsQueryLanguage = BstrAlloc(strQueryLanguage); 71e5b75505Sopenharmony_ci bsQuery = BstrAlloc(strQuery); 72e5b75505Sopenharmony_ci 73e5b75505Sopenharmony_ci hr = IWbemServices_ExecNotificationQueryAsync(pSvc, bsQueryLanguage, 74e5b75505Sopenharmony_ci bsQuery, lFlags, pCtx, 75e5b75505Sopenharmony_ci pResponseHandler); 76e5b75505Sopenharmony_ci 77e5b75505Sopenharmony_ci BstrFree(bsQueryLanguage); 78e5b75505Sopenharmony_ci BstrFree(bsQuery); 79e5b75505Sopenharmony_ci 80e5b75505Sopenharmony_ci return hr; 81e5b75505Sopenharmony_ci} 82e5b75505Sopenharmony_ci 83e5b75505Sopenharmony_ci 84e5b75505Sopenharmony_ciHRESULT STDMETHODCALLTYPE call_IWbemLocator_ConnectServer( 85e5b75505Sopenharmony_ci IWbemLocator *pLoc, LPCWSTR strNetworkResource, LPCWSTR strUser, 86e5b75505Sopenharmony_ci LPCWSTR strPassword, LPCWSTR strLocale, long lSecurityFlags, 87e5b75505Sopenharmony_ci LPCWSTR strAuthority, IWbemContext *pCtx, IWbemServices **ppNamespace) 88e5b75505Sopenharmony_ci{ 89e5b75505Sopenharmony_ci BSTR bsNetworkResource, bsUser, bsPassword, bsLocale, bsAuthority; 90e5b75505Sopenharmony_ci HRESULT hr; 91e5b75505Sopenharmony_ci 92e5b75505Sopenharmony_ci bsNetworkResource = BstrAlloc(strNetworkResource); 93e5b75505Sopenharmony_ci bsUser = BstrAlloc(strUser); 94e5b75505Sopenharmony_ci bsPassword = BstrAlloc(strPassword); 95e5b75505Sopenharmony_ci bsLocale = BstrAlloc(strLocale); 96e5b75505Sopenharmony_ci bsAuthority = BstrAlloc(strAuthority); 97e5b75505Sopenharmony_ci 98e5b75505Sopenharmony_ci hr = IWbemLocator_ConnectServer(pLoc, bsNetworkResource, bsUser, 99e5b75505Sopenharmony_ci bsPassword, bsLocale, lSecurityFlags, 100e5b75505Sopenharmony_ci bsAuthority, pCtx, ppNamespace); 101e5b75505Sopenharmony_ci 102e5b75505Sopenharmony_ci BstrFree(bsNetworkResource); 103e5b75505Sopenharmony_ci BstrFree(bsUser); 104e5b75505Sopenharmony_ci BstrFree(bsPassword); 105e5b75505Sopenharmony_ci BstrFree(bsLocale); 106e5b75505Sopenharmony_ci BstrFree(bsAuthority); 107e5b75505Sopenharmony_ci 108e5b75505Sopenharmony_ci return hr; 109e5b75505Sopenharmony_ci} 110e5b75505Sopenharmony_ci 111e5b75505Sopenharmony_ci 112e5b75505Sopenharmony_cienum event_types { EVENT_CONNECT, EVENT_DISCONNECT, EVENT_MEDIA_SPECIFIC, 113e5b75505Sopenharmony_ci EVENT_ADAPTER_ARRIVAL, EVENT_ADAPTER_REMOVAL }; 114e5b75505Sopenharmony_ci 115e5b75505Sopenharmony_cistatic int ndis_events_get_adapter(struct ndis_events_data *events, 116e5b75505Sopenharmony_ci const char *ifname, const char *desc); 117e5b75505Sopenharmony_ci 118e5b75505Sopenharmony_ci 119e5b75505Sopenharmony_cistatic int ndis_events_constructor(struct ndis_events_data *events) 120e5b75505Sopenharmony_ci{ 121e5b75505Sopenharmony_ci events->ref = 1; 122e5b75505Sopenharmony_ci 123e5b75505Sopenharmony_ci if (!CreatePipe(&events->read_pipe, &events->write_pipe, NULL, 512)) { 124e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "CreatePipe() failed: %d", 125e5b75505Sopenharmony_ci (int) GetLastError()); 126e5b75505Sopenharmony_ci return -1; 127e5b75505Sopenharmony_ci } 128e5b75505Sopenharmony_ci events->event_avail = CreateEvent(NULL, TRUE, FALSE, NULL); 129e5b75505Sopenharmony_ci if (events->event_avail == NULL) { 130e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "CreateEvent() failed: %d", 131e5b75505Sopenharmony_ci (int) GetLastError()); 132e5b75505Sopenharmony_ci CloseHandle(events->read_pipe); 133e5b75505Sopenharmony_ci CloseHandle(events->write_pipe); 134e5b75505Sopenharmony_ci return -1; 135e5b75505Sopenharmony_ci } 136e5b75505Sopenharmony_ci 137e5b75505Sopenharmony_ci return 0; 138e5b75505Sopenharmony_ci} 139e5b75505Sopenharmony_ci 140e5b75505Sopenharmony_ci 141e5b75505Sopenharmony_cistatic void ndis_events_destructor(struct ndis_events_data *events) 142e5b75505Sopenharmony_ci{ 143e5b75505Sopenharmony_ci CloseHandle(events->read_pipe); 144e5b75505Sopenharmony_ci CloseHandle(events->write_pipe); 145e5b75505Sopenharmony_ci CloseHandle(events->event_avail); 146e5b75505Sopenharmony_ci IWbemServices_Release(events->pSvc); 147e5b75505Sopenharmony_ci IWbemLocator_Release(events->pLoc); 148e5b75505Sopenharmony_ci if (--wmi_refcnt == 0) 149e5b75505Sopenharmony_ci CoUninitialize(); 150e5b75505Sopenharmony_ci} 151e5b75505Sopenharmony_ci 152e5b75505Sopenharmony_ci 153e5b75505Sopenharmony_cistatic HRESULT STDMETHODCALLTYPE 154e5b75505Sopenharmony_cindis_events_query_interface(IWbemObjectSink *this, REFIID riid, void **obj) 155e5b75505Sopenharmony_ci{ 156e5b75505Sopenharmony_ci *obj = NULL; 157e5b75505Sopenharmony_ci 158e5b75505Sopenharmony_ci if (IsEqualIID(riid, &IID_IUnknown) || 159e5b75505Sopenharmony_ci IsEqualIID(riid, &IID_IWbemObjectSink)) { 160e5b75505Sopenharmony_ci *obj = this; 161e5b75505Sopenharmony_ci IWbemObjectSink_AddRef(this); 162e5b75505Sopenharmony_ci return NOERROR; 163e5b75505Sopenharmony_ci } 164e5b75505Sopenharmony_ci 165e5b75505Sopenharmony_ci return E_NOINTERFACE; 166e5b75505Sopenharmony_ci} 167e5b75505Sopenharmony_ci 168e5b75505Sopenharmony_ci 169e5b75505Sopenharmony_cistatic ULONG STDMETHODCALLTYPE ndis_events_add_ref(IWbemObjectSink *this) 170e5b75505Sopenharmony_ci{ 171e5b75505Sopenharmony_ci struct ndis_events_data *events = (struct ndis_events_data *) this; 172e5b75505Sopenharmony_ci return ++events->ref; 173e5b75505Sopenharmony_ci} 174e5b75505Sopenharmony_ci 175e5b75505Sopenharmony_ci 176e5b75505Sopenharmony_cistatic ULONG STDMETHODCALLTYPE ndis_events_release(IWbemObjectSink *this) 177e5b75505Sopenharmony_ci{ 178e5b75505Sopenharmony_ci struct ndis_events_data *events = (struct ndis_events_data *) this; 179e5b75505Sopenharmony_ci 180e5b75505Sopenharmony_ci if (--events->ref != 0) 181e5b75505Sopenharmony_ci return events->ref; 182e5b75505Sopenharmony_ci 183e5b75505Sopenharmony_ci ndis_events_destructor(events); 184e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: terminated"); 185e5b75505Sopenharmony_ci os_free(events->adapter_desc); 186e5b75505Sopenharmony_ci os_free(events->ifname); 187e5b75505Sopenharmony_ci os_free(events); 188e5b75505Sopenharmony_ci return 0; 189e5b75505Sopenharmony_ci} 190e5b75505Sopenharmony_ci 191e5b75505Sopenharmony_ci 192e5b75505Sopenharmony_cistatic int ndis_events_send_event(struct ndis_events_data *events, 193e5b75505Sopenharmony_ci enum event_types type, 194e5b75505Sopenharmony_ci char *data, size_t data_len) 195e5b75505Sopenharmony_ci{ 196e5b75505Sopenharmony_ci char buf[512], *pos, *end; 197e5b75505Sopenharmony_ci int _type; 198e5b75505Sopenharmony_ci DWORD written; 199e5b75505Sopenharmony_ci 200e5b75505Sopenharmony_ci end = buf + sizeof(buf); 201e5b75505Sopenharmony_ci _type = (int) type; 202e5b75505Sopenharmony_ci os_memcpy(buf, &_type, sizeof(_type)); 203e5b75505Sopenharmony_ci pos = buf + sizeof(_type); 204e5b75505Sopenharmony_ci 205e5b75505Sopenharmony_ci if (data) { 206e5b75505Sopenharmony_ci if (2 + data_len > (size_t) (end - pos)) { 207e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Not enough room for send_event " 208e5b75505Sopenharmony_ci "data (%d)", data_len); 209e5b75505Sopenharmony_ci return -1; 210e5b75505Sopenharmony_ci } 211e5b75505Sopenharmony_ci *pos++ = data_len >> 8; 212e5b75505Sopenharmony_ci *pos++ = data_len & 0xff; 213e5b75505Sopenharmony_ci os_memcpy(pos, data, data_len); 214e5b75505Sopenharmony_ci pos += data_len; 215e5b75505Sopenharmony_ci } 216e5b75505Sopenharmony_ci 217e5b75505Sopenharmony_ci if (WriteFile(events->write_pipe, buf, pos - buf, &written, NULL)) { 218e5b75505Sopenharmony_ci SetEvent(events->event_avail); 219e5b75505Sopenharmony_ci return 0; 220e5b75505Sopenharmony_ci } 221e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, "WriteFile() failed: %d", (int) GetLastError()); 222e5b75505Sopenharmony_ci return -1; 223e5b75505Sopenharmony_ci} 224e5b75505Sopenharmony_ci 225e5b75505Sopenharmony_ci 226e5b75505Sopenharmony_cistatic void ndis_events_media_connect(struct ndis_events_data *events) 227e5b75505Sopenharmony_ci{ 228e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaConnect"); 229e5b75505Sopenharmony_ci ndis_events_send_event(events, EVENT_CONNECT, NULL, 0); 230e5b75505Sopenharmony_ci} 231e5b75505Sopenharmony_ci 232e5b75505Sopenharmony_ci 233e5b75505Sopenharmony_cistatic void ndis_events_media_disconnect(struct ndis_events_data *events) 234e5b75505Sopenharmony_ci{ 235e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaDisconnect"); 236e5b75505Sopenharmony_ci ndis_events_send_event(events, EVENT_DISCONNECT, NULL, 0); 237e5b75505Sopenharmony_ci} 238e5b75505Sopenharmony_ci 239e5b75505Sopenharmony_ci 240e5b75505Sopenharmony_cistatic void ndis_events_media_specific(struct ndis_events_data *events, 241e5b75505Sopenharmony_ci IWbemClassObject *pObj) 242e5b75505Sopenharmony_ci{ 243e5b75505Sopenharmony_ci VARIANT vt; 244e5b75505Sopenharmony_ci HRESULT hr; 245e5b75505Sopenharmony_ci LONG lower, upper, k; 246e5b75505Sopenharmony_ci UCHAR ch; 247e5b75505Sopenharmony_ci char *data, *pos; 248e5b75505Sopenharmony_ci size_t data_len; 249e5b75505Sopenharmony_ci 250e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaSpecificIndication"); 251e5b75505Sopenharmony_ci 252e5b75505Sopenharmony_ci /* This is the StatusBuffer from NdisMIndicateStatus() call */ 253e5b75505Sopenharmony_ci hr = IWbemClassObject_Get(pObj, L"NdisStatusMediaSpecificIndication", 254e5b75505Sopenharmony_ci 0, &vt, NULL, NULL); 255e5b75505Sopenharmony_ci if (FAILED(hr)) { 256e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Could not get " 257e5b75505Sopenharmony_ci "NdisStatusMediaSpecificIndication from " 258e5b75505Sopenharmony_ci "the object?!"); 259e5b75505Sopenharmony_ci return; 260e5b75505Sopenharmony_ci } 261e5b75505Sopenharmony_ci 262e5b75505Sopenharmony_ci SafeArrayGetLBound(V_ARRAY(&vt), 1, &lower); 263e5b75505Sopenharmony_ci SafeArrayGetUBound(V_ARRAY(&vt), 1, &upper); 264e5b75505Sopenharmony_ci data_len = upper - lower + 1; 265e5b75505Sopenharmony_ci data = os_malloc(data_len); 266e5b75505Sopenharmony_ci if (data == NULL) { 267e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Failed to allocate buffer for event " 268e5b75505Sopenharmony_ci "data"); 269e5b75505Sopenharmony_ci VariantClear(&vt); 270e5b75505Sopenharmony_ci return; 271e5b75505Sopenharmony_ci } 272e5b75505Sopenharmony_ci 273e5b75505Sopenharmony_ci pos = data; 274e5b75505Sopenharmony_ci for (k = lower; k <= upper; k++) { 275e5b75505Sopenharmony_ci SafeArrayGetElement(V_ARRAY(&vt), &k, &ch); 276e5b75505Sopenharmony_ci *pos++ = ch; 277e5b75505Sopenharmony_ci } 278e5b75505Sopenharmony_ci wpa_hexdump(MSG_DEBUG, "MediaSpecificEvent", (u8 *) data, data_len); 279e5b75505Sopenharmony_ci 280e5b75505Sopenharmony_ci VariantClear(&vt); 281e5b75505Sopenharmony_ci 282e5b75505Sopenharmony_ci ndis_events_send_event(events, EVENT_MEDIA_SPECIFIC, data, data_len); 283e5b75505Sopenharmony_ci 284e5b75505Sopenharmony_ci os_free(data); 285e5b75505Sopenharmony_ci} 286e5b75505Sopenharmony_ci 287e5b75505Sopenharmony_ci 288e5b75505Sopenharmony_cistatic void ndis_events_adapter_arrival(struct ndis_events_data *events) 289e5b75505Sopenharmony_ci{ 290e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterArrival"); 291e5b75505Sopenharmony_ci ndis_events_send_event(events, EVENT_ADAPTER_ARRIVAL, NULL, 0); 292e5b75505Sopenharmony_ci} 293e5b75505Sopenharmony_ci 294e5b75505Sopenharmony_ci 295e5b75505Sopenharmony_cistatic void ndis_events_adapter_removal(struct ndis_events_data *events) 296e5b75505Sopenharmony_ci{ 297e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterRemoval"); 298e5b75505Sopenharmony_ci ndis_events_send_event(events, EVENT_ADAPTER_REMOVAL, NULL, 0); 299e5b75505Sopenharmony_ci} 300e5b75505Sopenharmony_ci 301e5b75505Sopenharmony_ci 302e5b75505Sopenharmony_cistatic HRESULT STDMETHODCALLTYPE 303e5b75505Sopenharmony_cindis_events_indicate(IWbemObjectSink *this, long lObjectCount, 304e5b75505Sopenharmony_ci IWbemClassObject __RPC_FAR *__RPC_FAR *ppObjArray) 305e5b75505Sopenharmony_ci{ 306e5b75505Sopenharmony_ci struct ndis_events_data *events = (struct ndis_events_data *) this; 307e5b75505Sopenharmony_ci long i; 308e5b75505Sopenharmony_ci 309e5b75505Sopenharmony_ci if (events->terminating) { 310e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore " 311e5b75505Sopenharmony_ci "indication - terminating"); 312e5b75505Sopenharmony_ci return WBEM_NO_ERROR; 313e5b75505Sopenharmony_ci } 314e5b75505Sopenharmony_ci /* wpa_printf(MSG_DEBUG, "Notification received - %d object(s)", 315e5b75505Sopenharmony_ci lObjectCount); */ 316e5b75505Sopenharmony_ci 317e5b75505Sopenharmony_ci for (i = 0; i < lObjectCount; i++) { 318e5b75505Sopenharmony_ci IWbemClassObject *pObj = ppObjArray[i]; 319e5b75505Sopenharmony_ci HRESULT hr; 320e5b75505Sopenharmony_ci VARIANT vtClass, vt; 321e5b75505Sopenharmony_ci 322e5b75505Sopenharmony_ci hr = IWbemClassObject_Get(pObj, L"__CLASS", 0, &vtClass, NULL, 323e5b75505Sopenharmony_ci NULL); 324e5b75505Sopenharmony_ci if (FAILED(hr)) { 325e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Failed to get __CLASS from " 326e5b75505Sopenharmony_ci "event."); 327e5b75505Sopenharmony_ci break; 328e5b75505Sopenharmony_ci } 329e5b75505Sopenharmony_ci /* wpa_printf(MSG_DEBUG, "CLASS: '%S'", vtClass.bstrVal); */ 330e5b75505Sopenharmony_ci 331e5b75505Sopenharmony_ci hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, 332e5b75505Sopenharmony_ci NULL); 333e5b75505Sopenharmony_ci if (FAILED(hr)) { 334e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Failed to get InstanceName " 335e5b75505Sopenharmony_ci "from event."); 336e5b75505Sopenharmony_ci VariantClear(&vtClass); 337e5b75505Sopenharmony_ci break; 338e5b75505Sopenharmony_ci } 339e5b75505Sopenharmony_ci 340e5b75505Sopenharmony_ci if (wcscmp(vtClass.bstrVal, 341e5b75505Sopenharmony_ci L"MSNdis_NotifyAdapterArrival") == 0) { 342e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events_indicate: Try to " 343e5b75505Sopenharmony_ci "update adapter description since it may " 344e5b75505Sopenharmony_ci "have changed with new adapter instance"); 345e5b75505Sopenharmony_ci ndis_events_get_adapter(events, events->ifname, NULL); 346e5b75505Sopenharmony_ci } 347e5b75505Sopenharmony_ci 348e5b75505Sopenharmony_ci if (wcscmp(events->adapter_desc, vt.bstrVal) != 0) { 349e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore " 350e5b75505Sopenharmony_ci "indication for foreign adapter: " 351e5b75505Sopenharmony_ci "InstanceName: '%S' __CLASS: '%S'", 352e5b75505Sopenharmony_ci vt.bstrVal, vtClass.bstrVal); 353e5b75505Sopenharmony_ci VariantClear(&vtClass); 354e5b75505Sopenharmony_ci VariantClear(&vt); 355e5b75505Sopenharmony_ci continue; 356e5b75505Sopenharmony_ci } 357e5b75505Sopenharmony_ci VariantClear(&vt); 358e5b75505Sopenharmony_ci 359e5b75505Sopenharmony_ci if (wcscmp(vtClass.bstrVal, 360e5b75505Sopenharmony_ci L"MSNdis_StatusMediaSpecificIndication") == 0) { 361e5b75505Sopenharmony_ci ndis_events_media_specific(events, pObj); 362e5b75505Sopenharmony_ci } else if (wcscmp(vtClass.bstrVal, 363e5b75505Sopenharmony_ci L"MSNdis_StatusMediaConnect") == 0) { 364e5b75505Sopenharmony_ci ndis_events_media_connect(events); 365e5b75505Sopenharmony_ci } else if (wcscmp(vtClass.bstrVal, 366e5b75505Sopenharmony_ci L"MSNdis_StatusMediaDisconnect") == 0) { 367e5b75505Sopenharmony_ci ndis_events_media_disconnect(events); 368e5b75505Sopenharmony_ci } else if (wcscmp(vtClass.bstrVal, 369e5b75505Sopenharmony_ci L"MSNdis_NotifyAdapterArrival") == 0) { 370e5b75505Sopenharmony_ci ndis_events_adapter_arrival(events); 371e5b75505Sopenharmony_ci } else if (wcscmp(vtClass.bstrVal, 372e5b75505Sopenharmony_ci L"MSNdis_NotifyAdapterRemoval") == 0) { 373e5b75505Sopenharmony_ci ndis_events_adapter_removal(events); 374e5b75505Sopenharmony_ci } else { 375e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Unepected event - __CLASS: " 376e5b75505Sopenharmony_ci "'%S'", vtClass.bstrVal); 377e5b75505Sopenharmony_ci } 378e5b75505Sopenharmony_ci 379e5b75505Sopenharmony_ci VariantClear(&vtClass); 380e5b75505Sopenharmony_ci } 381e5b75505Sopenharmony_ci 382e5b75505Sopenharmony_ci return WBEM_NO_ERROR; 383e5b75505Sopenharmony_ci} 384e5b75505Sopenharmony_ci 385e5b75505Sopenharmony_ci 386e5b75505Sopenharmony_cistatic HRESULT STDMETHODCALLTYPE 387e5b75505Sopenharmony_cindis_events_set_status(IWbemObjectSink *this, long lFlags, HRESULT hResult, 388e5b75505Sopenharmony_ci BSTR strParam, IWbemClassObject __RPC_FAR *pObjParam) 389e5b75505Sopenharmony_ci{ 390e5b75505Sopenharmony_ci return WBEM_NO_ERROR; 391e5b75505Sopenharmony_ci} 392e5b75505Sopenharmony_ci 393e5b75505Sopenharmony_ci 394e5b75505Sopenharmony_cistatic int notification_query(IWbemObjectSink *pDestSink, 395e5b75505Sopenharmony_ci IWbemServices *pSvc, const char *class_name) 396e5b75505Sopenharmony_ci{ 397e5b75505Sopenharmony_ci HRESULT hr; 398e5b75505Sopenharmony_ci WCHAR query[256]; 399e5b75505Sopenharmony_ci 400e5b75505Sopenharmony_ci _snwprintf(query, 256, 401e5b75505Sopenharmony_ci L"SELECT * FROM %S", class_name); 402e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); 403e5b75505Sopenharmony_ci hr = call_IWbemServices_ExecNotificationQueryAsync( 404e5b75505Sopenharmony_ci pSvc, L"WQL", query, 0, 0, pDestSink); 405e5b75505Sopenharmony_ci if (FAILED(hr)) { 406e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for %s " 407e5b75505Sopenharmony_ci "failed with hresult of 0x%x", 408e5b75505Sopenharmony_ci class_name, (int) hr); 409e5b75505Sopenharmony_ci return -1; 410e5b75505Sopenharmony_ci } 411e5b75505Sopenharmony_ci 412e5b75505Sopenharmony_ci return 0; 413e5b75505Sopenharmony_ci} 414e5b75505Sopenharmony_ci 415e5b75505Sopenharmony_ci 416e5b75505Sopenharmony_cistatic int register_async_notification(IWbemObjectSink *pDestSink, 417e5b75505Sopenharmony_ci IWbemServices *pSvc) 418e5b75505Sopenharmony_ci{ 419e5b75505Sopenharmony_ci int i; 420e5b75505Sopenharmony_ci const char *class_list[] = { 421e5b75505Sopenharmony_ci "MSNdis_StatusMediaConnect", 422e5b75505Sopenharmony_ci "MSNdis_StatusMediaDisconnect", 423e5b75505Sopenharmony_ci "MSNdis_StatusMediaSpecificIndication", 424e5b75505Sopenharmony_ci "MSNdis_NotifyAdapterArrival", 425e5b75505Sopenharmony_ci "MSNdis_NotifyAdapterRemoval", 426e5b75505Sopenharmony_ci NULL 427e5b75505Sopenharmony_ci }; 428e5b75505Sopenharmony_ci 429e5b75505Sopenharmony_ci for (i = 0; class_list[i]; i++) { 430e5b75505Sopenharmony_ci if (notification_query(pDestSink, pSvc, class_list[i]) < 0) 431e5b75505Sopenharmony_ci return -1; 432e5b75505Sopenharmony_ci } 433e5b75505Sopenharmony_ci 434e5b75505Sopenharmony_ci return 0; 435e5b75505Sopenharmony_ci} 436e5b75505Sopenharmony_ci 437e5b75505Sopenharmony_ci 438e5b75505Sopenharmony_civoid ndis_events_deinit(struct ndis_events_data *events) 439e5b75505Sopenharmony_ci{ 440e5b75505Sopenharmony_ci events->terminating = 1; 441e5b75505Sopenharmony_ci IWbemServices_CancelAsyncCall(events->pSvc, &events->sink); 442e5b75505Sopenharmony_ci IWbemObjectSink_Release(&events->sink); 443e5b75505Sopenharmony_ci /* 444e5b75505Sopenharmony_ci * Rest of deinitialization is done in ndis_events_destructor() once 445e5b75505Sopenharmony_ci * all reference count drops to zero. 446e5b75505Sopenharmony_ci */ 447e5b75505Sopenharmony_ci} 448e5b75505Sopenharmony_ci 449e5b75505Sopenharmony_ci 450e5b75505Sopenharmony_cistatic int ndis_events_use_desc(struct ndis_events_data *events, 451e5b75505Sopenharmony_ci const char *desc) 452e5b75505Sopenharmony_ci{ 453e5b75505Sopenharmony_ci char *tmp, *pos; 454e5b75505Sopenharmony_ci size_t len; 455e5b75505Sopenharmony_ci 456e5b75505Sopenharmony_ci if (desc == NULL) { 457e5b75505Sopenharmony_ci if (events->adapter_desc == NULL) 458e5b75505Sopenharmony_ci return -1; 459e5b75505Sopenharmony_ci /* Continue using old description */ 460e5b75505Sopenharmony_ci return 0; 461e5b75505Sopenharmony_ci } 462e5b75505Sopenharmony_ci 463e5b75505Sopenharmony_ci tmp = os_strdup(desc); 464e5b75505Sopenharmony_ci if (tmp == NULL) 465e5b75505Sopenharmony_ci return -1; 466e5b75505Sopenharmony_ci 467e5b75505Sopenharmony_ci pos = os_strstr(tmp, " (Microsoft's Packet Scheduler)"); 468e5b75505Sopenharmony_ci if (pos) 469e5b75505Sopenharmony_ci *pos = '\0'; 470e5b75505Sopenharmony_ci 471e5b75505Sopenharmony_ci len = os_strlen(tmp); 472e5b75505Sopenharmony_ci events->adapter_desc = os_malloc((len + 1) * sizeof(WCHAR)); 473e5b75505Sopenharmony_ci if (events->adapter_desc == NULL) { 474e5b75505Sopenharmony_ci os_free(tmp); 475e5b75505Sopenharmony_ci return -1; 476e5b75505Sopenharmony_ci } 477e5b75505Sopenharmony_ci _snwprintf(events->adapter_desc, len + 1, L"%S", tmp); 478e5b75505Sopenharmony_ci os_free(tmp); 479e5b75505Sopenharmony_ci return 0; 480e5b75505Sopenharmony_ci} 481e5b75505Sopenharmony_ci 482e5b75505Sopenharmony_ci 483e5b75505Sopenharmony_cistatic int ndis_events_get_adapter(struct ndis_events_data *events, 484e5b75505Sopenharmony_ci const char *ifname, const char *desc) 485e5b75505Sopenharmony_ci{ 486e5b75505Sopenharmony_ci HRESULT hr; 487e5b75505Sopenharmony_ci IWbemServices *pSvc; 488e5b75505Sopenharmony_ci#define MAX_QUERY_LEN 256 489e5b75505Sopenharmony_ci WCHAR query[MAX_QUERY_LEN]; 490e5b75505Sopenharmony_ci IEnumWbemClassObject *pEnumerator; 491e5b75505Sopenharmony_ci IWbemClassObject *pObj; 492e5b75505Sopenharmony_ci ULONG uReturned; 493e5b75505Sopenharmony_ci VARIANT vt; 494e5b75505Sopenharmony_ci int len, pos; 495e5b75505Sopenharmony_ci 496e5b75505Sopenharmony_ci /* 497e5b75505Sopenharmony_ci * Try to get adapter descriptor through WMI CIMv2 Win32_NetworkAdapter 498e5b75505Sopenharmony_ci * to have better probability of matching with InstanceName from 499e5b75505Sopenharmony_ci * MSNdis events. If this fails, use the provided description. 500e5b75505Sopenharmony_ci */ 501e5b75505Sopenharmony_ci 502e5b75505Sopenharmony_ci os_free(events->adapter_desc); 503e5b75505Sopenharmony_ci events->adapter_desc = NULL; 504e5b75505Sopenharmony_ci 505e5b75505Sopenharmony_ci hr = call_IWbemLocator_ConnectServer( 506e5b75505Sopenharmony_ci events->pLoc, L"ROOT\\CIMV2", NULL, NULL, 0, 0, 0, 0, &pSvc); 507e5b75505Sopenharmony_ci if (FAILED(hr)) { 508e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "ndis_events: Could not connect to WMI " 509e5b75505Sopenharmony_ci "server (ROOT\\CIMV2) - error 0x%x", (int) hr); 510e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 511e5b75505Sopenharmony_ci } 512e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Connected to ROOT\\CIMV2."); 513e5b75505Sopenharmony_ci 514e5b75505Sopenharmony_ci _snwprintf(query, MAX_QUERY_LEN, 515e5b75505Sopenharmony_ci L"SELECT Index FROM Win32_NetworkAdapterConfiguration " 516e5b75505Sopenharmony_ci L"WHERE SettingID='%S'", ifname); 517e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); 518e5b75505Sopenharmony_ci 519e5b75505Sopenharmony_ci hr = call_IWbemServices_ExecQuery( 520e5b75505Sopenharmony_ci pSvc, L"WQL", query, 521e5b75505Sopenharmony_ci WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 522e5b75505Sopenharmony_ci NULL, &pEnumerator); 523e5b75505Sopenharmony_ci if (!SUCCEEDED(hr)) { 524e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " 525e5b75505Sopenharmony_ci "GUID from Win32_NetworkAdapterConfiguration: " 526e5b75505Sopenharmony_ci "0x%x", (int) hr); 527e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 528e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 529e5b75505Sopenharmony_ci } 530e5b75505Sopenharmony_ci 531e5b75505Sopenharmony_ci uReturned = 0; 532e5b75505Sopenharmony_ci hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, 533e5b75505Sopenharmony_ci &pObj, &uReturned); 534e5b75505Sopenharmony_ci if (!SUCCEEDED(hr) || uReturned == 0) { 535e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " 536e5b75505Sopenharmony_ci "GUID from Win32_NetworkAdapterConfiguration: " 537e5b75505Sopenharmony_ci "0x%x", (int) hr); 538e5b75505Sopenharmony_ci IEnumWbemClassObject_Release(pEnumerator); 539e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 540e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 541e5b75505Sopenharmony_ci } 542e5b75505Sopenharmony_ci IEnumWbemClassObject_Release(pEnumerator); 543e5b75505Sopenharmony_ci 544e5b75505Sopenharmony_ci VariantInit(&vt); 545e5b75505Sopenharmony_ci hr = IWbemClassObject_Get(pObj, L"Index", 0, &vt, NULL, NULL); 546e5b75505Sopenharmony_ci if (!SUCCEEDED(hr)) { 547e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Index from " 548e5b75505Sopenharmony_ci "Win32_NetworkAdapterConfiguration: 0x%x", 549e5b75505Sopenharmony_ci (int) hr); 550e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 551e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 552e5b75505Sopenharmony_ci } 553e5b75505Sopenharmony_ci 554e5b75505Sopenharmony_ci _snwprintf(query, MAX_QUERY_LEN, 555e5b75505Sopenharmony_ci L"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE " 556e5b75505Sopenharmony_ci L"Index=%d", 557e5b75505Sopenharmony_ci vt.uintVal); 558e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); 559e5b75505Sopenharmony_ci VariantClear(&vt); 560e5b75505Sopenharmony_ci IWbemClassObject_Release(pObj); 561e5b75505Sopenharmony_ci 562e5b75505Sopenharmony_ci hr = call_IWbemServices_ExecQuery( 563e5b75505Sopenharmony_ci pSvc, L"WQL", query, 564e5b75505Sopenharmony_ci WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 565e5b75505Sopenharmony_ci NULL, &pEnumerator); 566e5b75505Sopenharmony_ci if (!SUCCEEDED(hr)) { 567e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " 568e5b75505Sopenharmony_ci "from Win32_NetworkAdapter: 0x%x", (int) hr); 569e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 570e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 571e5b75505Sopenharmony_ci } 572e5b75505Sopenharmony_ci 573e5b75505Sopenharmony_ci uReturned = 0; 574e5b75505Sopenharmony_ci hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, 575e5b75505Sopenharmony_ci &pObj, &uReturned); 576e5b75505Sopenharmony_ci if (!SUCCEEDED(hr) || uReturned == 0) { 577e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " 578e5b75505Sopenharmony_ci "from Win32_NetworkAdapter: 0x%x", (int) hr); 579e5b75505Sopenharmony_ci IEnumWbemClassObject_Release(pEnumerator); 580e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 581e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 582e5b75505Sopenharmony_ci } 583e5b75505Sopenharmony_ci IEnumWbemClassObject_Release(pEnumerator); 584e5b75505Sopenharmony_ci 585e5b75505Sopenharmony_ci hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL); 586e5b75505Sopenharmony_ci if (!SUCCEEDED(hr)) { 587e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from " 588e5b75505Sopenharmony_ci "Win32_NetworkAdapter: 0x%x", (int) hr); 589e5b75505Sopenharmony_ci IWbemClassObject_Release(pObj); 590e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 591e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 592e5b75505Sopenharmony_ci } 593e5b75505Sopenharmony_ci 594e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::Name='%S'", 595e5b75505Sopenharmony_ci vt.bstrVal); 596e5b75505Sopenharmony_ci events->adapter_desc = _wcsdup(vt.bstrVal); 597e5b75505Sopenharmony_ci VariantClear(&vt); 598e5b75505Sopenharmony_ci 599e5b75505Sopenharmony_ci /* 600e5b75505Sopenharmony_ci * Try to get even better candidate for matching with InstanceName 601e5b75505Sopenharmony_ci * from Win32_PnPEntity. This is needed at least for some USB cards 602e5b75505Sopenharmony_ci * that can change the InstanceName whenever being unplugged and 603e5b75505Sopenharmony_ci * plugged again. 604e5b75505Sopenharmony_ci */ 605e5b75505Sopenharmony_ci 606e5b75505Sopenharmony_ci hr = IWbemClassObject_Get(pObj, L"PNPDeviceID", 0, &vt, NULL, NULL); 607e5b75505Sopenharmony_ci if (!SUCCEEDED(hr)) { 608e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to get PNPDeviceID " 609e5b75505Sopenharmony_ci "from Win32_NetworkAdapter: 0x%x", (int) hr); 610e5b75505Sopenharmony_ci IWbemClassObject_Release(pObj); 611e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 612e5b75505Sopenharmony_ci if (events->adapter_desc == NULL) 613e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 614e5b75505Sopenharmony_ci return 0; /* use Win32_NetworkAdapter::Name */ 615e5b75505Sopenharmony_ci } 616e5b75505Sopenharmony_ci 617e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::PNPDeviceID=" 618e5b75505Sopenharmony_ci "'%S'", vt.bstrVal); 619e5b75505Sopenharmony_ci 620e5b75505Sopenharmony_ci len = _snwprintf(query, MAX_QUERY_LEN, 621e5b75505Sopenharmony_ci L"SELECT Name FROM Win32_PnPEntity WHERE DeviceID='"); 622e5b75505Sopenharmony_ci if (len < 0 || len >= MAX_QUERY_LEN - 1) { 623e5b75505Sopenharmony_ci VariantClear(&vt); 624e5b75505Sopenharmony_ci IWbemClassObject_Release(pObj); 625e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 626e5b75505Sopenharmony_ci if (events->adapter_desc == NULL) 627e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 628e5b75505Sopenharmony_ci return 0; /* use Win32_NetworkAdapter::Name */ 629e5b75505Sopenharmony_ci } 630e5b75505Sopenharmony_ci 631e5b75505Sopenharmony_ci /* Escape \ as \\ */ 632e5b75505Sopenharmony_ci for (pos = 0; vt.bstrVal[pos] && len < MAX_QUERY_LEN - 2; pos++) { 633e5b75505Sopenharmony_ci if (vt.bstrVal[pos] == '\\') { 634e5b75505Sopenharmony_ci if (len >= MAX_QUERY_LEN - 3) 635e5b75505Sopenharmony_ci break; 636e5b75505Sopenharmony_ci query[len++] = '\\'; 637e5b75505Sopenharmony_ci } 638e5b75505Sopenharmony_ci query[len++] = vt.bstrVal[pos]; 639e5b75505Sopenharmony_ci } 640e5b75505Sopenharmony_ci query[len++] = L'\''; 641e5b75505Sopenharmony_ci query[len] = L'\0'; 642e5b75505Sopenharmony_ci VariantClear(&vt); 643e5b75505Sopenharmony_ci IWbemClassObject_Release(pObj); 644e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); 645e5b75505Sopenharmony_ci 646e5b75505Sopenharmony_ci hr = call_IWbemServices_ExecQuery( 647e5b75505Sopenharmony_ci pSvc, L"WQL", query, 648e5b75505Sopenharmony_ci WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 649e5b75505Sopenharmony_ci NULL, &pEnumerator); 650e5b75505Sopenharmony_ci if (!SUCCEEDED(hr)) { 651e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " 652e5b75505Sopenharmony_ci "Name from Win32_PnPEntity: 0x%x", (int) hr); 653e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 654e5b75505Sopenharmony_ci if (events->adapter_desc == NULL) 655e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 656e5b75505Sopenharmony_ci return 0; /* use Win32_NetworkAdapter::Name */ 657e5b75505Sopenharmony_ci } 658e5b75505Sopenharmony_ci 659e5b75505Sopenharmony_ci uReturned = 0; 660e5b75505Sopenharmony_ci hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, 661e5b75505Sopenharmony_ci &pObj, &uReturned); 662e5b75505Sopenharmony_ci if (!SUCCEEDED(hr) || uReturned == 0) { 663e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " 664e5b75505Sopenharmony_ci "from Win32_PnPEntity: 0x%x", (int) hr); 665e5b75505Sopenharmony_ci IEnumWbemClassObject_Release(pEnumerator); 666e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 667e5b75505Sopenharmony_ci if (events->adapter_desc == NULL) 668e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 669e5b75505Sopenharmony_ci return 0; /* use Win32_NetworkAdapter::Name */ 670e5b75505Sopenharmony_ci } 671e5b75505Sopenharmony_ci IEnumWbemClassObject_Release(pEnumerator); 672e5b75505Sopenharmony_ci 673e5b75505Sopenharmony_ci hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL); 674e5b75505Sopenharmony_ci if (!SUCCEEDED(hr)) { 675e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from " 676e5b75505Sopenharmony_ci "Win32_PnPEntity: 0x%x", (int) hr); 677e5b75505Sopenharmony_ci IWbemClassObject_Release(pObj); 678e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 679e5b75505Sopenharmony_ci if (events->adapter_desc == NULL) 680e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 681e5b75505Sopenharmony_ci return 0; /* use Win32_NetworkAdapter::Name */ 682e5b75505Sopenharmony_ci } 683e5b75505Sopenharmony_ci 684e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: Win32_PnPEntity::Name='%S'", 685e5b75505Sopenharmony_ci vt.bstrVal); 686e5b75505Sopenharmony_ci os_free(events->adapter_desc); 687e5b75505Sopenharmony_ci events->adapter_desc = _wcsdup(vt.bstrVal); 688e5b75505Sopenharmony_ci VariantClear(&vt); 689e5b75505Sopenharmony_ci 690e5b75505Sopenharmony_ci IWbemClassObject_Release(pObj); 691e5b75505Sopenharmony_ci 692e5b75505Sopenharmony_ci IWbemServices_Release(pSvc); 693e5b75505Sopenharmony_ci 694e5b75505Sopenharmony_ci if (events->adapter_desc == NULL) 695e5b75505Sopenharmony_ci return ndis_events_use_desc(events, desc); 696e5b75505Sopenharmony_ci 697e5b75505Sopenharmony_ci return 0; 698e5b75505Sopenharmony_ci} 699e5b75505Sopenharmony_ci 700e5b75505Sopenharmony_ci 701e5b75505Sopenharmony_cistruct ndis_events_data * 702e5b75505Sopenharmony_cindis_events_init(HANDLE *read_pipe, HANDLE *event_avail, 703e5b75505Sopenharmony_ci const char *ifname, const char *desc) 704e5b75505Sopenharmony_ci{ 705e5b75505Sopenharmony_ci HRESULT hr; 706e5b75505Sopenharmony_ci IWbemObjectSink *pSink; 707e5b75505Sopenharmony_ci struct ndis_events_data *events; 708e5b75505Sopenharmony_ci 709e5b75505Sopenharmony_ci events = os_zalloc(sizeof(*events)); 710e5b75505Sopenharmony_ci if (events == NULL) { 711e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Could not allocate sink for events."); 712e5b75505Sopenharmony_ci return NULL; 713e5b75505Sopenharmony_ci } 714e5b75505Sopenharmony_ci events->ifname = os_strdup(ifname); 715e5b75505Sopenharmony_ci if (events->ifname == NULL) { 716e5b75505Sopenharmony_ci os_free(events); 717e5b75505Sopenharmony_ci return NULL; 718e5b75505Sopenharmony_ci } 719e5b75505Sopenharmony_ci 720e5b75505Sopenharmony_ci if (wmi_refcnt++ == 0) { 721e5b75505Sopenharmony_ci hr = CoInitializeEx(0, COINIT_MULTITHREADED); 722e5b75505Sopenharmony_ci if (FAILED(hr)) { 723e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "CoInitializeEx() failed - " 724e5b75505Sopenharmony_ci "returned 0x%x", (int) hr); 725e5b75505Sopenharmony_ci os_free(events); 726e5b75505Sopenharmony_ci return NULL; 727e5b75505Sopenharmony_ci } 728e5b75505Sopenharmony_ci } 729e5b75505Sopenharmony_ci 730e5b75505Sopenharmony_ci if (wmi_first) { 731e5b75505Sopenharmony_ci /* CoInitializeSecurity() must be called once and only once 732e5b75505Sopenharmony_ci * per process, so let's use wmi_first flag to protect against 733e5b75505Sopenharmony_ci * multiple calls. */ 734e5b75505Sopenharmony_ci wmi_first = 0; 735e5b75505Sopenharmony_ci 736e5b75505Sopenharmony_ci hr = CoInitializeSecurity(NULL, -1, NULL, NULL, 737e5b75505Sopenharmony_ci RPC_C_AUTHN_LEVEL_PKT_PRIVACY, 738e5b75505Sopenharmony_ci RPC_C_IMP_LEVEL_IMPERSONATE, 739e5b75505Sopenharmony_ci NULL, EOAC_SECURE_REFS, NULL); 740e5b75505Sopenharmony_ci if (FAILED(hr)) { 741e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "CoInitializeSecurity() failed " 742e5b75505Sopenharmony_ci "- returned 0x%x", (int) hr); 743e5b75505Sopenharmony_ci os_free(events); 744e5b75505Sopenharmony_ci return NULL; 745e5b75505Sopenharmony_ci } 746e5b75505Sopenharmony_ci } 747e5b75505Sopenharmony_ci 748e5b75505Sopenharmony_ci hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, 749e5b75505Sopenharmony_ci &IID_IWbemLocator, 750e5b75505Sopenharmony_ci (LPVOID *) (void *) &events->pLoc); 751e5b75505Sopenharmony_ci if (FAILED(hr)) { 752e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "CoCreateInstance() failed - returned " 753e5b75505Sopenharmony_ci "0x%x", (int) hr); 754e5b75505Sopenharmony_ci CoUninitialize(); 755e5b75505Sopenharmony_ci os_free(events); 756e5b75505Sopenharmony_ci return NULL; 757e5b75505Sopenharmony_ci } 758e5b75505Sopenharmony_ci 759e5b75505Sopenharmony_ci if (ndis_events_get_adapter(events, ifname, desc) < 0) { 760e5b75505Sopenharmony_ci CoUninitialize(); 761e5b75505Sopenharmony_ci os_free(events); 762e5b75505Sopenharmony_ci return NULL; 763e5b75505Sopenharmony_ci } 764e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "ndis_events: use adapter descriptor '%S'", 765e5b75505Sopenharmony_ci events->adapter_desc); 766e5b75505Sopenharmony_ci 767e5b75505Sopenharmony_ci hr = call_IWbemLocator_ConnectServer( 768e5b75505Sopenharmony_ci events->pLoc, L"ROOT\\WMI", NULL, NULL, 769e5b75505Sopenharmony_ci 0, 0, 0, 0, &events->pSvc); 770e5b75505Sopenharmony_ci if (FAILED(hr)) { 771e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "Could not connect to server - error " 772e5b75505Sopenharmony_ci "0x%x", (int) hr); 773e5b75505Sopenharmony_ci CoUninitialize(); 774e5b75505Sopenharmony_ci os_free(events->adapter_desc); 775e5b75505Sopenharmony_ci os_free(events); 776e5b75505Sopenharmony_ci return NULL; 777e5b75505Sopenharmony_ci } 778e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Connected to ROOT\\WMI."); 779e5b75505Sopenharmony_ci 780e5b75505Sopenharmony_ci ndis_events_constructor(events); 781e5b75505Sopenharmony_ci pSink = &events->sink; 782e5b75505Sopenharmony_ci pSink->lpVtbl = &events->sink_vtbl; 783e5b75505Sopenharmony_ci events->sink_vtbl.QueryInterface = ndis_events_query_interface; 784e5b75505Sopenharmony_ci events->sink_vtbl.AddRef = ndis_events_add_ref; 785e5b75505Sopenharmony_ci events->sink_vtbl.Release = ndis_events_release; 786e5b75505Sopenharmony_ci events->sink_vtbl.Indicate = ndis_events_indicate; 787e5b75505Sopenharmony_ci events->sink_vtbl.SetStatus = ndis_events_set_status; 788e5b75505Sopenharmony_ci 789e5b75505Sopenharmony_ci if (register_async_notification(pSink, events->pSvc) < 0) { 790e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "Failed to register async " 791e5b75505Sopenharmony_ci "notifications"); 792e5b75505Sopenharmony_ci ndis_events_destructor(events); 793e5b75505Sopenharmony_ci os_free(events->adapter_desc); 794e5b75505Sopenharmony_ci os_free(events); 795e5b75505Sopenharmony_ci return NULL; 796e5b75505Sopenharmony_ci } 797e5b75505Sopenharmony_ci 798e5b75505Sopenharmony_ci *read_pipe = events->read_pipe; 799e5b75505Sopenharmony_ci *event_avail = events->event_avail; 800e5b75505Sopenharmony_ci 801e5b75505Sopenharmony_ci return events; 802e5b75505Sopenharmony_ci} 803