⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xsupgui_windows.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
/**
 * Licensed under a dual GPL/BSD license. (See LICENSE file for more info.)
 *
 * \file xsupgui_windows.c
 *
 * \author chris@open1x.org
 *
 * $Id: xsupgui_windows.c,v 1.1.2.39 2007/09/16 21:44:14 chessing Exp $
 * $Date: 2007/09/16 21:44:14 $
 **/
#ifdef WINDOWS

#include <windows.h>
#include <libxml/parser.h>

#include "../libxsupconfig/xsupconfig_structs.h"
#include "xsupgui_request.h"
#include "xsupgui_xml_common.h"
#include "xsup_gui_trace.h"

//#define TRACELOG   1        ///< Comment this out to disable library level tracing.  (Normally you want this commented out!!)

#define MAXBUF   4096   ///< 4k is the MTU for our IPC messages.

HANDLE pipehdl = INVALID_HANDLE_VALUE;         ///< The read/write handle to our pipe request/response pipe.
HANDLE eventhdl = INVALID_HANDLE_VALUE;        ///< The handle to the windows event we bind to our request/response pipe.
HANDLE eventpipe = INVALID_HANDLE_VALUE;       ///< Handle to the IPC event generation pipe.
HANDLE eventevent = INVALID_HANDLE_VALUE;      ///< The handle to the windows event we bind to our event pipe.
OVERLAPPED ovr;         ///< Overlapped structure used for non-blocking access to \ref pipehdl.
OVERLAPPED eovr;        ///< Overlapped structure used for non-blocking access to \ref eventpipe.

xmlDocPtr recvmsg = NULL;      ///< XML Document that represents an async event that we receiqved.

int ctrl_connected = FALSE;
int evt_connected = FALSE;

LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\open1x_ctrl");  ///< Path to Windows pipe used for IPC.

// Uncomment to see printf() debug messages.
#define DEBUG_WINDOWS_GUI  1

/**
 *  \brief Return the xmlDocPtr that contains the event document.
 *
 *  \retval xmlDocPtr containing the event message.  (May be NULL.)
 **/
xmlDocPtr xsupgui_windows_get_event_doc()
{
	return recvmsg;
}

/**
 *  \brief Establish a connection to a request/response IPC Windows pipe.
 *
 *  \retval 0 on success
 *  \retval -1 on error.
 *
 *  \warning A return value of -1 indicates that the supplicant
 *           probably isn't running.  The UI should notify the user of this!
 **/
int xsupgui_windows_connect()
{
	DWORD dwMode;

	// Make sure we aren't already connected.
	if (ctrl_connected == TRUE) return IPC_ERROR_CTRL_ALREADY_CONNECTED;

#ifdef TRACELOG
	xsup_gui_trace_enable("c:\\guitrace.log");
#endif

	// Establish an event handle.
	if (eventhdl != INVALID_HANDLE_VALUE) return -1;

	eventhdl = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (eventhdl == INVALID_HANDLE_VALUE) return -1;

	ovr.hEvent = eventhdl;

	pipehdl = CreateFile(lpszPipename, GENERIC_READ | GENERIC_WRITE,
				0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 

	if (pipehdl == INVALID_HANDLE_VALUE) return -1;

	xsup_gui_trace("Connected control handle %d, event %d\n", pipehdl, eventhdl);

	dwMode = PIPE_READMODE_MESSAGE;
	if (SetNamedPipeHandleState(pipehdl, &dwMode, NULL, NULL) == FALSE) return -1;
	xsup_gui_trace("After state change : %d\n", pipehdl);

	ctrl_connected = TRUE;

	return 0;  // We have a valid handle now.
}

/**
 *  \brief Establish a connection to a Windows IPC event listener pipe.
 *
 *  \retval 0 on success
 *  \retval -1 on error
 *
 *  \warning A return value of -1 indicates that the supplicant
 *           probably isn't running.  The UI should notify the user of this!
 **/
int xsupgui_windows_connect_event_listener()
{
	char *result = NULL;
	int ressize = 0;
	DWORD dwMode;

	if (evt_connected == TRUE) return IPC_ERROR_EVT_ALREADY_CONNECTED;

	recvmsg = NULL;

	// Establish an event handle.
	eventevent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (eventevent == INVALID_HANDLE_VALUE) return -1;

	eovr.hEvent = eventevent;

	eventpipe = CreateFile(lpszPipename, GENERIC_READ | GENERIC_WRITE,
				0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 

	if (eventpipe == INVALID_HANDLE_VALUE) return -1;

	xsup_gui_trace("Connected event handle %d, event %d\n", eventpipe, eventevent);

	dwMode = PIPE_READMODE_MESSAGE;
	if (SetNamedPipeHandleState(eventpipe, &dwMode, NULL, NULL) == FALSE) return -1;

	evt_connected = TRUE;

	if (xsupgui_request_set_as_event(&result, &ressize) == REQUEST_FAILURE)
		return -1;

	if (xsupgui_windows_send_to_event(result, ressize) == REQUEST_FAILURE)
	{
		free(result);
		result = NULL;
		return -1;
	}

	free(result);

	return 0;  // We have a valid handle now.
}

/**
 *  \brief Disconnect the connection to the request/response IPC Windows pipe.
 *
 *  \retval 0 on success
 *  \retval -1 on error
 **/
int xsupgui_windows_disconnect()
{
	xsup_gui_trace("Disconnect control pipe %d, event %d.\n", pipehdl, eventhdl);
	if (eventhdl != INVALID_HANDLE_VALUE) CloseHandle(eventhdl);
	if (pipehdl != INVALID_HANDLE_VALUE) CloseHandle(pipehdl);
  eventhdl = INVALID_HANDLE_VALUE;
  pipehdl = INVALID_HANDLE_VALUE;

#ifdef TRACELOG
  xsup_gui_trace_disable();
#endif

	ctrl_connected = FALSE;
	return 0;
}

/**
 *  \brief Disconnect the connection to the Windows IPC event pipe.
 *
 *  \retval 0 on success
 *  \retval -1 on error
 **/
int xsupgui_windows_disconnect_event_listener()
{
	xmlFreeDoc(recvmsg);
    recvmsg = NULL; 

	xsup_gui_trace("Disconnect control pipe %d, event %d.\n", eventpipe, eventevent);
	if (eventevent != INVALID_HANDLE_VALUE) CloseHandle(eventevent);
	if (eventpipe != INVALID_HANDLE_VALUE) CloseHandle(eventpipe);
  eventevent = INVALID_HANDLE_VALUE;
  eventpipe = INVALID_HANDLE_VALUE;

  evt_connected = FALSE;
	return 0;
}

/**
 * \brief Flush a named pipe to be sure there isn't any cruft in it.  This should
 *        be used before sending a command to the engine via the named pipe.
 *        On exit from this function, the caller should be fairly sure that the 
 *        pipe is empty, and ready to use.
 **/
void xsupgui_windows_flush_ctrl_pipe()
{
	LPVOID tempbuf;
	char buffer[4096];
	DWORD bread;
	OVERLAPPED ovr;
	HANDLE hevent;

	
	if (!PeekNamedPipe(pipehdl, NULL, 0, NULL, &bread, NULL)) return;  // ACK!
	xsup_gui_trace("(%s) Control pipe handle %d\n", __FUNCTION__, pipehdl);

	while (bread > 0)
	{
		hevent = CreateEvent(NULL, 0, 0, NULL);
		if (hevent == INVALID_HANDLE_VALUE) return;   // ACK!  This should't ever happen.

		ovr.hEvent = hevent;
		
		// There is some data in the buffer.  Read it out and throw it away.
		if (ReadFile(pipehdl, (LPVOID)&buffer, 4096, &bread, (LPOVERLAPPED)&ovr) == FALSE)
		{
			// It may be an overlapped read (which would be weird, but possible).
			if (GetLastError() != ERROR_IO_PENDING)
			{
				// ACK!  We are not in a good place.  Bail out.
				return;
			}

			if (WaitForSingleObject(ovr.hEvent, INFINITE) != WAIT_OBJECT_0)
			{
				// ACK!  This shouldn't happen!
				return;
			}

			if (!GetOverlappedResult(pipehdl, &ovr, &bread, TRUE))  // TRUE should be safe because we know there is something ready.
			{
				// ACK!  Shouldn't happen!
				return;
			}
		}

		CloseHandle(hevent);

		if (!PeekNamedPipe(pipehdl, NULL, 0, NULL, &bread, NULL)) return;  // ACK!
		xsup_gui_trace("(In loop) Control pipe handle %d\n", pipehdl);
	}
}

/**
 *  \brief Process events from the supplicant.
 *
 *  Catch unsolicited events that are generated by the supplicant.  
 *
 * @param[out] evttype   The event type that generated the event.
 *

 *  \warning This is a *BLOCKING* call, so it should
 *  be run from a different thread, and signals should be passed
 *  back to the core of the UI.
 *
 *  \retval 1 there is a new event to process.  
 *  \retval 0 if there is nothing to process
 *  \retval >300 on error
 **/
long int xsupgui_windows_process(int *evttype)
{
	int retval = 1;
	char *eventbuf = NULL;
	int eventbufressize = 0;

	if (evttype == NULL) return IPC_ERROR_INVALID_PARAMETERS;

	// If eventbuf points to something, we have a problem.
	if (recvmsg != NULL) 
		return IPC_ERROR_STALE_BUFFER_DATA;

	retval = xsupgui_windows_recv_event(&eventbuf, &eventbufressize);

	if (retval != REQUEST_SUCCESS)
	{
		if (retval == IPC_EVENT_COM_BROKEN)
		{
			(*evttype) = IPC_EVENT_COM_BROKEN;
			return REQUEST_SUCCESS;
		}

		return retval;
	}

	if ((eventbuf == NULL) || ((eventbufressize-5) < 0))
	{
		recvmsg = NULL;
		if (eventbuf != NULL) free(eventbuf);
		return IPC_ERROR_RUNT_RESPONSE;
	}

	recvmsg = xmlReadMemory(&eventbuf[5], (eventbufressize-5), "ipc_event.xml", NULL, 0);
	if (recvmsg == NULL) 
	{
		retval = GetLastError();

//		xsup_gui_trace("XML Dump :\n");
//		xsup_gui_trace("%s\n", &eventbuf[5]);
//		xsup_gui_trace("------  Windows Error : %d\n", retval);

		free(eventbuf);
		return IPC_ERROR_BAD_RESPONSE;
	}

	if (eventbuf != NULL) free(eventbuf);
	eventbuf = NULL;

	(*evttype) = xsupgui_events_get_event_num(recvmsg);

	return REQUEST_SUCCESS;
}

/**
 *  \brief Read data from an already connected Windows pipe.
 *
 *  Get data from a pipe.  This may be used to get data that is a response from
 *  a previously issued request, or get the data for an unsolicited event.
 *
 *  @param[out] result   A buffer to the data that was read.  (This function will allocate it, the
 *                       caller is expected to free it.)
 *  @param[out] resultsize   The amount of data that the buffer contains.
 *
 *  \retval REQUEST_SUCCESS on success
 *  \retval >=300 on error.
 *  \retval REQUEST_TIMEOUT on timeout
 **/
int xsupgui_windows_recv(unsigned char **result, int *resultsize)
{
	unsigned char *resdata = NULL;
	uint8_t *data = NULL;
	int done = FALSE;
	int size = 0;
	int i = 0;
	int offset = 0;
	ipc_header *hdr = NULL;
	uint32_t value32 = 0;
	int retval = 0;

	(*result) = NULL;
	(*resultsize) = 0;

	if (ctrl_connected != TRUE) return IPC_ERROR_CTRL_NOT_CONNECTED;

	resdata = malloc(MAXBUF);
	if (resdata == NULL) 
	{
#ifdef DEBUG_WINDOWS_GUI

⌨️ 快捷键说明

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