~ubuntu-branches/ubuntu/lucid/wpasupplicant/lucid-updates

« back to all changes in this revision

Viewing changes to ndis_events.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2006-10-05 08:04:01 UTC
  • mfrom: (1.1.5 upstream) (3 etch)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20061005080401-r8lqlix4390yos7b
Tags: 0.5.5-2
* Update madwifi headers to latest SVN. (Closes: #388316)
* Remove failed attempt at action locking. [debian/functions.sh,
  debian/wpa_action.sh]
* Add hysteresis checking functions, to avoid "event loops" while
  using wpa-roam. [debian/functions.sh, debian/wpa_action.sh]
* Change of co-maintainer email address.
* Add ishex() function to functions.sh to determine wpa-psk value type in
  plaintext or hex. This effectively eliminates the need for the bogus and
  somewhat confusing wpa-passphrase contruct specific to our scripts and
  allows wpa-psk to work with either a 8 to 63 character long plaintext
  string or 64 character long hex string.
* Adjust README.modes to not refer to the redundant wpa-passphrase stuff.
* Add big fat NOTE about acceptable wpa-psk's to top of example gallery.
* Strip surrounding quotes from wpa-ssid if present, instead of just whining
  about them.
* Update email address in copyright blurb of functions.sh, ifupdown.sh and
  wpa_action.sh.  

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include "common.h"
25
25
 
26
26
 
 
27
static int wmi_refcnt = 0;
 
28
 
27
29
struct ndis_events_data {
28
30
        IWbemObjectSink sink;
29
31
        IWbemObjectSinkVtbl sink_vtbl;
34
36
        HANDLE read_pipe, write_pipe, event_avail;
35
37
        UINT ref;
36
38
        int terminating;
 
39
        char *ifname; /* {GUID..} */
 
40
        WCHAR *adapter_desc;
37
41
};
38
42
 
39
43
enum event_types { EVENT_CONNECT, EVENT_DISCONNECT, EVENT_MEDIA_SPECIFIC,
40
44
                   EVENT_ADAPTER_ARRIVAL, EVENT_ADAPTER_REMOVAL };
41
45
 
 
46
static int ndis_events_get_adapter(struct ndis_events_data *events,
 
47
                                   const char *ifname, const char *desc);
 
48
 
42
49
 
43
50
static int ndis_events_constructor(struct ndis_events_data *events)
44
51
{
69
76
        CloseHandle(events->event_avail);
70
77
        IWbemServices_Release(events->pSvc);
71
78
        IWbemLocator_Release(events->pLoc);
72
 
        CoUninitialize();
 
79
        if (--wmi_refcnt == 0)
 
80
                CoUninitialize();
73
81
}
74
82
 
75
83
 
105
113
 
106
114
        ndis_events_destructor(events);
107
115
        wpa_printf(MSG_DEBUG, "ndis_events: terminated");
 
116
        free(events->adapter_desc);
 
117
        free(events->ifname);
108
118
        free(events);
109
119
        return 0;
110
120
}
111
121
 
112
122
 
113
123
static int ndis_events_send_event(struct ndis_events_data *events,
114
 
                                  enum event_types type, BSTR instance,
 
124
                                  enum event_types type,
115
125
                                  char *data, size_t data_len)
116
126
{
117
127
        char buf[512], *pos, *end;
118
 
        int len, _type;
 
128
        int _type;
119
129
        DWORD written;
120
130
 
121
131
        end = buf + sizeof(buf);
123
133
        memcpy(buf, &_type, sizeof(_type));
124
134
        pos = buf + sizeof(_type);
125
135
 
126
 
        len = _snprintf(pos + 1, end - pos - 1, "%S", instance);
127
 
        if (len < 0)
128
 
                return -1;
129
 
        if (len > 255)
130
 
                len = 255;
131
 
        *pos = (unsigned char) len;
132
 
        pos += 1 + len;
133
136
        if (data) {
134
 
                if (data_len > 255 || 1 + data_len > (size_t) (end - pos)) {
 
137
                if (2 + data_len > (size_t) (end - pos)) {
135
138
                        wpa_printf(MSG_DEBUG, "Not enough room for send_event "
136
139
                                   "data (%d)", data_len);
137
140
                        return -1;
138
141
                }
139
 
                *pos++ = (unsigned char) data_len;
 
142
                *pos++ = data_len >> 8;
 
143
                *pos++ = data_len & 0xff;
140
144
                memcpy(pos, data, data_len);
141
145
                pos += data_len;
142
146
        }
150
154
}
151
155
 
152
156
 
153
 
static void ndis_events_media_connect(struct ndis_events_data *events,
154
 
                                      IWbemClassObject *pObj)
 
157
static void ndis_events_media_connect(struct ndis_events_data *events)
155
158
{
156
 
        VARIANT vt;
157
 
        HRESULT hr;
158
159
        wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaConnect");
159
 
        hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, NULL);
160
 
        if (SUCCEEDED(hr)) {
161
 
                wpa_printf(MSG_DEBUG, "  InstanceName: '%S'", vt.bstrVal);
162
 
                ndis_events_send_event(events, EVENT_CONNECT, vt.bstrVal,
163
 
                                       NULL, 0);
164
 
                VariantClear(&vt);
165
 
        }
 
160
        ndis_events_send_event(events, EVENT_CONNECT, NULL, 0);
166
161
}
167
162
 
168
163
 
169
 
static void ndis_events_media_disconnect(struct ndis_events_data *events,
170
 
                                         IWbemClassObject *pObj)
 
164
static void ndis_events_media_disconnect(struct ndis_events_data *events)
171
165
{
172
 
        VARIANT vt;
173
 
        HRESULT hr;
174
166
        wpa_printf(MSG_DEBUG, "MSNdis_StatusMediaDisconnect");
175
 
        hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, NULL);
176
 
        if (SUCCEEDED(hr)) {
177
 
                wpa_printf(MSG_DEBUG, "  InstanceName: '%S'", vt.bstrVal);
178
 
                ndis_events_send_event(events, EVENT_DISCONNECT, vt.bstrVal,
179
 
                                       NULL, 0);
180
 
                VariantClear(&vt);
181
 
        }
 
167
        ndis_events_send_event(events, EVENT_DISCONNECT, NULL, 0);
182
168
}
183
169
 
184
170
 
224
210
 
225
211
        VariantClear(&vt);
226
212
 
227
 
        hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, NULL);
228
 
        if (SUCCEEDED(hr)) {
229
 
                wpa_printf(MSG_DEBUG, "  InstanceName: '%S'", vt.bstrVal);
230
 
                ndis_events_send_event(events, EVENT_MEDIA_SPECIFIC,
231
 
                                       vt.bstrVal, data, data_len);
232
 
                VariantClear(&vt);
233
 
        }
 
213
        ndis_events_send_event(events, EVENT_MEDIA_SPECIFIC, data, data_len);
234
214
 
235
215
        free(data);
236
216
}
237
217
 
238
218
 
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)
241
220
{
242
 
        VARIANT vt;
243
 
        HRESULT hr;
244
 
        wpa_printf(MSG_DEBUG, "MSNdis_NotifierAdapterArrival");
245
 
        hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, NULL);
246
 
        if (SUCCEEDED(hr)) {
247
 
                wpa_printf(MSG_DEBUG, "  InstanceName: '%S'", vt.bstrVal);
248
 
                ndis_events_send_event(events, EVENT_ADAPTER_ARRIVAL,
249
 
                                       vt.bstrVal, NULL, 0);
250
 
                VariantClear(&vt);
251
 
        }
 
221
        wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterArrival");
 
222
        ndis_events_send_event(events, EVENT_ADAPTER_ARRIVAL, NULL, 0);
252
223
}
253
224
 
254
225
 
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)
257
227
{
258
 
        VARIANT vt;
259
 
        HRESULT hr;
260
 
        wpa_printf(MSG_DEBUG, "MSNdis_NotifierAdapterRemoval");
261
 
        hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL, NULL);
262
 
        if (SUCCEEDED(hr)) {
263
 
                wpa_printf(MSG_DEBUG, "  InstanceName: '%S'", vt.bstrVal);
264
 
                ndis_events_send_event(events, EVENT_ADAPTER_REMOVAL,
265
 
                                       vt.bstrVal, NULL, 0);
266
 
                VariantClear(&vt);
267
 
        }
 
228
        wpa_printf(MSG_DEBUG, "MSNdis_NotifyAdapterRemoval");
 
229
        ndis_events_send_event(events, EVENT_ADAPTER_REMOVAL, NULL, 0);
268
230
}
269
231
 
270
232
 
286
248
        for (i = 0; i < lObjectCount; i++) {
287
249
                IWbemClassObject *pObj = ppObjArray[i];
288
250
                HRESULT hr;
289
 
                VARIANT vtClass;
 
251
                VARIANT vtClass, vt;
290
252
 
291
253
                hr = IWbemClassObject_Get(pObj, L"__CLASS", 0, &vtClass, NULL,
292
254
                                          NULL);
297
259
                }
298
260
                /* wpa_printf(MSG_DEBUG, "CLASS: '%S'", vtClass.bstrVal); */
299
261
 
 
262
                hr = IWbemClassObject_Get(pObj, L"InstanceName", 0, &vt, NULL,
 
263
                                          NULL);
 
264
                if (FAILED(hr)) {
 
265
                        wpa_printf(MSG_DEBUG, "Failed to get InstanceName "
 
266
                                   "from event.");
 
267
                        VariantClear(&vtClass);
 
268
                        break;
 
269
                }
 
270
 
 
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);
 
277
                }
 
278
 
 
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);
 
285
                        VariantClear(&vt);
 
286
                        continue;
 
287
                }
 
288
                VariantClear(&vt);
 
289
 
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);
315
305
                } else {
316
306
                        wpa_printf(MSG_DEBUG, "Unepected event - __CLASS: "
317
307
                                   "'%S'", vtClass.bstrVal);
332
322
}
333
323
 
334
324
 
 
325
static int notification_query(IWbemObjectSink *pDestSink,
 
326
                              IWbemServices *pSvc, const char *class_name)
 
327
{
 
328
        HRESULT hr;
 
329
        WCHAR query[256];
 
330
 
 
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,
 
335
                                                      0, pDestSink);
 
336
        if (FAILED(hr)) {
 
337
                wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for %s "
 
338
                           "failed with hresult of 0x%x",
 
339
                           class_name, (int) hr);
 
340
                return -1;
 
341
        }
 
342
 
 
343
        return 0;
 
344
}
 
345
 
 
346
 
335
347
static int register_async_notification(IWbemObjectSink *pDestSink,
336
348
                                       IWbemServices *pSvc)
337
349
{
338
 
        HRESULT hr;
339
 
        int err = 0;
340
 
        BSTR lang = SysAllocString(L"WQL");
341
 
 
342
 
        BSTR query = SysAllocString(
343
 
                L"SELECT * FROM MSNdis_StatusMediaConnect");
344
 
        hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
345
 
                                                      pDestSink);
346
 
        SysFreeString(query);
347
 
        if (FAILED(hr)) {
348
 
                wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
349
 
                           "MSNdis_StatusMediaConnect failed with hresult of "
350
 
                           "0x%x", (int) hr);
351
 
                err = -1;
352
 
        }
353
 
 
354
 
        query = SysAllocString(
355
 
                L"SELECT * FROM MSNdis_StatusMediaDisconnect");
356
 
        hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
357
 
                                                      pDestSink);
358
 
        SysFreeString(query);
359
 
        if (FAILED(hr)) {
360
 
                wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
361
 
                           "MSNdis_StatusMediaDisconnect failed with hresult "
362
 
                           "of 0x%x", (int) hr);
363
 
                err = -1;
364
 
        }
365
 
 
366
 
        query = SysAllocString(
367
 
                L"SELECT * FROM MSNdis_StatusMediaSpecificIndication");
368
 
        hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
369
 
                                                      pDestSink);
370
 
        SysFreeString(query);
371
 
        if (FAILED(hr)) {
372
 
                wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
373
 
                           "MSNdis_StatusMediaSpecificIndication failed with "
374
 
                           "hresult of 0x%x", (int) hr);
375
 
                err = -1;
376
 
        }
377
 
 
378
 
        query = SysAllocString(
379
 
                L"SELECT * FROM MSNdis_NotifyAdapterArrival");
380
 
        hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
381
 
                                                      pDestSink);
382
 
        SysFreeString(query);
383
 
        if (FAILED(hr)) {
384
 
                wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
385
 
                           "MSNdis_NotifyAdapterArrival failed with hresult "
386
 
                           "of 0x%x", (int) hr);
387
 
                err = -1;
388
 
        }
389
 
 
390
 
        query = SysAllocString(
391
 
                L"SELECT * FROM MSNdis_NotifyAdapterRemoval");
392
 
        hr = IWbemServices_ExecNotificationQueryAsync(pSvc, lang, query, 0, 0,
393
 
                                                      pDestSink);
394
 
        SysFreeString(query);
395
 
        if (FAILED(hr)) {
396
 
                wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for "
397
 
                           "MSNdis_NotifyAdapterRemoval failed with hresult "
398
 
                           "of 0x%x", (int) hr);
399
 
                err = -1;
400
 
        }
401
 
 
402
 
        SysFreeString(lang);
403
 
 
404
 
        return err;
 
350
        int i;
 
351
        const char *class_list[] = {
 
352
                "MSNdis_StatusMediaConnect",
 
353
                "MSNdis_StatusMediaDisconnect",
 
354
                "MSNdis_StatusMediaSpecificIndication",
 
355
                "MSNdis_NotifyAdapterArrival",
 
356
                "MSNdis_NotifyAdapterRemoval",
 
357
                NULL
 
358
        };
 
359
 
 
360
        for (i = 0; class_list[i]; i++) {
 
361
                if (notification_query(pDestSink, pSvc, class_list[i]) < 0)
 
362
                        return -1;
 
363
        }
 
364
 
 
365
        return 0;
405
366
}
406
367
 
407
368
 
417
378
}
418
379
 
419
380
 
 
381
static int ndis_events_use_desc(struct ndis_events_data *events,
 
382
                                const char *desc)
 
383
{
 
384
        char *tmp, *pos;
 
385
        size_t len;
 
386
 
 
387
        if (desc == NULL) {
 
388
                if (events->adapter_desc == NULL)
 
389
                        return -1;
 
390
                /* Continue using old description */
 
391
                return 0;
 
392
        }
 
393
 
 
394
        tmp = strdup(desc);
 
395
        if (tmp == NULL)
 
396
                return -1;
 
397
 
 
398
        pos = strstr(tmp, " (Microsoft's Packet Scheduler)");
 
399
        if (pos)
 
400
                *pos = '\0';
 
401
 
 
402
        len = strlen(tmp);
 
403
        events->adapter_desc = malloc((len + 1) * sizeof(WCHAR));
 
404
        if (events->adapter_desc == NULL) {
 
405
                free(tmp);
 
406
                return -1;
 
407
        }
 
408
        _snwprintf(events->adapter_desc, len + 1, L"%S", tmp);
 
409
        free(tmp);
 
410
        return 0;
 
411
}
 
412
 
 
413
 
 
414
static int ndis_events_get_adapter(struct ndis_events_data *events,
 
415
                                   const char *ifname, const char *desc)
 
416
{
 
417
        HRESULT hr;
 
418
        IWbemServices *pSvc;
 
419
#define MAX_QUERY_LEN 256
 
420
        WCHAR query[MAX_QUERY_LEN];
 
421
        IEnumWbemClassObject *pEnumerator;
 
422
        IWbemClassObject *pObj;
 
423
        ULONG uReturned;
 
424
        VARIANT vt;
 
425
        int len, pos;
 
426
 
 
427
        /*
 
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.
 
431
         */
 
432
 
 
433
        free(events->adapter_desc);
 
434
        events->adapter_desc = NULL;
 
435
 
 
436
        hr = IWbemLocator_ConnectServer(events->pLoc, L"ROOT\\CIMV2", NULL,
 
437
                                        NULL, 0, 0, 0, 0, &pSvc);
 
438
        if (hr) {
 
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);
 
442
        }
 
443
        wpa_printf(MSG_DEBUG, "ndis_events: Connected to ROOT\\CIMV2.");
 
444
 
 
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);
 
449
 
 
450
        hr = IWbemServices_ExecQuery(pSvc, L"WQL", query,
 
451
                                     WBEM_FLAG_FORWARD_ONLY |
 
452
                                     WBEM_FLAG_RETURN_IMMEDIATELY,
 
453
                                     NULL, &pEnumerator);
 
454
        if (!SUCCEEDED(hr)) {
 
455
                wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface "
 
456
                           "GUID from Win32_NetworkAdapterConfiguration: "
 
457
                           "0x%x", (int) hr);
 
458
                IWbemServices_Release(pSvc);
 
459
                return ndis_events_use_desc(events, desc);
 
460
        }
 
461
 
 
462
        uReturned = 0;
 
463
        hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
 
464
                                       &pObj, &uReturned);
 
465
        if (!SUCCEEDED(hr) || uReturned == 0) {
 
466
                wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface "
 
467
                           "GUID from Win32_NetworkAdapterConfiguration: "
 
468
                           "0x%x", (int) hr);
 
469
                IEnumWbemClassObject_Release(pEnumerator);
 
470
                IWbemServices_Release(pSvc);
 
471
                return ndis_events_use_desc(events, desc);
 
472
        }
 
473
        IEnumWbemClassObject_Release(pEnumerator);
 
474
 
 
475
        VariantInit(&vt);
 
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",
 
480
                           (int) hr);
 
481
                IWbemServices_Release(pSvc);
 
482
                return ndis_events_use_desc(events, desc);
 
483
        }
 
484
 
 
485
        _snwprintf(query, MAX_QUERY_LEN,
 
486
                  L"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE "
 
487
                  L"Index=%d",
 
488
                  vt.uintVal);
 
489
        wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
 
490
        VariantClear(&vt);
 
491
        IWbemClassObject_Release(pObj);
 
492
 
 
493
        hr = IWbemServices_ExecQuery(pSvc, L"WQL", query,
 
494
                                     WBEM_FLAG_FORWARD_ONLY |
 
495
                                     WBEM_FLAG_RETURN_IMMEDIATELY,
 
496
                                     NULL, &pEnumerator);
 
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);
 
502
        }
 
503
 
 
504
        uReturned = 0;
 
505
        hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
 
506
                                       &pObj, &uReturned);
 
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);
 
513
        }
 
514
        IEnumWbemClassObject_Release(pEnumerator);
 
515
 
 
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);
 
523
        }
 
524
 
 
525
        wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::Name='%S'",
 
526
                   vt.bstrVal);
 
527
        events->adapter_desc = _wcsdup(vt.bstrVal);
 
528
        VariantClear(&vt);
 
529
 
 
530
        /*
 
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
 
534
         * plugged again.
 
535
         */
 
536
 
 
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 */
 
546
        }
 
547
 
 
548
        wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::PNPDeviceID="
 
549
                   "'%S'", vt.bstrVal);
 
550
 
 
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) {
 
554
                VariantClear(&vt);
 
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 */
 
560
        }
 
561
 
 
562
        /* Escape \ as \\ */
 
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)
 
566
                                break;
 
567
                        query[len++] = '\\';
 
568
                }
 
569
                query[len++] = vt.bstrVal[pos];
 
570
        }
 
571
        query[len++] = L'\'';
 
572
        query[len] = L'\0';
 
573
        VariantClear(&vt);
 
574
        IWbemClassObject_Release(pObj);
 
575
        wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query);
 
576
 
 
577
        hr = IWbemServices_ExecQuery(pSvc, L"WQL", query,
 
578
                                     WBEM_FLAG_FORWARD_ONLY |
 
579
                                     WBEM_FLAG_RETURN_IMMEDIATELY,
 
580
                                     NULL, &pEnumerator);
 
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 */
 
588
        }
 
589
 
 
590
        uReturned = 0;
 
591
        hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
 
592
                                       &pObj, &uReturned);
 
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 */
 
601
        }
 
602
        IEnumWbemClassObject_Release(pEnumerator);
 
603
 
 
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 */
 
613
        }
 
614
 
 
615
        wpa_printf(MSG_DEBUG, "ndis_events: Win32_PnPEntity::Name='%S'",
 
616
                   vt.bstrVal);
 
617
        free(events->adapter_desc);
 
618
        events->adapter_desc = _wcsdup(vt.bstrVal);
 
619
        VariantClear(&vt);
 
620
 
 
621
        IWbemClassObject_Release(pObj);
 
622
 
 
623
        IWbemServices_Release(pSvc);
 
624
 
 
625
        if (events->adapter_desc == NULL)
 
626
                return ndis_events_use_desc(events, desc);
 
627
 
 
628
        return 0;
 
629
}
 
630
 
 
631
 
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)
422
635
{
423
636
        HRESULT hr;
424
637
        IWbemObjectSink *pSink;
429
642
                wpa_printf(MSG_ERROR, "Could not allocate sink for events.");
430
643
                return NULL;
431
644
        }
432
 
 
433
 
        hr = CoInitializeEx(0, COINIT_MULTITHREADED);
434
 
        if (FAILED(hr)) {
435
 
                wpa_printf(MSG_ERROR, "CoInitializeEx() failed - returned "
436
 
                           "0x%x", (int) hr);
 
645
        events->ifname = strdup(ifname);
 
646
        if (events->ifname == NULL) {
437
647
                free(events);
438
648
                return NULL;
439
649
        }
440
650
 
441
 
        hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
442
 
                                  RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
443
 
                                  RPC_C_IMP_LEVEL_IMPERSONATE,
444
 
                                  NULL, EOAC_SECURE_REFS, NULL);
445
 
        if (FAILED(hr)) {
446
 
                wpa_printf(MSG_ERROR, "CoInitializeSecurity() failed - "
447
 
                           "returned 0x%x", (int) hr);
448
 
                free(events);
449
 
                return NULL;
 
651
        if (wmi_refcnt++ == 0) {
 
652
                hr = CoInitializeEx(0, COINIT_MULTITHREADED);
 
653
                if (FAILED(hr)) {
 
654
                        wpa_printf(MSG_ERROR, "CoInitializeEx() failed - "
 
655
                                   "returned 0x%x", (int) hr);
 
656
                        free(events);
 
657
                        return NULL;
 
658
                }
 
659
 
 
660
                hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
 
661
                                          RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
 
662
                                          RPC_C_IMP_LEVEL_IMPERSONATE,
 
663
                                          NULL, EOAC_SECURE_REFS, NULL);
 
664
                if (FAILED(hr)) {
 
665
                        wpa_printf(MSG_ERROR, "CoInitializeSecurity() failed "
 
666
                                   "- returned 0x%x", (int) hr);
 
667
                        free(events);
 
668
                        return NULL;
 
669
                }
450
670
        }
451
671
 
452
672
        hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
459
679
                return NULL;
460
680
        }
461
681
 
 
682
        if (ndis_events_get_adapter(events, ifname, desc) < 0) {
 
683
                CoUninitialize();
 
684
                free(events);
 
685
                return NULL;
 
686
        }
 
687
        wpa_printf(MSG_DEBUG, "ndis_events: use adapter descriptor '%S'",
 
688
                   events->adapter_desc);
 
689
 
462
690
        hr = IWbemLocator_ConnectServer(events->pLoc, L"ROOT\\WMI", NULL, NULL,
463
691
                                        0, 0, 0, 0, &events->pSvc);
464
692
        if (hr) {
465
693
                wpa_printf(MSG_ERROR, "Could not connect to server - error "
466
694
                           "0x%x", (int) hr);
467
695
                CoUninitialize();
 
696
                free(events->adapter_desc);
468
697
                free(events);
469
698
                return NULL;
470
699
        }
482
711
        if (register_async_notification(pSink, events->pSvc) < 0) {
483
712
                wpa_printf(MSG_DEBUG, "Failed to register async "
484
713
                           "notifications");
485
 
                CoUninitialize();
486
714
                ndis_events_destructor(events);
 
715
                free(events->adapter_desc);
487
716
                free(events);
488
717
                return NULL;
489
718
        }