[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 04/14] Make the monitor service multi-console aware
From: Owen Smith <owen.smith@xxxxxxxxxx> * Create a list of instances, 1 per interface found. * Moves Add / Remove inline (remove events) * Enumerates all interfaces present * Uses IOCTL to query console name * Creates named pipe based on the console name (\\.\pipe\xencons\<name>) * Moves Executable registry key to subkey, based on console name * Changes tty process to use \\.\pipe\xencons\default * Change INF file to write tty to subkey * define UNICODE SetupApi returns ascii/unicode, device events are always unicode * reorder thread start to ensure device and pipe server are running before monitor thread Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> --- src/monitor/monitor.c | 1239 +++++++++++++++++++++++++++---------------------- src/tty/tty.c | 2 +- src/xencons.inf | 2 +- 3 files changed, 677 insertions(+), 566 deletions(-) diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c index 08ae0f2..69a8194 100644 --- a/src/monitor/monitor.c +++ b/src/monitor/monitor.c @@ -30,6 +30,7 @@ */ #define INITGUID 1 +#define UNICODE #include <windows.h> #include <tchar.h> @@ -41,6 +42,7 @@ #include <setupapi.h> #include <malloc.h> #include <assert.h> +#include <winioctl.h> #include <xencons_device.h> #include <version.h> @@ -50,7 +52,26 @@ #define MONITOR_NAME __MODULE__ #define MONITOR_DISPLAYNAME MONITOR_NAME +typedef struct _MONITOR_HANDLE { + PTCHAR DevicePath; + PTCHAR Executable; + PCHAR Name; + HDEVNOTIFY DeviceNotification; + HANDLE Device; + HANDLE MonitorEvent; + HANDLE MonitorThread; + HANDLE DeviceEvent; + HANDLE DeviceThread; + HANDLE ServerEvent; + HANDLE ServerThread; + CRITICAL_SECTION CriticalSection; + LIST_ENTRY ListHead; + DWORD ListCount; + LIST_ENTRY ListEntry; +} MONITOR_HANDLE, *PMONITOR_HANDLE; + typedef struct _MONITOR_PIPE { + PMONITOR_HANDLE Handle; HANDLE Pipe; HANDLE Event; HANDLE Thread; @@ -63,19 +84,7 @@ typedef struct _MONITOR_CONTEXT { HKEY ParametersKey; HANDLE EventLog; HANDLE StopEvent; - HANDLE AddEvent; - HANDLE RemoveEvent; - PTCHAR Executable; HDEVNOTIFY InterfaceNotification; - PTCHAR DevicePath; - HDEVNOTIFY DeviceNotification; - HANDLE Device; - HANDLE MonitorEvent; - HANDLE MonitorThread; - HANDLE DeviceEvent; - HANDLE DeviceThread; - HANDLE ServerEvent; - HANDLE ServerThread; CRITICAL_SECTION CriticalSection; LIST_ENTRY ListHead; DWORD ListCount; @@ -98,7 +107,7 @@ MONITOR_CONTEXT MonitorContext; static VOID #pragma prefast(suppress:6262) // Function uses '1036' bytes of stack: exceeds /analyze:stacksize'1024' __Log( - IN const CHAR *Format, + IN const TCHAR *Format, IN ... ) { @@ -217,7 +226,7 @@ ReportStatus( BOOL Success; HRESULT Error; - Log("====> (%s)", ServiceStateName(CurrentState)); + Log("====> (%hs)", ServiceStateName(CurrentState)); Context->Status.dwCurrentState = CurrentState; Context->Status.dwWin32ExitCode = Win32ExitCode; @@ -256,111 +265,6 @@ fail1: } } -static BOOL -MonitorGetPath( - IN const GUID *Guid, - OUT PTCHAR *Path - ) -{ - HDEVINFO DeviceInfoSet; - SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; - PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetail; - DWORD Size; - HRESULT Error; - BOOL Success; - - Log("====>"); - - DeviceInfoSet = SetupDiGetClassDevs(Guid, - NULL, - NULL, - DIGCF_PRESENT | - DIGCF_DEVICEINTERFACE); - if (DeviceInfoSet == INVALID_HANDLE_VALUE) - goto fail1; - - DeviceInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA); - - Success = SetupDiEnumDeviceInterfaces(DeviceInfoSet, - NULL, - Guid, - 0, - &DeviceInterfaceData); - if (!Success) - goto fail2; - - Success = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, - &DeviceInterfaceData, - NULL, - 0, - &Size, - NULL); - if (!Success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) - goto fail3; - - DeviceInterfaceDetail = calloc(1, Size); - if (DeviceInterfaceDetail == NULL) - goto fail4; - - DeviceInterfaceDetail->cbSize = - sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); - - Success = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, - &DeviceInterfaceData, - DeviceInterfaceDetail, - Size, - NULL, - NULL); - if (!Success) - goto fail5; - - *Path = _tcsdup(DeviceInterfaceDetail->DevicePath); - - if (*Path == NULL) - goto fail6; - - Log("%s", *Path); - - free(DeviceInterfaceDetail); - - SetupDiDestroyDeviceInfoList(DeviceInfoSet); - - Log("<===="); - - return TRUE; - -fail6: - Log("fail6"); - -fail5: - Log("fail5"); - - free(DeviceInterfaceDetail); - -fail4: - Log("fail4"); - -fail3: - Log("fail3"); - -fail2: - Log("fail2"); - - SetupDiDestroyDeviceInfoList(DeviceInfoSet); - -fail1: - Error = GetLastError(); - - { - PTCHAR Message; - Message = GetErrorMessage(Error); - Log("fail1 (%s)", Message); - LocalFree(Message); - } - - return FALSE; -} - static FORCEINLINE VOID __InitializeListHead( IN PLIST_ENTRY ListEntry @@ -430,16 +334,16 @@ PipeThread( IN LPVOID Argument ) { - PMONITOR_CONTEXT Context = &MonitorContext; PMONITOR_PIPE Pipe = (PMONITOR_PIPE)Argument; + PMONITOR_HANDLE Handle = Pipe->Handle; UCHAR Buffer[MAXIMUM_BUFFER_SIZE]; OVERLAPPED Overlapped; - HANDLE Handle[2]; + HANDLE Handles[2]; DWORD Length; DWORD Object; HRESULT Error; - Log("====>"); + Log("====> %hs", Handle->Name); ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); Overlapped.hEvent = CreateEvent(NULL, @@ -449,13 +353,13 @@ PipeThread( if (Overlapped.hEvent == NULL) goto fail1; - Handle[0] = Pipe->Event; - Handle[1] = Overlapped.hEvent; + Handles[0] = Pipe->Event; + Handles[1] = Overlapped.hEvent; - EnterCriticalSection(&Context->CriticalSection); - __InsertTailList(&Context->ListHead, &Pipe->ListEntry); - ++Context->ListCount; - LeaveCriticalSection(&Context->CriticalSection); + EnterCriticalSection(&Handle->CriticalSection); + __InsertTailList(&Handle->ListHead, &Pipe->ListEntry); + ++Handle->ListCount; + LeaveCriticalSection(&Handle->CriticalSection); for (;;) { (VOID) ReadFile(Pipe->Pipe, @@ -464,8 +368,8 @@ PipeThread( NULL, &Overlapped); - Object = WaitForMultipleObjects(ARRAYSIZE(Handle), - Handle, + Object = WaitForMultipleObjects(ARRAYSIZE(Handles), + Handles, FALSE, INFINITE); if (Object == WAIT_OBJECT_0) @@ -479,15 +383,15 @@ PipeThread( ResetEvent(Overlapped.hEvent); - PutString(Context->Device, + PutString(Handle->Device, Buffer, Length); } - EnterCriticalSection(&Context->CriticalSection); + EnterCriticalSection(&Handle->CriticalSection); __RemoveEntryList(&Pipe->ListEntry); - --Context->ListCount; - LeaveCriticalSection(&Context->CriticalSection); + --Handle->ListCount; + LeaveCriticalSection(&Handle->CriticalSection); CloseHandle(Overlapped.hEvent); @@ -497,7 +401,7 @@ PipeThread( CloseHandle(Pipe->Thread); free(Pipe); - Log("<===="); + Log("<==== %hs", Handle->Name); return 0; @@ -519,17 +423,16 @@ ServerThread( IN LPVOID Argument ) { - PMONITOR_CONTEXT Context = &MonitorContext; + PMONITOR_HANDLE Handle = (PMONITOR_HANDLE)Argument; OVERLAPPED Overlapped; - HANDLE Handle[2]; + HANDLE Handles[2]; HANDLE Pipe; DWORD Object; + TCHAR PipeName[MAX_PATH]; PMONITOR_PIPE Instance; HRESULT Error; - UNREFERENCED_PARAMETER(Argument); - - Log("====>"); + Log("====> %hs", Handle->Name); ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); Overlapped.hEvent = CreateEvent(NULL, @@ -539,11 +442,22 @@ ServerThread( if (Overlapped.hEvent == NULL) goto fail1; - Handle[0] = Context->ServerEvent; - Handle[1] = Overlapped.hEvent; + Handles[0] = Handle->ServerEvent; + Handles[1] = Overlapped.hEvent; + + Error = StringCbPrintf(PipeName, + sizeof(PipeName), + TEXT("%s\\%hs"), + PIPE_NAME, + Handle->Name); + + if (Error != S_OK && Error != STRSAFE_E_INSUFFICIENT_BUFFER) + goto fail2; + + Log("PipeName = %s", PipeName); for (;;) { - Pipe = CreateNamedPipe(PIPE_NAME, + Pipe = CreateNamedPipe(PipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, @@ -552,13 +466,13 @@ ServerThread( 0, NULL); if (Pipe == INVALID_HANDLE_VALUE) - goto fail2; + goto fail3; - (VOID) ConnectNamedPipe(Pipe, - &Overlapped); + (VOID)ConnectNamedPipe(Pipe, + &Overlapped); - Object = WaitForMultipleObjects(ARRAYSIZE(Handle), - Handle, + Object = WaitForMultipleObjects(ARRAYSIZE(Handles), + Handles, FALSE, INFINITE); if (Object == WAIT_OBJECT_0) { @@ -570,11 +484,12 @@ ServerThread( Instance = (PMONITOR_PIPE)malloc(sizeof(MONITOR_PIPE)); if (Instance == NULL) - goto fail3; + goto fail4; __InitializeListHead(&Instance->ListEntry); + Instance->Handle = Handle; Instance->Pipe = Pipe; - Instance->Event = Context->ServerEvent; + Instance->Event = Handle->ServerEvent; Instance->Thread = CreateThread(NULL, 0, PipeThread, @@ -582,28 +497,33 @@ ServerThread( 0, NULL); if (Instance->Thread == INVALID_HANDLE_VALUE) - goto fail4; + goto fail5; } CloseHandle(Overlapped.hEvent); - Log("<===="); + Log("<==== %hs", Handle->Name); return 0; +fail5: + Log("fail5"); + + free(Instance); + fail4: Log("fail4"); - free(Instance); + CloseHandle(Pipe); fail3: Log("fail3"); - CloseHandle(Pipe); - fail2: Log("fail2"); + CloseHandle(Overlapped.hEvent); + fail1: Error = GetLastError(); @@ -622,20 +542,18 @@ MonitorThread( IN LPVOID Argument ) { - PMONITOR_CONTEXT Context = &MonitorContext; + PMONITOR_HANDLE Handle = (PMONITOR_HANDLE)Argument; PROCESS_INFORMATION ProcessInfo; STARTUPINFO StartupInfo; BOOL Success; - HANDLE Handle[2]; + HANDLE Handles[2]; DWORD Object; HRESULT Error; - UNREFERENCED_PARAMETER(Argument); - - Log("====>"); + Log("====> %hs", Handle->Name); // If there is no executable, this thread can finish now. - if (Context->Executable == NULL) + if (Handle->Executable == NULL) goto done; again: @@ -643,11 +561,11 @@ again: ZeroMemory(&StartupInfo, sizeof (StartupInfo)); StartupInfo.cb = sizeof (StartupInfo); - Log("Executing: %s", Context->Executable); + Log("Executing: %s", Handle->Executable); #pragma warning(suppress:6053) // CommandLine might not be NUL-terminated Success = CreateProcess(NULL, - Context->Executable, + Handle->Executable, NULL, NULL, FALSE, @@ -660,11 +578,11 @@ again: if (!Success) goto fail1; - Handle[0] = Context->MonitorEvent; - Handle[1] = ProcessInfo.hProcess; + Handles[0] = Handle->MonitorEvent; + Handles[1] = ProcessInfo.hProcess; - Object = WaitForMultipleObjects(ARRAYSIZE(Handle), - Handle, + Object = WaitForMultipleObjects(ARRAYSIZE(Handles), + Handles, FALSE, INFINITE); @@ -672,7 +590,7 @@ again: switch (Object) { case WAIT_OBJECT_0: - ResetEvent(Context->MonitorEvent); + ResetEvent(Handle->MonitorEvent); TerminateProcess(ProcessInfo.hProcess, 1); CloseHandle(ProcessInfo.hProcess); @@ -691,7 +609,7 @@ again: //#undef WAIT_OBJECT_1 done: - Log("<===="); + Log("<==== %hs", Handle->Name); return 0; @@ -713,7 +631,7 @@ DeviceThread( IN LPVOID Argument ) { - PMONITOR_CONTEXT Context = &MonitorContext; + PMONITOR_HANDLE Handle = (PMONITOR_HANDLE)Argument; OVERLAPPED Overlapped; HANDLE Device; UCHAR Buffer[MAXIMUM_BUFFER_SIZE]; @@ -722,9 +640,7 @@ DeviceThread( HANDLE Handles[2]; DWORD Error; - UNREFERENCED_PARAMETER(Argument); - - Log("====>"); + Log("====> %hs", Handle->Name); ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); Overlapped.hEvent = CreateEvent(NULL, @@ -734,10 +650,10 @@ DeviceThread( if (Overlapped.hEvent == NULL) goto fail1; - Handles[0] = Context->DeviceEvent; + Handles[0] = Handle->DeviceEvent; Handles[1] = Overlapped.hEvent; - Device = CreateFile(Context->DevicePath, + Device = CreateFile(Handle->DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, @@ -771,10 +687,10 @@ DeviceThread( ResetEvent(Overlapped.hEvent); - EnterCriticalSection(&Context->CriticalSection); + EnterCriticalSection(&Handle->CriticalSection); - for (ListEntry = Context->ListHead.Flink; - ListEntry != &Context->ListHead; + for (ListEntry = Handle->ListHead.Flink; + ListEntry != &Handle->ListHead; ListEntry = ListEntry->Flink) { PMONITOR_PIPE Instance; @@ -784,14 +700,14 @@ DeviceThread( Buffer, Length); } - LeaveCriticalSection(&Context->CriticalSection); + LeaveCriticalSection(&Handle->CriticalSection); } CloseHandle(Device); CloseHandle(Overlapped.hEvent); - Log("<===="); + Log("<==== %hs", Handle->Name); return 0; @@ -817,205 +733,34 @@ fail1: PutString((_Handle), (PUCHAR)TEXT(_Buffer), (DWORD)_tcslen((_Buffer)) * sizeof(TCHAR)) static VOID -MonitorAdd( - VOID - ) -{ - PMONITOR_CONTEXT Context = &MonitorContext; - PTCHAR Path; - DEV_BROADCAST_HANDLE Handle; - HRESULT Error; - BOOL Success; - - if (Context->Device != INVALID_HANDLE_VALUE) - return; - - Log("====>"); - - Success = MonitorGetPath(&GUID_XENCONS_DEVICE, &Path); - - if (!Success) - goto fail1; - - Context->Device = CreateFile(Path, - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (Context->Device == INVALID_HANDLE_VALUE) - goto fail2; - - ECHO(Context->Device, "\r\n[ATTACHED]\r\n"); - - ZeroMemory(&Handle, sizeof (Handle)); - Handle.dbch_size = sizeof (Handle); - Handle.dbch_devicetype = DBT_DEVTYP_HANDLE; - Handle.dbch_handle = Context->Device; - - Context->DeviceNotification = - RegisterDeviceNotification(Context->Service, - &Handle, - DEVICE_NOTIFY_SERVICE_HANDLE); - if (Context->DeviceNotification == NULL) - goto fail3; - - Context->DevicePath = Path; - __InitializeListHead(&Context->ListHead); - InitializeCriticalSection(&Context->CriticalSection); - - Context->MonitorEvent = CreateEvent(NULL, - TRUE, - FALSE, - NULL); - - if (Context->MonitorEvent == NULL) - goto fail4; - - Context->MonitorThread = CreateThread(NULL, - 0, - MonitorThread, - NULL, - 0, - NULL); - - if (Context->MonitorThread == INVALID_HANDLE_VALUE) - goto fail5; - - Context->DeviceEvent = CreateEvent(NULL, - TRUE, - FALSE, - NULL); - - if (Context->DeviceEvent == NULL) - goto fail6; - - Context->DeviceThread = CreateThread(NULL, - 0, - DeviceThread, - NULL, - 0, - NULL); - - 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"); - - CloseHandle(Context->DeviceEvent); - Context->DeviceEvent = NULL; - -fail6: - Log("fail6\n"); - - SetEvent(Context->MonitorThread); - WaitForSingleObject(Context->MonitorThread, INFINITE); - -fail5: - Log("fail5"); - - CloseHandle(Context->MonitorEvent); - Context->MonitorEvent = NULL; - -fail4: - Log("fail4"); - - DeleteCriticalSection(&Context->CriticalSection); - ZeroMemory(&Context->ListHead, sizeof(LIST_ENTRY)); - - free(Context->DevicePath); - Context->DevicePath = NULL; - - UnregisterDeviceNotification(Context->DeviceNotification); - Context->DeviceNotification = NULL; - -fail3: - Log("fail3"); - - CloseHandle(Context->Device); - Context->Device = INVALID_HANDLE_VALUE; - -fail2: - Log("fail2"); - - free(Path); - -fail1: - Error = GetLastError(); - - { - PTCHAR Message; - Message = GetErrorMessage(Error); - Log("fail1 (%s)", Message); - LocalFree(Message); - } -} - -static VOID MonitorWaitForPipeThreads( - VOID + IN PMONITOR_HANDLE Handle ) { - PMONITOR_CONTEXT Context = &MonitorContext; HANDLE *Handles; DWORD Index; PLIST_ENTRY ListEntry; - EnterCriticalSection(&Context->CriticalSection); + EnterCriticalSection(&Handle->CriticalSection); - if (Context->ListCount == 0) + if (Handle->ListCount == 0) goto fail1; - Handles = (HANDLE*)malloc(sizeof(HANDLE) * Context->ListCount); + Handles = (HANDLE*)malloc(sizeof(HANDLE) * Handle->ListCount); if (Handles == NULL) goto fail2; Index = 0; - for (ListEntry = Context->ListHead.Flink; - ListEntry != &Context->ListHead && Index < Context->ListCount; + for (ListEntry = Handle->ListHead.Flink; + ListEntry != &Handle->ListHead && Index < Handle->ListCount; ListEntry = ListEntry->Flink) { PMONITOR_PIPE Pipe = CONTAINING_RECORD(ListEntry, MONITOR_PIPE, ListEntry); Handles[Index++] = Pipe->Thread; } - Context->ListCount = 0; + Handle->ListCount = 0; - LeaveCriticalSection(&Context->CriticalSection); + LeaveCriticalSection(&Handle->CriticalSection); #pragma warning(suppress:6385) // Reading invalid data from 'Handles'... WaitForMultipleObjects(Index, @@ -1031,55 +776,567 @@ fail2: fail1: Log("fail1"); - LeaveCriticalSection(&Context->CriticalSection); + LeaveCriticalSection(&Handle->CriticalSection); return; } -static VOID -MonitorRemove( - VOID - ) +static BOOL +GetExecutable( + IN PCHAR Name, + OUT PTCHAR *Executable + ) { PMONITOR_CONTEXT Context = &MonitorContext; + DWORD MaxValueLength; + DWORD ExecutableLength; + HKEY Key; + DWORD Type; + HRESULT Error; + + + Error = RegOpenKeyExA(Context->ParametersKey, + Name, + 0, + KEY_READ, + &Key); + if (Error != ERROR_SUCCESS) { + SetLastError(Error); + goto fail1; + } + + Error = RegQueryInfoKey(Key, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &MaxValueLength, + NULL, + NULL); + if (Error != ERROR_SUCCESS) { + SetLastError(Error); + goto fail2; + } + + ExecutableLength = MaxValueLength + sizeof (TCHAR); + + *Executable = calloc(1, ExecutableLength); + if (Executable == NULL) + goto fail3; + + Error = RegQueryValueEx(Key, + TEXT("Executable"), + NULL, + &Type, + (LPBYTE)(*Executable), + &ExecutableLength); + if (Error != ERROR_SUCCESS) { + SetLastError(Error); + goto fail4; + } + + if (Type != REG_SZ) { + SetLastError(ERROR_BAD_FORMAT); + goto fail5; + } + + RegCloseKey(Key); + + return TRUE; + +fail5: + Log("fail5"); - if (Context->Device == INVALID_HANDLE_VALUE) +fail4: + Log("fail4"); + + free(*Executable); + +fail3: + Log("fail3"); + +fail2: + Log("fail2"); + + RegCloseKey(Key); + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return FALSE; +} + +static BOOL +MonitorCreateHandle( + IN PTCHAR DevicePath, + OUT PMONITOR_HANDLE *Handle + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + DEV_BROADCAST_HANDLE Notification; + CHAR Name[MAX_PATH]; + DWORD Bytes; + HRESULT Error; + BOOL Success; + + Log("====> %s", DevicePath); + + *Handle = malloc(sizeof(MONITOR_HANDLE)); + if (*Handle == NULL) + goto fail1; + + (*Handle)->DevicePath = _wcsdup(DevicePath); + if ((*Handle)->DevicePath == NULL) + goto fail2; + + (*Handle)->Device = CreateFile(DevicePath, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if ((*Handle)->Device == INVALID_HANDLE_VALUE) + goto fail3; + + ECHO((*Handle)->Device, "\r\n[ATTACHED]\r\n"); + + ZeroMemory(&Notification, sizeof(Notification)); + Notification.dbch_size = sizeof(Notification); + Notification.dbch_devicetype = DBT_DEVTYP_HANDLE; + Notification.dbch_handle = (*Handle)->Device; + + (*Handle)->DeviceNotification = + RegisterDeviceNotification(Context->Service, + &Notification, + DEVICE_NOTIFY_SERVICE_HANDLE); + if ((*Handle)->DeviceNotification == NULL) + goto fail4; + + memset(Name, 0, sizeof(Name)); + Success = DeviceIoControl((*Handle)->Device, + IOCTL_XENCONS_GET_NAME, + NULL, + 0, + Name, + sizeof(Name), + &Bytes, + NULL); + if (!Success) + goto fail5; + + Log("Name = %hs", Name); + + (*Handle)->Name = _strdup(Name); + if ((*Handle)->Name == NULL) + goto fail6; + + Success = GetExecutable((*Handle)->Name, &(*Handle)->Executable); + if (!Success) + (*Handle)->Executable = NULL; + + Log("Executable = %s", (*Handle)->Executable); + + __InitializeListHead(&(*Handle)->ListHead); + InitializeCriticalSection(&(*Handle)->CriticalSection); + + (*Handle)->DeviceEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + + if ((*Handle)->DeviceEvent == NULL) + goto fail7; + + (*Handle)->DeviceThread = CreateThread(NULL, + 0, + DeviceThread, + *Handle, + 0, + NULL); + + if ((*Handle)->DeviceThread == NULL) + goto fail8; + + (*Handle)->ServerEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + if ((*Handle)->ServerEvent == NULL) + goto fail9; + + (*Handle)->ServerThread = CreateThread(NULL, + 0, + ServerThread, + *Handle, + 0, + NULL); + if ((*Handle)->ServerThread == NULL) + goto fail10; + + (*Handle)->MonitorEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + + if ((*Handle)->MonitorEvent == NULL) + goto fail11; + + (*Handle)->MonitorThread = CreateThread(NULL, + 0, + MonitorThread, + *Handle, + 0, + NULL); + + if ((*Handle)->MonitorThread == NULL) + goto fail12; + + Log("<==== 0x%p", (PVOID)(*Handle)->Device); + + return TRUE; + +fail12: + Log("fail12"); + + CloseHandle((*Handle)->MonitorEvent); + (*Handle)->MonitorEvent = NULL; + +fail11: + Log("fail11"); + + SetEvent((*Handle)->ServerEvent); + WaitForSingleObject((*Handle)->ServerThread, INFINITE); + +fail10: + Log("fail10"); + + CloseHandle((*Handle)->ServerEvent); + (*Handle)->ServerEvent = NULL; + +fail9: + Log("fail9"); + + SetEvent((*Handle)->DeviceEvent); + WaitForSingleObject((*Handle)->DeviceThread, INFINITE); + +fail8: + Log("fail8\n"); + + CloseHandle((*Handle)->DeviceEvent); + (*Handle)->DeviceEvent = NULL; + +fail7: + Log("fail7"); + + DeleteCriticalSection(&(*Handle)->CriticalSection); + ZeroMemory(&(*Handle)->ListHead, sizeof(LIST_ENTRY)); + + free((*Handle)->Executable); + (*Handle)->Executable = NULL; + + free((*Handle)->Name); + (*Handle)->Name = NULL; + +fail6: + Log("fail6"); + +fail5: + Log("fail5"); + + UnregisterDeviceNotification((*Handle)->DeviceNotification); + (*Handle)->DeviceNotification = NULL; + + ECHO((*Handle)->Device, "\r\n[DETACHED]\r\n"); + +fail4: + Log("fail4"); + + CloseHandle((*Handle)->Device); + (*Handle)->Device = INVALID_HANDLE_VALUE; + +fail3: + Log("fail3"); + + free((*Handle)->DevicePath); + (*Handle)->DevicePath = NULL; + +fail2: + Log("fail2"); + + free(*Handle); + *Handle = NULL; + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return FALSE; +} + +static VOID +MonitorDeleteHandle( + IN PMONITOR_HANDLE Handle + ) +{ + Log("====> %s", Handle->DevicePath); + + SetEvent(Handle->MonitorEvent); + WaitForSingleObject(Handle->MonitorThread, INFINITE); + + CloseHandle(Handle->MonitorEvent); + Handle->MonitorEvent = NULL; + + SetEvent(Handle->ServerEvent); + MonitorWaitForPipeThreads(Handle); + WaitForSingleObject(Handle->ServerThread, INFINITE); + + CloseHandle(Handle->ServerEvent); + Handle->ServerEvent = NULL; + + SetEvent(Handle->DeviceEvent); + WaitForSingleObject(Handle->DeviceThread, INFINITE); + + CloseHandle(Handle->DeviceEvent); + Handle->DeviceEvent = NULL; + + DeleteCriticalSection(&Handle->CriticalSection); + ZeroMemory(&Handle->ListHead, sizeof(LIST_ENTRY)); + + free(Handle->Executable); + Handle->Executable = NULL; + + free(Handle->Name); + Handle->Name = NULL; + + free(Handle->DevicePath); + Handle->DevicePath = NULL; + + UnregisterDeviceNotification(Handle->DeviceNotification); + Handle->DeviceNotification = NULL; + + ECHO(Handle->Device, "\r\n[DETACHED]\r\n"); + + CloseHandle(Handle->Device); + Handle->Device = INVALID_HANDLE_VALUE; + + free(Handle); + + Log("<===="); +} + +static VOID +MonitorAdd( + IN PTCHAR DevicePath + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + PMONITOR_HANDLE Handle; + BOOL Success; + + Log("====> %s", DevicePath); + + Success = MonitorCreateHandle(DevicePath, &Handle); + if (!Success) + goto fail1; + + EnterCriticalSection(&Context->CriticalSection); + __InsertTailList(&Context->ListHead, &Handle->ListEntry); + ++Context->ListCount; + LeaveCriticalSection(&Context->CriticalSection); + + Log("<===="); + + return; + +fail1: + Log("fail1"); + + return; +} + +static VOID +MonitorRemove( + IN HANDLE Device + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + PMONITOR_HANDLE Handle; + PLIST_ENTRY ListEntry; + + Log("====> 0x%p", (PVOID)Device); + + EnterCriticalSection(&Context->CriticalSection); + for (ListEntry = Context->ListHead.Flink; + ListEntry != &Context->ListHead; + ListEntry = ListEntry->Flink) { + Handle = CONTAINING_RECORD(ListEntry, + MONITOR_HANDLE, + ListEntry); + + if (Handle->Device != Device) + continue; + + LeaveCriticalSection(&Context->CriticalSection); + + MonitorDeleteHandle(Handle); + + Log("<===="); return; + } + LeaveCriticalSection(&Context->CriticalSection); + + Log("<===="); +} + +static BOOL +MonitorEnumerate( + VOID + ) +{ + HDEVINFO DeviceInfoSet; + SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetail; + DWORD Size; + DWORD Index; + HRESULT Error; + BOOL Success; Log("====>"); - SetEvent(Context->ServerEvent); - MonitorWaitForPipeThreads(); - WaitForSingleObject(Context->ServerThread, INFINITE); + DeviceInfoSet = SetupDiGetClassDevs(&GUID_XENCONS_DEVICE, + NULL, + NULL, + DIGCF_PRESENT | + DIGCF_DEVICEINTERFACE); + if (DeviceInfoSet == INVALID_HANDLE_VALUE) + goto fail1; - CloseHandle(Context->ServerEvent); - Context->ServerEvent = NULL; + for (Index = 0; TRUE; ++Index) { + DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - SetEvent(Context->DeviceEvent); - WaitForSingleObject(Context->DeviceThread, INFINITE); + Success = SetupDiEnumDeviceInterfaces(DeviceInfoSet, + NULL, + &GUID_XENCONS_DEVICE, + Index, + &DeviceInterfaceData); + if (!Success) + break; - CloseHandle(Context->DeviceEvent); - Context->DeviceEvent = NULL; + Success = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, + &DeviceInterfaceData, + NULL, + 0, + &Size, + NULL); + if (!Success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + goto fail2; - SetEvent(Context->MonitorEvent); - WaitForSingleObject(Context->MonitorThread, INFINITE); + DeviceInterfaceDetail = calloc(1, Size); + if (DeviceInterfaceDetail == NULL) + goto fail3; - CloseHandle(Context->MonitorEvent); - Context->MonitorEvent = NULL; + DeviceInterfaceDetail->cbSize = + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); - DeleteCriticalSection(&Context->CriticalSection); - ZeroMemory(&Context->ListHead, sizeof(LIST_ENTRY)); + Success = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, + &DeviceInterfaceData, + DeviceInterfaceDetail, + Size, + NULL, + NULL); + if (!Success) + goto fail4; - free(Context->DevicePath); - Context->DevicePath = NULL; + MonitorAdd(DeviceInterfaceDetail->DevicePath); - UnregisterDeviceNotification(Context->DeviceNotification); - Context->DeviceNotification = NULL; + free(DeviceInterfaceDetail); + continue; - ECHO(Context->Device, "\r\n[DETACHED]\r\n"); +fail4: + Log("fail4"); - CloseHandle(Context->Device); - Context->Device = INVALID_HANDLE_VALUE; + free(DeviceInterfaceDetail); + +fail3: + Log("fail3"); + +fail2: + Log("fail2"); + + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + + goto fail1; + } + + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + + Log("<===="); + + return TRUE; + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return FALSE; +} + +static VOID +MonitorRemoveAll( + VOID + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + PMONITOR_HANDLE Handle; + PLIST_ENTRY ListEntry; + + Log("====>"); + + EnterCriticalSection(&Context->CriticalSection); + for (;;) { + ListEntry = Context->ListHead.Flink; + if (ListEntry == &Context->ListHead) + break; + + __RemoveEntryList(ListEntry); + + LeaveCriticalSection(&Context->CriticalSection); + + Handle = CONTAINING_RECORD(ListEntry, + MONITOR_HANDLE, + ListEntry); + + + MonitorDeleteHandle(Handle); + + EnterCriticalSection(&Context->CriticalSection); + } + LeaveCriticalSection(&Context->CriticalSection); Log("<===="); } @@ -1116,8 +1373,8 @@ MonitorCtrlHandlerEx( PDEV_BROADCAST_DEVICEINTERFACE Interface = EventData; if (IsEqualGUID(&Interface->dbcc_classguid, - &GUID_XENCONS_DEVICE)) - SetEvent(Context->AddEvent); + &GUID_XENCONS_DEVICE)) + MonitorAdd(Interface->dbcc_name); } break; @@ -1127,8 +1384,7 @@ MonitorCtrlHandlerEx( if (Header->dbch_devicetype == DBT_DEVTYP_HANDLE) { PDEV_BROADCAST_HANDLE Device = EventData; - if (Device->dbch_handle == Context->Device) - SetEvent(Context->RemoveEvent); + MonitorRemove(Device->dbch_handle); } break; } @@ -1143,84 +1399,6 @@ MonitorCtrlHandlerEx( return ERROR_CALL_NOT_IMPLEMENTED; } -static BOOL -GetExecutable( - OUT PTCHAR *Executable - ) -{ - PMONITOR_CONTEXT Context = &MonitorContext; - DWORD MaxValueLength; - DWORD ExecutableLength; - DWORD Type; - HRESULT Error; - - Error = RegQueryInfoKey(Context->ParametersKey, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - &MaxValueLength, - NULL, - NULL); - if (Error != ERROR_SUCCESS) { - SetLastError(Error); - goto fail1; - } - - ExecutableLength = MaxValueLength + sizeof (TCHAR); - - *Executable = calloc(1, ExecutableLength); - if (Executable == NULL) - goto fail2; - - Error = RegQueryValueEx(Context->ParametersKey, - "Executable", - NULL, - &Type, - (LPBYTE)(*Executable), - &ExecutableLength); - if (Error != ERROR_SUCCESS) { - SetLastError(Error); - goto fail3; - } - - if (Type != REG_SZ) { - SetLastError(ERROR_BAD_FORMAT); - goto fail4; - } - - Log("%s", *Executable); - - return TRUE; - -fail4: - Log("fail4"); - -fail3: - Log("fail3"); - - free(*Executable); - -fail2: - Log("fail2"); - -fail1: - Error = GetLastError(); - - { - PTCHAR Message; - Message = GetErrorMessage(Error); - Log("fail1 (%s)", Message); - LocalFree(Message); - } - - return FALSE; -} - VOID WINAPI MonitorMain( _In_ DWORD argc, @@ -1230,29 +1408,31 @@ MonitorMain( PMONITOR_CONTEXT Context = &MonitorContext; DEV_BROADCAST_DEVICEINTERFACE Interface; HRESULT Error; - BOOL Success; UNREFERENCED_PARAMETER(argc); UNREFERENCED_PARAMETER(argv); Log("====>"); + __InitializeListHead(&Context->ListHead); + InitializeCriticalSection(&Context->CriticalSection); + Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - PARAMETERS_KEY(__MODULE__), + TEXT(PARAMETERS_KEY(__MODULE__)), 0, KEY_READ, &Context->ParametersKey); if (Error != ERROR_SUCCESS) goto fail1; - Context->Service = RegisterServiceCtrlHandlerEx(MONITOR_NAME, + Context->Service = RegisterServiceCtrlHandlerEx(TEXT(MONITOR_NAME), MonitorCtrlHandlerEx, NULL); if (Context->Service == NULL) goto fail2; Context->EventLog = RegisterEventSource(NULL, - MONITOR_NAME); + TEXT(MONITOR_NAME)); if (Context->EventLog == NULL) goto fail3; @@ -1269,28 +1449,6 @@ MonitorMain( if (Context->StopEvent == NULL) goto fail4; - Context->AddEvent = CreateEvent(NULL, - TRUE, - FALSE, - NULL); - - if (Context->AddEvent == NULL) - goto fail5; - - Context->RemoveEvent = CreateEvent(NULL, - TRUE, - FALSE, - NULL); - - if (Context->RemoveEvent == NULL) - goto fail6; - - Success = GetExecutable(&Context->Executable); - if (!Success) - Context->Executable = NULL; - - Context->Device = INVALID_HANDLE_VALUE; - ZeroMemory(&Interface, sizeof (Interface)); Interface.dbcc_size = sizeof (Interface); Interface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; @@ -1301,64 +1459,21 @@ MonitorMain( &Interface, DEVICE_NOTIFY_SERVICE_HANDLE); if (Context->InterfaceNotification == NULL) - goto fail7; + goto fail5; // The device may already by present - SetEvent(Context->AddEvent); + MonitorEnumerate(); ReportStatus(SERVICE_RUNNING, NO_ERROR, 0); - for (;;) { - HANDLE Events[3]; - DWORD Object; - - Events[0] = Context->StopEvent; - Events[1] = Context->AddEvent; - Events[2] = Context->RemoveEvent; + // wait until service is shut down + WaitForSingleObject(Context->StopEvent, + INFINITE); - Log("waiting (%u)...", ARRAYSIZE(Events)); - Object = WaitForMultipleObjects(ARRAYSIZE(Events), - Events, - FALSE, - INFINITE); - Log("awake"); - -#define WAIT_OBJECT_1 (WAIT_OBJECT_0 + 1) -#define WAIT_OBJECT_2 (WAIT_OBJECT_0 + 2) - - switch (Object) { - case WAIT_OBJECT_0: - ResetEvent(Context->StopEvent); - goto done; - - case WAIT_OBJECT_1: - ResetEvent(Context->AddEvent); - MonitorAdd(); - break; - - case WAIT_OBJECT_2: - ResetEvent(Context->RemoveEvent); - MonitorRemove(); - - default: - break; - } - -#undef WAIT_OBJECT_1 -#undef WAIT_OBJECT_2 - } - -done: - MonitorRemove(); + MonitorRemoveAll(); UnregisterDeviceNotification(Context->InterfaceNotification); - free(Context->Executable); - - CloseHandle(Context->RemoveEvent); - - CloseHandle(Context->AddEvent); - CloseHandle(Context->StopEvent); ReportStatus(SERVICE_STOPPED, NO_ERROR, 0); @@ -1367,20 +1482,13 @@ done: CloseHandle(Context->ParametersKey); + DeleteCriticalSection(&Context->CriticalSection); + ZeroMemory(&Context->ListHead, sizeof(LIST_ENTRY)); + Log("<===="); return; -fail7: - Log("fail7"); - - CloseHandle(Context->RemoveEvent); - -fail6: - Log("fail6"); - - CloseHandle(Context->AddEvent); - fail5: Log("fail5"); @@ -1404,6 +1512,9 @@ fail2: fail1: Error = GetLastError(); + DeleteCriticalSection(&Context->CriticalSection); + ZeroMemory(&Context->ListHead, sizeof(LIST_ENTRY)); + { PTCHAR Message; Message = GetErrorMessage(Error); @@ -1435,8 +1546,8 @@ MonitorCreate( goto fail2; Service = CreateService(SCManager, - MONITOR_NAME, - MONITOR_DISPLAYNAME, + TEXT(MONITOR_NAME), + TEXT(MONITOR_DISPLAYNAME), SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, @@ -1500,7 +1611,7 @@ MonitorDelete( goto fail1; Service = OpenService(SCManager, - MONITOR_NAME, + TEXT(MONITOR_NAME), SERVICE_ALL_ACCESS); if (Service == NULL) @@ -1557,21 +1668,21 @@ MonitorEntry( ) { SERVICE_TABLE_ENTRY Table[] = { - { MONITOR_NAME, MonitorMain }, + { TEXT(MONITOR_NAME), MonitorMain }, { NULL, NULL } }; HRESULT Error; Log("%s (%s) ====>", - MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR, - DAY_STR "/" MONTH_STR "/" YEAR_STR); + TEXT(MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR), + TEXT(DAY_STR "/" MONTH_STR "/" YEAR_STR)); if (!StartServiceCtrlDispatcher(Table)) goto fail1; Log("%s (%s) <====", - MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR, - DAY_STR "/" MONTH_STR "/" YEAR_STR); + TEXT(MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR), + TEXT(DAY_STR "/" MONTH_STR "/" YEAR_STR)); return TRUE; @@ -1603,9 +1714,9 @@ _tWinMain( UNREFERENCED_PARAMETER(CmdShow); if (_tcslen(CmdLine) != 0) { - if (_tcsicmp(CmdLine, TEXT("create")) == 0) + if (_stricmp(CmdLine, "create") == 0) Success = MonitorCreate(); - else if (_tcsicmp(CmdLine, TEXT("delete")) == 0) + else if (_stricmp(CmdLine, "delete") == 0) Success = MonitorDelete(); else Success = FALSE; diff --git a/src/tty/tty.c b/src/tty/tty.c index 94d4f65..0ed599e 100644 --- a/src/tty/tty.c +++ b/src/tty/tty.c @@ -39,7 +39,7 @@ typedef struct _TTY_STREAM { HANDLE Write; } TTY_STREAM, *PTTY_STREAM; -#define PIPE_NAME TEXT("\\\\.\\pipe\\xencons") +#define PIPE_NAME TEXT("\\\\.\\pipe\\xencons\\default") #define MAXIMUM_BUFFER_SIZE 1024 typedef struct _TTY_CONTEXT { diff --git a/src/xencons.inf b/src/xencons.inf index 3cbdd96..37bc628 100644 --- a/src/xencons.inf +++ b/src/xencons.inf @@ -113,7 +113,7 @@ AddReg = Monitor_Parameters [Monitor_Parameters] HKR,"Parameters",,0x00000010 -HKR,"Parameters","Executable",0x00000000,"xencons_tty_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.exe" +HKR,"Parameters\default","Executable",0x00000000,"xencons_tty_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.exe" [Monitor_EventLog] AddReg=Monitor_EventLog_AddReg -- 2.8.3 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |