2 * ndis_events - Receive NdisMIndicateStatus() events using WMI
3 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
15 #define _WIN32_WINNT 0x0400
21 #endif /* COBJMACROS */
27 static int wmi_refcnt
= 0;
28 static int wmi_first
= 1;
30 struct ndis_events_data
{
32 IWbemObjectSinkVtbl sink_vtbl
;
37 HANDLE read_pipe
, write_pipe
, event_avail
;
40 char *ifname
; /* {GUID..} */
44 #define BstrAlloc(x) (x) ? SysAllocString(x) : NULL
45 #define BstrFree(x) if (x) SysFreeString(x)
47 /* WBEM / WMI wrapper functions, to perform in-place conversion of WCHARs to
49 HRESULT STDMETHODCALLTYPE
call_IWbemServices_ExecQuery(
50 IWbemServices
*pSvc
, LPCWSTR strQueryLanguage
, LPCWSTR strQuery
,
51 long lFlags
, IWbemContext
*pCtx
, IEnumWbemClassObject
**ppEnum
)
53 BSTR bsQueryLanguage
, bsQuery
;
56 bsQueryLanguage
= BstrAlloc(strQueryLanguage
);
57 bsQuery
= BstrAlloc(strQuery
);
59 hr
= IWbemServices_ExecQuery(pSvc
, bsQueryLanguage
, bsQuery
, lFlags
,
62 BstrFree(bsQueryLanguage
);
69 HRESULT STDMETHODCALLTYPE
call_IWbemServices_ExecNotificationQueryAsync(
70 IWbemServices
*pSvc
, LPCWSTR strQueryLanguage
, LPCWSTR strQuery
,
71 long lFlags
, IWbemContext
*pCtx
, IWbemObjectSink
*pResponseHandler
)
73 BSTR bsQueryLanguage
, bsQuery
;
76 bsQueryLanguage
= BstrAlloc(strQueryLanguage
);
77 bsQuery
= BstrAlloc(strQuery
);
79 hr
= IWbemServices_ExecNotificationQueryAsync(pSvc
, bsQueryLanguage
,
80 bsQuery
, lFlags
, pCtx
,
83 BstrFree(bsQueryLanguage
);
90 HRESULT STDMETHODCALLTYPE
call_IWbemLocator_ConnectServer(
91 IWbemLocator
*pLoc
, LPCWSTR strNetworkResource
, LPCWSTR strUser
,
92 LPCWSTR strPassword
, LPCWSTR strLocale
, long lSecurityFlags
,
93 LPCWSTR strAuthority
, IWbemContext
*pCtx
, IWbemServices
**ppNamespace
)
95 BSTR bsNetworkResource
, bsUser
, bsPassword
, bsLocale
, bsAuthority
;
98 bsNetworkResource
= BstrAlloc(strNetworkResource
);
99 bsUser
= BstrAlloc(strUser
);
100 bsPassword
= BstrAlloc(strPassword
);
101 bsLocale
= BstrAlloc(strLocale
);
102 bsAuthority
= BstrAlloc(strAuthority
);
104 hr
= IWbemLocator_ConnectServer(pLoc
, bsNetworkResource
, bsUser
,
105 bsPassword
, bsLocale
, lSecurityFlags
,
106 bsAuthority
, pCtx
, ppNamespace
);
108 BstrFree(bsNetworkResource
);
110 BstrFree(bsPassword
);
112 BstrFree(bsAuthority
);
118 enum event_types
{ EVENT_CONNECT
, EVENT_DISCONNECT
, EVENT_MEDIA_SPECIFIC
,
119 EVENT_ADAPTER_ARRIVAL
, EVENT_ADAPTER_REMOVAL
};
121 static int ndis_events_get_adapter(struct ndis_events_data
*events
,
122 const char *ifname
, const char *desc
);
125 static int ndis_events_constructor(struct ndis_events_data
*events
)
129 if (!CreatePipe(&events
->read_pipe
, &events
->write_pipe
, NULL
, 512)) {
130 wpa_printf(MSG_ERROR
, "CreatePipe() failed: %d",
131 (int) GetLastError());
134 events
->event_avail
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
135 if (events
->event_avail
== NULL
) {
136 wpa_printf(MSG_ERROR
, "CreateEvent() failed: %d",
137 (int) GetLastError());
138 CloseHandle(events
->read_pipe
);
139 CloseHandle(events
->write_pipe
);
147 static void ndis_events_destructor(struct ndis_events_data
*events
)
149 CloseHandle(events
->read_pipe
);
150 CloseHandle(events
->write_pipe
);
151 CloseHandle(events
->event_avail
);
152 IWbemServices_Release(events
->pSvc
);
153 IWbemLocator_Release(events
->pLoc
);
154 if (--wmi_refcnt
== 0)
159 static HRESULT STDMETHODCALLTYPE
160 ndis_events_query_interface(IWbemObjectSink
*this, REFIID riid
, void **obj
)
164 if (IsEqualIID(riid
, &IID_IUnknown
) ||
165 IsEqualIID(riid
, &IID_IWbemObjectSink
)) {
167 IWbemObjectSink_AddRef(this);
171 return E_NOINTERFACE
;
175 static ULONG STDMETHODCALLTYPE
ndis_events_add_ref(IWbemObjectSink
*this)
177 struct ndis_events_data
*events
= (struct ndis_events_data
*) this;
178 return ++events
->ref
;
182 static ULONG STDMETHODCALLTYPE
ndis_events_release(IWbemObjectSink
*this)
184 struct ndis_events_data
*events
= (struct ndis_events_data
*) this;
186 if (--events
->ref
!= 0)
189 ndis_events_destructor(events
);
190 wpa_printf(MSG_DEBUG
, "ndis_events: terminated");
191 os_free(events
->adapter_desc
);
192 os_free(events
->ifname
);
198 static int ndis_events_send_event(struct ndis_events_data
*events
,
199 enum event_types type
,
200 char *data
, size_t data_len
)
202 char buf
[512], *pos
, *end
;
206 end
= buf
+ sizeof(buf
);
208 os_memcpy(buf
, &_type
, sizeof(_type
));
209 pos
= buf
+ sizeof(_type
);
212 if (2 + data_len
> (size_t) (end
- pos
)) {
213 wpa_printf(MSG_DEBUG
, "Not enough room for send_event "
214 "data (%d)", data_len
);
217 *pos
++ = data_len
>> 8;
218 *pos
++ = data_len
& 0xff;
219 os_memcpy(pos
, data
, data_len
);
223 if (WriteFile(events
->write_pipe
, buf
, pos
- buf
, &written
, NULL
)) {
224 SetEvent(events
->event_avail
);
227 wpa_printf(MSG_INFO
, "WriteFile() failed: %d", (int) GetLastError());
232 static void ndis_events_media_connect(struct ndis_events_data
*events
)
234 wpa_printf(MSG_DEBUG
, "MSNdis_StatusMediaConnect");
235 ndis_events_send_event(events
, EVENT_CONNECT
, NULL
, 0);
239 static void ndis_events_media_disconnect(struct ndis_events_data
*events
)
241 wpa_printf(MSG_DEBUG
, "MSNdis_StatusMediaDisconnect");
242 ndis_events_send_event(events
, EVENT_DISCONNECT
, NULL
, 0);
246 static void ndis_events_media_specific(struct ndis_events_data
*events
,
247 IWbemClassObject
*pObj
)
251 LONG lower
, upper
, k
;
256 wpa_printf(MSG_DEBUG
, "MSNdis_StatusMediaSpecificIndication");
258 /* This is the StatusBuffer from NdisMIndicateStatus() call */
259 hr
= IWbemClassObject_Get(pObj
, L
"NdisStatusMediaSpecificIndication",
262 wpa_printf(MSG_DEBUG
, "Could not get "
263 "NdisStatusMediaSpecificIndication from "
268 SafeArrayGetLBound(V_ARRAY(&vt
), 1, &lower
);
269 SafeArrayGetUBound(V_ARRAY(&vt
), 1, &upper
);
270 data_len
= upper
- lower
+ 1;
271 data
= os_malloc(data_len
);
273 wpa_printf(MSG_DEBUG
, "Failed to allocate buffer for event "
280 for (k
= lower
; k
<= upper
; k
++) {
281 SafeArrayGetElement(V_ARRAY(&vt
), &k
, &ch
);
284 wpa_hexdump(MSG_DEBUG
, "MediaSpecificEvent", data
, data_len
);
288 ndis_events_send_event(events
, EVENT_MEDIA_SPECIFIC
, data
, data_len
);
294 static void ndis_events_adapter_arrival(struct ndis_events_data
*events
)
296 wpa_printf(MSG_DEBUG
, "MSNdis_NotifyAdapterArrival");
297 ndis_events_send_event(events
, EVENT_ADAPTER_ARRIVAL
, NULL
, 0);
301 static void ndis_events_adapter_removal(struct ndis_events_data
*events
)
303 wpa_printf(MSG_DEBUG
, "MSNdis_NotifyAdapterRemoval");
304 ndis_events_send_event(events
, EVENT_ADAPTER_REMOVAL
, NULL
, 0);
308 static HRESULT STDMETHODCALLTYPE
309 ndis_events_indicate(IWbemObjectSink
*this, long lObjectCount
,
310 IWbemClassObject __RPC_FAR
*__RPC_FAR
*ppObjArray
)
312 struct ndis_events_data
*events
= (struct ndis_events_data
*) this;
315 if (events
->terminating
) {
316 wpa_printf(MSG_DEBUG
, "ndis_events_indicate: Ignore "
317 "indication - terminating");
318 return WBEM_NO_ERROR
;
320 /* wpa_printf(MSG_DEBUG, "Notification received - %d object(s)",
323 for (i
= 0; i
< lObjectCount
; i
++) {
324 IWbemClassObject
*pObj
= ppObjArray
[i
];
328 hr
= IWbemClassObject_Get(pObj
, L
"__CLASS", 0, &vtClass
, NULL
,
331 wpa_printf(MSG_DEBUG
, "Failed to get __CLASS from "
335 /* wpa_printf(MSG_DEBUG, "CLASS: '%S'", vtClass.bstrVal); */
337 hr
= IWbemClassObject_Get(pObj
, L
"InstanceName", 0, &vt
, NULL
,
340 wpa_printf(MSG_DEBUG
, "Failed to get InstanceName "
342 VariantClear(&vtClass
);
346 if (wcscmp(vtClass
.bstrVal
,
347 L
"MSNdis_NotifyAdapterArrival") == 0) {
348 wpa_printf(MSG_DEBUG
, "ndis_events_indicate: Try to "
349 "update adapter description since it may "
350 "have changed with new adapter instance");
351 ndis_events_get_adapter(events
, events
->ifname
, NULL
);
354 if (wcscmp(events
->adapter_desc
, vt
.bstrVal
) != 0) {
355 wpa_printf(MSG_DEBUG
, "ndis_events_indicate: Ignore "
356 "indication for foreign adapter: "
357 "InstanceName: '%S' __CLASS: '%S'",
358 vt
.bstrVal
, vtClass
.bstrVal
);
359 VariantClear(&vtClass
);
365 if (wcscmp(vtClass
.bstrVal
,
366 L
"MSNdis_StatusMediaSpecificIndication") == 0) {
367 ndis_events_media_specific(events
, pObj
);
368 } else if (wcscmp(vtClass
.bstrVal
,
369 L
"MSNdis_StatusMediaConnect") == 0) {
370 ndis_events_media_connect(events
);
371 } else if (wcscmp(vtClass
.bstrVal
,
372 L
"MSNdis_StatusMediaDisconnect") == 0) {
373 ndis_events_media_disconnect(events
);
374 } else if (wcscmp(vtClass
.bstrVal
,
375 L
"MSNdis_NotifyAdapterArrival") == 0) {
376 ndis_events_adapter_arrival(events
);
377 } else if (wcscmp(vtClass
.bstrVal
,
378 L
"MSNdis_NotifyAdapterRemoval") == 0) {
379 ndis_events_adapter_removal(events
);
381 wpa_printf(MSG_DEBUG
, "Unepected event - __CLASS: "
382 "'%S'", vtClass
.bstrVal
);
385 VariantClear(&vtClass
);
388 return WBEM_NO_ERROR
;
392 static HRESULT STDMETHODCALLTYPE
393 ndis_events_set_status(IWbemObjectSink
*this, long lFlags
, HRESULT hResult
,
394 BSTR strParam
, IWbemClassObject __RPC_FAR
*pObjParam
)
396 return WBEM_NO_ERROR
;
400 static int notification_query(IWbemObjectSink
*pDestSink
,
401 IWbemServices
*pSvc
, const char *class_name
)
406 _snwprintf(query
, 256,
407 L
"SELECT * FROM %S", class_name
);
408 wpa_printf(MSG_DEBUG
, "ndis_events: WMI: %S", query
);
409 hr
= call_IWbemServices_ExecNotificationQueryAsync(
410 pSvc
, L
"WQL", query
, 0, 0, pDestSink
);
412 wpa_printf(MSG_DEBUG
, "ExecNotificationQueryAsync for %s "
413 "failed with hresult of 0x%x",
414 class_name
, (int) hr
);
422 static int register_async_notification(IWbemObjectSink
*pDestSink
,
426 const char *class_list
[] = {
427 "MSNdis_StatusMediaConnect",
428 "MSNdis_StatusMediaDisconnect",
429 "MSNdis_StatusMediaSpecificIndication",
430 "MSNdis_NotifyAdapterArrival",
431 "MSNdis_NotifyAdapterRemoval",
435 for (i
= 0; class_list
[i
]; i
++) {
436 if (notification_query(pDestSink
, pSvc
, class_list
[i
]) < 0)
444 void ndis_events_deinit(struct ndis_events_data
*events
)
446 events
->terminating
= 1;
447 IWbemServices_CancelAsyncCall(events
->pSvc
, &events
->sink
);
448 IWbemObjectSink_Release(&events
->sink
);
450 * Rest of deinitialization is done in ndis_events_destructor() once
451 * all reference count drops to zero.
456 static int ndis_events_use_desc(struct ndis_events_data
*events
,
463 if (events
->adapter_desc
== NULL
)
465 /* Continue using old description */
469 tmp
= os_strdup(desc
);
473 pos
= os_strstr(tmp
, " (Microsoft's Packet Scheduler)");
477 len
= os_strlen(tmp
);
478 events
->adapter_desc
= os_malloc((len
+ 1) * sizeof(WCHAR
));
479 if (events
->adapter_desc
== NULL
) {
483 _snwprintf(events
->adapter_desc
, len
+ 1, L
"%S", tmp
);
489 static int ndis_events_get_adapter(struct ndis_events_data
*events
,
490 const char *ifname
, const char *desc
)
494 #define MAX_QUERY_LEN 256
495 WCHAR query
[MAX_QUERY_LEN
];
496 IEnumWbemClassObject
*pEnumerator
;
497 IWbemClassObject
*pObj
;
503 * Try to get adapter descriptor through WMI CIMv2 Win32_NetworkAdapter
504 * to have better probability of matching with InstanceName from
505 * MSNdis events. If this fails, use the provided description.
508 os_free(events
->adapter_desc
);
509 events
->adapter_desc
= NULL
;
511 hr
= call_IWbemLocator_ConnectServer(
512 events
->pLoc
, L
"ROOT\\CIMV2", NULL
, NULL
, 0, 0, 0, 0, &pSvc
);
514 wpa_printf(MSG_ERROR
, "ndis_events: Could not connect to WMI "
515 "server (ROOT\\CIMV2) - error 0x%x", (int) hr
);
516 return ndis_events_use_desc(events
, desc
);
518 wpa_printf(MSG_DEBUG
, "ndis_events: Connected to ROOT\\CIMV2.");
520 _snwprintf(query
, MAX_QUERY_LEN
,
521 L
"SELECT Index FROM Win32_NetworkAdapterConfiguration "
522 L
"WHERE SettingID='%S'", ifname
);
523 wpa_printf(MSG_DEBUG
, "ndis_events: WMI: %S", query
);
525 hr
= call_IWbemServices_ExecQuery(
527 WBEM_FLAG_FORWARD_ONLY
| WBEM_FLAG_RETURN_IMMEDIATELY
,
529 if (!SUCCEEDED(hr
)) {
530 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to query interface "
531 "GUID from Win32_NetworkAdapterConfiguration: "
533 IWbemServices_Release(pSvc
);
534 return ndis_events_use_desc(events
, desc
);
538 hr
= IEnumWbemClassObject_Next(pEnumerator
, WBEM_INFINITE
, 1,
540 if (!SUCCEEDED(hr
) || uReturned
== 0) {
541 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to find interface "
542 "GUID from Win32_NetworkAdapterConfiguration: "
544 IEnumWbemClassObject_Release(pEnumerator
);
545 IWbemServices_Release(pSvc
);
546 return ndis_events_use_desc(events
, desc
);
548 IEnumWbemClassObject_Release(pEnumerator
);
551 hr
= IWbemClassObject_Get(pObj
, L
"Index", 0, &vt
, NULL
, NULL
);
552 if (!SUCCEEDED(hr
)) {
553 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to get Index from "
554 "Win32_NetworkAdapterConfiguration: 0x%x",
556 IWbemServices_Release(pSvc
);
557 return ndis_events_use_desc(events
, desc
);
560 _snwprintf(query
, MAX_QUERY_LEN
,
561 L
"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE "
564 wpa_printf(MSG_DEBUG
, "ndis_events: WMI: %S", query
);
566 IWbemClassObject_Release(pObj
);
568 hr
= call_IWbemServices_ExecQuery(
570 WBEM_FLAG_FORWARD_ONLY
| WBEM_FLAG_RETURN_IMMEDIATELY
,
572 if (!SUCCEEDED(hr
)) {
573 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to query interface "
574 "from Win32_NetworkAdapter: 0x%x", (int) hr
);
575 IWbemServices_Release(pSvc
);
576 return ndis_events_use_desc(events
, desc
);
580 hr
= IEnumWbemClassObject_Next(pEnumerator
, WBEM_INFINITE
, 1,
582 if (!SUCCEEDED(hr
) || uReturned
== 0) {
583 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to find interface "
584 "from Win32_NetworkAdapter: 0x%x", (int) hr
);
585 IEnumWbemClassObject_Release(pEnumerator
);
586 IWbemServices_Release(pSvc
);
587 return ndis_events_use_desc(events
, desc
);
589 IEnumWbemClassObject_Release(pEnumerator
);
591 hr
= IWbemClassObject_Get(pObj
, L
"Name", 0, &vt
, NULL
, NULL
);
592 if (!SUCCEEDED(hr
)) {
593 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to get Name from "
594 "Win32_NetworkAdapter: 0x%x", (int) hr
);
595 IWbemClassObject_Release(pObj
);
596 IWbemServices_Release(pSvc
);
597 return ndis_events_use_desc(events
, desc
);
600 wpa_printf(MSG_DEBUG
, "ndis_events: Win32_NetworkAdapter::Name='%S'",
602 events
->adapter_desc
= _wcsdup(vt
.bstrVal
);
606 * Try to get even better candidate for matching with InstanceName
607 * from Win32_PnPEntity. This is needed at least for some USB cards
608 * that can change the InstanceName whenever being unplugged and
612 hr
= IWbemClassObject_Get(pObj
, L
"PNPDeviceID", 0, &vt
, NULL
, NULL
);
613 if (!SUCCEEDED(hr
)) {
614 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to get PNPDeviceID "
615 "from Win32_NetworkAdapter: 0x%x", (int) hr
);
616 IWbemClassObject_Release(pObj
);
617 IWbemServices_Release(pSvc
);
618 if (events
->adapter_desc
== NULL
)
619 return ndis_events_use_desc(events
, desc
);
620 return 0; /* use Win32_NetworkAdapter::Name */
623 wpa_printf(MSG_DEBUG
, "ndis_events: Win32_NetworkAdapter::PNPDeviceID="
626 len
= _snwprintf(query
, MAX_QUERY_LEN
,
627 L
"SELECT Name FROM Win32_PnPEntity WHERE DeviceID='");
628 if (len
< 0 || len
>= MAX_QUERY_LEN
- 1) {
630 IWbemClassObject_Release(pObj
);
631 IWbemServices_Release(pSvc
);
632 if (events
->adapter_desc
== NULL
)
633 return ndis_events_use_desc(events
, desc
);
634 return 0; /* use Win32_NetworkAdapter::Name */
638 for (pos
= 0; vt
.bstrVal
[pos
] && len
< MAX_QUERY_LEN
- 2; pos
++) {
639 if (vt
.bstrVal
[pos
] == '\\') {
640 if (len
>= MAX_QUERY_LEN
- 3)
644 query
[len
++] = vt
.bstrVal
[pos
];
646 query
[len
++] = L
'\'';
649 IWbemClassObject_Release(pObj
);
650 wpa_printf(MSG_DEBUG
, "ndis_events: WMI: %S", query
);
652 hr
= call_IWbemServices_ExecQuery(
654 WBEM_FLAG_FORWARD_ONLY
| WBEM_FLAG_RETURN_IMMEDIATELY
,
656 if (!SUCCEEDED(hr
)) {
657 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to query interface "
658 "Name from Win32_PnPEntity: 0x%x", (int) hr
);
659 IWbemServices_Release(pSvc
);
660 if (events
->adapter_desc
== NULL
)
661 return ndis_events_use_desc(events
, desc
);
662 return 0; /* use Win32_NetworkAdapter::Name */
666 hr
= IEnumWbemClassObject_Next(pEnumerator
, WBEM_INFINITE
, 1,
668 if (!SUCCEEDED(hr
) || uReturned
== 0) {
669 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to find interface "
670 "from Win32_PnPEntity: 0x%x", (int) hr
);
671 IEnumWbemClassObject_Release(pEnumerator
);
672 IWbemServices_Release(pSvc
);
673 if (events
->adapter_desc
== NULL
)
674 return ndis_events_use_desc(events
, desc
);
675 return 0; /* use Win32_NetworkAdapter::Name */
677 IEnumWbemClassObject_Release(pEnumerator
);
679 hr
= IWbemClassObject_Get(pObj
, L
"Name", 0, &vt
, NULL
, NULL
);
680 if (!SUCCEEDED(hr
)) {
681 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to get Name from "
682 "Win32_PnPEntity: 0x%x", (int) hr
);
683 IWbemClassObject_Release(pObj
);
684 IWbemServices_Release(pSvc
);
685 if (events
->adapter_desc
== NULL
)
686 return ndis_events_use_desc(events
, desc
);
687 return 0; /* use Win32_NetworkAdapter::Name */
690 wpa_printf(MSG_DEBUG
, "ndis_events: Win32_PnPEntity::Name='%S'",
692 os_free(events
->adapter_desc
);
693 events
->adapter_desc
= _wcsdup(vt
.bstrVal
);
696 IWbemClassObject_Release(pObj
);
698 IWbemServices_Release(pSvc
);
700 if (events
->adapter_desc
== NULL
)
701 return ndis_events_use_desc(events
, desc
);
707 struct ndis_events_data
*
708 ndis_events_init(HANDLE
*read_pipe
, HANDLE
*event_avail
,
709 const char *ifname
, const char *desc
)
712 IWbemObjectSink
*pSink
;
713 struct ndis_events_data
*events
;
715 events
= os_zalloc(sizeof(*events
));
716 if (events
== NULL
) {
717 wpa_printf(MSG_ERROR
, "Could not allocate sink for events.");
720 events
->ifname
= os_strdup(ifname
);
721 if (events
->ifname
== NULL
) {
726 if (wmi_refcnt
++ == 0) {
727 hr
= CoInitializeEx(0, COINIT_MULTITHREADED
);
729 wpa_printf(MSG_ERROR
, "CoInitializeEx() failed - "
730 "returned 0x%x", (int) hr
);
737 /* CoInitializeSecurity() must be called once and only once
738 * per process, so let's use wmi_first flag to protect against
742 hr
= CoInitializeSecurity(NULL
, -1, NULL
, NULL
,
743 RPC_C_AUTHN_LEVEL_PKT_PRIVACY
,
744 RPC_C_IMP_LEVEL_IMPERSONATE
,
745 NULL
, EOAC_SECURE_REFS
, NULL
);
747 wpa_printf(MSG_ERROR
, "CoInitializeSecurity() failed "
748 "- returned 0x%x", (int) hr
);
754 hr
= CoCreateInstance(&CLSID_WbemLocator
, 0, CLSCTX_INPROC_SERVER
,
755 &IID_IWbemLocator
, (LPVOID
*) &events
->pLoc
);
757 wpa_printf(MSG_ERROR
, "CoCreateInstance() failed - returned "
764 if (ndis_events_get_adapter(events
, ifname
, desc
) < 0) {
769 wpa_printf(MSG_DEBUG
, "ndis_events: use adapter descriptor '%S'",
770 events
->adapter_desc
);
772 hr
= call_IWbemLocator_ConnectServer(
773 events
->pLoc
, L
"ROOT\\WMI", NULL
, NULL
,
774 0, 0, 0, 0, &events
->pSvc
);
776 wpa_printf(MSG_ERROR
, "Could not connect to server - error "
779 os_free(events
->adapter_desc
);
783 wpa_printf(MSG_DEBUG
, "Connected to ROOT\\WMI.");
785 ndis_events_constructor(events
);
786 pSink
= &events
->sink
;
787 pSink
->lpVtbl
= &events
->sink_vtbl
;
788 events
->sink_vtbl
.QueryInterface
= ndis_events_query_interface
;
789 events
->sink_vtbl
.AddRef
= ndis_events_add_ref
;
790 events
->sink_vtbl
.Release
= ndis_events_release
;
791 events
->sink_vtbl
.Indicate
= ndis_events_indicate
;
792 events
->sink_vtbl
.SetStatus
= ndis_events_set_status
;
794 if (register_async_notification(pSink
, events
->pSvc
) < 0) {
795 wpa_printf(MSG_DEBUG
, "Failed to register async "
797 ndis_events_destructor(events
);
798 os_free(events
->adapter_desc
);
803 *read_pipe
= events
->read_pipe
;
804 *event_avail
= events
->event_avail
;