[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 3/6] Add named pipe server
From: Owen Smith <owen.smith@xxxxxxxxxx> Create a threaded NamedPipe server for the device. This will be used to pass data from the console to child processes, and read data from the child processes to pass to the console device. Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> --- src/monitor/monitor.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c index df94934..e3979b8 100644 --- a/src/monitor/monitor.c +++ b/src/monitor/monitor.c @@ -50,6 +50,13 @@ #define MONITOR_NAME __MODULE__ #define MONITOR_DISPLAYNAME MONITOR_NAME +typedef struct _MONITOR_PIPE { + HANDLE Pipe; + HANDLE Event; + HANDLE Thread; + LIST_ENTRY ListEntry; +} MONITOR_PIPE, *PMONITOR_PIPE; + typedef struct _MONITOR_CONTEXT { SERVICE_STATUS Status; SERVICE_STATUS_HANDLE Service; @@ -67,10 +74,17 @@ typedef struct _MONITOR_CONTEXT { HANDLE MonitorThread; HANDLE DeviceEvent; HANDLE DeviceThread; + HANDLE ServerEvent; + HANDLE ServerThread; + CRITICAL_SECTION CriticalSection; + LIST_ENTRY ListHead; + DWORD ListCount; } MONITOR_CONTEXT, *PMONITOR_CONTEXT; MONITOR_CONTEXT MonitorContext; +#define PIPE_NAME TEXT("\\\\.\\pipe\\xencons") + #define MAXIMUM_BUFFER_SIZE 1024 #define SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services" @@ -347,6 +361,219 @@ fail1: return FALSE; } +static FORCEINLINE VOID +InitializeListHead( + IN PLIST_ENTRY ListEntry + ) +{ + ListEntry->Flink = ListEntry; + ListEntry->Blink = ListEntry; +} + +static FORCEINLINE VOID +InsertTailList( + IN PLIST_ENTRY ListHead, + IN PLIST_ENTRY ListEntry + ) +{ + ListEntry->Blink = ListHead->Blink; + ListEntry->Flink = ListHead; + ListHead->Blink->Flink = ListEntry; + ListHead->Blink = ListEntry; +} + +static FORCEINLINE VOID +RemoveEntryList( + IN PLIST_ENTRY ListEntry + ) +{ + PLIST_ENTRY Flink; + PLIST_ENTRY Blink; + + Flink = ListEntry->Flink; + Blink = ListEntry->Blink; + Flink->Blink = Blink; + Blink->Flink = Flink; + + ListEntry->Flink = ListEntry; + ListEntry->Blink = ListEntry; +} + +DWORD WINAPI +PipeThread( + IN LPVOID Argument + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + PMONITOR_PIPE Pipe = (PMONITOR_PIPE)Argument; + UCHAR Buffer[MAXIMUM_BUFFER_SIZE]; + OVERLAPPED Overlapped; + HANDLE Handle[2]; + DWORD Length; + DWORD Object; + HRESULT Error; + + Log("====>"); + + memset(&Overlapped, 0, sizeof(OVERLAPPED)); + Overlapped.hEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + if (Overlapped.hEvent == NULL) + goto fail1; + + Handle[0] = Pipe->Event; + Handle[1] = Overlapped.hEvent; + + EnterCriticalSection(&Context->CriticalSection); + InsertTailList(&Context->ListHead, &Pipe->ListEntry); + ++Context->ListCount; + LeaveCriticalSection(&Context->CriticalSection); + + for (;;) { + (VOID) ReadFile(Pipe->Pipe, + Buffer, + sizeof(Buffer), + NULL, + &Overlapped); + + Object = WaitForMultipleObjects(ARRAYSIZE(Handle), + Handle, + FALSE, + INFINITE); + if (Object == WAIT_OBJECT_0) + break; + + if (!GetOverlappedResult(Pipe->Pipe, + &Overlapped, + &Length, + FALSE)) + break; + + ResetEvent(Overlapped.hEvent); + + // Length bytes of Buffer have been read + } + + EnterCriticalSection(&Context->CriticalSection); + RemoveEntryList(&Pipe->ListEntry); + --Context->ListCount; + LeaveCriticalSection(&Context->CriticalSection); + + CloseHandle(Overlapped.hEvent); + + Log("<===="); + + return 0; + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return 1; +} + +DWORD WINAPI +ServerThread( + IN LPVOID Argument + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + OVERLAPPED Overlapped; + HANDLE Handle[2]; + DWORD Object; + HRESULT Error; + + UNREFERENCED_PARAMETER(Argument); + + Log("====>"); + + memset(&Overlapped, 0, sizeof(OVERLAPPED)); + Overlapped.hEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + if (Overlapped.hEvent == NULL) + goto fail1; + + Handle[0] = Context->ServerEvent; + Handle[1] = Overlapped.hEvent; + + for (;;) { + HANDLE Pipe; + PMONITOR_PIPE Instance; + + Pipe = CreateNamedPipe(PIPE_NAME, + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, + PIPE_UNLIMITED_INSTANCES, + MAXIMUM_BUFFER_SIZE, + MAXIMUM_BUFFER_SIZE, + 0, + NULL); + if (Pipe == INVALID_HANDLE_VALUE) + break; + + (VOID) ConnectNamedPipe(Pipe, + &Overlapped); + + Object = WaitForMultipleObjects(ARRAYSIZE(Handle), + Handle, + FALSE, + INFINITE); + if (Object == WAIT_OBJECT_0) + break; + + ResetEvent(Overlapped.hEvent); + + Instance = (PMONITOR_PIPE)malloc(sizeof(MONITOR_PIPE)); + if (Instance == NULL) { + CloseHandle(Pipe); + break; + } + + InitializeListHead(&Instance->ListEntry); + Instance->Pipe = Pipe; + Instance->Event = Context->ServerEvent; + Instance->Thread = CreateThread(NULL, + 0, + PipeThread, + Instance, + 0, + NULL); + if (Instance->Thread == INVALID_HANDLE_VALUE) { + free(Instance); + CloseHandle(Pipe); + break; + } + } + + CloseHandle(Overlapped.hEvent); + + Log("<===="); + + return 0; + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return 1; +} + DWORD WINAPI MonitorThread( IN LPVOID Argument @@ -624,6 +851,8 @@ MonitorAdd( goto fail3; Context->DevicePath = Path; + InitializeListHead(&Context->ListHead); + InitializeCriticalSection(&Context->CriticalSection); Context->MonitorEvent = CreateEvent(NULL, TRUE, @@ -661,10 +890,38 @@ MonitorAdd( if (Context->DeviceThread == INVALID_HANDLE_VALUE) goto fail7; + Context->ServerEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + if (Context->ServerEvent == NULL) + goto fail8; + + Context->ServerThread = CreateThread(NULL, + 0, + ServerThread, + NULL, + 0, + NULL); + if (Context->ServerThread == INVALID_HANDLE_VALUE) + goto fail9; + Log("<===="); return; +fail9: + Log("fail9"); + + CloseHandle(Context->ServerEvent); + Context->ServerEvent = NULL; + +fail8: + Log("fail8"); + + SetEvent(Context->DeviceEvent); + WaitForSingleObject(Context->DeviceThread, INFINITE); + fail7: Log("fail7\n"); @@ -686,6 +943,9 @@ fail5: fail4: Log("fail4"); + DeleteCriticalSection(&Context->CriticalSection); + memset(&Context->ListHead, 0, sizeof(LIST_ENTRY)); + free(Context->DevicePath); Context->DevicePath = NULL; @@ -715,6 +975,56 @@ fail1: } static VOID +MonitorWaitForPipeThreads( + VOID + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + HANDLE *Handles; + DWORD Index; + PLIST_ENTRY ListEntry; + + EnterCriticalSection(&Context->CriticalSection); + + if (Context->ListCount == 0) + goto fail1; + + Handles = (HANDLE*)malloc(sizeof(HANDLE) * Context->ListCount); + if (Handles == NULL) + goto fail2; + + Index = 0; + for (ListEntry = Context->ListHead.Flink; + ListEntry != &Context->ListHead && Index < Context->ListCount; + ListEntry = ListEntry->Flink) { + PMONITOR_PIPE Pipe = CONTAINING_RECORD(ListEntry, MONITOR_PIPE, ListEntry); + Handles[Index++] = Pipe->Thread; + } + + Context->ListCount = 0; + + LeaveCriticalSection(&Context->CriticalSection); + +#pragma warning(suppress:6385) // Reading invalid data from 'Handles'... + WaitForMultipleObjects(Index, + Handles, + TRUE, + INFINITE); + free(Handles); + return; + +fail2: + Log("fail2"); + +fail1: + Log("fail1"); + + LeaveCriticalSection(&Context->CriticalSection); + + return; +} + +static VOID MonitorRemove( VOID ) @@ -726,6 +1036,13 @@ MonitorRemove( Log("====>"); + SetEvent(Context->ServerEvent); + MonitorWaitForPipeThreads(); + WaitForSingleObject(Context->ServerThread, INFINITE); + + CloseHandle(Context->ServerEvent); + Context->ServerEvent = NULL; + SetEvent(Context->DeviceEvent); WaitForSingleObject(Context->DeviceThread, INFINITE); @@ -738,6 +1055,9 @@ MonitorRemove( CloseHandle(Context->MonitorEvent); Context->MonitorEvent = NULL; + DeleteCriticalSection(&Context->CriticalSection); + memset(&Context->ListHead, 0, sizeof(LIST_ENTRY)); + free(Context->DevicePath); Context->DevicePath = NULL; -- 2.8.3 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |