2 * ndis_events - Receive NdisMIndicateStatus() events using WMI
3 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #define _WIN32_WINNT 0x0400
15 #endif /* COBJMACROS */
21 static int wmi_refcnt
= 0;
22 static int wmi_first
= 1;
24 struct ndis_events_data
{
26 IWbemObjectSinkVtbl sink_vtbl
;
31 HANDLE read_pipe
, write_pipe
, event_avail
;
34 char *ifname
; /* {GUID..} */
38 #define BstrAlloc(x) (x) ? SysAllocString(x) : NULL
39 #define BstrFree(x) if (x) SysFreeString(x)
41 /* WBEM / WMI wrapper functions, to perform in-place conversion of WCHARs to
43 HRESULT STDMETHODCALLTYPE
call_IWbemServices_ExecQuery(
44 IWbemServices
*pSvc
, LPCWSTR strQueryLanguage
, LPCWSTR strQuery
,
45 long lFlags
, IWbemContext
*pCtx
, IEnumWbemClassObject
**ppEnum
)
47 BSTR bsQueryLanguage
, bsQuery
;
50 bsQueryLanguage
= BstrAlloc(strQueryLanguage
);
51 bsQuery
= BstrAlloc(strQuery
);
53 hr
= IWbemServices_ExecQuery(pSvc
, bsQueryLanguage
, bsQuery
, lFlags
,
56 BstrFree(bsQueryLanguage
);
63 HRESULT STDMETHODCALLTYPE
call_IWbemServices_ExecNotificationQueryAsync(
64 IWbemServices
*pSvc
, LPCWSTR strQueryLanguage
, LPCWSTR strQuery
,
65 long lFlags
, IWbemContext
*pCtx
, IWbemObjectSink
*pResponseHandler
)
67 BSTR bsQueryLanguage
, bsQuery
;
70 bsQueryLanguage
= BstrAlloc(strQueryLanguage
);
71 bsQuery
= BstrAlloc(strQuery
);
73 hr
= IWbemServices_ExecNotificationQueryAsync(pSvc
, bsQueryLanguage
,
74 bsQuery
, lFlags
, pCtx
,
77 BstrFree(bsQueryLanguage
);
84 HRESULT STDMETHODCALLTYPE
call_IWbemLocator_ConnectServer(
85 IWbemLocator
*pLoc
, LPCWSTR strNetworkResource
, LPCWSTR strUser
,
86 LPCWSTR strPassword
, LPCWSTR strLocale
, long lSecurityFlags
,
87 LPCWSTR strAuthority
, IWbemContext
*pCtx
, IWbemServices
**ppNamespace
)
89 BSTR bsNetworkResource
, bsUser
, bsPassword
, bsLocale
, bsAuthority
;
92 bsNetworkResource
= BstrAlloc(strNetworkResource
);
93 bsUser
= BstrAlloc(strUser
);
94 bsPassword
= BstrAlloc(strPassword
);
95 bsLocale
= BstrAlloc(strLocale
);
96 bsAuthority
= BstrAlloc(strAuthority
);
98 hr
= IWbemLocator_ConnectServer(pLoc
, bsNetworkResource
, bsUser
,
99 bsPassword
, bsLocale
, lSecurityFlags
,
100 bsAuthority
, pCtx
, ppNamespace
);
102 BstrFree(bsNetworkResource
);
104 BstrFree(bsPassword
);
106 BstrFree(bsAuthority
);
112 enum event_types
{ EVENT_CONNECT
, EVENT_DISCONNECT
, EVENT_MEDIA_SPECIFIC
,
113 EVENT_ADAPTER_ARRIVAL
, EVENT_ADAPTER_REMOVAL
};
115 static int ndis_events_get_adapter(struct ndis_events_data
*events
,
116 const char *ifname
, const char *desc
);
119 static int ndis_events_constructor(struct ndis_events_data
*events
)
123 if (!CreatePipe(&events
->read_pipe
, &events
->write_pipe
, NULL
, 512)) {
124 wpa_printf(MSG_ERROR
, "CreatePipe() failed: %d",
125 (int) GetLastError());
128 events
->event_avail
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
129 if (events
->event_avail
== NULL
) {
130 wpa_printf(MSG_ERROR
, "CreateEvent() failed: %d",
131 (int) GetLastError());
132 CloseHandle(events
->read_pipe
);
133 CloseHandle(events
->write_pipe
);
141 static void ndis_events_destructor(struct ndis_events_data
*events
)
143 CloseHandle(events
->read_pipe
);
144 CloseHandle(events
->write_pipe
);
145 CloseHandle(events
->event_avail
);
146 IWbemServices_Release(events
->pSvc
);
147 IWbemLocator_Release(events
->pLoc
);
148 if (--wmi_refcnt
== 0)
153 static HRESULT STDMETHODCALLTYPE
154 ndis_events_query_interface(IWbemObjectSink
*this, REFIID riid
, void **obj
)
158 if (IsEqualIID(riid
, &IID_IUnknown
) ||
159 IsEqualIID(riid
, &IID_IWbemObjectSink
)) {
161 IWbemObjectSink_AddRef(this);
165 return E_NOINTERFACE
;
169 static ULONG STDMETHODCALLTYPE
ndis_events_add_ref(IWbemObjectSink
*this)
171 struct ndis_events_data
*events
= (struct ndis_events_data
*) this;
172 return ++events
->ref
;
176 static ULONG STDMETHODCALLTYPE
ndis_events_release(IWbemObjectSink
*this)
178 struct ndis_events_data
*events
= (struct ndis_events_data
*) this;
180 if (--events
->ref
!= 0)
183 ndis_events_destructor(events
);
184 wpa_printf(MSG_DEBUG
, "ndis_events: terminated");
185 os_free(events
->adapter_desc
);
186 os_free(events
->ifname
);
192 static int ndis_events_send_event(struct ndis_events_data
*events
,
193 enum event_types type
,
194 char *data
, size_t data_len
)
196 char buf
[512], *pos
, *end
;
200 end
= buf
+ sizeof(buf
);
202 os_memcpy(buf
, &_type
, sizeof(_type
));
203 pos
= buf
+ sizeof(_type
);
206 if (2 + data_len
> (size_t) (end
- pos
)) {
207 wpa_printf(MSG_DEBUG
, "Not enough room for send_event "
208 "data (%d)", data_len
);
211 *pos
++ = data_len
>> 8;
212 *pos
++ = data_len
& 0xff;
213 os_memcpy(pos
, data
, data_len
);
217 if (WriteFile(events
->write_pipe
, buf
, pos
- buf
, &written
, NULL
)) {
218 SetEvent(events
->event_avail
);
221 wpa_printf(MSG_INFO
, "WriteFile() failed: %d", (int) GetLastError());
226 static void ndis_events_media_connect(struct ndis_events_data
*events
)
228 wpa_printf(MSG_DEBUG
, "MSNdis_StatusMediaConnect");
229 ndis_events_send_event(events
, EVENT_CONNECT
, NULL
, 0);
233 static void ndis_events_media_disconnect(struct ndis_events_data
*events
)
235 wpa_printf(MSG_DEBUG
, "MSNdis_StatusMediaDisconnect");
236 ndis_events_send_event(events
, EVENT_DISCONNECT
, NULL
, 0);
240 static void ndis_events_media_specific(struct ndis_events_data
*events
,
241 IWbemClassObject
*pObj
)
245 LONG lower
, upper
, k
;
250 wpa_printf(MSG_DEBUG
, "MSNdis_StatusMediaSpecificIndication");
252 /* This is the StatusBuffer from NdisMIndicateStatus() call */
253 hr
= IWbemClassObject_Get(pObj
, L
"NdisStatusMediaSpecificIndication",
256 wpa_printf(MSG_DEBUG
, "Could not get "
257 "NdisStatusMediaSpecificIndication from "
262 SafeArrayGetLBound(V_ARRAY(&vt
), 1, &lower
);
263 SafeArrayGetUBound(V_ARRAY(&vt
), 1, &upper
);
264 data_len
= upper
- lower
+ 1;
265 data
= os_malloc(data_len
);
267 wpa_printf(MSG_DEBUG
, "Failed to allocate buffer for event "
274 for (k
= lower
; k
<= upper
; k
++) {
275 SafeArrayGetElement(V_ARRAY(&vt
), &k
, &ch
);
278 wpa_hexdump(MSG_DEBUG
, "MediaSpecificEvent", (u8
*) data
, data_len
);
282 ndis_events_send_event(events
, EVENT_MEDIA_SPECIFIC
, data
, data_len
);
288 static void ndis_events_adapter_arrival(struct ndis_events_data
*events
)
290 wpa_printf(MSG_DEBUG
, "MSNdis_NotifyAdapterArrival");
291 ndis_events_send_event(events
, EVENT_ADAPTER_ARRIVAL
, NULL
, 0);
295 static void ndis_events_adapter_removal(struct ndis_events_data
*events
)
297 wpa_printf(MSG_DEBUG
, "MSNdis_NotifyAdapterRemoval");
298 ndis_events_send_event(events
, EVENT_ADAPTER_REMOVAL
, NULL
, 0);
302 static HRESULT STDMETHODCALLTYPE
303 ndis_events_indicate(IWbemObjectSink
*this, long lObjectCount
,
304 IWbemClassObject __RPC_FAR
*__RPC_FAR
*ppObjArray
)
306 struct ndis_events_data
*events
= (struct ndis_events_data
*) this;
309 if (events
->terminating
) {
310 wpa_printf(MSG_DEBUG
, "ndis_events_indicate: Ignore "
311 "indication - terminating");
312 return WBEM_NO_ERROR
;
314 /* wpa_printf(MSG_DEBUG, "Notification received - %d object(s)",
317 for (i
= 0; i
< lObjectCount
; i
++) {
318 IWbemClassObject
*pObj
= ppObjArray
[i
];
322 hr
= IWbemClassObject_Get(pObj
, L
"__CLASS", 0, &vtClass
, NULL
,
325 wpa_printf(MSG_DEBUG
, "Failed to get __CLASS from "
329 /* wpa_printf(MSG_DEBUG, "CLASS: '%S'", vtClass.bstrVal); */
331 hr
= IWbemClassObject_Get(pObj
, L
"InstanceName", 0, &vt
, NULL
,
334 wpa_printf(MSG_DEBUG
, "Failed to get InstanceName "
336 VariantClear(&vtClass
);
340 if (wcscmp(vtClass
.bstrVal
,
341 L
"MSNdis_NotifyAdapterArrival") == 0) {
342 wpa_printf(MSG_DEBUG
, "ndis_events_indicate: Try to "
343 "update adapter description since it may "
344 "have changed with new adapter instance");
345 ndis_events_get_adapter(events
, events
->ifname
, NULL
);
348 if (wcscmp(events
->adapter_desc
, vt
.bstrVal
) != 0) {
349 wpa_printf(MSG_DEBUG
, "ndis_events_indicate: Ignore "
350 "indication for foreign adapter: "
351 "InstanceName: '%S' __CLASS: '%S'",
352 vt
.bstrVal
, vtClass
.bstrVal
);
353 VariantClear(&vtClass
);
359 if (wcscmp(vtClass
.bstrVal
,
360 L
"MSNdis_StatusMediaSpecificIndication") == 0) {
361 ndis_events_media_specific(events
, pObj
);
362 } else if (wcscmp(vtClass
.bstrVal
,
363 L
"MSNdis_StatusMediaConnect") == 0) {
364 ndis_events_media_connect(events
);
365 } else if (wcscmp(vtClass
.bstrVal
,
366 L
"MSNdis_StatusMediaDisconnect") == 0) {
367 ndis_events_media_disconnect(events
);
368 } else if (wcscmp(vtClass
.bstrVal
,
369 L
"MSNdis_NotifyAdapterArrival") == 0) {
370 ndis_events_adapter_arrival(events
);
371 } else if (wcscmp(vtClass
.bstrVal
,
372 L
"MSNdis_NotifyAdapterRemoval") == 0) {
373 ndis_events_adapter_removal(events
);
375 wpa_printf(MSG_DEBUG
, "Unepected event - __CLASS: "
376 "'%S'", vtClass
.bstrVal
);
379 VariantClear(&vtClass
);
382 return WBEM_NO_ERROR
;
386 static HRESULT STDMETHODCALLTYPE
387 ndis_events_set_status(IWbemObjectSink
*this, long lFlags
, HRESULT hResult
,
388 BSTR strParam
, IWbemClassObject __RPC_FAR
*pObjParam
)
390 return WBEM_NO_ERROR
;
394 static int notification_query(IWbemObjectSink
*pDestSink
,
395 IWbemServices
*pSvc
, const char *class_name
)
400 _snwprintf(query
, 256,
401 L
"SELECT * FROM %S", class_name
);
402 wpa_printf(MSG_DEBUG
, "ndis_events: WMI: %S", query
);
403 hr
= call_IWbemServices_ExecNotificationQueryAsync(
404 pSvc
, L
"WQL", query
, 0, 0, pDestSink
);
406 wpa_printf(MSG_DEBUG
, "ExecNotificationQueryAsync for %s "
407 "failed with hresult of 0x%x",
408 class_name
, (int) hr
);
416 static int register_async_notification(IWbemObjectSink
*pDestSink
,
420 const char *class_list
[] = {
421 "MSNdis_StatusMediaConnect",
422 "MSNdis_StatusMediaDisconnect",
423 "MSNdis_StatusMediaSpecificIndication",
424 "MSNdis_NotifyAdapterArrival",
425 "MSNdis_NotifyAdapterRemoval",
429 for (i
= 0; class_list
[i
]; i
++) {
430 if (notification_query(pDestSink
, pSvc
, class_list
[i
]) < 0)
438 void ndis_events_deinit(struct ndis_events_data
*events
)
440 events
->terminating
= 1;
441 IWbemServices_CancelAsyncCall(events
->pSvc
, &events
->sink
);
442 IWbemObjectSink_Release(&events
->sink
);
444 * Rest of deinitialization is done in ndis_events_destructor() once
445 * all reference count drops to zero.
450 static int ndis_events_use_desc(struct ndis_events_data
*events
,
457 if (events
->adapter_desc
== NULL
)
459 /* Continue using old description */
463 tmp
= os_strdup(desc
);
467 pos
= os_strstr(tmp
, " (Microsoft's Packet Scheduler)");
471 len
= os_strlen(tmp
);
472 events
->adapter_desc
= os_malloc((len
+ 1) * sizeof(WCHAR
));
473 if (events
->adapter_desc
== NULL
) {
477 _snwprintf(events
->adapter_desc
, len
+ 1, L
"%S", tmp
);
483 static int ndis_events_get_adapter(struct ndis_events_data
*events
,
484 const char *ifname
, const char *desc
)
488 #define MAX_QUERY_LEN 256
489 WCHAR query
[MAX_QUERY_LEN
];
490 IEnumWbemClassObject
*pEnumerator
;
491 IWbemClassObject
*pObj
;
497 * Try to get adapter descriptor through WMI CIMv2 Win32_NetworkAdapter
498 * to have better probability of matching with InstanceName from
499 * MSNdis events. If this fails, use the provided description.
502 os_free(events
->adapter_desc
);
503 events
->adapter_desc
= NULL
;
505 hr
= call_IWbemLocator_ConnectServer(
506 events
->pLoc
, L
"ROOT\\CIMV2", NULL
, NULL
, 0, 0, 0, 0, &pSvc
);
508 wpa_printf(MSG_ERROR
, "ndis_events: Could not connect to WMI "
509 "server (ROOT\\CIMV2) - error 0x%x", (int) hr
);
510 return ndis_events_use_desc(events
, desc
);
512 wpa_printf(MSG_DEBUG
, "ndis_events: Connected to ROOT\\CIMV2.");
514 _snwprintf(query
, MAX_QUERY_LEN
,
515 L
"SELECT Index FROM Win32_NetworkAdapterConfiguration "
516 L
"WHERE SettingID='%S'", ifname
);
517 wpa_printf(MSG_DEBUG
, "ndis_events: WMI: %S", query
);
519 hr
= call_IWbemServices_ExecQuery(
521 WBEM_FLAG_FORWARD_ONLY
| WBEM_FLAG_RETURN_IMMEDIATELY
,
523 if (!SUCCEEDED(hr
)) {
524 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to query interface "
525 "GUID from Win32_NetworkAdapterConfiguration: "
527 IWbemServices_Release(pSvc
);
528 return ndis_events_use_desc(events
, desc
);
532 hr
= IEnumWbemClassObject_Next(pEnumerator
, WBEM_INFINITE
, 1,
534 if (!SUCCEEDED(hr
) || uReturned
== 0) {
535 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to find interface "
536 "GUID from Win32_NetworkAdapterConfiguration: "
538 IEnumWbemClassObject_Release(pEnumerator
);
539 IWbemServices_Release(pSvc
);
540 return ndis_events_use_desc(events
, desc
);
542 IEnumWbemClassObject_Release(pEnumerator
);
545 hr
= IWbemClassObject_Get(pObj
, L
"Index", 0, &vt
, NULL
, NULL
);
546 if (!SUCCEEDED(hr
)) {
547 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to get Index from "
548 "Win32_NetworkAdapterConfiguration: 0x%x",
550 IWbemServices_Release(pSvc
);
551 return ndis_events_use_desc(events
, desc
);
554 _snwprintf(query
, MAX_QUERY_LEN
,
555 L
"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE "
558 wpa_printf(MSG_DEBUG
, "ndis_events: WMI: %S", query
);
560 IWbemClassObject_Release(pObj
);
562 hr
= call_IWbemServices_ExecQuery(
564 WBEM_FLAG_FORWARD_ONLY
| WBEM_FLAG_RETURN_IMMEDIATELY
,
566 if (!SUCCEEDED(hr
)) {
567 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to query interface "
568 "from Win32_NetworkAdapter: 0x%x", (int) hr
);
569 IWbemServices_Release(pSvc
);
570 return ndis_events_use_desc(events
, desc
);
574 hr
= IEnumWbemClassObject_Next(pEnumerator
, WBEM_INFINITE
, 1,
576 if (!SUCCEEDED(hr
) || uReturned
== 0) {
577 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to find interface "
578 "from Win32_NetworkAdapter: 0x%x", (int) hr
);
579 IEnumWbemClassObject_Release(pEnumerator
);
580 IWbemServices_Release(pSvc
);
581 return ndis_events_use_desc(events
, desc
);
583 IEnumWbemClassObject_Release(pEnumerator
);
585 hr
= IWbemClassObject_Get(pObj
, L
"Name", 0, &vt
, NULL
, NULL
);
586 if (!SUCCEEDED(hr
)) {
587 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to get Name from "
588 "Win32_NetworkAdapter: 0x%x", (int) hr
);
589 IWbemClassObject_Release(pObj
);
590 IWbemServices_Release(pSvc
);
591 return ndis_events_use_desc(events
, desc
);
594 wpa_printf(MSG_DEBUG
, "ndis_events: Win32_NetworkAdapter::Name='%S'",
596 events
->adapter_desc
= _wcsdup(vt
.bstrVal
);
600 * Try to get even better candidate for matching with InstanceName
601 * from Win32_PnPEntity. This is needed at least for some USB cards
602 * that can change the InstanceName whenever being unplugged and
606 hr
= IWbemClassObject_Get(pObj
, L
"PNPDeviceID", 0, &vt
, NULL
, NULL
);
607 if (!SUCCEEDED(hr
)) {
608 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to get PNPDeviceID "
609 "from Win32_NetworkAdapter: 0x%x", (int) hr
);
610 IWbemClassObject_Release(pObj
);
611 IWbemServices_Release(pSvc
);
612 if (events
->adapter_desc
== NULL
)
613 return ndis_events_use_desc(events
, desc
);
614 return 0; /* use Win32_NetworkAdapter::Name */
617 wpa_printf(MSG_DEBUG
, "ndis_events: Win32_NetworkAdapter::PNPDeviceID="
620 len
= _snwprintf(query
, MAX_QUERY_LEN
,
621 L
"SELECT Name FROM Win32_PnPEntity WHERE DeviceID='");
622 if (len
< 0 || len
>= MAX_QUERY_LEN
- 1) {
624 IWbemClassObject_Release(pObj
);
625 IWbemServices_Release(pSvc
);
626 if (events
->adapter_desc
== NULL
)
627 return ndis_events_use_desc(events
, desc
);
628 return 0; /* use Win32_NetworkAdapter::Name */
632 for (pos
= 0; vt
.bstrVal
[pos
] && len
< MAX_QUERY_LEN
- 2; pos
++) {
633 if (vt
.bstrVal
[pos
] == '\\') {
634 if (len
>= MAX_QUERY_LEN
- 3)
638 query
[len
++] = vt
.bstrVal
[pos
];
640 query
[len
++] = L
'\'';
643 IWbemClassObject_Release(pObj
);
644 wpa_printf(MSG_DEBUG
, "ndis_events: WMI: %S", query
);
646 hr
= call_IWbemServices_ExecQuery(
648 WBEM_FLAG_FORWARD_ONLY
| WBEM_FLAG_RETURN_IMMEDIATELY
,
650 if (!SUCCEEDED(hr
)) {
651 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to query interface "
652 "Name from Win32_PnPEntity: 0x%x", (int) hr
);
653 IWbemServices_Release(pSvc
);
654 if (events
->adapter_desc
== NULL
)
655 return ndis_events_use_desc(events
, desc
);
656 return 0; /* use Win32_NetworkAdapter::Name */
660 hr
= IEnumWbemClassObject_Next(pEnumerator
, WBEM_INFINITE
, 1,
662 if (!SUCCEEDED(hr
) || uReturned
== 0) {
663 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to find interface "
664 "from Win32_PnPEntity: 0x%x", (int) hr
);
665 IEnumWbemClassObject_Release(pEnumerator
);
666 IWbemServices_Release(pSvc
);
667 if (events
->adapter_desc
== NULL
)
668 return ndis_events_use_desc(events
, desc
);
669 return 0; /* use Win32_NetworkAdapter::Name */
671 IEnumWbemClassObject_Release(pEnumerator
);
673 hr
= IWbemClassObject_Get(pObj
, L
"Name", 0, &vt
, NULL
, NULL
);
674 if (!SUCCEEDED(hr
)) {
675 wpa_printf(MSG_DEBUG
, "ndis_events: Failed to get Name from "
676 "Win32_PnPEntity: 0x%x", (int) hr
);
677 IWbemClassObject_Release(pObj
);
678 IWbemServices_Release(pSvc
);
679 if (events
->adapter_desc
== NULL
)
680 return ndis_events_use_desc(events
, desc
);
681 return 0; /* use Win32_NetworkAdapter::Name */
684 wpa_printf(MSG_DEBUG
, "ndis_events: Win32_PnPEntity::Name='%S'",
686 os_free(events
->adapter_desc
);
687 events
->adapter_desc
= _wcsdup(vt
.bstrVal
);
690 IWbemClassObject_Release(pObj
);
692 IWbemServices_Release(pSvc
);
694 if (events
->adapter_desc
== NULL
)
695 return ndis_events_use_desc(events
, desc
);
701 struct ndis_events_data
*
702 ndis_events_init(HANDLE
*read_pipe
, HANDLE
*event_avail
,
703 const char *ifname
, const char *desc
)
706 IWbemObjectSink
*pSink
;
707 struct ndis_events_data
*events
;
709 events
= os_zalloc(sizeof(*events
));
710 if (events
== NULL
) {
711 wpa_printf(MSG_ERROR
, "Could not allocate sink for events.");
714 events
->ifname
= os_strdup(ifname
);
715 if (events
->ifname
== NULL
) {
720 if (wmi_refcnt
++ == 0) {
721 hr
= CoInitializeEx(0, COINIT_MULTITHREADED
);
723 wpa_printf(MSG_ERROR
, "CoInitializeEx() failed - "
724 "returned 0x%x", (int) hr
);
731 /* CoInitializeSecurity() must be called once and only once
732 * per process, so let's use wmi_first flag to protect against
736 hr
= CoInitializeSecurity(NULL
, -1, NULL
, NULL
,
737 RPC_C_AUTHN_LEVEL_PKT_PRIVACY
,
738 RPC_C_IMP_LEVEL_IMPERSONATE
,
739 NULL
, EOAC_SECURE_REFS
, NULL
);
741 wpa_printf(MSG_ERROR
, "CoInitializeSecurity() failed "
742 "- returned 0x%x", (int) hr
);
748 hr
= CoCreateInstance(&CLSID_WbemLocator
, 0, CLSCTX_INPROC_SERVER
,
750 (LPVOID
*) (void *) &events
->pLoc
);
752 wpa_printf(MSG_ERROR
, "CoCreateInstance() failed - returned "
759 if (ndis_events_get_adapter(events
, ifname
, desc
) < 0) {
764 wpa_printf(MSG_DEBUG
, "ndis_events: use adapter descriptor '%S'",
765 events
->adapter_desc
);
767 hr
= call_IWbemLocator_ConnectServer(
768 events
->pLoc
, L
"ROOT\\WMI", NULL
, NULL
,
769 0, 0, 0, 0, &events
->pSvc
);
771 wpa_printf(MSG_ERROR
, "Could not connect to server - error "
774 os_free(events
->adapter_desc
);
778 wpa_printf(MSG_DEBUG
, "Connected to ROOT\\WMI.");
780 ndis_events_constructor(events
);
781 pSink
= &events
->sink
;
782 pSink
->lpVtbl
= &events
->sink_vtbl
;
783 events
->sink_vtbl
.QueryInterface
= ndis_events_query_interface
;
784 events
->sink_vtbl
.AddRef
= ndis_events_add_ref
;
785 events
->sink_vtbl
.Release
= ndis_events_release
;
786 events
->sink_vtbl
.Indicate
= ndis_events_indicate
;
787 events
->sink_vtbl
.SetStatus
= ndis_events_set_status
;
789 if (register_async_notification(pSink
, events
->pSvc
) < 0) {
790 wpa_printf(MSG_DEBUG
, "Failed to register async "
792 ndis_events_destructor(events
);
793 os_free(events
->adapter_desc
);
798 *read_pipe
= events
->read_pipe
;
799 *event_avail
= events
->event_avail
;