cardif_windows_wmi.c

来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 2,302 行 · 第 1/5 页

C
2,302
字号
	if (FAILED(hr))
	{
		debug_printf(DEBUG_NORMAL, "Couldn't determine array data via WMI query!\n");
		IWbemClassObject_Release(pEnumerator);
		VariantClear(&vtProp);
		IWbemClassObject_Release(pclsObj);
		return NULL;
	}

	if (vtProp.parray == NULL) return NULL;

	// Whew!  After all that, we should have an IP address now.
	hr = SafeArrayAccessData(vtProp.parray, (void HUGEP**)&pbstr);
	if (FAILED(hr)) 
	{
		debug_printf(DEBUG_NORMAL, "Get variant array data failed!\n");
		IWbemClassObject_Release(pEnumerator);
		VariantClear(&vtProp);
		IWbemClassObject_Release(pclsObj);
		return NULL;
	}

	debug_printf(DEBUG_INT, "Data : %ws\n", pbstr[0]);
	retval = _wcsdup(pbstr[0]);
	SafeArrayUnaccessData(vtProp.parray);
	
	// Clean up.
	IWbemClassObject_Release(pEnumerator);
	VariantClear(&vtProp);
	IWbemClassObject_Release(pclsObj);

	return retval;
}

/**
 * \brief Convert a unicode string to a UTF-8 string.
 *
 * @param[in] instr  A pointer to a wchar_t string that needs to be converted.
 *
 * \retval NULL on error
 * \retval ptr  instr converted to UTF-8.
 **/
char *convert_unicode_to_chars(wchar_t *instr)
{
	char *utf8result = NULL;

	utf8result = Malloc(wcslen(instr)+2);
	if (utf8result == NULL)
	{
		debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store UTF-8 result at %s()!\n",
				__FUNCTION__);
		return NULL;
	}

	sprintf(utf8result, "%ws", instr);

	return utf8result;
}

/**
 * \brief Get the IP address for a given device.
 *
 * If this is the first time we have requested information about this interface,
 * we will need to call cardif_windows_wmi_get_idx() to populate it's index number.
 * Once we have cached the index number, we shouldn't need to query for the index
 * again.
 *
 * @param[in] ctx  A pointer to the context for this interface.
 *
 * \retval NULL on error
 * \retval ptr  A pointer to a unicode string that identifies the IP address.  You should
 *               use the cardif_windows_wmi_get_ip_utf8() call to get a utf8 string.
 **/
wchar_t *cardif_windows_wmi_get_ip(context *ctx)
{
	return cardif_windows_wmi_get_array_idx0(ctx, L"IPAddress");
}

/**
 * \brief Get the IP address for a given device in UTF-8 format.
 *
 *  This function will call cardif_windows_wmi_get_ip(), and convert the
 *  resulting wide characater string in to UTF-8.
 *
 * \warning This function assumes that the resulting interface name will
 *          not contain characters with values > 0xff.  If they do, the
 *          resulting string will be invalid.
 *
 * \retval NULL on failure
 * \retval ptr  A pointer to a string that identifies the IP address.
 **/
char *cardif_windows_wmi_get_ip_utf8(context *ctx)
{
	wchar_t *wresult = NULL;
	char *utf8result = NULL;

	wresult = cardif_windows_wmi_get_ip(ctx);
	if (wresult == NULL) return NULL;

	utf8result = convert_unicode_to_chars(wresult);
	FREE(wresult);
	return utf8result;
}

/**
 * \brief Get the IP network mask for a given device.
 *
 * If this is the first time we have requested information about this interface,
 * we will need to call cardif_windows_wmi_get_idx() to populate it's index number.
 * Once we have cached the index number, we shouldn't need to query for the index
 * again.
 *
 * @param[in] ctx  A pointer to the context for this interface.
 *
 * \retval NULL on failure
 * \retval ptr  A pointer to a unicode string that identifies the IP network mask.  You should
 *               use the cardif_windows_wmi_get_netmask_utf8() call to get a utf8 string.
 **/
wchar_t *cardif_windows_wmi_get_netmask(context *ctx)
{
	return cardif_windows_wmi_get_array_idx0(ctx, L"IPSubnet");
}

/**
 * \brief Get the IP network mask for a given device in UTF-8 format.
 *
 *  This function will call cardif_windows_wmi_get_netmask(), and convert the
 *  resulting wide characater string in to UTF-8.
 *
 * \warning This function assumes that the resulting interface name will
 *          not contain characters with values > 0xff.  If they do, the
 *          resulting string will be invalid.
 *
 * \retval NULL on failure
 * \retval ptr  A pointer to a string that identifies the IP network mask.
 **/
char *cardif_windows_wmi_get_netmask_utf8(context *ctx)
{
	wchar_t *wresult = NULL;
	char *utf8result = NULL;

	wresult = cardif_windows_wmi_get_netmask(ctx);
	if (wresult == NULL) return NULL;

	utf8result = convert_unicode_to_chars(wresult);
	FREE(wresult);
	return utf8result;
}

/**
 * \brief Get the IP default gateway for a given device.
 *
 * If this is the first time we have requested information about this interface,
 * we will need to call cardif_windows_wmi_get_idx() to populate it's index number.
 * Once we have cached the index number, we shouldn't need to query for the index
 * again.
 *
 * @param[in] ctx  A pointer to the context for this interface.
 *
 * \todo Fix!
 *
 * \retval NULL on failure
 * \retval ptr  A pointer to a unicode string that identifies the IP default gateway.  You should
 *               use the cardif_windows_wmi_get_gw_utf8() call to get a utf8 string.
 **/
wchar_t *cardif_windows_wmi_get_gw(context *ctx)
{
	return NULL;
	return cardif_windows_wmi_get_array_idx0(ctx, L"DefaultIPGateway");
}

/**
 * \brief Get the IP default gateway address for a given device in UTF-8 format.
 *
 *  This function will call cardif_windows_wmi_get_gw(), and convert the
 *  resulting wide characater string in to UTF-8.
 *
 * \warning This function assumes that the resulting interface name will
 *          not contain characters with values > 0xff.  If they do, the
 *          resulting string will be invalid.
 *
 * \retval NULL on failure
 * \retval ptr  A pointer to a string that identifies the IP default gateway.
 **/
char *cardif_windows_wmi_get_gw_utf8(context *ctx)
{
	wchar_t *wresult = NULL;
	char *utf8result = NULL;

	wresult = cardif_windows_wmi_get_gw(ctx);
	if (wresult == NULL) return NULL;

	utf8result = convert_unicode_to_chars(wresult);
	FREE(wresult);
	return utf8result;
}

/**
 * \brief Free all memory used in an allocated 'SAFEARRAY'.
 *
 * @param[in] myarray  The SAFEARRAY we want to destroy.
 *
 **/
void cardif_windows_wmi_destroy_safearray(SAFEARRAY **myarray)
{
	SafeArrayDestroyData((*myarray));
	SafeArrayDestroyDescriptor((*myarray));
	(*myarray) = NULL;
}

/**
 * \brief Set the value of element 0 in the 'SAFEARRAY' to be the string
 *        passed in.
 *
 * \todo Do we need to free mybstr?
 *
 * @param[in] psa   A pointer to an allocated 'SAFEARRAY' that we want
 *                  to populate.
 * @param[in] mystr   The string to put in element 0 of the 'SAFEARRAY'.
 *
 * \retval HRESULT   An HRESULT value for the calls.
 **/
HRESULT cardif_windows_wmi_set_safearray_str(SAFEARRAY *psa, char *mystr)
{
	wchar_t *pbstr = NULL;
	LONG index[] = {0};
	BSTR mybstr = NULL;

	pbstr = malloc(strlen(mystr)*4);   // Should be big enough, and then some.
	if (pbstr == NULL)
	{
		// This is a garbage error, but it will cause the right thing to
		// happen.
		return MAKE_HRESULT(1, FACILITY_CONFIGURATION, 0);
	}

	memset(pbstr, 0x00, (strlen(mystr) * 4));
	mbstowcs(pbstr, mystr, (strlen(mystr)*4));

	mybstr = SysAllocString(pbstr);
	if (mybstr == NULL)
	{
		// This is a garbage error, but it will cause the right thing to
		// happen.
		return MAKE_HRESULT(1, FACILITY_CONFIGURATION, 0);
	}

	free(pbstr);

	return SafeArrayPutElement(psa, index, mybstr);
}

/**
 * \brief Make a WMI call that doesn't require any parameters.  (Semisync version)
 *
 * @param[in] ctx   The context to execute the command against.
 * @param[in] cmdname   The WMI command name to execute.
 * @param[in] callname   The name of the call for debugging and logging purposes.
 * @param[in] callback   The callback that will be called when this call finishes.
 *
 * \retval <0 an error occurred
 * \retval >=0 value returned from WMI call.
 **/
static int cardif_windows_wmi_call_async(context *ctx, char *cmdname, char *callname, void *callback)
{
	struct win_sock_data *sockData = NULL;
	HRESULT hr;
	char lcmdname[200];
    BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
	BSTR MethodName = NULL;
    IWbemClassObject* pClass = NULL;
    IWbemClassObject* pOutParams = NULL;
	IWbemCallResult *pResult = NULL;
	LPVOID lpMsgBuf = NULL;
	VARIANT varReturnValue;
	BSTR IntPath = NULL;
	char apath[100];
	char lpath[200];
	int retval = 0;

	if (ctx == NULL)
	{
		retval = -1;
		goto done;
	}

	if (!xsup_assert((cmdname != NULL), "cmdname != NULL", FALSE))
	{
		retval = -1;
		goto done;
	}

	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 -1;
	}

	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__);
			retval = -1;
			goto done;
		}
	}

	sprintf(&apath, "Win32_NetworkAdapterConfiguration.Index='%d'", sockData->wmiIntIdx);
	mbstowcs((wchar_t *)&lpath, apath, strlen(apath)+1);

	IntPath = SysAllocString((OLECHAR *)&lpath);
	if (IntPath == NULL)
	{
		debug_printf(DEBUG_NORMAL, "Couldn't create interface path!\n");
		retval = -1;
		goto done;
	}

	mbstowcs((wchar_t *)&lcmdname, cmdname, strlen(cmdname)+1);
	MethodName = SysAllocString((OLECHAR *)&lcmdname);
	if (MethodName == NULL)
	{
		debug_printf(DEBUG_NORMAL, "Couldn't create long command name!\n");
		retval = -1;
		goto done;
	}

    hr = IWbemServices_GetObject(wmiSvc, ClassName, 0, NULL, &pClass, NULL);
	if (FAILED(hr))
	{
		debug_printf(DEBUG_NORMAL, "Failed to get object for 'Win32_NetworkAdapterConfiguration'"
				" class!\n");
		debug_printf(DEBUG_NORMAL, "Error #%x\n", hr);
		lpMsgBuf = GetLastErrorStr(GetLastError());

		debug_printf(DEBUG_NORMAL, "Error was : %s", lpMsgBuf);

		LocalFree(lpMsgBuf);

		retval = -1;
		goto done;
	}

    hr = IWbemServices_ExecMethod(wmiSvc, IntPath, MethodName, WBEM_FLAG_RETURN_IMMEDIATELY, // | WBEM_FLAG_FORWARD_ONLY, 
		NULL, pClass, NULL, &pResult);
    if (FAILED(hr))
    {
        debug_printf(DEBUG_NORMAL, "Could not execute method. Error code = 0x%x\n", hr);

		lpMsgBuf = GetLastErrorStr(GetLastError());

		debug_printf(DEBUG_NORMAL, "Error : %s\n", lpMsgBuf);

		LocalFree(lpMsgBuf);
		retval = -1;
		goto done;
	}

done:
	// Clean up.
	if (pOutParams) IWbemClassObject_Release(pOutParams);
	if (pClass) IWbemClassObject_Release(pClass);

	if (MethodName) SysFreeString(MethodName);
	if (IntPath) SysFreeString(IntPath);
	if (ClassName) SysFreeString(ClassName);

	if (retval != 0) return retval;

	return cardif_windows_wmi_async(callname, ctx, pResult, callback);
}

/**
 * \brief Make a WMI call that doesn't require any parameters.
 *
 * @param[in] ctx   The context to execute the command against.
 * @param[in] cmdname   The WMI command name to execute.
 *
 * \retval <0 an error occurred
 * \retval >=0 value returned from WMI call.
 **/
static int cardif_windows_wmi_call(context *ctx, char *cmdname)
{
	struct win_sock_data *sockData = NULL;
	HRESULT hr;
	char lcmdname[200];
    BSTR ClassName = SysAllocString(L"Win32_NetworkAdapterConfiguration");
	BSTR MethodName = NULL;
    IWbemClassObject* pClass = NULL;
    IWbemClassObject* pOutParams = NULL;
	LPVOID lpMsgBuf = NULL;
	VARIANT varReturnValue;
	BSTR IntPath = NULL;
	char apath[100];
	char lpath[200];
	int retval = 0;

	if (ctx == NULL)
	{
		retval = -1;
		goto done;
	}

	if (!xsup_assert((cmdname != NULL), "cmdname != NULL", FALSE))
	{
		retval = -1;
		goto done;
	}

	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);
		retval = -1;
		goto done;
	}

	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__);
			retval = -1;
			goto done;
		}
	}

	sprintf(&apath, "Win32_NetworkAdapterConfiguration.Index='%d'", sockData->wmiIntIdx);
	mbstowcs((wchar_t *)&lpath, apath, strlen(apath)+1);

	IntPath = SysAllocString((OLECHAR *)&lpath);
	if (IntPath == NULL)
	{
		debug_printf(DEBUG_NORMAL, "Couldn't create interface path!\n");
		retval = -1;
		goto done;
	}

	mbstowcs((wchar_t *)&lcmdname, cmdname, strlen(cmdname)+1);
	MethodName = SysAllocString((OLECHAR *)&lcmdname);
	if (MethodName == NULL)
	{
		debug_printf(DEBUG_NORMAL, "Couldn't create long command name!\n");
		retval = -1;
		goto done;
	}

    hr = IWbemServices_GetObject(wmiSvc, ClassName, 0, NULL, &pClass, NULL);
	if (FAILED(hr))
	{
		debug_printf(DEBUG_NORMAL, "Failed to get object for 'Win32_NetworkAdapterConfiguration'"
				" class!\n");
		debug_printf(DEBUG_NORMAL, "Error #%x\n", hr);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?