[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [win-pv-devel] [PATCH 06/14 v2] Make monitor service multi-console aware



> -----Original Message-----
> From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On
> Behalf Of owen.smith@xxxxxxxxxx
> Sent: 23 February 2018 14:22
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Owen Smith <owen.smith@xxxxxxxxxx>
> Subject: [win-pv-devel] [PATCH 06/14 v2] Make monitor service multi-
> console aware
> 
> From: Owen Smith <owen.smith@xxxxxxxxxx>
> 
> * Move console specific data to a seperate structure
> * Make all threads' use the console data
> * Removes the Add and Remove event in favor of inline add/remove
> * Convert Win32 calls to explicit narrow/wide character set as appropriate
> * Removes tchar.h include to force narrow/wide character usage
> * Renames structures and thread functions
> * Pipe names are based on console name
> * INF file stores "Executable" under console's name subkey
> * Change pipe name tty.exe uses
> * Add WaitNamedPipe() before connecting to pipes in tty.exe
> 
> Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>

Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx>

> ---
>  src/monitor/monitor.c | 1445 ++++++++++++++++++++++++++---------------
> --------
>  src/tty/tty.c         |   20 +-
>  src/xencons.inf       |    2 +-
>  3 files changed, 792 insertions(+), 675 deletions(-)
> 
> diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
> index 08ae0f2..510ba6f 100644
> --- a/src/monitor/monitor.c
> +++ b/src/monitor/monitor.c
> @@ -32,7 +32,7 @@
>  #define INITGUID 1
> 
>  #include <windows.h>
> -#include <tchar.h>
> +#include <winioctl.h>
>  #include <stdlib.h>
>  #include <strsafe.h>
>  #include <wtsapi32.h>
> @@ -50,40 +50,45 @@
>  #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;
> -    HKEY                    ParametersKey;
>      HANDLE                  EventLog;
>      HANDLE                  StopEvent;
> -    HANDLE                  AddEvent;
> -    HANDLE                  RemoveEvent;
> -    PTCHAR                  Executable;
> +    HKEY                    ParametersKey;
>      HDEVNOTIFY              InterfaceNotification;
> -    PTCHAR                  DevicePath;
> +    CRITICAL_SECTION        CriticalSection;
> +    LIST_ENTRY              ListHead;
> +    DWORD                   ListCount;
> +} MONITOR_CONTEXT, *PMONITOR_CONTEXT;
> +
> +typedef struct _MONITOR_CONSOLE {
> +    LIST_ENTRY              ListEntry;
> +    PWCHAR                  DevicePath;
> +    HANDLE                  DeviceHandle;
>      HDEVNOTIFY              DeviceNotification;
> -    HANDLE                  Device;
> -    HANDLE                  MonitorEvent;
> -    HANDLE                  MonitorThread;
> -    HANDLE                  DeviceEvent;
> +    PCHAR                   DeviceName; // protocol and instance?
> +    HANDLE                  ExecutableThread;
> +    HANDLE                  ExecutableEvent;
>      HANDLE                  DeviceThread;
> -    HANDLE                  ServerEvent;
> +    HANDLE                  DeviceEvent;
>      HANDLE                  ServerThread;
> +    HANDLE                  ServerEvent;
>      CRITICAL_SECTION        CriticalSection;
>      LIST_ENTRY              ListHead;
>      DWORD                   ListCount;
> -} MONITOR_CONTEXT, *PMONITOR_CONTEXT;
> +} MONITOR_CONSOLE, *PMONITOR_CONSOLE;
> +
> +typedef struct _MONITOR_CONNECTION {
> +    PMONITOR_CONSOLE        Console;
> +    LIST_ENTRY              ListEntry;
> +    HANDLE                  Pipe;
> +    HANDLE                  Thread;
> +} MONITOR_CONNECTION, *PMONITOR_CONNECTION;
> 
> -MONITOR_CONTEXT MonitorContext;
> +static MONITOR_CONTEXT MonitorContext;
> 
> -#define PIPE_NAME TEXT("\\\\.\\pipe\\xencons")
> +#define PIPE_BASE_NAME "\\\\.\\pipe\\xencons\\"
> 
>  #define MAXIMUM_BUFFER_SIZE 1024
> 
> @@ -104,15 +109,15 @@ __Log(
>  {
>  #if DBG
>      PMONITOR_CONTEXT    Context = &MonitorContext;
> -    const TCHAR         *Strings[1];
> +    const CHAR          *Strings[1];
>  #endif
> -    TCHAR               Buffer[MAXIMUM_BUFFER_SIZE];
> +    CHAR                Buffer[MAXIMUM_BUFFER_SIZE];
>      va_list             Arguments;
>      size_t              Length;
>      HRESULT             Result;
> 
>      va_start(Arguments, Format);
> -    Result = StringCchVPrintf(Buffer,
> +    Result = StringCchVPrintfA(Buffer,
>                                MAXIMUM_BUFFER_SIZE,
>                                Format,
>                                Arguments);
> @@ -121,7 +126,7 @@ __Log(
>      if (Result != S_OK && Result != STRSAFE_E_INSUFFICIENT_BUFFER)
>          return;
> 
> -    Result = StringCchLength(Buffer, MAXIMUM_BUFFER_SIZE, &Length);
> +    Result = StringCchLengthA(Buffer, MAXIMUM_BUFFER_SIZE, &Length);
>      if (Result != S_OK)
>          return;
> 
> @@ -139,7 +144,7 @@ __Log(
>      Strings[0] = Buffer;
> 
>      if (Context->EventLog != NULL)
> -        ReportEvent(Context->EventLog,
> +        ReportEventA(Context->EventLog,
>                      EVENTLOG_INFORMATION_TYPE,
>                      0,
>                      MONITOR_LOG,
> @@ -152,23 +157,23 @@ __Log(
>  }
> 
>  #define Log(_Format, ...) \
> -    __Log(TEXT(__MODULE__ "|" __FUNCTION__ ": " _Format),
> __VA_ARGS__)
> +    __Log(__MODULE__ "|" __FUNCTION__ ": " _Format, __VA_ARGS__)
> 
> -static PTCHAR
> +static PCHAR
>  GetErrorMessage(
>      IN  HRESULT Error
>      )
>  {
> -    PTCHAR      Message;
> +    PCHAR       Message;
>      ULONG       Index;
> 
> -    if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
> +    if (!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
>                         FORMAT_MESSAGE_FROM_SYSTEM |
>                         FORMAT_MESSAGE_IGNORE_INSERTS,
>                         NULL,
>                         Error,
>                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
> -                       (LPTSTR)&Message,
> +                       (LPSTR)&Message,
>                         0,
>                         NULL))
>          return NULL;
> @@ -210,7 +215,8 @@ static VOID
>  ReportStatus(
>      IN  DWORD           CurrentState,
>      IN  DWORD           Win32ExitCode,
> -    IN  DWORD           WaitHint)
> +    IN  DWORD           WaitHint
> +    )
>  {
>      PMONITOR_CONTEXT    Context = &MonitorContext;
>      static DWORD        CheckPoint = 1;
> @@ -249,116 +255,11 @@ fail1:
>      Error = GetLastError();
> 
>      {
> -        PTCHAR  Message;
> -        Message = GetErrorMessage(Error);
> -        Log("fail1 (%s)", Message);
> -        LocalFree(Message);
> -    }
> -}
> -
> -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;
> +        PCHAR  Message;
>          Message = GetErrorMessage(Error);
>          Log("fail1 (%s)", Message);
>          LocalFree(Message);
>      }
> -
> -    return FALSE;
>  }
> 
>  static FORCEINLINE VOID
> @@ -425,22 +326,25 @@ PutString(
>      }
>  }
> 
> +#define ECHO(_Handle, _Buffer) \
> +    PutString((_Handle), (PUCHAR)_Buffer, (DWORD)strlen((_Buffer)) *
> sizeof(CHAR))
> +
>  DWORD WINAPI
> -PipeThread(
> +ConnectionThread(
>      IN  LPVOID          Argument
>      )
>  {
> -    PMONITOR_CONTEXT    Context = &MonitorContext;
> -    PMONITOR_PIPE       Pipe = (PMONITOR_PIPE)Argument;
> +    PMONITOR_CONNECTION Connection =
> (PMONITOR_CONNECTION)Argument;
> +    PMONITOR_CONSOLE    Console = Connection->Console;
>      UCHAR               Buffer[MAXIMUM_BUFFER_SIZE];
>      OVERLAPPED          Overlapped;
>      HANDLE              Handle[2];
>      DWORD               Length;
>      DWORD               Object;
>      HRESULT             Error;
> -
> -    Log("====>");
> -
> +
> +    Log("====> %s", Console->DeviceName);
> +
>      ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
>      Overlapped.hEvent = CreateEvent(NULL,
>                                      TRUE,
> @@ -448,69 +352,69 @@ PipeThread(
>                                      NULL);
>      if (Overlapped.hEvent == NULL)
>          goto fail1;
> -
> -    Handle[0] = Pipe->Event;
> +
> +    Handle[0] = Console->ServerEvent;
>      Handle[1] = Overlapped.hEvent;
> -
> -    EnterCriticalSection(&Context->CriticalSection);
> -    __InsertTailList(&Context->ListHead, &Pipe->ListEntry);
> -    ++Context->ListCount;
> -    LeaveCriticalSection(&Context->CriticalSection);
> -
> +
> +    EnterCriticalSection(&Console->CriticalSection);
> +    __InsertTailList(&Console->ListHead, &Connection->ListEntry);
> +    ++Console->ListCount;
> +    LeaveCriticalSection(&Console->CriticalSection);
> +
>      for (;;) {
> -        (VOID) ReadFile(Pipe->Pipe,
> +        (VOID) ReadFile(Connection->Pipe,
>                          Buffer,
>                          sizeof(Buffer),
>                          NULL,
>                          &Overlapped);
> -
> +
>          Object = WaitForMultipleObjects(ARRAYSIZE(Handle),
>                                          Handle,
>                                          FALSE,
>                                          INFINITE);
>          if (Object == WAIT_OBJECT_0)
>              break;
> -
> -        if (!GetOverlappedResult(Pipe->Pipe,
> +
> +        if (!GetOverlappedResult(Connection->Pipe,
>                                   &Overlapped,
>                                   &Length,
>                                   FALSE))
>              break;
> -
> +
>          ResetEvent(Overlapped.hEvent);
> -
> -        PutString(Context->Device,
> +
> +        PutString(Console->DeviceHandle,
>                    Buffer,
>                    Length);
>      }
> -
> -    EnterCriticalSection(&Context->CriticalSection);
> -    __RemoveEntryList(&Pipe->ListEntry);
> -    --Context->ListCount;
> -    LeaveCriticalSection(&Context->CriticalSection);
> -
> +
> +    EnterCriticalSection(&Console->CriticalSection);
> +    __RemoveEntryList(&Connection->ListEntry);
> +    --Console->ListCount;
> +    LeaveCriticalSection(&Console->CriticalSection);
> +
>      CloseHandle(Overlapped.hEvent);
> -
> -    FlushFileBuffers(Pipe->Pipe);
> -    DisconnectNamedPipe(Pipe->Pipe);
> -    CloseHandle(Pipe->Pipe);
> -    CloseHandle(Pipe->Thread);
> -    free(Pipe);
> -
> -    Log("<====");
> -
> +
> +    FlushFileBuffers(Connection->Pipe);
> +    DisconnectNamedPipe(Connection->Pipe);
> +    CloseHandle(Connection->Pipe);
> +    CloseHandle(Connection->Thread);
> +    free(Connection);
> +
> +    Log("<==== %s", Console->DeviceName);
> +
>      return 0;
> -
> +
>  fail1:
>      Error = GetLastError();
> -
> +
>      {
>          PTCHAR  Message;
>          Message = GetErrorMessage(Error);
>          Log("fail1 (%s)", Message);
>          LocalFree(Message);
>      }
> -
> +
>      return 1;
>  }
> 
> @@ -519,18 +423,17 @@ ServerThread(
>      IN  LPVOID          Argument
>      )
>  {
> -    PMONITOR_CONTEXT    Context = &MonitorContext;
> +    PMONITOR_CONSOLE    Console = (PMONITOR_CONSOLE)Argument;
> +    CHAR                PipeName[MAXIMUM_BUFFER_SIZE];
>      OVERLAPPED          Overlapped;
>      HANDLE              Handle[2];
>      HANDLE              Pipe;
>      DWORD               Object;
> -    PMONITOR_PIPE       Instance;
> +    PMONITOR_CONNECTION Connection;
>      HRESULT             Error;
> -
> -    UNREFERENCED_PARAMETER(Argument);
> -
> -    Log("====>");
> -
> +
> +    Log("====> %s", Console->DeviceName);
> +
>      ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
>      Overlapped.hEvent = CreateEvent(NULL,
>                                      TRUE,
> @@ -538,12 +441,22 @@ ServerThread(
>                                      NULL);
>      if (Overlapped.hEvent == NULL)
>          goto fail1;
> -
> -    Handle[0] = Context->ServerEvent;
> +
> +    Handle[0] = Console->ServerEvent;
>      Handle[1] = Overlapped.hEvent;
> +
> +    Error = StringCchPrintfA(PipeName,
> +                             MAXIMUM_BUFFER_SIZE,
> +                             "%s%s",
> +                             PIPE_BASE_NAME,
> +                             Console->DeviceName);
> +    if (Error != S_OK && Error != STRSAFE_E_INSUFFICIENT_BUFFER)
> +        goto fail2;
> +
> +    Log("%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,11 +465,11 @@ ServerThread(
>                                 0,
>                                 NULL);
>          if (Pipe == INVALID_HANDLE_VALUE)
> -            goto fail2;
> -
> +            goto fail3;
> +
>          (VOID) ConnectNamedPipe(Pipe,
>                                  &Overlapped);
> -
> +
>          Object = WaitForMultipleObjects(ARRAYSIZE(Handle),
>                                          Handle,
>                                          FALSE,
> @@ -565,146 +478,60 @@ ServerThread(
>              CloseHandle(Pipe);
>              break;
>          }
> -
> +
>          ResetEvent(Overlapped.hEvent);
> -
> -        Instance = (PMONITOR_PIPE)malloc(sizeof(MONITOR_PIPE));
> -        if (Instance == NULL)
> -            goto fail3;
> -
> -        __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)
> +
> +        Connection =
> (PMONITOR_CONNECTION)malloc(sizeof(MONITOR_CONNECTION));
> +        if (Connection == NULL)
>              goto fail4;
> +
> +        __InitializeListHead(&Connection->ListEntry);
> +        Connection->Console = Console;
> +        Connection->Pipe = Pipe;
> +        Connection->Thread = CreateThread(NULL,
> +                                          0,
> +                                          ConnectionThread,
> +                                          Connection,
> +                                          0,
> +                                          NULL);
> +        if (Connection->Thread == NULL)
> +            goto fail5;
>      }
> -
> +
>      CloseHandle(Overlapped.hEvent);
> +
> +    Log("<==== %s", Console->DeviceName);
> +
> +    return 0;
> 
> -    Log("<====");
> +fail5:
> +    Log("fail5");
> 
> -    return 0;
> +    free(Connection);
> 
>  fail4:
>      Log("fail4");
> 
> -    free(Instance);
> +    CloseHandle(Pipe);
> 
>  fail3:
>      Log("fail3");
> 
> -    CloseHandle(Pipe);
> -
>  fail2:
>      Log("fail2");
> +
> +    CloseHandle(Overlapped.hEvent);
> 
>  fail1:
>      Error = GetLastError();
> -
> -    {
> -        PTCHAR  Message;
> -        Message = GetErrorMessage(Error);
> -        Log("fail1 (%s)", Message);
> -        LocalFree(Message);
> -    }
> -
> -    return 1;
> -}
> -
> -DWORD WINAPI
> -MonitorThread(
> -    IN  LPVOID          Argument
> -    )
> -{
> -    PMONITOR_CONTEXT    Context = &MonitorContext;
> -    PROCESS_INFORMATION ProcessInfo;
> -    STARTUPINFO         StartupInfo;
> -    BOOL                Success;
> -    HANDLE              Handle[2];
> -    DWORD               Object;
> -    HRESULT             Error;
> -
> -    UNREFERENCED_PARAMETER(Argument);
> -
> -    Log("====>");
> -
> -    // If there is no executable, this thread can finish now.
> -    if (Context->Executable == NULL)
> -        goto done;
> -
> -again:
> -    ZeroMemory(&ProcessInfo, sizeof (ProcessInfo));
> -    ZeroMemory(&StartupInfo, sizeof (StartupInfo));
> -    StartupInfo.cb = sizeof (StartupInfo);
> -
> -    Log("Executing: %s", Context->Executable);
> -
> -#pragma warning(suppress:6053) // CommandLine might not be NUL-
> terminated
> -    Success = CreateProcess(NULL,
> -                            Context->Executable,
> -                            NULL,
> -                            NULL,
> -                            FALSE,
> -                            CREATE_NO_WINDOW |
> -                            CREATE_NEW_PROCESS_GROUP,
> -                            NULL,
> -                            NULL,
> -                            &StartupInfo,
> -                            &ProcessInfo);
> -    if (!Success)
> -        goto fail1;
> -
> -    Handle[0] = Context->MonitorEvent;
> -    Handle[1] = ProcessInfo.hProcess;
> -
> -    Object = WaitForMultipleObjects(ARRAYSIZE(Handle),
> -                                   Handle,
> -                                   FALSE,
> -                                   INFINITE);
> -
> -#define WAIT_OBJECT_1 (WAIT_OBJECT_0 + 1)
> -
> -    switch (Object) {
> -    case WAIT_OBJECT_0:
> -        ResetEvent(Context->MonitorEvent);
> -
> -        TerminateProcess(ProcessInfo.hProcess, 1);
> -        CloseHandle(ProcessInfo.hProcess);
> -        CloseHandle(ProcessInfo.hThread);
> -        break;
> -
> -    case WAIT_OBJECT_1:
> -        CloseHandle(ProcessInfo.hProcess);
> -        CloseHandle(ProcessInfo.hThread);
> -        goto again;
> -
> -    default:
> -        break;
> -    }
> -
> -//#undef WAIT_OBJECT_1
> -
> -done:
> -    Log("<====");
> -
> -    return 0;
> -
> -fail1:
> -    Error = GetLastError();
> -
> +
>      {
>          PTCHAR  Message;
>          Message = GetErrorMessage(Error);
>          Log("fail1 (%s)", Message);
>          LocalFree(Message);
>      }
> -
> +
>      return 1;
>  }
> 
> @@ -713,7 +540,7 @@ DeviceThread(
>      IN  LPVOID          Argument
>      )
>  {
> -    PMONITOR_CONTEXT    Context = &MonitorContext;
> +    PMONITOR_CONSOLE    Console = (PMONITOR_CONSOLE)Argument;
>      OVERLAPPED          Overlapped;
>      HANDLE              Device;
>      UCHAR               Buffer[MAXIMUM_BUFFER_SIZE];
> @@ -721,11 +548,9 @@ DeviceThread(
>      DWORD               Wait;
>      HANDLE              Handles[2];
>      DWORD               Error;
> -
> -    UNREFERENCED_PARAMETER(Argument);
> -
> -    Log("====>");
> -
> +
> +    Log("====> %s", Console->DeviceName);
> +
>      ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
>      Overlapped.hEvent = CreateEvent(NULL,
>                                      TRUE,
> @@ -733,72 +558,172 @@ DeviceThread(
>                                      NULL);
>      if (Overlapped.hEvent == NULL)
>          goto fail1;
> -
> -    Handles[0] = Context->DeviceEvent;
> +
> +    Handles[0] = Console->DeviceEvent;
>      Handles[1] = Overlapped.hEvent;
> -
> -    Device = CreateFile(Context->DevicePath,
> -                        GENERIC_READ,
> -                        FILE_SHARE_READ | FILE_SHARE_WRITE,
> -                        NULL,
> -                        OPEN_EXISTING,
> -                        FILE_FLAG_OVERLAPPED,
> -                        NULL);
> +
> +    Device = CreateFileW(Console->DevicePath,
> +                         GENERIC_READ,
> +                         FILE_SHARE_READ | FILE_SHARE_WRITE,
> +                         NULL,
> +                         OPEN_EXISTING,
> +                         FILE_FLAG_OVERLAPPED,
> +                         NULL);
>      if (Device == INVALID_HANDLE_VALUE)
>          goto fail2;
> -
> +
>      for (;;) {
>          PLIST_ENTRY     ListEntry;
> -
> +
>          (VOID) ReadFile(Device,
>                          Buffer,
>                          sizeof(Buffer),
>                          NULL,
>                          &Overlapped);
> -
> +
>          Wait = WaitForMultipleObjects(ARRAYSIZE(Handles),
>                                        Handles,
>                                        FALSE,
>                                        INFINITE);
>          if (Wait == WAIT_OBJECT_0)
>              break;
> -
> +
>          if (!GetOverlappedResult(Device,
>                                   &Overlapped,
>                                   &Length,
>                                   FALSE))
>              break;
> -
> +
>          ResetEvent(Overlapped.hEvent);
> +
> +        EnterCriticalSection(&Console->CriticalSection);
> +
> +        for (ListEntry = Console->ListHead.Flink;
> +                ListEntry != &Console->ListHead;
> +                ListEntry = ListEntry->Flink) {
> +            PMONITOR_CONNECTION Connection;
> +
> +            Connection = CONTAINING_RECORD(ListEntry,
> +                                           MONITOR_CONNECTION,
> +                                           ListEntry);
> +
> +            PutString(Connection->Pipe,
> +                      Buffer,
> +                      Length);
> +        }
> 
> -        EnterCriticalSection(&Context->CriticalSection);
> +        LeaveCriticalSection(&Console->CriticalSection);
> +    }
> +
> +    CloseHandle(Device);
> +
> +    CloseHandle(Overlapped.hEvent);
> +
> +    Log("<==== %s", Console->DeviceName);
> +
> +    return 0;
> +
> +fail2:
> +    Log("fail2\n");
> +
> +    CloseHandle(Overlapped.hEvent);
> +
> +fail1:
> +    Error = GetLastError();
> +
> +    {
> +        PTCHAR  Message;
> +        Message = GetErrorMessage(Error);
> +        Log("fail1 (%s)", Message);
> +        LocalFree(Message);
> +    }
> +
> +    return 1;
> +}
> 
> -        for (ListEntry = Context->ListHead.Flink;
> -             ListEntry != &Context->ListHead;
> -             ListEntry = ListEntry->Flink) {
> -            PMONITOR_PIPE   Instance;
> +static BOOL
> +GetExecutable(
> +    IN  PCHAR           DeviceName,
> +    OUT PCHAR           *Executable
> +    )
> +{
> +    PMONITOR_CONTEXT    Context = &MonitorContext;
> +    HKEY                Key;
> +    DWORD               MaxValueLength;
> +    DWORD               ExecutableLength;
> +    DWORD               Type;
> +    HRESULT             Error;
> 
> -            Instance = CONTAINING_RECORD(ListEntry, MONITOR_PIPE,
> ListEntry);
> +    Error = RegOpenKeyExA(Context->ParametersKey,
> +                          DeviceName,
> +                          0,
> +                          KEY_READ,
> +                          &Key);
> +    if (Error != ERROR_SUCCESS) {
> +        SetLastError(Error);
> +        goto fail1;
> +    }
> 
> -            PutString(Instance->Pipe,
> -                      Buffer,
> -                      Length);
> -        }
> -        LeaveCriticalSection(&Context->CriticalSection);
> +    Error = RegQueryInfoKey(Key,
> +                            NULL,
> +                            NULL,
> +                            NULL,
> +                            NULL,
> +                            NULL,
> +                            NULL,
> +                            NULL,
> +                            NULL,
> +                            &MaxValueLength,
> +                            NULL,
> +                            NULL);
> +    if (Error != ERROR_SUCCESS) {
> +        SetLastError(Error);
> +        goto fail2;
>      }
> 
> -    CloseHandle(Device);
> +    ExecutableLength = MaxValueLength;
> 
> -    CloseHandle(Overlapped.hEvent);
> +    *Executable = calloc(1, ExecutableLength);
> +    if (Executable == NULL)
> +        goto fail3;
> 
> -    Log("<====");
> +    Error = RegQueryValueExA(Key,
> +                             "Executable",
> +                             NULL,
> +                             &Type,
> +                             (LPBYTE)(*Executable),
> +                             &ExecutableLength);
> +    if (Error != ERROR_SUCCESS) {
> +        SetLastError(Error);
> +        goto fail4;
> +    }
> 
> -    return 0;
> +    if (Type != REG_SZ) {
> +        SetLastError(ERROR_BAD_FORMAT);
> +        goto fail5;
> +    }
> +
> +    Log("%s = %s", DeviceName, *Executable);
> +
> +    RegCloseKey(Key);
> +
> +    return TRUE;
> +
> +fail5:
> +    Log("fail5");
> +
> +fail4:
> +    Log("fail4");
> +
> +    free(*Executable);
> +
> +fail3:
> +    Log("fail3");
> 
>  fail2:
> -    Log("fail2\n");
> +    Log("fail2");
> 
> -    CloseHandle(Overlapped.hEvent);
> +    RegCloseKey(Key);
> 
>  fail1:
>      Error = GetLastError();
> @@ -810,278 +735,614 @@ fail1:
>          LocalFree(Message);
>      }
> 
> -    return 1;
> +    return FALSE;
>  }
> 
> -#define ECHO(_Handle, _Buffer) \
> -    PutString((_Handle), (PUCHAR)TEXT(_Buffer),
> (DWORD)_tcslen((_Buffer)) * sizeof(TCHAR))
> +DWORD WINAPI
> +ExecutableThread(
> +    IN  LPVOID          Argument
> +    )
> +{
> +    PMONITOR_CONSOLE    Console = (PMONITOR_CONSOLE)Argument;
> +    PCHAR               Executable;
> +    PROCESS_INFORMATION ProcessInfo;
> +    STARTUPINFO         StartupInfo;
> +    BOOL                Success;
> +    HANDLE              Handle[2];
> +    DWORD               Object;
> +    HRESULT             Error;
> +
> +    Log("====> %s", Console->DeviceName);
> +
> +    // If there is no executable, this thread can finish now.
> +    if (!GetExecutable(Console->DeviceName,
> +                       &Executable))
> +        goto done;
> +    if (Executable == NULL)
> +        goto done;
> +
> +again:
> +    ZeroMemory(&ProcessInfo, sizeof (ProcessInfo));
> +    ZeroMemory(&StartupInfo, sizeof (StartupInfo));
> +    StartupInfo.cb = sizeof (StartupInfo);
> +
> +    Log("Executing: %s", Executable);
> +
> +#pragma warning(suppress:6053) // CommandLine might not be NUL-
> terminated
> +    Success = CreateProcess(NULL,
> +                            Executable,
> +                            NULL,
> +                            NULL,
> +                            FALSE,
> +                            CREATE_NO_WINDOW |
> +                            CREATE_NEW_PROCESS_GROUP,
> +                            NULL,
> +                            NULL,
> +                            &StartupInfo,
> +                            &ProcessInfo);
> +    if (!Success)
> +        goto fail1;
> +
> +    Handle[0] = Console->ExecutableEvent;
> +    Handle[1] = ProcessInfo.hProcess;
> +
> +    Object = WaitForMultipleObjects(ARRAYSIZE(Handle),
> +                                    Handle,
> +                                    FALSE,
> +                                    INFINITE);
> +
> +#define WAIT_OBJECT_1 (WAIT_OBJECT_0 + 1)
> +
> +    switch (Object) {
> +    case WAIT_OBJECT_0:
> +        ResetEvent(Console->ExecutableEvent);
> +
> +        TerminateProcess(ProcessInfo.hProcess, 1);
> +        CloseHandle(ProcessInfo.hProcess);
> +        CloseHandle(ProcessInfo.hThread);
> +        break;
> +
> +    case WAIT_OBJECT_1:
> +        CloseHandle(ProcessInfo.hProcess);
> +        CloseHandle(ProcessInfo.hThread);
> +        goto again;
> +
> +    default:
> +        break;
> +    }
> +
> +//#undef WAIT_OBJECT_1
> +
> +    free(Executable);
> 
> -static VOID
> -MonitorAdd(
> -    VOID
> +done:
> +    Log("<==== %s", Console->DeviceName);
> +
> +    return 0;
> +
> +fail1:
> +    Error = GetLastError();
> +
> +    free(Executable);
> +
> +    {
> +        PTCHAR  Message;
> +        Message = GetErrorMessage(Error);
> +        Log("fail1 (%s)", Message);
> +        LocalFree(Message);
> +    }
> +
> +    return 1;
> +}
> +
> +static PMONITOR_CONSOLE
> +ConsoleCreate(
> +    IN  PWCHAR              DevicePath
>      )
>  {
>      PMONITOR_CONTEXT        Context = &MonitorContext;
> -    PTCHAR                  Path;
> +    PMONITOR_CONSOLE        Console;
>      DEV_BROADCAST_HANDLE    Handle;
> -    HRESULT                 Error;
> +    CHAR                    DeviceName[MAX_PATH];
> +    DWORD                   Bytes;
>      BOOL                    Success;
> +    HRESULT                 Error;
> 
> -    if (Context->Device != INVALID_HANDLE_VALUE)
> -        return;
> -
> -    Log("====>");
> -
> -    Success = MonitorGetPath(&GUID_XENCONS_DEVICE, &Path);
> +    Log("====> %ws", DevicePath);
> 
> -    if (!Success)
> +    Console = malloc(sizeof(MONITOR_CONSOLE));
> +    if (Console == NULL)
>          goto fail1;
> 
> -    Context->Device = CreateFile(Path,
> -                                 GENERIC_WRITE,
> -                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
> -                                 NULL,
> -                                 OPEN_EXISTING,
> -                                 FILE_ATTRIBUTE_NORMAL,
> -                                 NULL);
> +    memset(Console, 0, sizeof(MONITOR_CONSOLE));
> +    __InitializeListHead(&Console->ListHead);
> +    __InitializeListHead(&Console->ListEntry);
> +    InitializeCriticalSection(&Console->CriticalSection);
> 
> -    if (Context->Device == INVALID_HANDLE_VALUE)
> +    Console->DevicePath = _wcsdup(DevicePath);
> +    if (Console->DevicePath == NULL)
>          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,
> +    Console->DeviceHandle = CreateFileW(DevicePath,
> +                                        GENERIC_READ | GENERIC_WRITE,
> +                                        FILE_SHARE_READ | FILE_SHARE_WRITE,
> +                                        NULL,
> +                                        OPEN_EXISTING,
> +                                        FILE_ATTRIBUTE_NORMAL,
>                                          NULL);
> +    if (Console->DeviceHandle == INVALID_HANDLE_VALUE)
> +        goto fail3;
> 
> -    if (Context->MonitorEvent == NULL)
> +    Success = DeviceIoControl(Console->DeviceHandle,
> +                              IOCTL_XENCONS_GET_NAME,
> +                              NULL,
> +                              0,
> +                              DeviceName,
> +                              sizeof(DeviceName),
> +                              &Bytes,
> +                              NULL);
> +    if (!Success)
>          goto fail4;
> 
> -    Context->MonitorThread = CreateThread(NULL,
> -                                          0,
> -                                          MonitorThread,
> -                                          NULL,
> -                                          0,
> -                                          NULL);
> +    DeviceName[MAX_PATH - 1] = '\0';
> 
> -    if (Context->MonitorThread == INVALID_HANDLE_VALUE)
> +    Console->DeviceName = _strdup(DeviceName);
> +    if (Console->DeviceName == NULL)
>          goto fail5;
> 
> -    Context->DeviceEvent = CreateEvent(NULL,
> +    ECHO(Console->DeviceHandle, "\r\n[ATTACHED]\r\n");
> +
> +    ZeroMemory(&Handle, sizeof (Handle));
> +    Handle.dbch_size = sizeof (Handle);
> +    Handle.dbch_devicetype = DBT_DEVTYP_HANDLE;
> +    Handle.dbch_handle = Console->DeviceHandle;
> +
> +    Console->DeviceNotification =
> +        RegisterDeviceNotification(Context->Service,
> +                                    &Handle,
> +                                    DEVICE_NOTIFY_SERVICE_HANDLE);
> +    if (Console->DeviceNotification == NULL)
> +        goto fail6;
> +
> +    Console->DeviceEvent = CreateEvent(NULL,
>                                         TRUE,
>                                         FALSE,
>                                         NULL);
> +    if (Console->DeviceEvent == NULL)
> +        goto fail7;
> 
> -    if (Context->DeviceEvent == NULL)
> -        goto fail6;
> -
> -    Context->DeviceThread = CreateThread(NULL,
> +    Console->DeviceThread = CreateThread(NULL,
>                                           0,
>                                           DeviceThread,
> -                                         NULL,
> +                                         Console,
>                                           0,
>                                           NULL);
> +    if (Console->DeviceThread == NULL)
> +        goto fail8;
> 
> -    if (Context->DeviceThread == INVALID_HANDLE_VALUE)
> -        goto fail7;
> -
> -    Context->ServerEvent = CreateEvent(NULL,
> +    Console->ServerEvent = CreateEvent(NULL,
>                                         TRUE,
>                                         FALSE,
>                                         NULL);
> -    if (Context->ServerEvent == NULL)
> -        goto fail8;
> +    if (Console->ServerEvent == NULL)
> +        goto fail9;
> 
> -    Context->ServerThread = CreateThread(NULL,
> +    Console->ServerThread = CreateThread(NULL,
>                                           0,
>                                           ServerThread,
> -                                         NULL,
> +                                         Console,
>                                           0,
>                                           NULL);
> -    if (Context->ServerThread == INVALID_HANDLE_VALUE)
> -        goto fail9;
> +    if (Console->ServerThread == NULL)
> +        goto fail10;
> 
> -    Log("<====");
> +    Console->ExecutableEvent = CreateEvent(NULL,
> +                                           TRUE,
> +                                           FALSE,
> +                                           NULL);
> +    if (Console->ExecutableEvent == NULL)
> +        goto fail11;
> 
> -    return;
> +    Console->ExecutableThread = CreateThread(NULL,
> +                                             0,
> +                                             ExecutableThread,
> +                                             Console,
> +                                             0,
> +                                             NULL);
> +    if (Console->ExecutableThread == NULL)
> +        goto fail12;
> +
> +    Log("<==== %s", Console->DeviceName);
> +
> +    return Console;
> +
> +fail12:
> +    Log("fail12");
> +
> +    CloseHandle(Console->ExecutableEvent);
> +    Console->ExecutableEvent = NULL;
> +
> +fail11:
> +    Log("fail11");
> +
> +    SetEvent(Console->ServerEvent);
> +    WaitForSingleObject(Console->ServerThread, INFINITE);
> +
> +fail10:
> +    Log("fail10");
> +
> +    CloseHandle(Console->ServerEvent);
> +    Console->ServerEvent = NULL;
> 
>  fail9:
>      Log("fail9");
> 
> -    CloseHandle(Context->ServerEvent);
> -    Context->ServerEvent = NULL;
> +    SetEvent(Console->DeviceEvent);
> +    WaitForSingleObject(Console->DeviceThread, INFINITE);
> 
>  fail8:
>      Log("fail8");
> 
> -    SetEvent(Context->DeviceEvent);
> -    WaitForSingleObject(Context->DeviceThread, INFINITE);
> +    CloseHandle(Console->DeviceEvent);
> +    Console->DeviceEvent = NULL;
> 
>  fail7:
> -    Log("fail7\n");
> +    Log("fail7");
> 
> -    CloseHandle(Context->DeviceEvent);
> -    Context->DeviceEvent = NULL;
> +    UnregisterDeviceNotification(Console->DeviceNotification);
> +    Console->DeviceNotification = NULL;
> 
>  fail6:
> -    Log("fail6\n");
> +    Log("fail6");
> 
> -    SetEvent(Context->MonitorThread);
> -    WaitForSingleObject(Context->MonitorThread, INFINITE);
> +    ECHO(Console->DeviceHandle, "\r\n[DETACHED]\r\n");
> +
> +    free(Console->DevicePath);
> +    Console->DevicePath = NULL;
> 
>  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;
> +    CloseHandle(Console->DeviceHandle);
> +    Console->DeviceHandle = INVALID_HANDLE_VALUE;
> 
>  fail3:
>      Log("fail3");
> 
> -    CloseHandle(Context->Device);
> -    Context->Device = INVALID_HANDLE_VALUE;
> +    free(Console->DevicePath);
> +    Console->DevicePath = NULL;
> 
>  fail2:
>      Log("fail2");
> 
> -    free(Path);
> +    DeleteCriticalSection(&Console->CriticalSection);
> +    ZeroMemory(&Console->ListHead, sizeof(LIST_ENTRY));
> +    ZeroMemory(&Console->ListEntry, sizeof(LIST_ENTRY));
> +
> +    free(Console);
> 
>  fail1:
>      Error = GetLastError();
> 
>      {
> -        PTCHAR  Message;
> +        PCHAR  Message;
>          Message = GetErrorMessage(Error);
>          Log("fail1 (%s)", Message);
>          LocalFree(Message);
>      }
> +
> +    return NULL;
>  }
> 
> -static VOID
> -MonitorWaitForPipeThreads(
> -    VOID
> +static FORCEINLINE VOID
> +ConsoleWaitForPipes(
> +    IN  PMONITOR_CONSOLE    Console
>      )
>  {
> -    PMONITOR_CONTEXT    Context = &MonitorContext;
> -    HANDLE              *Handles;
> -    DWORD               Index;
> -    PLIST_ENTRY         ListEntry;
> +    PLIST_ENTRY             ListEntry;
> +    HANDLE                  *Events;
> +    DWORD                   Count;
> +    DWORD                   Index;
> 
> -    EnterCriticalSection(&Context->CriticalSection);
> +    EnterCriticalSection(&Console->CriticalSection);
> 
> -    if (Context->ListCount == 0)
> +    Count = Console->ListCount + 1;
> +    Events = malloc(Count * sizeof(HANDLE));
> +    if (Events == NULL)
>          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;
> +    for (ListEntry = Console->ListHead.Flink;
> +         ListEntry != &Console->ListHead;
>           ListEntry = ListEntry->Flink) {
> -        PMONITOR_PIPE Pipe = CONTAINING_RECORD(ListEntry,
> MONITOR_PIPE, ListEntry);
> -        Handles[Index++] = Pipe->Thread;
> +        PMONITOR_CONNECTION Connection;
> +
> +        Connection = CONTAINING_RECORD(ListEntry,
> +                                       MONITOR_CONNECTION,
> +                                       ListEntry);
> +
> +#pragma warning(suppress: 6386) // Buffer overflow
> +        Events[Index] = Connection->Thread;
> +        ++Index;
>      }
> +    Events[Count - 1] = Console->ServerThread;
> 
> -    Context->ListCount = 0;
> +    LeaveCriticalSection(&Console->CriticalSection);
> 
> -    LeaveCriticalSection(&Context->CriticalSection);
> +    SetEvent(Console->ServerEvent);
> +    WaitForMultipleObjects(Count, Events, TRUE, INFINITE);
> 
> -#pragma warning(suppress:6385) // Reading invalid data from 'Handles'...
> -    WaitForMultipleObjects(Index,
> -                           Handles,
> -                           TRUE,
> -                           INFINITE);
> -    free(Handles);
>      return;
> 
> -fail2:
> -    Log("fail2");
> -
>  fail1:
> -    Log("fail1");
> +    LeaveCriticalSection(&Console->CriticalSection);
> +
> +    // set the event and wait for the server thread anyway
> +    SetEvent(Console->ServerEvent);
> +    WaitForSingleObject(Console->ServerThread, INFINITE);
> +}
> +
> +static VOID
> +ConsoleDestroy(
> +    IN  PMONITOR_CONSOLE    Console
> +    )
> +{
> +    Log("====> %s", Console->DeviceName);
> +
> +    SetEvent(Console->ExecutableEvent);
> +    WaitForSingleObject(Console->ExecutableThread, INFINITE);
> +
> +    CloseHandle(Console->ExecutableEvent);
> +    Console->ExecutableEvent = NULL;
> +
> +    ConsoleWaitForPipes(Console);
> +
> +    CloseHandle(Console->ServerEvent);
> +    Console->ServerEvent = NULL;
> +
> +    SetEvent(Console->DeviceEvent);
> +    WaitForSingleObject(Console->DeviceThread, INFINITE);
> +
> +    CloseHandle(Console->DeviceEvent);
> +    Console->DeviceEvent = NULL;
> +
> +    UnregisterDeviceNotification(Console->DeviceNotification);
> +    Console->DeviceNotification = NULL;
> +
> +    ECHO(Console->DeviceHandle, "\r\n[DETACHED]\r\n");
> +
> +    free(Console->DevicePath);
> +    Console->DevicePath = NULL;
> +
> +    CloseHandle(Console->DeviceHandle);
> +    Console->DeviceHandle = INVALID_HANDLE_VALUE;
> +
> +    free(Console->DevicePath);
> +    Console->DevicePath = NULL;
> +
> +    DeleteCriticalSection(&Console->CriticalSection);
> +    ZeroMemory(&Console->ListHead, sizeof(LIST_ENTRY));
> +    ZeroMemory(&Console->ListEntry, sizeof(LIST_ENTRY));
> +
> +    free(Console);
> 
> +    Log("<====");
> +}
> +
> +static BOOL
> +MonitorAdd(
> +    IN  PWCHAR          DevicePath
> +    )
> +{
> +    PMONITOR_CONTEXT    Context = &MonitorContext;
> +    PMONITOR_CONSOLE    Console;
> +
> +    Log("=====> %ws", DevicePath);
> +
> +    Console = ConsoleCreate(DevicePath);
> +    if (Console == NULL)
> +        goto fail1;
> +
> +    EnterCriticalSection(&Context->CriticalSection);
> +    __InsertTailList(&Context->ListHead, &Console->ListEntry);
> +    ++Context->ListCount;
>      LeaveCriticalSection(&Context->CriticalSection);
> 
> -    return;
> +    Log("<===== %s", Console->DeviceName);
> +
> +    return TRUE;
> +
> +fail1:
> +    Log("fail1");
> +
> +    return FALSE;
>  }
> 
> -static VOID
> +static BOOL
>  MonitorRemove(
> -    VOID
> +    IN  HANDLE          DeviceHandle
>      )
>  {
>      PMONITOR_CONTEXT    Context = &MonitorContext;
> +    PMONITOR_CONSOLE    Console;
> +    PLIST_ENTRY         ListEntry;
> 
> -    if (Context->Device == INVALID_HANDLE_VALUE)
> -        return;
> +    Log("=====> 0x%p", DeviceHandle);
> +
> +    EnterCriticalSection(&Context->CriticalSection);
> +    for (ListEntry = Context->ListHead.Flink;
> +         ListEntry != &Context->ListHead;
> +         ListEntry = ListEntry->Flink) {
> +        Console = CONTAINING_RECORD(ListEntry,
> +                                    MONITOR_CONSOLE,
> +                                    ListEntry);
> +
> +        if (Console->DeviceHandle == DeviceHandle)
> +            goto found;
> +    }
> +    LeaveCriticalSection(&Context->CriticalSection);
> 
> +    Log("DeviceHandle 0x%p not found", DeviceHandle);
> +
> +    return FALSE;
> +
> +found:
> +    __RemoveEntryList(&Console->ListEntry);
> +    --Context->ListCount;
> +    LeaveCriticalSection(&Context->CriticalSection);
> +
> +    ConsoleDestroy(Console);
> +
> +    Log("<=====");
> +
> +    return TRUE;
> +}
> +
> +static BOOL
> +MonitorEnumerate(
> +    VOID
> +    )
> +{
> +    PMONITOR_CONTEXT                    Context = &MonitorContext;
> +    HDEVINFO                            DeviceInfoSet;
> +    SP_DEVICE_INTERFACE_DATA            DeviceInterfaceData;
> +    PSP_DEVICE_INTERFACE_DETAIL_DATA_W  DeviceInterfaceDetail;
> +    PMONITOR_CONSOLE                    Console;
> +    DWORD                               Size;
> +    DWORD                               Index;
> +    HRESULT                             Error;
> +    BOOL                                Success;
> +
>      Log("====>");
> +
> +    DeviceInfoSet = SetupDiGetClassDevs(&GUID_XENCONS_DEVICE,
> +                                        NULL,
> +                                        NULL,
> +                                        DIGCF_PRESENT |
> +                                        DIGCF_DEVICEINTERFACE);
> +    if (DeviceInfoSet == INVALID_HANDLE_VALUE)
> +        goto fail1;
> +
> +    DeviceInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
> 
> -    SetEvent(Context->ServerEvent);
> -    MonitorWaitForPipeThreads();
> -    WaitForSingleObject(Context->ServerThread, INFINITE);
> +    for (Index = 0; TRUE; ++Index) {
> +        Success = SetupDiEnumDeviceInterfaces(DeviceInfoSet,
> +                                              NULL,
> +                                              &GUID_XENCONS_DEVICE,
> +                                              Index,
> +                                              &DeviceInterfaceData);
> +        if (!Success)
> +            break;
> 
> -    CloseHandle(Context->ServerEvent);
> -    Context->ServerEvent = NULL;
> +        Success = SetupDiGetDeviceInterfaceDetailW(DeviceInfoSet,
> +                                                  &DeviceInterfaceData,
> +                                                  NULL,
> +                                                  0,
> +                                                  &Size,
> +                                                  NULL);
> +        if (!Success && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
> +            goto fail2;
> +
> +        DeviceInterfaceDetail = calloc(1, Size);
> +        if (DeviceInterfaceDetail == NULL)
> +            goto fail3;
> +
> +        DeviceInterfaceDetail->cbSize =
> +            sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA_W);
> +
> +        Success = SetupDiGetDeviceInterfaceDetailW(DeviceInfoSet,
> +                                                   &DeviceInterfaceData,
> +                                                   DeviceInterfaceDetail,
> +                                                   Size,
> +                                                   NULL,
> +                                                   NULL);
> +        if (!Success)
> +            goto fail4;
> 
> -    SetEvent(Context->DeviceEvent);
> -    WaitForSingleObject(Context->DeviceThread, INFINITE);
> +        Console = ConsoleCreate(DeviceInterfaceDetail->DevicePath);
> +        if (Console == NULL)
> +            goto fail5;
> 
> -    CloseHandle(Context->DeviceEvent);
> -    Context->DeviceEvent = NULL;
> +        EnterCriticalSection(&Context->CriticalSection);
> +        __InsertTailList(&Context->ListHead, &Console->ListEntry);
> +        ++Context->ListCount;
> +        LeaveCriticalSection(&Context->CriticalSection);
> 
> -    SetEvent(Context->MonitorEvent);
> -    WaitForSingleObject(Context->MonitorThread, INFINITE);
> +        free(DeviceInterfaceDetail);
> 
> -    CloseHandle(Context->MonitorEvent);
> -    Context->MonitorEvent = NULL;
> +        continue;
> 
> -    DeleteCriticalSection(&Context->CriticalSection);
> -    ZeroMemory(&Context->ListHead, sizeof(LIST_ENTRY));
> +    fail5:
> +        Log("fail5");
> +    fail4:
> +        Log("fail4");
> 
> -    free(Context->DevicePath);
> -    Context->DevicePath = NULL;
> +        free(DeviceInterfaceDetail);
> 
> -    UnregisterDeviceNotification(Context->DeviceNotification);
> -    Context->DeviceNotification = NULL;
> +    fail3:
> +        Log("fail3");
> +    fail2:
> +        Error = GetLastError();
> 
> -    ECHO(Context->Device, "\r\n[DETACHED]\r\n");
> +        {
> +            PCHAR  Message;
> +            Message = GetErrorMessage(Error);
> +            Log("fail2 (%s)", Message);
> +            LocalFree(Message);
> +        }
> +    }
> 
> -    CloseHandle(Context->Device);
> -    Context->Device = INVALID_HANDLE_VALUE;
> +    SetupDiDestroyDeviceInfoList(DeviceInfoSet);
> 
>      Log("<====");
> +
> +    return TRUE;
> +
> +fail1:
> +    Error = GetLastError();
> +
> +    {
> +        PCHAR  Message;
> +        Message = GetErrorMessage(Error);
> +        Log("fail1 (%s)", Message);
> +        LocalFree(Message);
> +    }
> +
> +    return FALSE;
> +}
> +
> +static VOID
> +MonitorRemoveAll(
> +    VOID
> +    )
> +{
> +    PMONITOR_CONTEXT    Context = &MonitorContext;
> +    PMONITOR_CONSOLE    Console;
> +
> +    Log("=====>");
> +
> +    for (;;) {
> +        EnterCriticalSection(&Context->CriticalSection);
> +        if (Context->ListHead.Flink == &Context->ListHead)
> +            break;
> +
> +        Console = CONTAINING_RECORD(Context->ListHead.Flink,
> +                                    MONITOR_CONSOLE,
> +                                    ListEntry);
> +
> +        __RemoveEntryList(&Console->ListEntry);
> +        --Context->ListCount;
> +
> +        LeaveCriticalSection(&Context->CriticalSection);
> +
> +        ConsoleDestroy(Console);
> +    }
> +    LeaveCriticalSection(&Context->CriticalSection);
> +
> +    Log("<=====");
>  }
> 
>  DWORD WINAPI
> @@ -1113,11 +1374,11 @@ MonitorCtrlHandlerEx(
>          switch (EventType) {
>          case DBT_DEVICEARRIVAL:
>              if (Header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
> -                PDEV_BROADCAST_DEVICEINTERFACE  Interface = EventData;
> +                PDEV_BROADCAST_DEVICEINTERFACE_W Interface = EventData;
> 
>                  if (IsEqualGUID(&Interface->dbcc_classguid,
> -                               &GUID_XENCONS_DEVICE))
> -                    SetEvent(Context->AddEvent);
> +                                &GUID_XENCONS_DEVICE))
> +                    MonitorAdd(Interface->dbcc_name);
>              }
>              break;
> 
> @@ -1127,8 +1388,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 +1403,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,14 +1412,13 @@ MonitorMain(
>      PMONITOR_CONTEXT                Context = &MonitorContext;
>      DEV_BROADCAST_DEVICEINTERFACE   Interface;
>      HRESULT                         Error;
> -    BOOL                            Success;
> 
>      UNREFERENCED_PARAMETER(argc);
>      UNREFERENCED_PARAMETER(argv);
> 
>      Log("====>");
> 
> -    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
> +    Error = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
>                           PARAMETERS_KEY(__MODULE__),
>                           0,
>                           KEY_READ,
> @@ -1245,13 +1426,13 @@ MonitorMain(
>      if (Error != ERROR_SUCCESS)
>          goto fail1;
> 
> -    Context->Service = RegisterServiceCtrlHandlerEx(MONITOR_NAME,
> +    Context->Service = RegisterServiceCtrlHandlerExA(MONITOR_NAME,
>                                                      MonitorCtrlHandlerEx,
>                                                      NULL);
>      if (Context->Service == NULL)
>          goto fail2;
> 
> -    Context->EventLog = RegisterEventSource(NULL,
> +    Context->EventLog = RegisterEventSourceA(NULL,
>                                              MONITOR_NAME);
>      if (Context->EventLog == NULL)
>          goto fail3;
> @@ -1269,28 +1450,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 +1460,26 @@ MonitorMain(
>                                     &Interface,
>                                     DEVICE_NOTIFY_SERVICE_HANDLE);
>      if (Context->InterfaceNotification == NULL)
> -        goto fail7;
> -
> -    // The device may already by present
> -    SetEvent(Context->AddEvent);
> +        goto fail5;
> 
>      ReportStatus(SERVICE_RUNNING, NO_ERROR, 0);
> 
> -    for (;;) {
> -        HANDLE  Events[3];
> -        DWORD   Object;
> -
> -        Events[0] = Context->StopEvent;
> -        Events[1] = Context->AddEvent;
> -        Events[2] = Context->RemoveEvent;
> -
> -        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;
> +    __InitializeListHead(&Context->ListHead);
> +    InitializeCriticalSection(&Context->CriticalSection);
> 
> -        case WAIT_OBJECT_1:
> -            ResetEvent(Context->AddEvent);
> -            MonitorAdd();
> -            break;
> +    MonitorEnumerate();
> 
> -        case WAIT_OBJECT_2:
> -            ResetEvent(Context->RemoveEvent);
> -            MonitorRemove();
> +    Log("Waiting...");
> +    WaitForSingleObject(Context->StopEvent, INFINITE);
> +    Log("Wait Complete");
> 
> -        default:
> -            break;
> -        }
> -
> -#undef WAIT_OBJECT_1
> -#undef WAIT_OBJECT_2
> -    }
> +    MonitorRemoveAll();
> 
> -done:
> -    MonitorRemove();
> +    DeleteCriticalSection(&Context->CriticalSection);
> +    ZeroMemory(&Context->ListHead, sizeof(LIST_ENTRY));
> 
>      UnregisterDeviceNotification(Context->InterfaceNotification);
> 
> -    free(Context->Executable);
> -
> -    CloseHandle(Context->RemoveEvent);
> -
> -    CloseHandle(Context->AddEvent);
> -
>      CloseHandle(Context->StopEvent);
> 
>      ReportStatus(SERVICE_STOPPED, NO_ERROR, 0);
> @@ -1371,16 +1492,6 @@ done:
> 
>      return;
> 
> -fail7:
> -    Log("fail7");
> -
> -    CloseHandle(Context->RemoveEvent);
> -
> -fail6:
> -    Log("fail6");
> -
> -    CloseHandle(Context->AddEvent);
> -
>  fail5:
>      Log("fail5");
> 
> @@ -1419,12 +1530,12 @@ MonitorCreate(
>  {
>      SC_HANDLE   SCManager;
>      SC_HANDLE   Service;
> -    TCHAR       Path[MAX_PATH];
> +    CHAR        Path[MAX_PATH];
>      HRESULT     Error;
> 
>      Log("====>");
> 
> -    if(!GetModuleFileName(NULL, Path, MAX_PATH))
> +    if(!GetModuleFileNameA(NULL, Path, MAX_PATH))
>          goto fail1;
> 
>      SCManager = OpenSCManager(NULL,
> @@ -1589,7 +1700,7 @@ fail1:
>  }
> 
>  int CALLBACK
> -_tWinMain(
> +WinMain(
>      _In_        HINSTANCE   Current,
>      _In_opt_    HINSTANCE   Previous,
>      _In_        LPSTR       CmdLine,
> @@ -1602,10 +1713,10 @@ _tWinMain(
>      UNREFERENCED_PARAMETER(Previous);
>      UNREFERENCED_PARAMETER(CmdShow);
> 
> -    if (_tcslen(CmdLine) != 0) {
> -         if (_tcsicmp(CmdLine, TEXT("create")) == 0)
> +    if (strlen(CmdLine) != 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..d623c21 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 {
> @@ -402,17 +402,23 @@ _tmain(
>      UNREFERENCED_PARAMETER(argc);
>      UNREFERENCED_PARAMETER(argv);
> 
> +    if (!WaitNamedPipe(PIPE_NAME, NMPWAIT_USE_DEFAULT_WAIT))
> +        ExitProcess(1);
> +
>      Context->Device.Read = CreateFile(PIPE_NAME,
> -                                      GENERIC_READ,
> -                                      FILE_SHARE_WRITE,
> -                                      NULL,
> -                                      OPEN_EXISTING,
> -                                      FILE_ATTRIBUTE_NORMAL,
> -                                      NULL);
> +                                        GENERIC_READ,
> +                                        FILE_SHARE_WRITE,
> +                                        NULL,
> +                                        OPEN_EXISTING,
> +                                        FILE_ATTRIBUTE_NORMAL,
> +                                        NULL);
> 
>      if (Context->Device.Read == INVALID_HANDLE_VALUE)
>          ExitProcess(1);
> 
> +    if (!WaitNamedPipe(PIPE_NAME, NMPWAIT_USE_DEFAULT_WAIT))
> +        ExitProcess(1);
> +
>      Context->Device.Write = CreateFile(PIPE_NAME,
>                                         GENERIC_WRITE,
>                                         FILE_SHARE_READ | FILE_SHARE_WRITE,
> 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_VERSI
> ON@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.ex
> e"
> +HKR,"Parameters\default","Executable",0x00000000,"xencons_tty_@MAJ
> OR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NU
> MBER@.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
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.