cardif_windows_wmi.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 2,302 行 · 第 1/5 页
C
2,302 行
/**
* Interface to Windows WMI for events, and getting various data.
*
* Licensed under a dual GPL/BSD license. (See LICENSE file for more info.)
*
* \file cardif_windows_wmi.c
*
* \author chris@open1x.org
*
* \todo Implement calls to get the list of DNS servers.
*
* $Id: cardif_windows_wmi.c,v 1.1.2.57 2008/01/21 22:51:48 chessing Exp $
* $Date: 2008/01/21 22:51:48 $
**/
#define _WIN32_DCOM
// We need to define COBJMACROS so that we can make the C calls
// to the IWbem* interfaces.
#ifndef COBJMACROS
#define COBJMACROS
#endif
#include <wbemidl.h>
#include <windows.h>
#include <iphlpapi.h>
#include <process.h>
#include "../../xsup_common.h"
#include "../../../lib/libxsupconfig/xsupconfig.h"
#include "../../../lib/libxsupconfig/xsupconfig_structs.h"
#include "../../context.h"
#include "../../xsup_debug.h"
#include "../../xsup_err.h"
#include "cardif_windows.h"
#include "../../event_core_win.h"
#include "../../ipc_events_index.h"
#include "../../eap_sm.h"
#include "../../error_prequeue.h"
#include "cardif_windows_wmi_async.h"
#include "cardif_windows_wmi.h"
///< The WQL select string that is needed to get adapter information for a specific interface.
#define GET_ADAPTER_BY_IDX L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index = %d"
typedef struct {
wchar_t *intName;
uint8_t numChecks;
uint8_t interval;
} check_type;
#define BIND_INTERVAL 5 // The amount of time to wait between bind checks.
#define NUM_BIND_CHECKS 3 // The number of times to attempt to bind before we give up.
#define BIND_CHECKS_SIZE 5 // We can only have 5 outstanding binding requests. This is probably plenty since they shouldn't last long.
check_type checks[5];
#define WMI_BIND_ADD 0
#define WMI_BIND_CHECK 1
// Some globals to make life easy.
IWbemLocator *wmiLoc = NULL;
IWbemServices *wmiSvc = NULL;
IWbemServices *wmiEvents = NULL;
IEnumWbemClassObject *pConnectEvent = NULL;
IEnumWbemClassObject *pDisconnectEvent = NULL;
IEnumWbemClassObject *pMediaSpecificEvent = NULL;
IEnumWbemClassObject *pInsertEvent = NULL;
IEnumWbemClassObject *pRemoveEvent = NULL;
int WMIConnected = FALSE;
// XXX ICK.. Do this better.
extern void (*imc_disconnect_callback)(uint32_t connectionID);
/**
* \brief Create an event handler to watch for media connect events.
*
* \retval 0 on success.
**/
int cardif_windows_wmi_event_setup_connect()
{
HRESULT hr;
hr = IWbemServices_ExecNotificationQuery(wmiEvents,
L"WQL",
L"SELECT * FROM MSNdis_StatusMediaConnect" ,
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
NULL, &pConnectEvent);
if (FAILED(hr)) return -1;
return 0;
}
/**
* \brief Check an event handler to see if any media connect events have happened.
*
* When an event is triggered here, this function will also take care of processing
* the event, and changing the needed state options for interfaces.
*
* \retval 0 on success
**/
int cardif_windows_wmi_event_check_connect()
{
HRESULT hr;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn;
context *ctx = NULL;
wireless_ctx *wctx = NULL;
char *intdesc = NULL;
VARIANT vtProp;
uint8_t bssid[6];
char ssid[34];
int ssidsize = 34;
if (pConnectEvent == NULL) return -1;
hr = IEnumWbemClassObject_Next(pConnectEvent, 0, 1, &pclsObj, &uReturn);
if (FAILED(hr)) return -1;
if (uReturn > 0)
{
// We have an event.
debug_printf(DEBUG_INT, "!!!!!!!!!!!!!!!!!!!! Connect Event !!!!!!!!!!!!!!!!!!!!!\n");
hr = IWbemClassObject_Get(pclsObj, L"InstanceName", 0, &vtProp, 0, 0);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Got a connect event, but it didn't seem to have any "
"information in it.\n");
}
// Locate the context we want to work on.
debug_printf(DEBUG_INT, "Looking for interface with caption : %ws\n", vtProp.bstrVal);
ctx = event_core_locate_by_caption(vtProp.bstrVal, FALSE);
if (ctx == NULL)
{
intdesc = uni_to_ascii(vtProp.bstrVal);
debug_printf(DEBUG_INT, "Couldn't find by caption, looking by description.\n");
ctx = event_core_locate_by_desc_strstr(intdesc);
if (ctx == NULL)
{
debug_printf(DEBUG_INT, "Couldn't locate a context for connect event. (Perhaps "
"we aren't managing this interface?)\n");
VariantClear(&vtProp);
return -1;
}
}
VariantClear(&vtProp);
debug_printf(DEBUG_INT, "Interface is : %s\n", ctx->intName);
// Send event.
ipc_events_ui(NULL, IPC_EVENT_UI_LINK_UP, ctx->desc);
if (ctx->intType == ETH_802_11_INT)
{
wctx = (wireless_ctx *)ctx->intTypeData;
if (wctx == NULL)
{
debug_printf(DEBUG_NORMAL, "Interface %s claims to be wireless, but doesn't "
"have a wireless context!?\n", ctx->intName);
return -1;
}
if (cardif_windows_wireless_get_bssid(ctx, &bssid) != 0)
{
debug_printf(DEBUG_NORMAL, "Unable to get BSSID for interface '%s'.\n", ctx->desc);
ctx->auths = 0; // Reset the number of authentications this interface has done.
}
else
{
if (cardif_windows_wireless_get_ssid(ctx, &ssid, ssidsize) != 0)
{
debug_printf(DEBUG_NORMAL, "Interface '%s' assocated to the AP with BSSID %02X:%02X:%02X:%02X:%02X:%02X\n",
ctx->desc, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
}
else
{
debug_printf(DEBUG_NORMAL, "Interface '%s' assocated to the SSID '%s' with BSSID %02X:%02X:%02X:%02X:%02X:%02X\n",
ctx->desc, ssid, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
}
if ((wctx->cur_essid != NULL) && (strcmp(ssid, wctx->cur_essid) != 0))
{
// We hopped to a new SSID. Reset our counters.
ctx->auths = 0;
}
}
if (memcmp(wctx->cur_bssid, &bssid, 6) != 0)
{
SET_FLAG(wctx->flags, WIRELESS_SM_ASSOCIATED); // We are now associated.
UNSET_FLAG(wctx->flags, WIRELESS_SM_STALE_ASSOCIATION);
// Reset the EAP state machine.
eap_sm_force_init(ctx->eap_state);
memcpy(wctx->cur_bssid, bssid, 6);
}
else
{
debug_printf(DEBUG_NORMAL, "Interface '%s' sent us an associate event about a BSSID we are already associated to. This usually indicates a firmware, driver, or environmental issue. This event has been ignored.\n", ctx->desc);
debug_printf(DEBUG_PHYSICAL_STATE, "Clearing replay counter.\n");
memset(&ctx->statemachine->replay_counter, 0x00, 8);
}
if (TEST_FLAG(wctx->flags, WIRELESS_SM_DOING_PSK))
{
ipc_events_ui(ctx, IPC_EVENT_BAD_PSK, ctx->intName);
// We sent the error so unset the flag.
UNSET_FLAG(wctx->flags, WIRELESS_SM_DOING_PSK);
}
}
else
{
debug_printf(DEBUG_INT, "Enabling wired port.\n");
debug_printf(DEBUG_NORMAL, "Interface '%s' now has link.\n", ctx->desc);
ctx->auths = 0;
// Reset the EAP state machine.
eap_sm_force_init(ctx->eap_state);
}
}
return 0;
}
/**
* \brief Create an event handler to watch for card insertion events.
*
* \retval 0 on success.
**/
int cardif_windows_wmi_event_setup_insert()
{
HRESULT hr;
hr = IWbemServices_ExecNotificationQuery(wmiEvents,
L"WQL",
L"SELECT * FROM MSNdis_NotifyAdapterArrival" ,
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
NULL, &pInsertEvent);
if (FAILED(hr)) return -1;
return 0;
}
/**
* \brief On some machines and interfaces Windows will send the WMI "card inserted"
* message before the interface is bound to our protocol driver. So, we need
* to give it some time to get bound.
*
* @param[in] action An int that defines the action to take. (One of WMI_BIND_ADD,
* WMI_BIND_CHECK)
* @param[in] name The name of the device we want to look for. (Only needed
* when action == WMI_BIND_ADD)
**/
void cardif_windows_wmi_late_bind_insert_check(int action, wchar_t *name)
{
int i = 0;
int retval = 0;
switch (action)
{
case WMI_BIND_ADD:
while ((checks[i].intName != NULL) && (i < BIND_CHECKS_SIZE)) i++;
if (i >= BIND_CHECKS_SIZE)
{
debug_printf(DEBUG_NORMAL, "All bind check slots are currently in use. The newly inserted interface won't be discovered!\n");
return;
}
checks[i].intName = wcsdup(name);
checks[i].interval = BIND_INTERVAL;
checks[i].numChecks = NUM_BIND_CHECKS;
return;
break;
case WMI_BIND_CHECK:
while (i < BIND_CHECKS_SIZE)
{
if (checks[i].intName != NULL)
{
checks[i].interval--;
if (checks[i].interval <= 0)
{
// Try to bind again.
retval = cardif_windows_wmi_post_insert_bind(checks[i].intName);
if (retval != -1)
{
// We are done looking for this interface!
if (retval == -2)
{
debug_printf(DEBUG_NORMAL, "An unrecoverable error was encountered binding the newly inserted interface '%ws'. "
"It will not be available for use.\n", checks[i].intName);
}
FREE(checks[i].intName);
return;
}
checks[i].numChecks--;
if (checks[i].numChecks <= 0)
{
debug_printf(DEBUG_NORMAL, "Failed to bind newly discovered interface '%ws'. It will not be usable.\n", checks[i].intName);
FREE(checks[i].intName);
return;
}
// Otherwise, reset 'interval'.
checks[i].interval = BIND_INTERVAL;
}
}
i++;
}
return;
break;
default:
debug_printf(DEBUG_NORMAL, "You attempted to make use of the function %s() in an naughty way! Stop that! ;)\n", __FUNCTION__);
break;
}
}
/**
* \brief Check an event handler to see if any insertion events have happened.
*
* When an event is triggered here, this function will also take care of processing
* the event, and sending an IPC event..
*
* \retval 0 on success
**/
int cardif_windows_wmi_event_check_insert()
{
HRESULT hr;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn;
VARIANT vtProp;
if (pInsertEvent == NULL) return -1;
hr = IEnumWbemClassObject_Next(pInsertEvent, 0, 1, &pclsObj, &uReturn);
if (FAILED(hr)) return -1;
if (uReturn > 0)
{
// We have an event.
debug_printf(DEBUG_INT, "!!!!!!!!!!!!!!!!!!!! Card Insertion Event !!!!!!!!!!!!!!!!!!!!!\n");
hr = IWbemClassObject_Get(pclsObj, L"InstanceName", 0, &vtProp, 0, 0);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Got a card insertion event, but it didn't seem to have any "
"information in it.\n");
}
// Locate the context we want to work on.
debug_printf(DEBUG_INT, "Looking for interface with caption : %ws\n", vtProp.bstrVal);
if (cardif_windows_wmi_post_insert_bind(vtProp.bstrVal) == -1)
{
// We get a LOT of insert events. The ones we care about have "Packet Scheduler Miniport" in the name.
if (wcsstr(vtProp.bstrVal, L"Packet Scheduler Miniport") != NULL)
{
// Need to queue it up to try to bind later.
debug_printf(DEBUG_NORMAL, "Windows indicated that an interface was inserted, but it doesn't appear to have bound to the "
"Open1X driver yet. We will wait and try again...\n");
cardif_windows_wmi_late_bind_insert_check(WMI_BIND_ADD, vtProp.bstrVal);
}
}
VariantClear(&vtProp);
}
return 0;
}
/**
* \brief Attempt to bind the interface that Windows told us was inserted.
*
* @param[in] name The name of the interface that we need to bind to.
*
* \retval 0 on success
* \retval -1 on failed (should try again.. to some point)
* \retval -2 on failed (unrecoverable failure)
**/
int cardif_windows_wmi_post_insert_bind(wchar_t *name)
{
char *intname = NULL;
char *intdesc = NULL;
struct xsup_interfaces *confints = NULL;
char mac[6];
char is_wireless = 0;
context *ctx = NULL;
intname = cardif_windows_find_os_name_from_desc(name);
intdesc = uni_to_ascii(name);
if (intname == NULL)
{
debug_printf(DEBUG_INT, "Couldn't locate information about this instance, ignoring.\n");
FREE(intdesc);
return -1;
}
if (intdesc == NULL)
{
debug_printf(DEBUG_INT, "Couldn't convert description string from this interface, ignoring.\n");
FREE(intname);
return 0;
}
// Send event.
ipc_events_ui(NULL, IPC_EVENT_INTERFACE_INSERTED, intname);
if (get_mac_by_name(intname, (char *)&mac) != 0)
{
debug_printf(DEBUG_NORMAL, "Unable to get the MAC address for interface with description '%s'. (OS Device Name : %s)\n", intdesc, intname);
return -2;
}
is_wireless = cardif_is_wireless_by_name(intname);
if (interfaces_add(intname, intdesc, mac, is_wireless) != 0)
{
debug_printf(DEBUG_NORMAL, "Unable to add interface '%s' to our live interfaces cache!\n", intdesc);
// Don't die here, because we may be able to manage it, which would at least be something.
}
confints = config_get_config_ints();
while ((confints != NULL) && (memcmp(mac, confints->mac, 6) != 0))
confints = confints->next;
if (confints != NULL)
{
// Build the interface, and start watching it.
if (context_init_interface(&ctx, intdesc, intname, NULL, 0) != XENONE)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate context to manage newly inserted interface!\n");
}
else
{
// Add it to the event loop.
debug_printf(DEBUG_NORMAL, "Interface '%s' was inserted or enabled.\n", intdesc);
}
}
else
{
debug_printf(DEBUG_NORMAL, "Interface '%s' isn't in our configuration file. We will not manage it.\n", intdesc);
}
FREE(intname);
FREE(intdesc);
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?