225
211
VariantClear(&vt);
227
hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, NULL);
229
wpa_printf(MSG_DEBUG, " InstanceName: '%S'", vt.bstrVal);
230
ndis_events_send_event(events, EVENT_MEDIA_SPECIFIC,
231
vt.bstrVal, data, data_len);
213
ndis_events_send_event(events, EVENT_MEDIA_SPECIFIC, data, data_len);
239
static void ndis_events_adapter_arrival(struct ndis_events_data *events,
240
IWbemClassObject *pObj)
219
static void ndis_events_adapter_arrival(struct ndis_events_data *events)
244
wpa_printf(MSG_DEBUG, "MSNdis_NotifierAdapterArrival");
245
hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, NULL);
247
wpa_printf(MSG_DEBUG, " InstanceName: '%S'", vt.bstrVal);
248
ndis_events_send_event(events, EVENT_ADAPTER_ARRIVAL,
249
vt.bstrVal, NULL, 0);
221
wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterArrival");
222
ndis_events_send_event(events, EVENT_ADAPTER_ARRIVAL, NULL, 0);
255
static void ndis_events_adapter_removal(struct ndis_events_data *events,
256
IWbemClassObject *pObj)
226
static void ndis_events_adapter_removal(struct ndis_events_data *events)
260
wpa_printf(MSG_DEBUG, "MSNdis_NotifierAdapterRemoval");
261
hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, NULL);
263
wpa_printf(MSG_DEBUG, " InstanceName: '%S'", vt.bstrVal);
264
ndis_events_send_event(events, EVENT_ADAPTER_REMOVAL,
265
vt.bstrVal, NULL, 0);
228
wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterRemoval");
229
ndis_events_send_event(events, EVENT_ADAPTER_REMOVAL, NULL, 0);
298
260
/* wpa_printf(MSG_DEBUG, "CLASS: '%S'", vtClass.bstrVal); */
262
hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL,
265
wpa_printf(MSG_DEBUG, "Failed to get InstanceName "
267
VariantClear(&vtClass);
271
if (wcscmp(vtClass.bstrVal,
272
L"MSNdis_NotifyAdapterArrival") == 0) {
273
wpa_printf(MSG_DEBUG, "ndis_events_indicate: Try to "
274
"update adapter description since it may "
275
"have changed with new adapter instance");
276
ndis_events_get_adapter(events, events->ifname, NULL);
279
if (wcscmp(events->adapter_desc, vt.bstrVal) != 0) {
280
wpa_printf(MSG_DEBUG, "ndis_events_indicate: Ignore "
281
"indication for foreign adapter: "
282
"InstanceName: '%S' __CLASS: '%S'",
283
vt.bstrVal, vtClass.bstrVal);
284
VariantClear(&vtClass);
300
290
if (wcscmp(vtClass.bstrVal,
301
291
L"MSNdis_StatusMediaSpecificIndication") == 0) {
302
292
ndis_events_media_specific(events, pObj);
303
293
} else if (wcscmp(vtClass.bstrVal,
304
294
L"MSNdis_StatusMediaConnect") == 0) {
305
ndis_events_media_connect(events, pObj);
295
ndis_events_media_connect(events);
306
296
} else if (wcscmp(vtClass.bstrVal,
307
297
L"MSNdis_StatusMediaDisconnect") == 0) {
308
ndis_events_media_disconnect(events, pObj);
298
ndis_events_media_disconnect(events);
309
299
} else if (wcscmp(vtClass.bstrVal,
310
300
L"MSNdis_NotifyAdapterArrival") == 0) {
311
ndis_events_adapter_arrival(events, pObj);
301
ndis_events_adapter_arrival(events);
312
302
} else if (wcscmp(vtClass.bstrVal,
313
303
L"MSNdis_NotifyAdapterRemoval") == 0) {
314
ndis_events_adapter_removal(events, pObj);
304
ndis_events_adapter_removal(events);
316
306
wpa_printf(MSG_DEBUG, "Unepected event - __CLASS: "
317
307
"'%S'", vtClass.bstrVal);
325
static int notification_query(IWbemObjectSink *pDestSink,
326
IWbemServices *pSvc, const char *class_name)
331
_snwprintf(query, 256,
332
L"SELECT * FROM %S", class_name);
333
wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
334
hr = IWbemServices_ExecNotificationQueryAsync(pSvc, L"WQL", query, 0,
337
wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for %s "
338
"failed with hresult of 0x%x",
339
class_name, (int) hr);
335
347
static int register_async_notification(IWbemObjectSink *pDestSink,
336
348
IWbemServices *pSvc)
340
BSTR lang = SysAllocString(L"WQL");
342
BSTR query = SysAllocString(
343
L"SELECT * FROM MSNdis_StatusMediaConnect");
344
hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
346
SysFreeString(query);
348
wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
349
"MSNdis_StatusMediaConnect failed with hresult of "
354
query = SysAllocString(
355
L"SELECT * FROM MSNdis_StatusMediaDisconnect");
356
hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
358
SysFreeString(query);
360
wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
361
"MSNdis_StatusMediaDisconnect failed with hresult "
362
"of 0x%x", (int) hr);
366
query = SysAllocString(
367
L"SELECT * FROM MSNdis_StatusMediaSpecificIndication");
368
hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
370
SysFreeString(query);
372
wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
373
"MSNdis_StatusMediaSpecificIndication failed with "
374
"hresult of 0x%x", (int) hr);
378
query = SysAllocString(
379
L"SELECT * FROM MSNdis_NotifyAdapterArrival");
380
hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
382
SysFreeString(query);
384
wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
385
"MSNdis_NotifyAdapterArrival failed with hresult "
386
"of 0x%x", (int) hr);
390
query = SysAllocString(
391
L"SELECT * FROM MSNdis_NotifyAdapterRemoval");
392
hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
394
SysFreeString(query);
396
wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
397
"MSNdis_NotifyAdapterRemoval failed with hresult "
398
"of 0x%x", (int) hr);
351
const char *class_list[] = {
352
"MSNdis_StatusMediaConnect",
353
"MSNdis_StatusMediaDisconnect",
354
"MSNdis_StatusMediaSpecificIndication",
355
"MSNdis_NotifyAdapterArrival",
356
"MSNdis_NotifyAdapterRemoval",
360
for (i = 0; class_list[i]; i++) {
361
if (notification_query(pDestSink, pSvc, class_list[i]) < 0)
381
static int ndis_events_use_desc(struct ndis_events_data *events,
388
if (events->adapter_desc == NULL)
390
/* Continue using old description */
398
pos = strstr(tmp, " (Microsoft's Packet Scheduler)");
403
events->adapter_desc = malloc((len + 1) * sizeof(WCHAR));
404
if (events->adapter_desc == NULL) {
408
_snwprintf(events->adapter_desc, len + 1, L"%S", tmp);
414
static int ndis_events_get_adapter(struct ndis_events_data *events,
415
const char *ifname, const char *desc)
419
#define MAX_QUERY_LEN 256
420
WCHAR query[MAX_QUERY_LEN];
421
IEnumWbemClassObject *pEnumerator;
422
IWbemClassObject *pObj;
428
* Try to get adapter descriptor through WMI CIMv2 Win32_NetworkAdapter
429
* to have better probability of matching with InstanceName from
430
* MSNdis events. If this fails, use the provided description.
433
free(events->adapter_desc);
434
events->adapter_desc = NULL;
436
hr = IWbemLocator_ConnectServer(events->pLoc, L"ROOT\\CIMV2", NULL,
437
NULL, 0, 0, 0, 0, &pSvc);
439
wpa_printf(MSG_ERROR, "ndis_events: Could not connect to WMI "
440
"server (ROOT\\CIMV2) - error 0x%x", (int) hr);
441
return ndis_events_use_desc(events, desc);
443
wpa_printf(MSG_DEBUG, "ndis_events: Connected to ROOT\\CIMV2.");
445
_snwprintf(query, MAX_QUERY_LEN,
446
L"SELECT Index FROM Win32_NetworkAdapterConfiguration "
447
L"WHERE SettingID='%S'", ifname);
448
wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
450
hr = IWbemServices_ExecQuery(pSvc, L"WQL", query,
451
WBEM_FLAG_FORWARD_ONLY |
452
WBEM_FLAG_RETURN_IMMEDIATELY,
454
if (!SUCCEEDED(hr)) {
455
wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
456
"GUID from Win32_NetworkAdapterConfiguration: "
458
IWbemServices_Release(pSvc);
459
return ndis_events_use_desc(events, desc);
463
hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
465
if (!SUCCEEDED(hr) || uReturned == 0) {
466
wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
467
"GUID from Win32_NetworkAdapterConfiguration: "
469
IEnumWbemClassObject_Release(pEnumerator);
470
IWbemServices_Release(pSvc);
471
return ndis_events_use_desc(events, desc);
473
IEnumWbemClassObject_Release(pEnumerator);
476
hr = IWbemClassObject_Get(pObj, L"Index", 0, &vt, NULL, NULL);
477
if (!SUCCEEDED(hr)) {
478
wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Index from "
479
"Win32_NetworkAdapterConfiguration: 0x%x",
481
IWbemServices_Release(pSvc);
482
return ndis_events_use_desc(events, desc);
485
_snwprintf(query, MAX_QUERY_LEN,
486
L"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE "
489
wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
491
IWbemClassObject_Release(pObj);
493
hr = IWbemServices_ExecQuery(pSvc, L"WQL", query,
494
WBEM_FLAG_FORWARD_ONLY |
495
WBEM_FLAG_RETURN_IMMEDIATELY,
497
if (!SUCCEEDED(hr)) {
498
wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
499
"from Win32_NetworkAdapter: 0x%x", (int) hr);
500
IWbemServices_Release(pSvc);
501
return ndis_events_use_desc(events, desc);
505
hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
507
if (!SUCCEEDED(hr) || uReturned == 0) {
508
wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
509
"from Win32_NetworkAdapter: 0x%x", (int) hr);
510
IEnumWbemClassObject_Release(pEnumerator);
511
IWbemServices_Release(pSvc);
512
return ndis_events_use_desc(events, desc);
514
IEnumWbemClassObject_Release(pEnumerator);
516
hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL);
517
if (!SUCCEEDED(hr)) {
518
wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from "
519
"Win32_NetworkAdapter: 0x%x", (int) hr);
520
IWbemClassObject_Release(pObj);
521
IWbemServices_Release(pSvc);
522
return ndis_events_use_desc(events, desc);
525
wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::Name='%S'",
527
events->adapter_desc = _wcsdup(vt.bstrVal);
531
* Try to get even better candidate for matching with InstanceName
532
* from Win32_PnPEntity. This is needed at least for some USB cards
533
* that can change the InstanceName whenever being unplugged and
537
hr = IWbemClassObject_Get(pObj, L"PNPDeviceID", 0, &vt, NULL, NULL);
538
if (!SUCCEEDED(hr)) {
539
wpa_printf(MSG_DEBUG, "ndis_events: Failed to get PNPDeviceID "
540
"from Win32_NetworkAdapter: 0x%x", (int) hr);
541
IWbemClassObject_Release(pObj);
542
IWbemServices_Release(pSvc);
543
if (events->adapter_desc == NULL)
544
return ndis_events_use_desc(events, desc);
545
return 0; /* use Win32_NetworkAdapter::Name */
548
wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::PNPDeviceID="
551
len = _snwprintf(query, MAX_QUERY_LEN,
552
L"SELECT Name FROM Win32_PnPEntity WHERE DeviceID='");
553
if (len < 0 || len >= MAX_QUERY_LEN - 1) {
555
IWbemClassObject_Release(pObj);
556
IWbemServices_Release(pSvc);
557
if (events->adapter_desc == NULL)
558
return ndis_events_use_desc(events, desc);
559
return 0; /* use Win32_NetworkAdapter::Name */
563
for (pos = 0; vt.bstrVal[pos] && len < MAX_QUERY_LEN - 1; pos++) {
564
if (vt.bstrVal[pos] == '\\') {
565
if (len >= MAX_QUERY_LEN - 2)
569
query[len++] = vt.bstrVal[pos];
571
query[len++] = L'\'';
574
IWbemClassObject_Release(pObj);
575
wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
577
hr = IWbemServices_ExecQuery(pSvc, L"WQL", query,
578
WBEM_FLAG_FORWARD_ONLY |
579
WBEM_FLAG_RETURN_IMMEDIATELY,
581
if (!SUCCEEDED(hr)) {
582
wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
583
"Name from Win32_PnPEntity: 0x%x", (int) hr);
584
IWbemServices_Release(pSvc);
585
if (events->adapter_desc == NULL)
586
return ndis_events_use_desc(events, desc);
587
return 0; /* use Win32_NetworkAdapter::Name */
591
hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
593
if (!SUCCEEDED(hr) || uReturned == 0) {
594
wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
595
"from Win32_PnPEntity: 0x%x", (int) hr);
596
IEnumWbemClassObject_Release(pEnumerator);
597
IWbemServices_Release(pSvc);
598
if (events->adapter_desc == NULL)
599
return ndis_events_use_desc(events, desc);
600
return 0; /* use Win32_NetworkAdapter::Name */
602
IEnumWbemClassObject_Release(pEnumerator);
604
hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL);
605
if (!SUCCEEDED(hr)) {
606
wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from "
607
"Win32_PnPEntity: 0x%x", (int) hr);
608
IWbemClassObject_Release(pObj);
609
IWbemServices_Release(pSvc);
610
if (events->adapter_desc == NULL)
611
return ndis_events_use_desc(events, desc);
612
return 0; /* use Win32_NetworkAdapter::Name */
615
wpa_printf(MSG_DEBUG, "ndis_events: Win32_PnPEntity::Name='%S'",
617
free(events->adapter_desc);
618
events->adapter_desc = _wcsdup(vt.bstrVal);
621
IWbemClassObject_Release(pObj);
623
IWbemServices_Release(pSvc);
625
if (events->adapter_desc == NULL)
626
return ndis_events_use_desc(events, desc);
420
632
struct ndis_events_data *
421
ndis_events_init(HANDLE *read_pipe, HANDLE *event_avail)
633
ndis_events_init(HANDLE *read_pipe, HANDLE *event_avail,
634
const char *ifname, const char *desc)
424
637
IWbemObjectSink *pSink;