cardif_windows_wmi.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 2,302 行 · 第 1/5 页
C
2,302 行
}
hr = CoInitializeSecurity(
NULL, // Security descriptor
-1, // COM negotiates authentication service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication level for proxies
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation level for proxies
NULL, // Authentication info
EOAC_NONE, // Additional capabilities of the client or server
NULL); // Reserved
if (hr != S_OK && hr != RPC_E_TOO_LATE)
{
debug_printf(DEBUG_NORMAL, "Failed to initialize COM security. Error code = 0x%02x\n", hr);
CoUninitialize();
return -1;
}
hr = CoCreateInstance(&CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &wmiLoc);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Failed to create IWbemLocator object. Err code = 0x%02x\n", hr);
CoUninitialize();
return -1;
}
if (cardif_windows_wmi_connect() != 0) return -1;
if (cardif_windows_wmi_event_connect() != 0) return -1;
return 0;
}
/**
* \brief Clean up the WMI connection(s) that we were using.
*
* \retval 0 on success
**/
int cardif_windows_wmi_deinit()
{
cardif_windows_wmi_event_disconnect();
cardif_windows_wmi_disconnect();
cardif_windows_wmi_async_cleanup();
if(wmiLoc != NULL)
IWbemLocator_Release(wmiLoc);
CoUninitialize();
return 0;
}
/**
* \brief Establish a connection to WMI to get interface events.
*
* This should only be called when the program starts up.
*
* \retval 0 on success
* \retval -1 on error
**/
int cardif_windows_wmi_event_connect()
{
HRESULT hr;
// Connect to the root\default namespace with the current user.
hr = IWbemLocator_ConnectServer(wmiLoc,
L"ROOT\\WMI",
NULL, NULL, 0, 0, 0, 0, &wmiEvents);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Could not connect. Error code = 0x%04x\n", hr);
return -1;
}
debug_printf(DEBUG_INT, "Connected to WMI\n");
hr = CoSetProxyBlanket(
(IUnknown *)wmiEvents, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Could not set proxy blanket. Error code = 0x%04x\n", hr);
return -1;
}
if (cardif_windows_wmi_event_setup_disconnect() != 0)
{
debug_printf(DEBUG_NORMAL, "Can't establish listener for media disconnect events.\n");
}
if (cardif_windows_wmi_event_setup_connect() != 0)
{
debug_printf(DEBUG_NORMAL, "Can't establish listener for media connect events.\n");
}
if (cardif_windows_wmi_event_setup_media_specific() != 0)
{
debug_printf(DEBUG_NORMAL, "Can't establish listener for media specific events.\n");
}
if (cardif_windows_wmi_event_setup_insert() != 0)
{
debug_printf(DEBUG_NORMAL, "Can't establish listener for card insertion events.\n");
}
if (cardif_windows_wmi_event_setup_remove() != 0)
{
debug_printf(DEBUG_NORMAL, "Can't establish listener for card removal events!\n");
}
return 0;
}
/**
* \brief Establish a connection to WMI for future requests.
*
* In general, this will only be called when the program starts up.
*
* \retval 0 on success
* \retval -1 on error
**/
int cardif_windows_wmi_connect()
{
HRESULT hr;
// Connect to the root\default namespace with the current user.
hr = IWbemLocator_ConnectServer(wmiLoc,
L"ROOT\\CIMV2",
NULL, NULL, 0, 0, 0, 0, &wmiSvc);
if (FAILED(hr))
{
error_prequeue_add("Unable to connect to WMI. The supplicant will be unable to establish a connection.");
debug_printf(DEBUG_NORMAL, "Could not connect. Error code = 0x%02x\n", hr);
return -1;
}
debug_printf(DEBUG_INT, "Connected to CIMV2\n");
hr = CoSetProxyBlanket(
(IUnknown *)wmiSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Could not set proxy blanket. Error code = 0x%02x\n", hr);
return -1;
}
WMIConnected = TRUE;
return XENONE;
}
/**
* \brief Disconnect from the WMI event service when we are done with it.
*
* This should be called when the program shuts down.
*
* \retval 0 on success
**/
int cardif_windows_wmi_event_disconnect()
{
if (pConnectEvent != NULL) IWbemClassObject_Release(pConnectEvent);
if (pDisconnectEvent != NULL) IWbemClassObject_Release(pDisconnectEvent);
if (pMediaSpecificEvent != NULL) IWbemClassObject_Release(pMediaSpecificEvent);
if (pInsertEvent != NULL) IWbemClassObject_Release(pInsertEvent);
if (pRemoveEvent != NULL) IWbemClassObject_Release(pRemoveEvent);
if (wmiEvents != NULL) IWbemServices_Release(wmiEvents);
WMIConnected = FALSE;
return XENONE;
}
/**
* \brief Disconnect from the WMI service when we are done with it.
*
* In general, this will only be called when the program has been asked to shut down.
*
* \retval XENONE on success
**/
int cardif_windows_wmi_disconnect()
{
if (wmiSvc != NULL)
IWbemServices_Release(wmiSvc);
return XENONE;
}
///< \todo Move to_unicode to xsup_common.
// This function is found in mschapv2.c, but we need it here, so
// prototype it, and let the linker figure it out. ;)
char *to_unicode(char *);
/**
* \brief Determine a device index given the context for a device.
*
* @param[in] ctx A pointer to the context for the interface we need to find the
* index of.
*
* \todo Find the proper way to convert unicode strings.
*
* \retval 0 on success
* \retval -1 on error
**/
int cardif_windows_wmi_get_idx(context *ctx, char **description)
{
char *matchstr = NULL;
char *unimstr = NULL;
HRESULT hr;
IEnumWbemClassObject* pEnumerator = NULL;
IWbemClassObject *pclsObj = NULL;
int index = -1;
ULONG uReturn = 0;
VARIANT vtProp;
struct win_sock_data *sockData = NULL;
if (ctx == NULL) return -1;
// First, we need to find the goop that follows the \DEVICE\ in the
// interface name.
matchstr = strstr(ctx->intName, "{");
if (matchstr == NULL) return -1; // It isn't there!? This is BAD!
if (wmiSvc == NULL)
{
debug_printf(DEBUG_NORMAL, "WMI Service is not available!\n");
return -1;
}
// Request information about ALL of the interfaces known to Windows.
hr = IWbemServices_ExecQuery(wmiSvc,
L"WQL",
L"SELECT * FROM Win32_NetworkAdapterConfiguration",
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hr))
{
printf("Query for known interfaces failed. Error code = 0x%02x\n", hr);
return -1;
}
// Then, search through them, looking for 'matchstr'.
unimstr = to_unicode(matchstr);
debug_printf(DEBUG_INT, "Searching for interface matching '%ws'.\n", unimstr);
while (pEnumerator)
{
hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
hr = IWbemClassObject_Get(pclsObj, L"SettingID", 0, &vtProp, 0, 0);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Unable to obtain the 'SettingID' from the return "
"results!\n");
FREE(unimstr);
IWbemClassObject_Release(pEnumerator);
IWbemClassObject_Release(pclsObj);
return -1;
}
if (wcscmp((wchar_t *)unimstr, vtProp.bstrVal) == 0)
{
debug_printf(DEBUG_INT, "Found interface.\n");
// Clean up, so we can get the index.
VariantClear(&vtProp);
hr = IWbemClassObject_Get(pclsObj, L"Index", 0, &vtProp, 0, 0);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Unable to obtain the Index for the desired "
"interface!\n");
FREE(unimstr);
IWbemClassObject_Release(pEnumerator);
IWbemClassObject_Release(pclsObj);
return -1;
}
// Otherwise, we now know the index.
debug_printf(DEBUG_INT, "Interface is at WMI index %d.\n", vtProp.intVal);
sockData = (struct win_sock_data *)ctx->sockData;
if (sockData == NULL)
{
debug_printf(DEBUG_NORMAL, "sockData for context '%s' is invalid!?\n",
ctx->intName);
FREE(unimstr);
IWbemClassObject_Release(pEnumerator);
IWbemClassObject_Release(pclsObj);
VariantClear(&vtProp);
return -1;
}
sockData->wmiIntIdx = vtProp.intVal;
VariantClear(&vtProp);
hr = IWbemClassObject_Get(pclsObj, L"Caption", 0, &vtProp, 0, 0);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Unable to obtain the Index for the desired "
"interface!\n");
FREE(unimstr);
IWbemClassObject_Release(pEnumerator);
IWbemClassObject_Release(pclsObj);
return -1;
}
// Store a copy of the caption for later use, if needed.
sockData->caption = _wcsdup(vtProp.bstrVal);
VariantClear(&vtProp);
debug_printf(DEBUG_INT, "Interface Caption : %ws\n", sockData->caption);
if (description != NULL)
{
hr = IWbemClassObject_Get(pclsObj, L"Description", 0, &vtProp, 0, 0);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Unable to obtain the Index for the desired "
"interface!\n");
FREE(unimstr);
IWbemClassObject_Release(pEnumerator);
IWbemClassObject_Release(pclsObj);
return -1;
}
(*description) = uni_to_ascii(vtProp.bstrVal);
VariantClear(&vtProp);
}
IWbemClassObject_Release(pclsObj);
break;
}
else
{
VariantClear(&vtProp);
IWbemClassObject_Release(pclsObj);
}
}
IWbemClassObject_Release(pEnumerator);
FREE(unimstr);
return XENONE;
}
/**
* \brief Do a WQL request against WMI, and get the value at index 0 of the
* resulting array.
*
* @param[in] ctx The context for the interface we want to get data about.
* @param[in] prop A wchar_t pointer that contains the property to be queried.
*
* \retval NULL on error
* \retval ptr to result
**/
wchar_t *cardif_windows_wmi_get_array_idx0(context *ctx, wchar_t *prop)
{
struct win_sock_data *sockData = NULL;
HRESULT hr;
wchar_t *adapt_select = NULL;
VARIANT vtProp;
IWbemClassObject *pclsObj = NULL;
IEnumWbemClassObject *pEnumerator = NULL;
ULONG uReturn;
BSTR HUGEP *pbstr = NULL;
wchar_t *retval = NULL;
if (ctx == NULL) return NULL;
sockData = (struct win_sock_data *)ctx->sockData;
if (sockData == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't get socket data for context '%s'!?\n",
ctx->intName);
return NULL;
}
if (sockData->wmiIntIdx == INVALID_WMI_IDX)
{
// We don't know the index, so locate it.
if (cardif_windows_wmi_get_idx(ctx, NULL) != XENONE)
{
debug_printf(DEBUG_NORMAL, "Couldn't determine WMI interface index in %s()!\n",
__FUNCTION__);
return NULL;
}
}
// We should know everything we need to locate the IP address for this interface.
// Request information about ALL of the interfaces known to Windows.
adapt_select = Malloc(512);
if (adapt_select == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store adapter select string!\n");
return NULL;
}
swprintf(adapt_select, L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index = %d", sockData->wmiIntIdx);
hr = IWbemServices_ExecQuery(wmiSvc,
L"WQL", adapt_select,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hr))
{
debug_printf(DEBUG_NORMAL, "Failed to locate the WMI configuration block for interface "
"'%s'!\n", ctx->intName);
FREE(adapt_select);
return NULL;
}
FREE(adapt_select);
hr = IEnumWbemClassObject_Next(pEnumerator, WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
debug_printf(DEBUG_NORMAL, "Couldn't build enumerator needed to get array data!\n");
// Clean up and return nothing.
IWbemClassObject_Release(pEnumerator);
return NULL;
}
// We should have a pointer to what we need to know now. So, get the data.
hr = IWbemClassObject_Get(pclsObj, prop, 0, &vtProp, 0, 0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?