📄 ndis_events.c
字号:
_snwprintf(query, 256, L"SELECT * FROM %S", class_name); wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); hr = call_IWbemServices_ExecNotificationQueryAsync( pSvc, L"WQL", query, 0, 0, pDestSink); if (FAILED(hr)) { wpa_printf(MSG_DEBUG, "ExecNotificationQueryAsync for %s " "failed with hresult of 0x%x", class_name, (int) hr); return -1; } return 0;}static int register_async_notification(IWbemObjectSink *pDestSink, IWbemServices *pSvc){ int i; const char *class_list[] = { "MSNdis_StatusMediaConnect", "MSNdis_StatusMediaDisconnect", "MSNdis_StatusMediaSpecificIndication", "MSNdis_NotifyAdapterArrival", "MSNdis_NotifyAdapterRemoval", NULL }; for (i = 0; class_list[i]; i++) { if (notification_query(pDestSink, pSvc, class_list[i]) < 0) return -1; } return 0;}void ndis_events_deinit(struct ndis_events_data *events){ events->terminating = 1; IWbemServices_CancelAsyncCall(events->pSvc, &events->sink); IWbemObjectSink_Release(&events->sink); /* * Rest of deinitialization is done in ndis_events_destructor() once * all reference count drops to zero. */}static int ndis_events_use_desc(struct ndis_events_data *events, const char *desc){ char *tmp, *pos; size_t len; if (desc == NULL) { if (events->adapter_desc == NULL) return -1; /* Continue using old description */ return 0; } tmp = os_strdup(desc); if (tmp == NULL) return -1; pos = os_strstr(tmp, " (Microsoft's Packet Scheduler)"); if (pos) *pos = '\0'; len = os_strlen(tmp); events->adapter_desc = os_malloc((len + 1) * sizeof(WCHAR)); if (events->adapter_desc == NULL) { os_free(tmp); return -1; } _snwprintf(events->adapter_desc, len + 1, L"%S", tmp); os_free(tmp); return 0;}static int ndis_events_get_adapter(struct ndis_events_data *events, const char *ifname, const char *desc){ HRESULT hr; IWbemServices *pSvc;#define MAX_QUERY_LEN 256 WCHAR query[MAX_QUERY_LEN]; IEnumWbemClassObject *pEnumerator; IWbemClassObject *pObj; ULONG uReturned; VARIANT vt; int len, pos; /* * Try to get adapter descriptor through WMI CIMv2 Win32_NetworkAdapter * to have better probability of matching with InstanceName from * MSNdis events. If this fails, use the provided description. */ os_free(events->adapter_desc); events->adapter_desc = NULL; hr = call_IWbemLocator_ConnectServer( events->pLoc, L"ROOT\\CIMV2", NULL, NULL, 0, 0, 0, 0, &pSvc); if (FAILED(hr)) { wpa_printf(MSG_ERROR, "ndis_events: Could not connect to WMI " "server (ROOT\\CIMV2) - error 0x%x", (int) hr); return ndis_events_use_desc(events, desc); } wpa_printf(MSG_DEBUG, "ndis_events: Connected to ROOT\\CIMV2."); _snwprintf(query, MAX_QUERY_LEN, L"SELECT Index FROM Win32_NetworkAdapterConfiguration " L"WHERE SettingID='%S'", ifname); wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); hr = call_IWbemServices_ExecQuery( pSvc, L"WQL", query, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (!SUCCEEDED(hr)) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " "GUID from Win32_NetworkAdapterConfiguration: " "0x%x", (int) hr); IWbemServices_Release(pSvc); return ndis_events_use_desc(events, desc); } uReturned = 0; hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, &pObj, &uReturned); if (!SUCCEEDED(hr) || uReturned == 0) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " "GUID from Win32_NetworkAdapterConfiguration: " "0x%x", (int) hr); IEnumWbemClassObject_Release(pEnumerator); IWbemServices_Release(pSvc); return ndis_events_use_desc(events, desc); } IEnumWbemClassObject_Release(pEnumerator); VariantInit(&vt); hr = IWbemClassObject_Get(pObj, L"Index", 0, &vt, NULL, NULL); if (!SUCCEEDED(hr)) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Index from " "Win32_NetworkAdapterConfiguration: 0x%x", (int) hr); IWbemServices_Release(pSvc); return ndis_events_use_desc(events, desc); } _snwprintf(query, MAX_QUERY_LEN, L"SELECT Name,PNPDeviceID FROM Win32_NetworkAdapter WHERE " L"Index=%d", vt.uintVal); wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); VariantClear(&vt); IWbemClassObject_Release(pObj); hr = call_IWbemServices_ExecQuery( pSvc, L"WQL", query, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (!SUCCEEDED(hr)) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " "from Win32_NetworkAdapter: 0x%x", (int) hr); IWbemServices_Release(pSvc); return ndis_events_use_desc(events, desc); } uReturned = 0; hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, &pObj, &uReturned); if (!SUCCEEDED(hr) || uReturned == 0) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " "from Win32_NetworkAdapter: 0x%x", (int) hr); IEnumWbemClassObject_Release(pEnumerator); IWbemServices_Release(pSvc); return ndis_events_use_desc(events, desc); } IEnumWbemClassObject_Release(pEnumerator); hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL); if (!SUCCEEDED(hr)) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from " "Win32_NetworkAdapter: 0x%x", (int) hr); IWbemClassObject_Release(pObj); IWbemServices_Release(pSvc); return ndis_events_use_desc(events, desc); } wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::Name='%S'", vt.bstrVal); events->adapter_desc = _wcsdup(vt.bstrVal); VariantClear(&vt); /* * Try to get even better candidate for matching with InstanceName * from Win32_PnPEntity. This is needed at least for some USB cards * that can change the InstanceName whenever being unplugged and * plugged again. */ hr = IWbemClassObject_Get(pObj, L"PNPDeviceID", 0, &vt, NULL, NULL); if (!SUCCEEDED(hr)) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to get PNPDeviceID " "from Win32_NetworkAdapter: 0x%x", (int) hr); IWbemClassObject_Release(pObj); IWbemServices_Release(pSvc); if (events->adapter_desc == NULL) return ndis_events_use_desc(events, desc); return 0; /* use Win32_NetworkAdapter::Name */ } wpa_printf(MSG_DEBUG, "ndis_events: Win32_NetworkAdapter::PNPDeviceID=" "'%S'", vt.bstrVal); len = _snwprintf(query, MAX_QUERY_LEN, L"SELECT Name FROM Win32_PnPEntity WHERE DeviceID='"); if (len < 0 || len >= MAX_QUERY_LEN - 1) { VariantClear(&vt); IWbemClassObject_Release(pObj); IWbemServices_Release(pSvc); if (events->adapter_desc == NULL) return ndis_events_use_desc(events, desc); return 0; /* use Win32_NetworkAdapter::Name */ } /* Escape \ as \\ */ for (pos = 0; vt.bstrVal[pos] && len < MAX_QUERY_LEN - 2; pos++) { if (vt.bstrVal[pos] == '\\') { if (len >= MAX_QUERY_LEN - 3) break; query[len++] = '\\'; } query[len++] = vt.bstrVal[pos]; } query[len++] = L'\''; query[len] = L'\0'; VariantClear(&vt); IWbemClassObject_Release(pObj); wpa_printf(MSG_DEBUG, "ndis_events: WMI: %S", query); hr = call_IWbemServices_ExecQuery( pSvc, L"WQL", query, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (!SUCCEEDED(hr)) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to query interface " "Name from Win32_PnPEntity: 0x%x", (int) hr); IWbemServices_Release(pSvc); if (events->adapter_desc == NULL) return ndis_events_use_desc(events, desc); return 0; /* use Win32_NetworkAdapter::Name */ } uReturned = 0; hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1, &pObj, &uReturned); if (!SUCCEEDED(hr) || uReturned == 0) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to find interface " "from Win32_PnPEntity: 0x%x", (int) hr); IEnumWbemClassObject_Release(pEnumerator); IWbemServices_Release(pSvc); if (events->adapter_desc == NULL) return ndis_events_use_desc(events, desc); return 0; /* use Win32_NetworkAdapter::Name */ } IEnumWbemClassObject_Release(pEnumerator); hr = IWbemClassObject_Get(pObj, L"Name", 0, &vt, NULL, NULL); if (!SUCCEEDED(hr)) { wpa_printf(MSG_DEBUG, "ndis_events: Failed to get Name from " "Win32_PnPEntity: 0x%x", (int) hr); IWbemClassObject_Release(pObj); IWbemServices_Release(pSvc); if (events->adapter_desc == NULL) return ndis_events_use_desc(events, desc); return 0; /* use Win32_NetworkAdapter::Name */ } wpa_printf(MSG_DEBUG, "ndis_events: Win32_PnPEntity::Name='%S'", vt.bstrVal); os_free(events->adapter_desc); events->adapter_desc = _wcsdup(vt.bstrVal); VariantClear(&vt); IWbemClassObject_Release(pObj); IWbemServices_Release(pSvc); if (events->adapter_desc == NULL) return ndis_events_use_desc(events, desc); return 0;}struct ndis_events_data *ndis_events_init(HANDLE *read_pipe, HANDLE *event_avail, const char *ifname, const char *desc){ HRESULT hr; IWbemObjectSink *pSink; struct ndis_events_data *events; events = os_zalloc(sizeof(*events)); if (events == NULL) { wpa_printf(MSG_ERROR, "Could not allocate sink for events."); return NULL; } events->ifname = os_strdup(ifname); if (events->ifname == NULL) { os_free(events); return NULL; } if (wmi_refcnt++ == 0) { hr = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hr)) { wpa_printf(MSG_ERROR, "CoInitializeEx() failed - " "returned 0x%x", (int) hr); os_free(events); return NULL; } } if (wmi_first) { /* CoInitializeSecurity() must be called once and only once * per process, so let's use wmi_first flag to protect against * multiple calls. */ wmi_first = 0; hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_SECURE_REFS, NULL); if (FAILED(hr)) { wpa_printf(MSG_ERROR, "CoInitializeSecurity() failed " "- returned 0x%x", (int) hr); os_free(events); return NULL; } } hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &events->pLoc); if (FAILED(hr)) { wpa_printf(MSG_ERROR, "CoCreateInstance() failed - returned " "0x%x", (int) hr); CoUninitialize(); os_free(events); return NULL; } if (ndis_events_get_adapter(events, ifname, desc) < 0) { CoUninitialize(); os_free(events); return NULL; } wpa_printf(MSG_DEBUG, "ndis_events: use adapter descriptor '%S'", events->adapter_desc); hr = call_IWbemLocator_ConnectServer( events->pLoc, L"ROOT\\WMI", NULL, NULL, 0, 0, 0, 0, &events->pSvc); if (FAILED(hr)) { wpa_printf(MSG_ERROR, "Could not connect to server - error " "0x%x", (int) hr); CoUninitialize(); os_free(events->adapter_desc); os_free(events); return NULL; } wpa_printf(MSG_DEBUG, "Connected to ROOT\\WMI."); ndis_events_constructor(events); pSink = &events->sink; pSink->lpVtbl = &events->sink_vtbl; events->sink_vtbl.QueryInterface = ndis_events_query_interface; events->sink_vtbl.AddRef = ndis_events_add_ref; events->sink_vtbl.Release = ndis_events_release; events->sink_vtbl.Indicate = ndis_events_indicate; events->sink_vtbl.SetStatus = ndis_events_set_status; if (register_async_notification(pSink, events->pSvc) < 0) { wpa_printf(MSG_DEBUG, "Failed to register async " "notifications"); ndis_events_destructor(events); os_free(events->adapter_desc); os_free(events); return NULL; } *read_pipe = events->read_pipe; *event_avail = events->event_avail; return events;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -