cardif_windows_wmi.c

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

C
2,302
字号
/**
 * \brief Create an event handler to watch for card removal events.
 *
 * \retval 0 on success.
 **/
int cardif_windows_wmi_event_setup_remove()
{
	HRESULT hr;

	hr = IWbemServices_ExecNotificationQuery(wmiEvents,
        L"WQL",
        L"SELECT * FROM MSNdis_NotifyAdapterRemoval" ,
        WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, 
        NULL, &pRemoveEvent);

	if (FAILED(hr)) return -1;

	return 0;
}

/**
 * \brief Check an event handler to see if any removal 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_remove()
{
	HRESULT hr;
    IWbemClassObject *pclsObj = NULL;
	ULONG uReturn;
	context *ctx = NULL;
	wireless_ctx *wctx = NULL;
	VARIANT vtProp;
	char *intdesc = NULL;

	if (pRemoveEvent == NULL) return -1;

	hr = IEnumWbemClassObject_Next(pRemoveEvent, 0, 1, &pclsObj, &uReturn);
	if (FAILED(hr)) return -1;

	if (uReturn > 0)
	{
		// We have an event.
		debug_printf(DEBUG_INT, "!!!!!!!!!!!!!!!!!!!! Card Removal Event !!!!!!!!!!!!!!!!!!!!!\n");
		hr = IWbemClassObject_Get(pclsObj, L"InstanceName", 0, &vtProp, 0, 0);
		if (FAILED(hr))
		{
			debug_printf(DEBUG_NORMAL, "Got a card removal 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);

		intdesc = uni_to_ascii(vtProp.bstrVal);

		if (intdesc != NULL)
		{
			// Try to delete the interface from the interface cache.
			if (interfaces_delete(intdesc) == TRUE)
			{
				debug_printf(DEBUG_NORMAL, "Removed device '%s' from our live interfaces list.\n", intdesc);
			}
		}

		ctx = event_core_locate_by_desc(intdesc);
		VariantClear(&vtProp);

		if (ctx == NULL)
		{
			debug_printf(DEBUG_INT, "Couldn't locate a context for removal event. (Perhaps "
				"we aren't managing this interface?)\n");

			FREE(intdesc);
			return -1;
		}

		debug_printf(DEBUG_INT, "Interface is : %s\n", ctx->intName);
		ipc_events_ui(ctx, IPC_EVENT_INTERFACE_REMOVED, ctx->desc);

		debug_printf(DEBUG_NORMAL, "Interface '%s' was removed or disabled.\n", ctx->desc);

#ifdef HAVE_TNC
		// If we are using a TNC enabled build, signal the IMC to clean up.
		if(imc_disconnect_callback != NULL)
			imc_disconnect_callback(ctx->tnc_connID);
#endif

		ctx->flags |= INT_GONE;
		if ((ctx != NULL) && (ctx->statemachine != NULL)) ctx->statemachine->portEnabled = FALSE;
		if ((ctx != NULL) && (ctx->eap_state != NULL)) ctx->eap_state->portEnabled = FALSE;
		event_core_deregister(((struct win_sock_data *)ctx->sockData)->devHandle);

		FREE(intdesc);
	}

	return 0;
}

/**
 * \brief Create an event handler to watch for media disconnect events.
 *
 * \retval 0 on success.
 **/
int cardif_windows_wmi_event_setup_disconnect()
{
	HRESULT hr;

	hr = IWbemServices_ExecNotificationQuery(wmiEvents,
        L"WQL",
        L"SELECT * FROM MSNdis_StatusMediaDisconnect" ,
        WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, 
        NULL, &pDisconnectEvent);

	if (FAILED(hr)) return -1;

	return 0;
}

/**
 * \brief Check an event handler to see if any media disconnect 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_disconnect()
{
	HRESULT hr;
    IWbemClassObject *pclsObj = NULL;
	ULONG uReturn;
	VARIANT vtProp;
	context *ctx = NULL;
	wireless_ctx *wctx = NULL;
	char *intdesc = NULL;
	char bssid_dest[6];

	if (pDisconnectEvent == NULL) return -1;

	hr = IEnumWbemClassObject_Next(pDisconnectEvent, 0, 1, &pclsObj, &uReturn);
	if (FAILED(hr)) return -1;

	if (uReturn > 0)
	{
		// We have an event.
		debug_printf(DEBUG_INT, "!!!!!!!!!!!!!!!!!!!! Disconnect Event !!!!!!!!!!!!!!!!!!!!!\n");
		hr = IWbemClassObject_Get(pclsObj, L"InstanceName", 0, &vtProp, 0, 0);
		if (FAILED(hr))
		{
			debug_printf(DEBUG_NORMAL, "Got a disconnect 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 disconnect event. (Perhaps "	
					"we aren't managing the 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_DOWN, ctx->desc);

		ctx->auths = 0;     // Reset the number of authentications this interface has done.

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

			// Double check to make sure that we really are disconnected.  Sometimes weird things
			// can happen because the events aren't being received in real time.
			if (cardif_windows_wireless_get_bssid(ctx, bssid_dest) != XENONE)
			{
				UNSET_FLAG(wctx->flags, WIRELESS_SM_ASSOCIATED);  // We are now disassociated.
				UNSET_FLAG(wctx->flags, WIRELESS_SM_STALE_ASSOCIATION);
			}

			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_NORMAL, "Interface '%s' no longer has link.\n", ctx->desc);
			ctx->eap_state->portEnabled = FALSE;
			ctx->statemachine->initialize = TRUE;
		}
	}

	return 0;
}

/**
 * \brief Create an event handler to watch for media specific events.
 *
 * \retval 0 on success.
 **/
int cardif_windows_wmi_event_setup_media_specific()
{
	HRESULT hr;

	hr = IWbemServices_ExecNotificationQuery(wmiEvents,
        L"WQL",
        L"SELECT * FROM MSNdis_StatusMediaSpecificIndication" ,
        WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, 
        NULL, &pMediaSpecificEvent);

	if (FAILED(hr)) return -1;

	return 0;
}

/**
 * \brief Check an event handler to see if any media specific events have happened.
 *
 *  When an event is triggered here, this function will also take care of processing
 *  the event, and changing any needed state options for interfaces.
 *
 * \retval 0 on success
 **/
int cardif_windows_wmi_event_check_media_specific()
{
	HRESULT hr;
    IWbemClassObject *pclsObj = NULL;
	ULONG uReturn;
	VARIANT vtProp;
	context *ctx = NULL;
	wireless_ctx *wctx = NULL;
	LONG k;

	BSTR *bstr = NULL;
	char *data = NULL;
	LONG lower, upper;
	UCHAR ch;

	if (pMediaSpecificEvent == NULL) return -1;

	return 0;  // Don't do the stuff below right now.


	hr = IEnumWbemClassObject_Next(pMediaSpecificEvent, 0, 1, &pclsObj, &uReturn);
	if (FAILED(hr)) return 0;
//	printf("hr = %d\n", hr);

//	while (uReturn > 0)
	{
		/*
		debug_printf(DEBUG_NORMAL, "!!!!!!!!!!!!!!!!!!!!!!!!!!!! Media Specific Event !!!!!!!!!!!!!!!!!!!!!!!!!\n");

		if (uReturn > 0)
		{
			hr = IWbemClassObject_Get(pclsObj, L"InstanceName", 0, &vtProp, 0, 0);
			if (FAILED(hr))
			{
				debug_printf(DEBUG_NORMAL, "Got a media specific event, but it didn't seem to have any "
						"information in it.\n");
			}

			/*
			IWbemClassObject_BeginEnumeration(pclsObj, WBEM_FLAG_REFS_ONLY);

			debug_printf(DEBUG_NORMAL, "------------- Properties ------------\n");

//			bstr = Malloc(1024);

			while (IWbemClassObject_Next(pclsObj, 0, bstr, NULL, NULL, NULL) != WBEM_S_NO_MORE_DATA)
			{
				data = uni_to_ascii(bstr);
				debug_printf(DEBUG_NORMAL, "Property Name : %s\n", data);
				wprintf("Property Name : %ws\n", bstr);
//				printf("Property Name : %s\n", data);
				if (bstr != NULL) SysFreeString(bstr);
				free(data);
			}

			IWbemClassObject_EndEnumeration(pclsObj);
			
		}

		hr = IEnumWbemClassObject_Next(pMediaSpecificEvent, 0, 1, &pclsObj, &uReturn);
*/

		if (uReturn > 0)
		{
			// We have an event.
			debug_printf(DEBUG_INT, "!!!!!!!!!!!!!!!!!!!! Media Specific Event !!!!!!!!!!!!!!!!!!!!!\n");
			hr = IWbemClassObject_Get(pclsObj, L"InstanceName", 0, &vtProp, 0, 0);
			if (FAILED(hr))
			{
				debug_printf(DEBUG_NORMAL, "Got a media specific 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);
			printf("Interface : %ws\n", vtProp.bstrVal);
			ctx = event_core_locate_by_caption(vtProp.bstrVal, FALSE);
			VariantClear(&vtProp);

			hr = IWbemClassObject_Get(pclsObj, L"NdisStatusMediaSpecificIndication", 0, &vtProp, 0, 0);
			SafeArrayGetLBound(V_ARRAY(&vtProp), 1, &lower);
			SafeArrayGetUBound(V_ARRAY(&vtProp), 1, &upper);
			
			for (k = lower; k < upper; k++)
			{
				SafeArrayGetElement(V_ARRAY(&vtProp), &k, &ch);
				printf(" %02X ", ch);
			}

			if (ctx == NULL)
			{
				debug_printf(DEBUG_INT, "Couldn't locate a context for media specific event. (Perhaps "
					"we aren't managing the interface?)\n");
				return -1;
			}

			debug_printf(DEBUG_INT, "Interface is : %s\n", ctx->intName);

			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;
				}
			}
			else
			{
				debug_printf(DEBUG_INT, "Interface isn't wireless.  Not doing anything with it for now.\n");
				return -1;
			}
		}
	}

	return 0;
}

/**
 * \brief Check to see if any events have triggered.
 **/
void cardif_windows_wmi_check_events()
{
	cardif_windows_wmi_event_check_media_specific();
	cardif_windows_wmi_event_check_connect();
	cardif_windows_wmi_event_check_disconnect();
	cardif_windows_wmi_event_check_insert();
	cardif_windows_wmi_event_check_remove();

	// Check to see if any WMI method calls have completed.
	cardif_windows_wmi_async_check();
	
	cardif_windows_wmi_late_bind_insert_check(WMI_BIND_CHECK, NULL);
}

int ipupdatecallback(context *ctx, HANDLE myhandle)
{
	LPOVERLAPPED ovr = NULL;

	ipc_events_ui(ctx, IPC_EVENT_UI_IP_ADDRESS_SET, NULL);

    ovr = event_core_get_ovr(myhandle);

	// myhandle should NEVER change, so this is safe.
	NotifyAddrChange(&myhandle, ovr);

	return 0;
}

/**
 * \brief This isn't really a WMI function, but WMI is inited only once, and we need to only init this once.
 *        The call above is the callback that is generated whenever an IP address is updated.
 **/
void cardif_windows_wmi_ip_update()
{
  DWORD ret;
  LPOVERLAPPED ovr;
  HANDLE hand = INVALID_HANDLE_VALUE;

  ovr = Malloc(sizeof(OVERLAPPED));
  if (ovr == NULL)
  {
	  debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for overlapped structure!\n");
	  return;
  }

  ovr->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

  ret = NotifyAddrChange(&hand, ovr);

  if ((ret != NO_ERROR) && (ret != 997))
  {
		debug_printf(DEBUG_NORMAL, "Can't establish IP address change notify handler.  Error was : %d\n", WSAGetLastError());			
      return;
  }

  if (event_core_register(hand, NULL, &ipupdatecallback, 0, "IP address change event") != 0)
  {
	  debug_printf(DEBUG_NORMAL, "Unable to register IP address change handler.\n");
	  return;
  }

  if (event_core_set_ovr(hand, ovr) != TRUE)
  {
	  debug_printf(DEBUG_NORMAL, "Couldn't set ovr!\n");
	  return;
  }
}

/**
 * \brief Initialize WMI so that we can use it.
 *
 * \retval 0 on success.
 **/
int cardif_windows_wmi_init()
{
	HRESULT hr;

	memset(checks, 0x00, sizeof(checks));

	// Set up notifications to let us know when an address has updated.
	cardif_windows_wmi_ip_update();

	hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED); 
	if ((hr != S_OK) && (hr != S_FALSE))
	{
		if (FAILED(hr)) 
		{ 
			debug_printf(DEBUG_NORMAL, "Failed to initialize COM library. Error code = 0x%02x\n", hr);
			error_prequeue_add("Failed to initialize COM library.");
			return -1;
		}

⌨️ 快捷键说明

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